diff options
28 files changed, 4792 insertions, 547 deletions
diff --git a/Documentation/devicetree/bindings/phy/apm-xgene-phy.txt b/Documentation/devicetree/bindings/phy/apm-xgene-phy.txt new file mode 100644 index 000000000000..5f3a65a9dd88 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/apm-xgene-phy.txt | |||
@@ -0,0 +1,79 @@ | |||
1 | * APM X-Gene 15Gbps Multi-purpose PHY nodes | ||
2 | |||
3 | PHY nodes are defined to describe on-chip 15Gbps Multi-purpose PHY. Each | ||
4 | PHY (pair of lanes) has its own node. | ||
5 | |||
6 | Required properties: | ||
7 | - compatible : Shall be "apm,xgene-phy". | ||
8 | - reg : PHY memory resource is the SDS PHY access resource. | ||
9 | - #phy-cells : Shall be 1 as it expects one argument for setting | ||
10 | the mode of the PHY. Possible values are 0 (SATA), | ||
11 | 1 (SGMII), 2 (PCIe), 3 (USB), and 4 (XFI). | ||
12 | |||
13 | Optional properties: | ||
14 | - status : Shall be "ok" if enabled or "disabled" if disabled. | ||
15 | Default is "ok". | ||
16 | - clocks : Reference to the clock entry. | ||
17 | - apm,tx-eye-tuning : Manual control to fine tune the capture of the serial | ||
18 | bit lines from the automatic calibrated position. | ||
19 | Two set of 3-tuple setting for each (up to 3) | ||
20 | supported link speed on the host. Range from 0 to | ||
21 | 127 in unit of one bit period. Default is 10. | ||
22 | - apm,tx-eye-direction : Eye tuning manual control direction. 0 means sample | ||
23 | data earlier than the nominal sampling point. 1 means | ||
24 | sample data later than the nominal sampling point. | ||
25 | Two set of 3-tuple setting for each (up to 3) | ||
26 | supported link speed on the host. Default is 0. | ||
27 | - apm,tx-boost-gain : Frequency boost AC (LSB 3-bit) and DC (2-bit) | ||
28 | gain control. Two set of 3-tuple setting for each | ||
29 | (up to 3) supported link speed on the host. Range is | ||
30 | between 0 to 31 in unit of dB. Default is 3. | ||
31 | - apm,tx-amplitude : Amplitude control. Two set of 3-tuple setting for | ||
32 | each (up to 3) supported link speed on the host. | ||
33 | Range is between 0 to 199500 in unit of uV. | ||
34 | Default is 199500 uV. | ||
35 | - apm,tx-pre-cursor1 : 1st pre-cursor emphasis taps control. Two set of | ||
36 | 3-tuple setting for each (up to 3) supported link | ||
37 | speed on the host. Range is 0 to 273000 in unit of | ||
38 | uV. Default is 0. | ||
39 | - apm,tx-pre-cursor2 : 2st pre-cursor emphasis taps control. Two set of | ||
40 | 3-tuple setting for each (up to 3) supported link | ||
41 | speed on the host. Range is 0 to 127400 in unit uV. | ||
42 | Default is 0x0. | ||
43 | - apm,tx-post-cursor : Post-cursor emphasis taps control. Two set of | ||
44 | 3-tuple setting for Gen1, Gen2, and Gen3. Range is | ||
45 | between 0 to 0x1f in unit of 18.2mV. Default is 0xf. | ||
46 | - apm,tx-speed : Tx operating speed. One set of 3-tuple for each | ||
47 | supported link speed on the host. | ||
48 | 0 = 1-2Gbps | ||
49 | 1 = 2-4Gbps (1st tuple default) | ||
50 | 2 = 4-8Gbps | ||
51 | 3 = 8-15Gbps (2nd tuple default) | ||
52 | 4 = 2.5-4Gbps | ||
53 | 5 = 4-5Gbps | ||
54 | 6 = 5-6Gbps | ||
55 | 7 = 6-16Gbps (3rd tuple default) | ||
56 | |||
57 | NOTE: PHY override parameters are board specific setting. | ||
58 | |||
59 | Example: | ||
60 | phy1: phy@1f21a000 { | ||
61 | compatible = "apm,xgene-phy"; | ||
62 | reg = <0x0 0x1f21a000 0x0 0x100>; | ||
63 | #phy-cells = <1>; | ||
64 | status = "disabled"; | ||
65 | }; | ||
66 | |||
67 | phy2: phy@1f22a000 { | ||
68 | compatible = "apm,xgene-phy"; | ||
69 | reg = <0x0 0x1f22a000 0x0 0x100>; | ||
70 | #phy-cells = <1>; | ||
71 | status = "ok"; | ||
72 | }; | ||
73 | |||
74 | phy3: phy@1f23a000 { | ||
75 | compatible = "apm,xgene-phy"; | ||
76 | reg = <0x0 0x1f23a000 0x0 0x100>; | ||
77 | #phy-cells = <1>; | ||
78 | status = "ok"; | ||
79 | }; | ||
diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt index c0fccaa1671e..28f9edb8f19c 100644 --- a/Documentation/devicetree/bindings/phy/samsung-phy.txt +++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt | |||
@@ -20,3 +20,57 @@ Required properties: | |||
20 | - compatible : should be "samsung,exynos5250-dp-video-phy"; | 20 | - compatible : should be "samsung,exynos5250-dp-video-phy"; |
21 | - reg : offset and length of the Display Port PHY register set; | 21 | - reg : offset and length of the Display Port PHY register set; |
22 | - #phy-cells : from the generic PHY bindings, must be 0; | 22 | - #phy-cells : from the generic PHY bindings, must be 0; |
23 | |||
24 | Samsung S5P/EXYNOS SoC series USB PHY | ||
25 | ------------------------------------------------- | ||
26 | |||
27 | Required properties: | ||
28 | - compatible : should be one of the listed compatibles: | ||
29 | - "samsung,exynos4210-usb2-phy" | ||
30 | - "samsung,exynos4x12-usb2-phy" | ||
31 | - "samsung,exynos5250-usb2-phy" | ||
32 | - reg : a list of registers used by phy driver | ||
33 | - first and obligatory is the location of phy modules registers | ||
34 | - samsung,sysreg-phandle - handle to syscon used to control the system registers | ||
35 | - samsung,pmureg-phandle - handle to syscon used to control PMU registers | ||
36 | - #phy-cells : from the generic phy bindings, must be 1; | ||
37 | - clocks and clock-names: | ||
38 | - the "phy" clock is required by the phy module, used as a gate | ||
39 | - the "ref" clock is used to get the rate of the clock provided to the | ||
40 | PHY module | ||
41 | |||
42 | The first phandle argument in the PHY specifier identifies the PHY, its | ||
43 | meaning is compatible dependent. For the currently supported SoCs (Exynos 4210 | ||
44 | and Exynos 4212) it is as follows: | ||
45 | 0 - USB device ("device"), | ||
46 | 1 - USB host ("host"), | ||
47 | 2 - HSIC0 ("hsic0"), | ||
48 | 3 - HSIC1 ("hsic1"), | ||
49 | |||
50 | Exynos 4210 and Exynos 4212 use mode switching and require that mode switch | ||
51 | register is supplied. | ||
52 | |||
53 | Example: | ||
54 | |||
55 | For Exynos 4412 (compatible with Exynos 4212): | ||
56 | |||
57 | usbphy: phy@125b0000 { | ||
58 | compatible = "samsung,exynos4x12-usb2-phy"; | ||
59 | reg = <0x125b0000 0x100>; | ||
60 | clocks = <&clock 305>, <&clock 2>; | ||
61 | clock-names = "phy", "ref"; | ||
62 | status = "okay"; | ||
63 | #phy-cells = <1>; | ||
64 | samsung,sysreg-phandle = <&sys_reg>; | ||
65 | samsung,pmureg-phandle = <&pmu_reg>; | ||
66 | }; | ||
67 | |||
68 | Then the PHY can be used in other nodes such as: | ||
69 | |||
70 | phy-consumer@12340000 { | ||
71 | phys = <&usbphy 2>; | ||
72 | phy-names = "phy"; | ||
73 | }; | ||
74 | |||
75 | Refer to DT bindings documentation of particular PHY consumer devices for more | ||
76 | information about required PHYs and the way of specification. | ||
diff --git a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt new file mode 100644 index 000000000000..a82361b62015 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt | |||
@@ -0,0 +1,26 @@ | |||
1 | Allwinner sun4i USB PHY | ||
2 | ----------------------- | ||
3 | |||
4 | Required properties: | ||
5 | - compatible : should be one of "allwinner,sun4i-a10-usb-phy", | ||
6 | "allwinner,sun5i-a13-usb-phy" or "allwinner,sun7i-a20-usb-phy" | ||
7 | - reg : a list of offset + length pairs | ||
8 | - reg-names : "phy_ctrl", "pmu1" and for sun4i or sun7i "pmu2" | ||
9 | - #phy-cells : from the generic phy bindings, must be 1 | ||
10 | - clocks : phandle + clock specifier for the phy clock | ||
11 | - clock-names : "usb_phy" | ||
12 | - resets : a list of phandle + reset specifier pairs | ||
13 | - reset-names : "usb0_reset", "usb1_reset" and for sun4i or sun7i "usb2_reset" | ||
14 | |||
15 | Example: | ||
16 | usbphy: phy@0x01c13400 { | ||
17 | #phy-cells = <1>; | ||
18 | compatible = "allwinner,sun4i-a10-usb-phy"; | ||
19 | /* phy base regs, phy1 pmu reg, phy2 pmu reg */ | ||
20 | reg = <0x01c13400 0x10 0x01c14800 0x4 0x01c1c800 0x4>; | ||
21 | reg-names = "phy_ctrl", "pmu1", "pmu2"; | ||
22 | clocks = <&usb_clk 8>; | ||
23 | clock-names = "usb_phy"; | ||
24 | resets = <&usb_clk 1>, <&usb_clk 2>; | ||
25 | reset-names = "usb1_reset", "usb2_reset"; | ||
26 | }; | ||
diff --git a/Documentation/phy/samsung-usb2.txt b/Documentation/phy/samsung-usb2.txt new file mode 100644 index 000000000000..ed12d437189d --- /dev/null +++ b/Documentation/phy/samsung-usb2.txt | |||
@@ -0,0 +1,135 @@ | |||
1 | .------------------------------------------------------------------------------+ | ||
2 | | Samsung USB 2.0 PHY adaptation layer | | ||
3 | +-----------------------------------------------------------------------------+' | ||
4 | |||
5 | | 1. Description | ||
6 | +---------------- | ||
7 | |||
8 | The architecture of the USB 2.0 PHY module in Samsung SoCs is similar | ||
9 | among many SoCs. In spite of the similarities it proved difficult to | ||
10 | create a one driver that would fit all these PHY controllers. Often | ||
11 | the differences were minor and were found in particular bits of the | ||
12 | registers of the PHY. In some rare cases the order of register writes or | ||
13 | the PHY powering up process had to be altered. This adaptation layer is | ||
14 | a compromise between having separate drivers and having a single driver | ||
15 | with added support for many special cases. | ||
16 | |||
17 | | 2. Files description | ||
18 | +---------------------- | ||
19 | |||
20 | - phy-samsung-usb2.c | ||
21 | This is the main file of the adaptation layer. This file contains | ||
22 | the probe function and provides two callbacks to the Generic PHY | ||
23 | Framework. This two callbacks are used to power on and power off the | ||
24 | phy. They carry out the common work that has to be done on all version | ||
25 | of the PHY module. Depending on which SoC was chosen they execute SoC | ||
26 | specific callbacks. The specific SoC version is selected by choosing | ||
27 | the appropriate compatible string. In addition, this file contains | ||
28 | struct of_device_id definitions for particular SoCs. | ||
29 | |||
30 | - phy-samsung-usb2.h | ||
31 | This is the include file. It declares the structures used by this | ||
32 | driver. In addition it should contain extern declarations for | ||
33 | structures that describe particular SoCs. | ||
34 | |||
35 | | 3. Supporting SoCs | ||
36 | +-------------------- | ||
37 | |||
38 | To support a new SoC a new file should be added to the drivers/phy | ||
39 | directory. Each SoC's configuration is stored in an instance of the | ||
40 | struct samsung_usb2_phy_config. | ||
41 | |||
42 | struct samsung_usb2_phy_config { | ||
43 | const struct samsung_usb2_common_phy *phys; | ||
44 | int (*rate_to_clk)(unsigned long, u32 *); | ||
45 | unsigned int num_phys; | ||
46 | bool has_mode_switch; | ||
47 | }; | ||
48 | |||
49 | The num_phys is the number of phys handled by the driver. *phys is an | ||
50 | array that contains the configuration for each phy. The has_mode_switch | ||
51 | property is a boolean flag that determines whether the SoC has USB host | ||
52 | and device on a single pair of pins. If so, a special register has to | ||
53 | be modified to change the internal routing of these pins between a USB | ||
54 | device or host module. | ||
55 | |||
56 | For example the configuration for Exynos 4210 is following: | ||
57 | |||
58 | const struct samsung_usb2_phy_config exynos4210_usb2_phy_config = { | ||
59 | .has_mode_switch = 0, | ||
60 | .num_phys = EXYNOS4210_NUM_PHYS, | ||
61 | .phys = exynos4210_phys, | ||
62 | .rate_to_clk = exynos4210_rate_to_clk, | ||
63 | } | ||
64 | |||
65 | - int (*rate_to_clk)(unsigned long, u32 *) | ||
66 | The rate_to_clk callback is to convert the rate of the clock | ||
67 | used as the reference clock for the PHY module to the value | ||
68 | that should be written in the hardware register. | ||
69 | |||
70 | The exynos4210_phys configuration array is as follows: | ||
71 | |||
72 | static const struct samsung_usb2_common_phy exynos4210_phys[] = { | ||
73 | { | ||
74 | .label = "device", | ||
75 | .id = EXYNOS4210_DEVICE, | ||
76 | .power_on = exynos4210_power_on, | ||
77 | .power_off = exynos4210_power_off, | ||
78 | }, | ||
79 | { | ||
80 | .label = "host", | ||
81 | .id = EXYNOS4210_HOST, | ||
82 | .power_on = exynos4210_power_on, | ||
83 | .power_off = exynos4210_power_off, | ||
84 | }, | ||
85 | { | ||
86 | .label = "hsic0", | ||
87 | .id = EXYNOS4210_HSIC0, | ||
88 | .power_on = exynos4210_power_on, | ||
89 | .power_off = exynos4210_power_off, | ||
90 | }, | ||
91 | { | ||
92 | .label = "hsic1", | ||
93 | .id = EXYNOS4210_HSIC1, | ||
94 | .power_on = exynos4210_power_on, | ||
95 | .power_off = exynos4210_power_off, | ||
96 | }, | ||
97 | {}, | ||
98 | }; | ||
99 | |||
100 | - int (*power_on)(struct samsung_usb2_phy_instance *); | ||
101 | - int (*power_off)(struct samsung_usb2_phy_instance *); | ||
102 | These two callbacks are used to power on and power off the phy | ||
103 | by modifying appropriate registers. | ||
104 | |||
105 | Final change to the driver is adding appropriate compatible value to the | ||
106 | phy-samsung-usb2.c file. In case of Exynos 4210 the following lines were | ||
107 | added to the struct of_device_id samsung_usb2_phy_of_match[] array: | ||
108 | |||
109 | #ifdef CONFIG_PHY_EXYNOS4210_USB2 | ||
110 | { | ||
111 | .compatible = "samsung,exynos4210-usb2-phy", | ||
112 | .data = &exynos4210_usb2_phy_config, | ||
113 | }, | ||
114 | #endif | ||
115 | |||
116 | To add further flexibility to the driver the Kconfig file enables to | ||
117 | include support for selected SoCs in the compiled driver. The Kconfig | ||
118 | entry for Exynos 4210 is following: | ||
119 | |||
120 | config PHY_EXYNOS4210_USB2 | ||
121 | bool "Support for Exynos 4210" | ||
122 | depends on PHY_SAMSUNG_USB2 | ||
123 | depends on CPU_EXYNOS4210 | ||
124 | help | ||
125 | Enable USB PHY support for Exynos 4210. This option requires that | ||
126 | Samsung USB 2.0 PHY driver is enabled and means that support for this | ||
127 | particular SoC is compiled in the driver. In case of Exynos 4210 four | ||
128 | phys are available - device, host, HSCI0 and HSCI1. | ||
129 | |||
130 | The newly created file that supports the new SoC has to be also added to the | ||
131 | Makefile. In case of Exynos 4210 the added line is following: | ||
132 | |||
133 | obj-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o | ||
134 | |||
135 | After completing these steps the support for the new SoC should be ready. | ||
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index c7a551c2d5f1..8d3c49cc500f 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig | |||
@@ -16,30 +16,56 @@ config GENERIC_PHY | |||
16 | framework should select this config. | 16 | framework should select this config. |
17 | 17 | ||
18 | config PHY_EXYNOS_MIPI_VIDEO | 18 | config PHY_EXYNOS_MIPI_VIDEO |
19 | depends on HAS_IOMEM | ||
20 | tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver" | 19 | tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver" |
20 | depends on HAS_IOMEM | ||
21 | depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST | ||
22 | select GENERIC_PHY | ||
23 | default y if ARCH_S5PV210 || ARCH_EXYNOS | ||
21 | help | 24 | help |
22 | Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P | 25 | Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P |
23 | and EXYNOS SoCs. | 26 | and EXYNOS SoCs. |
24 | 27 | ||
25 | config PHY_MVEBU_SATA | 28 | config PHY_MVEBU_SATA |
26 | def_bool y | 29 | def_bool y |
27 | depends on ARCH_KIRKWOOD || ARCH_DOVE | 30 | depends on ARCH_KIRKWOOD || ARCH_DOVE || MACH_DOVE |
28 | depends on OF | 31 | depends on OF |
29 | select GENERIC_PHY | 32 | select GENERIC_PHY |
30 | 33 | ||
34 | config OMAP_CONTROL_PHY | ||
35 | tristate "OMAP CONTROL PHY Driver" | ||
36 | help | ||
37 | Enable this to add support for the PHY part present in the control | ||
38 | module. This driver has API to power on the USB2 PHY and to write to | ||
39 | the mailbox. The mailbox is present only in omap4 and the register to | ||
40 | power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an | ||
41 | additional register to power on USB3 PHY/SATA PHY/PCIE PHY | ||
42 | (PIPE3 PHY). | ||
43 | |||
31 | config OMAP_USB2 | 44 | config OMAP_USB2 |
32 | tristate "OMAP USB2 PHY Driver" | 45 | tristate "OMAP USB2 PHY Driver" |
33 | depends on ARCH_OMAP2PLUS | 46 | depends on ARCH_OMAP2PLUS |
34 | depends on USB_PHY | 47 | depends on USB_PHY |
35 | select GENERIC_PHY | 48 | select GENERIC_PHY |
36 | select OMAP_CONTROL_USB | 49 | select OMAP_CONTROL_PHY |
50 | depends on OMAP_OCP2SCP | ||
37 | help | 51 | help |
38 | Enable this to support the transceiver that is part of SOC. This | 52 | Enable this to support the transceiver that is part of SOC. This |
39 | driver takes care of all the PHY functionality apart from comparator. | 53 | driver takes care of all the PHY functionality apart from comparator. |
40 | The USB OTG controller communicates with the comparator using this | 54 | The USB OTG controller communicates with the comparator using this |
41 | driver. | 55 | driver. |
42 | 56 | ||
57 | config TI_PIPE3 | ||
58 | tristate "TI PIPE3 PHY Driver" | ||
59 | depends on ARCH_OMAP2PLUS || COMPILE_TEST | ||
60 | select GENERIC_PHY | ||
61 | select OMAP_CONTROL_PHY | ||
62 | depends on OMAP_OCP2SCP | ||
63 | help | ||
64 | Enable this to support the PIPE3 PHY that is part of TI SOCs. This | ||
65 | driver takes care of all the PHY functionality apart from comparator. | ||
66 | This driver interacts with the "OMAP Control PHY Driver" to power | ||
67 | on/off the PHY. | ||
68 | |||
43 | config TWL4030_USB | 69 | config TWL4030_USB |
44 | tristate "TWL4030 USB Transceiver Driver" | 70 | tristate "TWL4030 USB Transceiver Driver" |
45 | depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS | 71 | depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS |
@@ -54,6 +80,8 @@ config TWL4030_USB | |||
54 | config PHY_EXYNOS_DP_VIDEO | 80 | config PHY_EXYNOS_DP_VIDEO |
55 | tristate "EXYNOS SoC series Display Port PHY driver" | 81 | tristate "EXYNOS SoC series Display Port PHY driver" |
56 | depends on OF | 82 | depends on OF |
83 | depends on ARCH_EXYNOS || COMPILE_TEST | ||
84 | default ARCH_EXYNOS | ||
57 | select GENERIC_PHY | 85 | select GENERIC_PHY |
58 | help | 86 | help |
59 | Support for Display Port PHY found on Samsung EXYNOS SoCs. | 87 | Support for Display Port PHY found on Samsung EXYNOS SoCs. |
@@ -65,4 +93,77 @@ config BCM_KONA_USB2_PHY | |||
65 | help | 93 | help |
66 | Enable this to support the Broadcom Kona USB 2.0 PHY. | 94 | Enable this to support the Broadcom Kona USB 2.0 PHY. |
67 | 95 | ||
96 | config PHY_EXYNOS5250_SATA | ||
97 | tristate "Exynos5250 Sata SerDes/PHY driver" | ||
98 | depends on SOC_EXYNOS5250 | ||
99 | depends on HAS_IOMEM | ||
100 | depends on OF | ||
101 | select GENERIC_PHY | ||
102 | select I2C | ||
103 | select I2C_S3C2410 | ||
104 | select MFD_SYSCON | ||
105 | help | ||
106 | Enable this to support SATA SerDes/Phy found on Samsung's | ||
107 | Exynos5250 based SoCs.This SerDes/Phy supports SATA 1.5 Gb/s, | ||
108 | SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host | ||
109 | port to accept one SATA device. | ||
110 | |||
111 | config PHY_SUN4I_USB | ||
112 | tristate "Allwinner sunxi SoC USB PHY driver" | ||
113 | depends on ARCH_SUNXI && HAS_IOMEM && OF | ||
114 | select GENERIC_PHY | ||
115 | help | ||
116 | Enable this to support the transceiver that is part of Allwinner | ||
117 | sunxi SoCs. | ||
118 | |||
119 | This driver controls the entire USB PHY block, both the USB OTG | ||
120 | parts, as well as the 2 regular USB 2 host PHYs. | ||
121 | |||
122 | config PHY_SAMSUNG_USB2 | ||
123 | tristate "Samsung USB 2.0 PHY driver" | ||
124 | select GENERIC_PHY | ||
125 | select MFD_SYSCON | ||
126 | help | ||
127 | Enable this to support the Samsung USB 2.0 PHY driver for Samsung | ||
128 | SoCs. This driver provides the interface for USB 2.0 PHY. Support for | ||
129 | particular SoCs has to be enabled in addition to this driver. Number | ||
130 | and type of supported phys depends on the SoC. | ||
131 | |||
132 | config PHY_EXYNOS4210_USB2 | ||
133 | bool "Support for Exynos 4210" | ||
134 | depends on PHY_SAMSUNG_USB2 | ||
135 | depends on CPU_EXYNOS4210 | ||
136 | help | ||
137 | Enable USB PHY support for Exynos 4210. This option requires that | ||
138 | Samsung USB 2.0 PHY driver is enabled and means that support for this | ||
139 | particular SoC is compiled in the driver. In case of Exynos 4210 four | ||
140 | phys are available - device, host, HSIC0 and HSIC1. | ||
141 | |||
142 | config PHY_EXYNOS4X12_USB2 | ||
143 | bool "Support for Exynos 4x12" | ||
144 | depends on PHY_SAMSUNG_USB2 | ||
145 | depends on (SOC_EXYNOS4212 || SOC_EXYNOS4412) | ||
146 | help | ||
147 | Enable USB PHY support for Exynos 4x12. This option requires that | ||
148 | Samsung USB 2.0 PHY driver is enabled and means that support for this | ||
149 | particular SoC is compiled in the driver. In case of Exynos 4x12 four | ||
150 | phys are available - device, host, HSIC0 and HSIC1. | ||
151 | |||
152 | config PHY_EXYNOS5250_USB2 | ||
153 | bool "Support for Exynos 5250" | ||
154 | depends on PHY_SAMSUNG_USB2 | ||
155 | depends on SOC_EXYNOS5250 | ||
156 | help | ||
157 | Enable USB PHY support for Exynos 5250. This option requires that | ||
158 | Samsung USB 2.0 PHY driver is enabled and means that support for this | ||
159 | particular SoC is compiled in the driver. In case of Exynos 5250 four | ||
160 | phys are available - device, host, HSIC0 and HSIC. | ||
161 | |||
162 | config PHY_XGENE | ||
163 | tristate "APM X-Gene 15Gbps PHY support" | ||
164 | depends on HAS_IOMEM && OF && (ARM64 || COMPILE_TEST) | ||
165 | select GENERIC_PHY | ||
166 | help | ||
167 | This option enables support for APM X-Gene SoC multi-purpose PHY. | ||
168 | |||
68 | endmenu | 169 | endmenu |
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index b57c25371cca..2faf78edc864 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile | |||
@@ -7,5 +7,14 @@ obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o | |||
7 | obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o | 7 | obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o |
8 | obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o | 8 | obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o |
9 | obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o | 9 | obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o |
10 | obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o | ||
10 | obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o | 11 | obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o |
12 | obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o | ||
11 | obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o | 13 | obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o |
14 | obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o | ||
15 | obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o | ||
16 | obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-samsung-usb2.o | ||
17 | obj-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o | ||
18 | obj-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o | ||
19 | obj-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o | ||
20 | obj-$(CONFIG_PHY_XGENE) += phy-xgene.o | ||
diff --git a/drivers/phy/phy-bcm-kona-usb2.c b/drivers/phy/phy-bcm-kona-usb2.c index efc5c1a13a5d..e94f5a6a5645 100644 --- a/drivers/phy/phy-bcm-kona-usb2.c +++ b/drivers/phy/phy-bcm-kona-usb2.c | |||
@@ -128,10 +128,8 @@ static int bcm_kona_usb2_probe(struct platform_device *pdev) | |||
128 | 128 | ||
129 | phy_provider = devm_of_phy_provider_register(dev, | 129 | phy_provider = devm_of_phy_provider_register(dev, |
130 | of_phy_simple_xlate); | 130 | of_phy_simple_xlate); |
131 | if (IS_ERR(phy_provider)) | ||
132 | return PTR_ERR(phy_provider); | ||
133 | 131 | ||
134 | return 0; | 132 | return PTR_ERR_OR_ZERO(phy_provider); |
135 | } | 133 | } |
136 | 134 | ||
137 | static const struct of_device_id bcm_kona_usb2_dt_ids[] = { | 135 | static const struct of_device_id bcm_kona_usb2_dt_ids[] = { |
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 6c738376daff..623b71c54b3e 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c | |||
@@ -274,8 +274,8 @@ int phy_power_off(struct phy *phy) | |||
274 | EXPORT_SYMBOL_GPL(phy_power_off); | 274 | EXPORT_SYMBOL_GPL(phy_power_off); |
275 | 275 | ||
276 | /** | 276 | /** |
277 | * of_phy_get() - lookup and obtain a reference to a phy by phandle | 277 | * _of_phy_get() - lookup and obtain a reference to a phy by phandle |
278 | * @dev: device that requests this phy | 278 | * @np: device_node for which to get the phy |
279 | * @index: the index of the phy | 279 | * @index: the index of the phy |
280 | * | 280 | * |
281 | * Returns the phy associated with the given phandle value, | 281 | * Returns the phy associated with the given phandle value, |
@@ -284,20 +284,17 @@ EXPORT_SYMBOL_GPL(phy_power_off); | |||
284 | * not yet loaded. This function uses of_xlate call back function provided | 284 | * not yet loaded. This function uses of_xlate call back function provided |
285 | * while registering the phy_provider to find the phy instance. | 285 | * while registering the phy_provider to find the phy instance. |
286 | */ | 286 | */ |
287 | static struct phy *of_phy_get(struct device *dev, int index) | 287 | static struct phy *_of_phy_get(struct device_node *np, int index) |
288 | { | 288 | { |
289 | int ret; | 289 | int ret; |
290 | struct phy_provider *phy_provider; | 290 | struct phy_provider *phy_provider; |
291 | struct phy *phy = NULL; | 291 | struct phy *phy = NULL; |
292 | struct of_phandle_args args; | 292 | struct of_phandle_args args; |
293 | 293 | ||
294 | ret = of_parse_phandle_with_args(dev->of_node, "phys", "#phy-cells", | 294 | ret = of_parse_phandle_with_args(np, "phys", "#phy-cells", |
295 | index, &args); | 295 | index, &args); |
296 | if (ret) { | 296 | if (ret) |
297 | dev_dbg(dev, "failed to get phy in %s node\n", | ||
298 | dev->of_node->full_name); | ||
299 | return ERR_PTR(-ENODEV); | 297 | return ERR_PTR(-ENODEV); |
300 | } | ||
301 | 298 | ||
302 | mutex_lock(&phy_provider_mutex); | 299 | mutex_lock(&phy_provider_mutex); |
303 | phy_provider = of_phy_provider_lookup(args.np); | 300 | phy_provider = of_phy_provider_lookup(args.np); |
@@ -317,6 +314,36 @@ err0: | |||
317 | } | 314 | } |
318 | 315 | ||
319 | /** | 316 | /** |
317 | * of_phy_get() - lookup and obtain a reference to a phy using a device_node. | ||
318 | * @np: device_node for which to get the phy | ||
319 | * @con_id: name of the phy from device's point of view | ||
320 | * | ||
321 | * Returns the phy driver, after getting a refcount to it; or | ||
322 | * -ENODEV if there is no such phy. The caller is responsible for | ||
323 | * calling phy_put() to release that count. | ||
324 | */ | ||
325 | struct phy *of_phy_get(struct device_node *np, const char *con_id) | ||
326 | { | ||
327 | struct phy *phy = NULL; | ||
328 | int index = 0; | ||
329 | |||
330 | if (con_id) | ||
331 | index = of_property_match_string(np, "phy-names", con_id); | ||
332 | |||
333 | phy = _of_phy_get(np, index); | ||
334 | if (IS_ERR(phy)) | ||
335 | return phy; | ||
336 | |||
337 | if (!try_module_get(phy->ops->owner)) | ||
338 | return ERR_PTR(-EPROBE_DEFER); | ||
339 | |||
340 | get_device(&phy->dev); | ||
341 | |||
342 | return phy; | ||
343 | } | ||
344 | EXPORT_SYMBOL_GPL(of_phy_get); | ||
345 | |||
346 | /** | ||
320 | * phy_put() - release the PHY | 347 | * phy_put() - release the PHY |
321 | * @phy: the phy returned by phy_get() | 348 | * @phy: the phy returned by phy_get() |
322 | * | 349 | * |
@@ -407,7 +434,7 @@ struct phy *phy_get(struct device *dev, const char *string) | |||
407 | if (dev->of_node) { | 434 | if (dev->of_node) { |
408 | index = of_property_match_string(dev->of_node, "phy-names", | 435 | index = of_property_match_string(dev->of_node, "phy-names", |
409 | string); | 436 | string); |
410 | phy = of_phy_get(dev, index); | 437 | phy = _of_phy_get(dev->of_node, index); |
411 | } else { | 438 | } else { |
412 | phy = phy_lookup(dev, string); | 439 | phy = phy_lookup(dev, string); |
413 | } | 440 | } |
@@ -499,6 +526,37 @@ struct phy *devm_phy_optional_get(struct device *dev, const char *string) | |||
499 | EXPORT_SYMBOL_GPL(devm_phy_optional_get); | 526 | EXPORT_SYMBOL_GPL(devm_phy_optional_get); |
500 | 527 | ||
501 | /** | 528 | /** |
529 | * devm_of_phy_get() - lookup and obtain a reference to a phy. | ||
530 | * @dev: device that requests this phy | ||
531 | * @np: node containing the phy | ||
532 | * @con_id: name of the phy from device's point of view | ||
533 | * | ||
534 | * Gets the phy using of_phy_get(), and associates a device with it using | ||
535 | * devres. On driver detach, release function is invoked on the devres data, | ||
536 | * then, devres data is freed. | ||
537 | */ | ||
538 | struct phy *devm_of_phy_get(struct device *dev, struct device_node *np, | ||
539 | const char *con_id) | ||
540 | { | ||
541 | struct phy **ptr, *phy; | ||
542 | |||
543 | ptr = devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL); | ||
544 | if (!ptr) | ||
545 | return ERR_PTR(-ENOMEM); | ||
546 | |||
547 | phy = of_phy_get(np, con_id); | ||
548 | if (!IS_ERR(phy)) { | ||
549 | *ptr = phy; | ||
550 | devres_add(dev, ptr); | ||
551 | } else { | ||
552 | devres_free(ptr); | ||
553 | } | ||
554 | |||
555 | return phy; | ||
556 | } | ||
557 | EXPORT_SYMBOL_GPL(devm_of_phy_get); | ||
558 | |||
559 | /** | ||
502 | * phy_create() - create a new phy | 560 | * phy_create() - create a new phy |
503 | * @dev: device that is creating the new phy | 561 | * @dev: device that is creating the new phy |
504 | * @ops: function pointers for performing phy operations | 562 | * @ops: function pointers for performing phy operations |
diff --git a/drivers/phy/phy-exynos4210-usb2.c b/drivers/phy/phy-exynos4210-usb2.c new file mode 100644 index 000000000000..236a52ad94eb --- /dev/null +++ b/drivers/phy/phy-exynos4210-usb2.c | |||
@@ -0,0 +1,261 @@ | |||
1 | /* | ||
2 | * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 4210 support | ||
3 | * | ||
4 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
5 | * Author: Kamil Debski <k.debski@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/delay.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/phy/phy.h> | ||
15 | #include <linux/regmap.h> | ||
16 | #include "phy-samsung-usb2.h" | ||
17 | |||
18 | /* Exynos USB PHY registers */ | ||
19 | |||
20 | /* PHY power control */ | ||
21 | #define EXYNOS_4210_UPHYPWR 0x0 | ||
22 | |||
23 | #define EXYNOS_4210_UPHYPWR_PHY0_SUSPEND BIT(0) | ||
24 | #define EXYNOS_4210_UPHYPWR_PHY0_PWR BIT(3) | ||
25 | #define EXYNOS_4210_UPHYPWR_PHY0_OTG_PWR BIT(4) | ||
26 | #define EXYNOS_4210_UPHYPWR_PHY0_SLEEP BIT(5) | ||
27 | #define EXYNOS_4210_UPHYPWR_PHY0 ( \ | ||
28 | EXYNOS_4210_UPHYPWR_PHY0_SUSPEND | \ | ||
29 | EXYNOS_4210_UPHYPWR_PHY0_PWR | \ | ||
30 | EXYNOS_4210_UPHYPWR_PHY0_OTG_PWR | \ | ||
31 | EXYNOS_4210_UPHYPWR_PHY0_SLEEP) | ||
32 | |||
33 | #define EXYNOS_4210_UPHYPWR_PHY1_SUSPEND BIT(6) | ||
34 | #define EXYNOS_4210_UPHYPWR_PHY1_PWR BIT(7) | ||
35 | #define EXYNOS_4210_UPHYPWR_PHY1_SLEEP BIT(8) | ||
36 | #define EXYNOS_4210_UPHYPWR_PHY1 ( \ | ||
37 | EXYNOS_4210_UPHYPWR_PHY1_SUSPEND | \ | ||
38 | EXYNOS_4210_UPHYPWR_PHY1_PWR | \ | ||
39 | EXYNOS_4210_UPHYPWR_PHY1_SLEEP) | ||
40 | |||
41 | #define EXYNOS_4210_UPHYPWR_HSIC0_SUSPEND BIT(9) | ||
42 | #define EXYNOS_4210_UPHYPWR_HSIC0_SLEEP BIT(10) | ||
43 | #define EXYNOS_4210_UPHYPWR_HSIC0 ( \ | ||
44 | EXYNOS_4210_UPHYPWR_HSIC0_SUSPEND | \ | ||
45 | EXYNOS_4210_UPHYPWR_HSIC0_SLEEP) | ||
46 | |||
47 | #define EXYNOS_4210_UPHYPWR_HSIC1_SUSPEND BIT(11) | ||
48 | #define EXYNOS_4210_UPHYPWR_HSIC1_SLEEP BIT(12) | ||
49 | #define EXYNOS_4210_UPHYPWR_HSIC1 ( \ | ||
50 | EXYNOS_4210_UPHYPWR_HSIC1_SUSPEND | \ | ||
51 | EXYNOS_4210_UPHYPWR_HSIC1_SLEEP) | ||
52 | |||
53 | /* PHY clock control */ | ||
54 | #define EXYNOS_4210_UPHYCLK 0x4 | ||
55 | |||
56 | #define EXYNOS_4210_UPHYCLK_PHYFSEL_MASK (0x3 << 0) | ||
57 | #define EXYNOS_4210_UPHYCLK_PHYFSEL_OFFSET 0 | ||
58 | #define EXYNOS_4210_UPHYCLK_PHYFSEL_48MHZ (0x0 << 0) | ||
59 | #define EXYNOS_4210_UPHYCLK_PHYFSEL_24MHZ (0x3 << 0) | ||
60 | #define EXYNOS_4210_UPHYCLK_PHYFSEL_12MHZ (0x2 << 0) | ||
61 | |||
62 | #define EXYNOS_4210_UPHYCLK_PHY0_ID_PULLUP BIT(2) | ||
63 | #define EXYNOS_4210_UPHYCLK_PHY0_COMMON_ON BIT(4) | ||
64 | #define EXYNOS_4210_UPHYCLK_PHY1_COMMON_ON BIT(7) | ||
65 | |||
66 | /* PHY reset control */ | ||
67 | #define EXYNOS_4210_UPHYRST 0x8 | ||
68 | |||
69 | #define EXYNOS_4210_URSTCON_PHY0 BIT(0) | ||
70 | #define EXYNOS_4210_URSTCON_OTG_HLINK BIT(1) | ||
71 | #define EXYNOS_4210_URSTCON_OTG_PHYLINK BIT(2) | ||
72 | #define EXYNOS_4210_URSTCON_PHY1_ALL BIT(3) | ||
73 | #define EXYNOS_4210_URSTCON_PHY1_P0 BIT(4) | ||
74 | #define EXYNOS_4210_URSTCON_PHY1_P1P2 BIT(5) | ||
75 | #define EXYNOS_4210_URSTCON_HOST_LINK_ALL BIT(6) | ||
76 | #define EXYNOS_4210_URSTCON_HOST_LINK_P0 BIT(7) | ||
77 | #define EXYNOS_4210_URSTCON_HOST_LINK_P1 BIT(8) | ||
78 | #define EXYNOS_4210_URSTCON_HOST_LINK_P2 BIT(9) | ||
79 | |||
80 | /* Isolation, configured in the power management unit */ | ||
81 | #define EXYNOS_4210_USB_ISOL_DEVICE_OFFSET 0x704 | ||
82 | #define EXYNOS_4210_USB_ISOL_DEVICE BIT(0) | ||
83 | #define EXYNOS_4210_USB_ISOL_HOST_OFFSET 0x708 | ||
84 | #define EXYNOS_4210_USB_ISOL_HOST BIT(0) | ||
85 | |||
86 | /* USBYPHY1 Floating prevention */ | ||
87 | #define EXYNOS_4210_UPHY1CON 0x34 | ||
88 | #define EXYNOS_4210_UPHY1CON_FLOAT_PREVENTION 0x1 | ||
89 | |||
90 | /* Mode switching SUB Device <-> Host */ | ||
91 | #define EXYNOS_4210_MODE_SWITCH_OFFSET 0x21c | ||
92 | #define EXYNOS_4210_MODE_SWITCH_MASK 1 | ||
93 | #define EXYNOS_4210_MODE_SWITCH_DEVICE 0 | ||
94 | #define EXYNOS_4210_MODE_SWITCH_HOST 1 | ||
95 | |||
96 | enum exynos4210_phy_id { | ||
97 | EXYNOS4210_DEVICE, | ||
98 | EXYNOS4210_HOST, | ||
99 | EXYNOS4210_HSIC0, | ||
100 | EXYNOS4210_HSIC1, | ||
101 | EXYNOS4210_NUM_PHYS, | ||
102 | }; | ||
103 | |||
104 | /* | ||
105 | * exynos4210_rate_to_clk() converts the supplied clock rate to the value that | ||
106 | * can be written to the phy register. | ||
107 | */ | ||
108 | static int exynos4210_rate_to_clk(unsigned long rate, u32 *reg) | ||
109 | { | ||
110 | switch (rate) { | ||
111 | case 12 * MHZ: | ||
112 | *reg = EXYNOS_4210_UPHYCLK_PHYFSEL_12MHZ; | ||
113 | break; | ||
114 | case 24 * MHZ: | ||
115 | *reg = EXYNOS_4210_UPHYCLK_PHYFSEL_24MHZ; | ||
116 | break; | ||
117 | case 48 * MHZ: | ||
118 | *reg = EXYNOS_4210_UPHYCLK_PHYFSEL_48MHZ; | ||
119 | break; | ||
120 | default: | ||
121 | return -EINVAL; | ||
122 | } | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static void exynos4210_isol(struct samsung_usb2_phy_instance *inst, bool on) | ||
128 | { | ||
129 | struct samsung_usb2_phy_driver *drv = inst->drv; | ||
130 | u32 offset; | ||
131 | u32 mask; | ||
132 | |||
133 | switch (inst->cfg->id) { | ||
134 | case EXYNOS4210_DEVICE: | ||
135 | offset = EXYNOS_4210_USB_ISOL_DEVICE_OFFSET; | ||
136 | mask = EXYNOS_4210_USB_ISOL_DEVICE; | ||
137 | break; | ||
138 | case EXYNOS4210_HOST: | ||
139 | offset = EXYNOS_4210_USB_ISOL_HOST_OFFSET; | ||
140 | mask = EXYNOS_4210_USB_ISOL_HOST; | ||
141 | break; | ||
142 | default: | ||
143 | return; | ||
144 | }; | ||
145 | |||
146 | regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask); | ||
147 | } | ||
148 | |||
149 | static void exynos4210_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on) | ||
150 | { | ||
151 | struct samsung_usb2_phy_driver *drv = inst->drv; | ||
152 | u32 rstbits = 0; | ||
153 | u32 phypwr = 0; | ||
154 | u32 rst; | ||
155 | u32 pwr; | ||
156 | u32 clk; | ||
157 | |||
158 | switch (inst->cfg->id) { | ||
159 | case EXYNOS4210_DEVICE: | ||
160 | phypwr = EXYNOS_4210_UPHYPWR_PHY0; | ||
161 | rstbits = EXYNOS_4210_URSTCON_PHY0; | ||
162 | break; | ||
163 | case EXYNOS4210_HOST: | ||
164 | phypwr = EXYNOS_4210_UPHYPWR_PHY1; | ||
165 | rstbits = EXYNOS_4210_URSTCON_PHY1_ALL | | ||
166 | EXYNOS_4210_URSTCON_PHY1_P0 | | ||
167 | EXYNOS_4210_URSTCON_PHY1_P1P2 | | ||
168 | EXYNOS_4210_URSTCON_HOST_LINK_ALL | | ||
169 | EXYNOS_4210_URSTCON_HOST_LINK_P0; | ||
170 | writel(on, drv->reg_phy + EXYNOS_4210_UPHY1CON); | ||
171 | break; | ||
172 | case EXYNOS4210_HSIC0: | ||
173 | phypwr = EXYNOS_4210_UPHYPWR_HSIC0; | ||
174 | rstbits = EXYNOS_4210_URSTCON_PHY1_P1P2 | | ||
175 | EXYNOS_4210_URSTCON_HOST_LINK_P1; | ||
176 | break; | ||
177 | case EXYNOS4210_HSIC1: | ||
178 | phypwr = EXYNOS_4210_UPHYPWR_HSIC1; | ||
179 | rstbits = EXYNOS_4210_URSTCON_PHY1_P1P2 | | ||
180 | EXYNOS_4210_URSTCON_HOST_LINK_P2; | ||
181 | break; | ||
182 | }; | ||
183 | |||
184 | if (on) { | ||
185 | clk = readl(drv->reg_phy + EXYNOS_4210_UPHYCLK); | ||
186 | clk &= ~EXYNOS_4210_UPHYCLK_PHYFSEL_MASK; | ||
187 | clk |= drv->ref_reg_val << EXYNOS_4210_UPHYCLK_PHYFSEL_OFFSET; | ||
188 | writel(clk, drv->reg_phy + EXYNOS_4210_UPHYCLK); | ||
189 | |||
190 | pwr = readl(drv->reg_phy + EXYNOS_4210_UPHYPWR); | ||
191 | pwr &= ~phypwr; | ||
192 | writel(pwr, drv->reg_phy + EXYNOS_4210_UPHYPWR); | ||
193 | |||
194 | rst = readl(drv->reg_phy + EXYNOS_4210_UPHYRST); | ||
195 | rst |= rstbits; | ||
196 | writel(rst, drv->reg_phy + EXYNOS_4210_UPHYRST); | ||
197 | udelay(10); | ||
198 | rst &= ~rstbits; | ||
199 | writel(rst, drv->reg_phy + EXYNOS_4210_UPHYRST); | ||
200 | /* The following delay is necessary for the reset sequence to be | ||
201 | * completed */ | ||
202 | udelay(80); | ||
203 | } else { | ||
204 | pwr = readl(drv->reg_phy + EXYNOS_4210_UPHYPWR); | ||
205 | pwr |= phypwr; | ||
206 | writel(pwr, drv->reg_phy + EXYNOS_4210_UPHYPWR); | ||
207 | } | ||
208 | } | ||
209 | |||
210 | static int exynos4210_power_on(struct samsung_usb2_phy_instance *inst) | ||
211 | { | ||
212 | /* Order of initialisation is important - first power then isolation */ | ||
213 | exynos4210_phy_pwr(inst, 1); | ||
214 | exynos4210_isol(inst, 0); | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static int exynos4210_power_off(struct samsung_usb2_phy_instance *inst) | ||
220 | { | ||
221 | exynos4210_isol(inst, 1); | ||
222 | exynos4210_phy_pwr(inst, 0); | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | |||
228 | static const struct samsung_usb2_common_phy exynos4210_phys[] = { | ||
229 | { | ||
230 | .label = "device", | ||
231 | .id = EXYNOS4210_DEVICE, | ||
232 | .power_on = exynos4210_power_on, | ||
233 | .power_off = exynos4210_power_off, | ||
234 | }, | ||
235 | { | ||
236 | .label = "host", | ||
237 | .id = EXYNOS4210_HOST, | ||
238 | .power_on = exynos4210_power_on, | ||
239 | .power_off = exynos4210_power_off, | ||
240 | }, | ||
241 | { | ||
242 | .label = "hsic0", | ||
243 | .id = EXYNOS4210_HSIC0, | ||
244 | .power_on = exynos4210_power_on, | ||
245 | .power_off = exynos4210_power_off, | ||
246 | }, | ||
247 | { | ||
248 | .label = "hsic1", | ||
249 | .id = EXYNOS4210_HSIC1, | ||
250 | .power_on = exynos4210_power_on, | ||
251 | .power_off = exynos4210_power_off, | ||
252 | }, | ||
253 | {}, | ||
254 | }; | ||
255 | |||
256 | const struct samsung_usb2_phy_config exynos4210_usb2_phy_config = { | ||
257 | .has_mode_switch = 0, | ||
258 | .num_phys = EXYNOS4210_NUM_PHYS, | ||
259 | .phys = exynos4210_phys, | ||
260 | .rate_to_clk = exynos4210_rate_to_clk, | ||
261 | }; | ||
diff --git a/drivers/phy/phy-exynos4x12-usb2.c b/drivers/phy/phy-exynos4x12-usb2.c new file mode 100644 index 000000000000..d92a7cc5698a --- /dev/null +++ b/drivers/phy/phy-exynos4x12-usb2.c | |||
@@ -0,0 +1,328 @@ | |||
1 | /* | ||
2 | * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 4x12 support | ||
3 | * | ||
4 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
5 | * Author: Kamil Debski <k.debski@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/delay.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/phy/phy.h> | ||
15 | #include <linux/regmap.h> | ||
16 | #include "phy-samsung-usb2.h" | ||
17 | |||
18 | /* Exynos USB PHY registers */ | ||
19 | |||
20 | /* PHY power control */ | ||
21 | #define EXYNOS_4x12_UPHYPWR 0x0 | ||
22 | |||
23 | #define EXYNOS_4x12_UPHYPWR_PHY0_SUSPEND BIT(0) | ||
24 | #define EXYNOS_4x12_UPHYPWR_PHY0_PWR BIT(3) | ||
25 | #define EXYNOS_4x12_UPHYPWR_PHY0_OTG_PWR BIT(4) | ||
26 | #define EXYNOS_4x12_UPHYPWR_PHY0_SLEEP BIT(5) | ||
27 | #define EXYNOS_4x12_UPHYPWR_PHY0 ( \ | ||
28 | EXYNOS_4x12_UPHYPWR_PHY0_SUSPEND | \ | ||
29 | EXYNOS_4x12_UPHYPWR_PHY0_PWR | \ | ||
30 | EXYNOS_4x12_UPHYPWR_PHY0_OTG_PWR | \ | ||
31 | EXYNOS_4x12_UPHYPWR_PHY0_SLEEP) | ||
32 | |||
33 | #define EXYNOS_4x12_UPHYPWR_PHY1_SUSPEND BIT(6) | ||
34 | #define EXYNOS_4x12_UPHYPWR_PHY1_PWR BIT(7) | ||
35 | #define EXYNOS_4x12_UPHYPWR_PHY1_SLEEP BIT(8) | ||
36 | #define EXYNOS_4x12_UPHYPWR_PHY1 ( \ | ||
37 | EXYNOS_4x12_UPHYPWR_PHY1_SUSPEND | \ | ||
38 | EXYNOS_4x12_UPHYPWR_PHY1_PWR | \ | ||
39 | EXYNOS_4x12_UPHYPWR_PHY1_SLEEP) | ||
40 | |||
41 | #define EXYNOS_4x12_UPHYPWR_HSIC0_SUSPEND BIT(9) | ||
42 | #define EXYNOS_4x12_UPHYPWR_HSIC0_PWR BIT(10) | ||
43 | #define EXYNOS_4x12_UPHYPWR_HSIC0_SLEEP BIT(11) | ||
44 | #define EXYNOS_4x12_UPHYPWR_HSIC0 ( \ | ||
45 | EXYNOS_4x12_UPHYPWR_HSIC0_SUSPEND | \ | ||
46 | EXYNOS_4x12_UPHYPWR_HSIC0_PWR | \ | ||
47 | EXYNOS_4x12_UPHYPWR_HSIC0_SLEEP) | ||
48 | |||
49 | #define EXYNOS_4x12_UPHYPWR_HSIC1_SUSPEND BIT(12) | ||
50 | #define EXYNOS_4x12_UPHYPWR_HSIC1_PWR BIT(13) | ||
51 | #define EXYNOS_4x12_UPHYPWR_HSIC1_SLEEP BIT(14) | ||
52 | #define EXYNOS_4x12_UPHYPWR_HSIC1 ( \ | ||
53 | EXYNOS_4x12_UPHYPWR_HSIC1_SUSPEND | \ | ||
54 | EXYNOS_4x12_UPHYPWR_HSIC1_PWR | \ | ||
55 | EXYNOS_4x12_UPHYPWR_HSIC1_SLEEP) | ||
56 | |||
57 | /* PHY clock control */ | ||
58 | #define EXYNOS_4x12_UPHYCLK 0x4 | ||
59 | |||
60 | #define EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK (0x7 << 0) | ||
61 | #define EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET 0 | ||
62 | #define EXYNOS_4x12_UPHYCLK_PHYFSEL_9MHZ6 (0x0 << 0) | ||
63 | #define EXYNOS_4x12_UPHYCLK_PHYFSEL_10MHZ (0x1 << 0) | ||
64 | #define EXYNOS_4x12_UPHYCLK_PHYFSEL_12MHZ (0x2 << 0) | ||
65 | #define EXYNOS_4x12_UPHYCLK_PHYFSEL_19MHZ2 (0x3 << 0) | ||
66 | #define EXYNOS_4x12_UPHYCLK_PHYFSEL_20MHZ (0x4 << 0) | ||
67 | #define EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ (0x5 << 0) | ||
68 | #define EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ (0x7 << 0) | ||
69 | |||
70 | #define EXYNOS_4x12_UPHYCLK_PHY0_ID_PULLUP BIT(3) | ||
71 | #define EXYNOS_4x12_UPHYCLK_PHY0_COMMON_ON BIT(4) | ||
72 | #define EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON BIT(7) | ||
73 | |||
74 | #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_MASK (0x7f << 10) | ||
75 | #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_OFFSET 10 | ||
76 | #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_12MHZ (0x24 << 10) | ||
77 | #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_15MHZ (0x1c << 10) | ||
78 | #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_16MHZ (0x1a << 10) | ||
79 | #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_19MHZ2 (0x15 << 10) | ||
80 | #define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_20MHZ (0x14 << 10) | ||
81 | |||
82 | /* PHY reset control */ | ||
83 | #define EXYNOS_4x12_UPHYRST 0x8 | ||
84 | |||
85 | #define EXYNOS_4x12_URSTCON_PHY0 BIT(0) | ||
86 | #define EXYNOS_4x12_URSTCON_OTG_HLINK BIT(1) | ||
87 | #define EXYNOS_4x12_URSTCON_OTG_PHYLINK BIT(2) | ||
88 | #define EXYNOS_4x12_URSTCON_HOST_PHY BIT(3) | ||
89 | #define EXYNOS_4x12_URSTCON_PHY1 BIT(4) | ||
90 | #define EXYNOS_4x12_URSTCON_HSIC0 BIT(5) | ||
91 | #define EXYNOS_4x12_URSTCON_HSIC1 BIT(6) | ||
92 | #define EXYNOS_4x12_URSTCON_HOST_LINK_ALL BIT(7) | ||
93 | #define EXYNOS_4x12_URSTCON_HOST_LINK_P0 BIT(8) | ||
94 | #define EXYNOS_4x12_URSTCON_HOST_LINK_P1 BIT(9) | ||
95 | #define EXYNOS_4x12_URSTCON_HOST_LINK_P2 BIT(10) | ||
96 | |||
97 | /* Isolation, configured in the power management unit */ | ||
98 | #define EXYNOS_4x12_USB_ISOL_OFFSET 0x704 | ||
99 | #define EXYNOS_4x12_USB_ISOL_OTG BIT(0) | ||
100 | #define EXYNOS_4x12_USB_ISOL_HSIC0_OFFSET 0x708 | ||
101 | #define EXYNOS_4x12_USB_ISOL_HSIC0 BIT(0) | ||
102 | #define EXYNOS_4x12_USB_ISOL_HSIC1_OFFSET 0x70c | ||
103 | #define EXYNOS_4x12_USB_ISOL_HSIC1 BIT(0) | ||
104 | |||
105 | /* Mode switching SUB Device <-> Host */ | ||
106 | #define EXYNOS_4x12_MODE_SWITCH_OFFSET 0x21c | ||
107 | #define EXYNOS_4x12_MODE_SWITCH_MASK 1 | ||
108 | #define EXYNOS_4x12_MODE_SWITCH_DEVICE 0 | ||
109 | #define EXYNOS_4x12_MODE_SWITCH_HOST 1 | ||
110 | |||
111 | enum exynos4x12_phy_id { | ||
112 | EXYNOS4x12_DEVICE, | ||
113 | EXYNOS4x12_HOST, | ||
114 | EXYNOS4x12_HSIC0, | ||
115 | EXYNOS4x12_HSIC1, | ||
116 | EXYNOS4x12_NUM_PHYS, | ||
117 | }; | ||
118 | |||
119 | /* | ||
120 | * exynos4x12_rate_to_clk() converts the supplied clock rate to the value that | ||
121 | * can be written to the phy register. | ||
122 | */ | ||
123 | static int exynos4x12_rate_to_clk(unsigned long rate, u32 *reg) | ||
124 | { | ||
125 | /* EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK */ | ||
126 | |||
127 | switch (rate) { | ||
128 | case 9600 * KHZ: | ||
129 | *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_9MHZ6; | ||
130 | break; | ||
131 | case 10 * MHZ: | ||
132 | *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_10MHZ; | ||
133 | break; | ||
134 | case 12 * MHZ: | ||
135 | *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_12MHZ; | ||
136 | break; | ||
137 | case 19200 * KHZ: | ||
138 | *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_19MHZ2; | ||
139 | break; | ||
140 | case 20 * MHZ: | ||
141 | *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_20MHZ; | ||
142 | break; | ||
143 | case 24 * MHZ: | ||
144 | *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ; | ||
145 | break; | ||
146 | case 50 * MHZ: | ||
147 | *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ; | ||
148 | break; | ||
149 | default: | ||
150 | return -EINVAL; | ||
151 | } | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static void exynos4x12_isol(struct samsung_usb2_phy_instance *inst, bool on) | ||
157 | { | ||
158 | struct samsung_usb2_phy_driver *drv = inst->drv; | ||
159 | u32 offset; | ||
160 | u32 mask; | ||
161 | |||
162 | switch (inst->cfg->id) { | ||
163 | case EXYNOS4x12_DEVICE: | ||
164 | case EXYNOS4x12_HOST: | ||
165 | offset = EXYNOS_4x12_USB_ISOL_OFFSET; | ||
166 | mask = EXYNOS_4x12_USB_ISOL_OTG; | ||
167 | break; | ||
168 | case EXYNOS4x12_HSIC0: | ||
169 | offset = EXYNOS_4x12_USB_ISOL_HSIC0_OFFSET; | ||
170 | mask = EXYNOS_4x12_USB_ISOL_HSIC0; | ||
171 | break; | ||
172 | case EXYNOS4x12_HSIC1: | ||
173 | offset = EXYNOS_4x12_USB_ISOL_HSIC1_OFFSET; | ||
174 | mask = EXYNOS_4x12_USB_ISOL_HSIC1; | ||
175 | break; | ||
176 | default: | ||
177 | return; | ||
178 | }; | ||
179 | |||
180 | regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask); | ||
181 | } | ||
182 | |||
183 | static void exynos4x12_setup_clk(struct samsung_usb2_phy_instance *inst) | ||
184 | { | ||
185 | struct samsung_usb2_phy_driver *drv = inst->drv; | ||
186 | u32 clk; | ||
187 | |||
188 | clk = readl(drv->reg_phy + EXYNOS_4x12_UPHYCLK); | ||
189 | clk &= ~EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK; | ||
190 | clk |= drv->ref_reg_val << EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET; | ||
191 | writel(clk, drv->reg_phy + EXYNOS_4x12_UPHYCLK); | ||
192 | } | ||
193 | |||
194 | static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on) | ||
195 | { | ||
196 | struct samsung_usb2_phy_driver *drv = inst->drv; | ||
197 | u32 rstbits = 0; | ||
198 | u32 phypwr = 0; | ||
199 | u32 rst; | ||
200 | u32 pwr; | ||
201 | u32 mode = 0; | ||
202 | u32 switch_mode = 0; | ||
203 | |||
204 | switch (inst->cfg->id) { | ||
205 | case EXYNOS4x12_DEVICE: | ||
206 | phypwr = EXYNOS_4x12_UPHYPWR_PHY0; | ||
207 | rstbits = EXYNOS_4x12_URSTCON_PHY0; | ||
208 | mode = EXYNOS_4x12_MODE_SWITCH_DEVICE; | ||
209 | switch_mode = 1; | ||
210 | break; | ||
211 | case EXYNOS4x12_HOST: | ||
212 | phypwr = EXYNOS_4x12_UPHYPWR_PHY1; | ||
213 | rstbits = EXYNOS_4x12_URSTCON_HOST_PHY; | ||
214 | mode = EXYNOS_4x12_MODE_SWITCH_HOST; | ||
215 | switch_mode = 1; | ||
216 | break; | ||
217 | case EXYNOS4x12_HSIC0: | ||
218 | phypwr = EXYNOS_4x12_UPHYPWR_HSIC0; | ||
219 | rstbits = EXYNOS_4x12_URSTCON_HSIC1 | | ||
220 | EXYNOS_4x12_URSTCON_HOST_LINK_P0 | | ||
221 | EXYNOS_4x12_URSTCON_HOST_PHY; | ||
222 | break; | ||
223 | case EXYNOS4x12_HSIC1: | ||
224 | phypwr = EXYNOS_4x12_UPHYPWR_HSIC1; | ||
225 | rstbits = EXYNOS_4x12_URSTCON_HSIC1 | | ||
226 | EXYNOS_4x12_URSTCON_HOST_LINK_P1; | ||
227 | break; | ||
228 | }; | ||
229 | |||
230 | if (on) { | ||
231 | if (switch_mode) | ||
232 | regmap_update_bits(drv->reg_sys, | ||
233 | EXYNOS_4x12_MODE_SWITCH_OFFSET, | ||
234 | EXYNOS_4x12_MODE_SWITCH_MASK, mode); | ||
235 | |||
236 | pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR); | ||
237 | pwr &= ~phypwr; | ||
238 | writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR); | ||
239 | |||
240 | rst = readl(drv->reg_phy + EXYNOS_4x12_UPHYRST); | ||
241 | rst |= rstbits; | ||
242 | writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST); | ||
243 | udelay(10); | ||
244 | rst &= ~rstbits; | ||
245 | writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST); | ||
246 | /* The following delay is necessary for the reset sequence to be | ||
247 | * completed */ | ||
248 | udelay(80); | ||
249 | } else { | ||
250 | pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR); | ||
251 | pwr |= phypwr; | ||
252 | writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR); | ||
253 | } | ||
254 | } | ||
255 | |||
256 | static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst) | ||
257 | { | ||
258 | struct samsung_usb2_phy_driver *drv = inst->drv; | ||
259 | |||
260 | inst->enabled = 1; | ||
261 | exynos4x12_setup_clk(inst); | ||
262 | exynos4x12_phy_pwr(inst, 1); | ||
263 | exynos4x12_isol(inst, 0); | ||
264 | |||
265 | /* Power on the device, as it is necessary for HSIC to work */ | ||
266 | if (inst->cfg->id == EXYNOS4x12_HSIC0) { | ||
267 | struct samsung_usb2_phy_instance *device = | ||
268 | &drv->instances[EXYNOS4x12_DEVICE]; | ||
269 | exynos4x12_phy_pwr(device, 1); | ||
270 | exynos4x12_isol(device, 0); | ||
271 | } | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst) | ||
277 | { | ||
278 | struct samsung_usb2_phy_driver *drv = inst->drv; | ||
279 | struct samsung_usb2_phy_instance *device = | ||
280 | &drv->instances[EXYNOS4x12_DEVICE]; | ||
281 | |||
282 | inst->enabled = 0; | ||
283 | exynos4x12_isol(inst, 1); | ||
284 | exynos4x12_phy_pwr(inst, 0); | ||
285 | |||
286 | if (inst->cfg->id == EXYNOS4x12_HSIC0 && !device->enabled) { | ||
287 | exynos4x12_isol(device, 1); | ||
288 | exynos4x12_phy_pwr(device, 0); | ||
289 | } | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | |||
295 | static const struct samsung_usb2_common_phy exynos4x12_phys[] = { | ||
296 | { | ||
297 | .label = "device", | ||
298 | .id = EXYNOS4x12_DEVICE, | ||
299 | .power_on = exynos4x12_power_on, | ||
300 | .power_off = exynos4x12_power_off, | ||
301 | }, | ||
302 | { | ||
303 | .label = "host", | ||
304 | .id = EXYNOS4x12_HOST, | ||
305 | .power_on = exynos4x12_power_on, | ||
306 | .power_off = exynos4x12_power_off, | ||
307 | }, | ||
308 | { | ||
309 | .label = "hsic0", | ||
310 | .id = EXYNOS4x12_HSIC0, | ||
311 | .power_on = exynos4x12_power_on, | ||
312 | .power_off = exynos4x12_power_off, | ||
313 | }, | ||
314 | { | ||
315 | .label = "hsic1", | ||
316 | .id = EXYNOS4x12_HSIC1, | ||
317 | .power_on = exynos4x12_power_on, | ||
318 | .power_off = exynos4x12_power_off, | ||
319 | }, | ||
320 | {}, | ||
321 | }; | ||
322 | |||
323 | const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config = { | ||
324 | .has_mode_switch = 1, | ||
325 | .num_phys = EXYNOS4x12_NUM_PHYS, | ||
326 | .phys = exynos4x12_phys, | ||
327 | .rate_to_clk = exynos4x12_rate_to_clk, | ||
328 | }; | ||
diff --git a/drivers/phy/phy-exynos5250-sata.c b/drivers/phy/phy-exynos5250-sata.c new file mode 100644 index 000000000000..c9361b731fa6 --- /dev/null +++ b/drivers/phy/phy-exynos5250-sata.c | |||
@@ -0,0 +1,251 @@ | |||
1 | /* | ||
2 | * Samsung SATA SerDes(PHY) driver | ||
3 | * | ||
4 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
5 | * Authors: Girish K S <ks.giri@samsung.com> | ||
6 | * Yuvaraj Kumar C D <yuvaraj.cd@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/clk.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/of.h> | ||
20 | #include <linux/of_address.h> | ||
21 | #include <linux/phy/phy.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/regmap.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/mfd/syscon.h> | ||
26 | |||
27 | #define SATAPHY_CONTROL_OFFSET 0x0724 | ||
28 | #define EXYNOS5_SATAPHY_PMU_ENABLE BIT(0) | ||
29 | #define EXYNOS5_SATA_RESET 0x4 | ||
30 | #define RESET_GLOBAL_RST_N BIT(0) | ||
31 | #define RESET_CMN_RST_N BIT(1) | ||
32 | #define RESET_CMN_BLOCK_RST_N BIT(2) | ||
33 | #define RESET_CMN_I2C_RST_N BIT(3) | ||
34 | #define RESET_TX_RX_PIPE_RST_N BIT(4) | ||
35 | #define RESET_TX_RX_BLOCK_RST_N BIT(5) | ||
36 | #define RESET_TX_RX_I2C_RST_N (BIT(6) | BIT(7)) | ||
37 | #define LINK_RESET 0xf0000 | ||
38 | #define EXYNOS5_SATA_MODE0 0x10 | ||
39 | #define SATA_SPD_GEN3 BIT(1) | ||
40 | #define EXYNOS5_SATA_CTRL0 0x14 | ||
41 | #define CTRL0_P0_PHY_CALIBRATED_SEL BIT(9) | ||
42 | #define CTRL0_P0_PHY_CALIBRATED BIT(8) | ||
43 | #define EXYNOS5_SATA_PHSATA_CTRLM 0xe0 | ||
44 | #define PHCTRLM_REF_RATE BIT(1) | ||
45 | #define PHCTRLM_HIGH_SPEED BIT(0) | ||
46 | #define EXYNOS5_SATA_PHSATA_STATM 0xf0 | ||
47 | #define PHSTATM_PLL_LOCKED BIT(0) | ||
48 | |||
49 | #define PHY_PLL_TIMEOUT (usecs_to_jiffies(1000)) | ||
50 | |||
51 | struct exynos_sata_phy { | ||
52 | struct phy *phy; | ||
53 | struct clk *phyclk; | ||
54 | void __iomem *regs; | ||
55 | struct regmap *pmureg; | ||
56 | struct i2c_client *client; | ||
57 | }; | ||
58 | |||
59 | static int wait_for_reg_status(void __iomem *base, u32 reg, u32 checkbit, | ||
60 | u32 status) | ||
61 | { | ||
62 | unsigned long timeout = jiffies + PHY_PLL_TIMEOUT; | ||
63 | |||
64 | while (time_before(jiffies, timeout)) { | ||
65 | if ((readl(base + reg) & checkbit) == status) | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | return -EFAULT; | ||
70 | } | ||
71 | |||
72 | static int exynos_sata_phy_power_on(struct phy *phy) | ||
73 | { | ||
74 | struct exynos_sata_phy *sata_phy = phy_get_drvdata(phy); | ||
75 | |||
76 | return regmap_update_bits(sata_phy->pmureg, SATAPHY_CONTROL_OFFSET, | ||
77 | EXYNOS5_SATAPHY_PMU_ENABLE, true); | ||
78 | |||
79 | } | ||
80 | |||
81 | static int exynos_sata_phy_power_off(struct phy *phy) | ||
82 | { | ||
83 | struct exynos_sata_phy *sata_phy = phy_get_drvdata(phy); | ||
84 | |||
85 | return regmap_update_bits(sata_phy->pmureg, SATAPHY_CONTROL_OFFSET, | ||
86 | EXYNOS5_SATAPHY_PMU_ENABLE, false); | ||
87 | |||
88 | } | ||
89 | |||
90 | static int exynos_sata_phy_init(struct phy *phy) | ||
91 | { | ||
92 | u32 val = 0; | ||
93 | int ret = 0; | ||
94 | u8 buf[] = { 0x3a, 0x0b }; | ||
95 | struct exynos_sata_phy *sata_phy = phy_get_drvdata(phy); | ||
96 | |||
97 | ret = regmap_update_bits(sata_phy->pmureg, SATAPHY_CONTROL_OFFSET, | ||
98 | EXYNOS5_SATAPHY_PMU_ENABLE, true); | ||
99 | if (ret != 0) | ||
100 | dev_err(&sata_phy->phy->dev, "phy init failed\n"); | ||
101 | |||
102 | writel(val, sata_phy->regs + EXYNOS5_SATA_RESET); | ||
103 | |||
104 | val = readl(sata_phy->regs + EXYNOS5_SATA_RESET); | ||
105 | val |= RESET_GLOBAL_RST_N | RESET_CMN_RST_N | RESET_CMN_BLOCK_RST_N | ||
106 | | RESET_CMN_I2C_RST_N | RESET_TX_RX_PIPE_RST_N | ||
107 | | RESET_TX_RX_BLOCK_RST_N | RESET_TX_RX_I2C_RST_N; | ||
108 | writel(val, sata_phy->regs + EXYNOS5_SATA_RESET); | ||
109 | |||
110 | val = readl(sata_phy->regs + EXYNOS5_SATA_RESET); | ||
111 | val |= LINK_RESET; | ||
112 | writel(val, sata_phy->regs + EXYNOS5_SATA_RESET); | ||
113 | |||
114 | val = readl(sata_phy->regs + EXYNOS5_SATA_RESET); | ||
115 | val |= RESET_CMN_RST_N; | ||
116 | writel(val, sata_phy->regs + EXYNOS5_SATA_RESET); | ||
117 | |||
118 | val = readl(sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM); | ||
119 | val &= ~PHCTRLM_REF_RATE; | ||
120 | writel(val, sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM); | ||
121 | |||
122 | /* High speed enable for Gen3 */ | ||
123 | val = readl(sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM); | ||
124 | val |= PHCTRLM_HIGH_SPEED; | ||
125 | writel(val, sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM); | ||
126 | |||
127 | val = readl(sata_phy->regs + EXYNOS5_SATA_CTRL0); | ||
128 | val |= CTRL0_P0_PHY_CALIBRATED_SEL | CTRL0_P0_PHY_CALIBRATED; | ||
129 | writel(val, sata_phy->regs + EXYNOS5_SATA_CTRL0); | ||
130 | |||
131 | val = readl(sata_phy->regs + EXYNOS5_SATA_MODE0); | ||
132 | val |= SATA_SPD_GEN3; | ||
133 | writel(val, sata_phy->regs + EXYNOS5_SATA_MODE0); | ||
134 | |||
135 | ret = i2c_master_send(sata_phy->client, buf, sizeof(buf)); | ||
136 | if (ret < 0) | ||
137 | return ret; | ||
138 | |||
139 | /* release cmu reset */ | ||
140 | val = readl(sata_phy->regs + EXYNOS5_SATA_RESET); | ||
141 | val &= ~RESET_CMN_RST_N; | ||
142 | writel(val, sata_phy->regs + EXYNOS5_SATA_RESET); | ||
143 | |||
144 | val = readl(sata_phy->regs + EXYNOS5_SATA_RESET); | ||
145 | val |= RESET_CMN_RST_N; | ||
146 | writel(val, sata_phy->regs + EXYNOS5_SATA_RESET); | ||
147 | |||
148 | ret = wait_for_reg_status(sata_phy->regs, | ||
149 | EXYNOS5_SATA_PHSATA_STATM, | ||
150 | PHSTATM_PLL_LOCKED, 1); | ||
151 | if (ret < 0) | ||
152 | dev_err(&sata_phy->phy->dev, | ||
153 | "PHY PLL locking failed\n"); | ||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | static struct phy_ops exynos_sata_phy_ops = { | ||
158 | .init = exynos_sata_phy_init, | ||
159 | .power_on = exynos_sata_phy_power_on, | ||
160 | .power_off = exynos_sata_phy_power_off, | ||
161 | .owner = THIS_MODULE, | ||
162 | }; | ||
163 | |||
164 | static int exynos_sata_phy_probe(struct platform_device *pdev) | ||
165 | { | ||
166 | struct exynos_sata_phy *sata_phy; | ||
167 | struct device *dev = &pdev->dev; | ||
168 | struct resource *res; | ||
169 | struct phy_provider *phy_provider; | ||
170 | struct device_node *node; | ||
171 | int ret = 0; | ||
172 | |||
173 | sata_phy = devm_kzalloc(dev, sizeof(*sata_phy), GFP_KERNEL); | ||
174 | if (!sata_phy) | ||
175 | return -ENOMEM; | ||
176 | |||
177 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
178 | |||
179 | sata_phy->regs = devm_ioremap_resource(dev, res); | ||
180 | if (IS_ERR(sata_phy->regs)) | ||
181 | return PTR_ERR(sata_phy->regs); | ||
182 | |||
183 | sata_phy->pmureg = syscon_regmap_lookup_by_phandle(dev->of_node, | ||
184 | "samsung,syscon-phandle"); | ||
185 | if (IS_ERR(sata_phy->pmureg)) { | ||
186 | dev_err(dev, "syscon regmap lookup failed.\n"); | ||
187 | return PTR_ERR(sata_phy->pmureg); | ||
188 | } | ||
189 | |||
190 | node = of_parse_phandle(dev->of_node, | ||
191 | "samsung,exynos-sataphy-i2c-phandle", 0); | ||
192 | if (!node) | ||
193 | return -EINVAL; | ||
194 | |||
195 | sata_phy->client = of_find_i2c_device_by_node(node); | ||
196 | if (!sata_phy->client) | ||
197 | return -EPROBE_DEFER; | ||
198 | |||
199 | dev_set_drvdata(dev, sata_phy); | ||
200 | |||
201 | sata_phy->phyclk = devm_clk_get(dev, "sata_phyctrl"); | ||
202 | if (IS_ERR(sata_phy->phyclk)) { | ||
203 | dev_err(dev, "failed to get clk for PHY\n"); | ||
204 | return PTR_ERR(sata_phy->phyclk); | ||
205 | } | ||
206 | |||
207 | ret = clk_prepare_enable(sata_phy->phyclk); | ||
208 | if (ret < 0) { | ||
209 | dev_err(dev, "failed to enable source clk\n"); | ||
210 | return ret; | ||
211 | } | ||
212 | |||
213 | sata_phy->phy = devm_phy_create(dev, &exynos_sata_phy_ops, NULL); | ||
214 | if (IS_ERR(sata_phy->phy)) { | ||
215 | clk_disable_unprepare(sata_phy->phyclk); | ||
216 | dev_err(dev, "failed to create PHY\n"); | ||
217 | return PTR_ERR(sata_phy->phy); | ||
218 | } | ||
219 | |||
220 | phy_set_drvdata(sata_phy->phy, sata_phy); | ||
221 | |||
222 | phy_provider = devm_of_phy_provider_register(dev, | ||
223 | of_phy_simple_xlate); | ||
224 | if (IS_ERR(phy_provider)) { | ||
225 | clk_disable_unprepare(sata_phy->phyclk); | ||
226 | return PTR_ERR(phy_provider); | ||
227 | } | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static const struct of_device_id exynos_sata_phy_of_match[] = { | ||
233 | { .compatible = "samsung,exynos5250-sata-phy" }, | ||
234 | { }, | ||
235 | }; | ||
236 | MODULE_DEVICE_TABLE(of, exynos_sata_phy_of_match); | ||
237 | |||
238 | static struct platform_driver exynos_sata_phy_driver = { | ||
239 | .probe = exynos_sata_phy_probe, | ||
240 | .driver = { | ||
241 | .of_match_table = exynos_sata_phy_of_match, | ||
242 | .name = "samsung,sata-phy", | ||
243 | .owner = THIS_MODULE, | ||
244 | } | ||
245 | }; | ||
246 | module_platform_driver(exynos_sata_phy_driver); | ||
247 | |||
248 | MODULE_DESCRIPTION("Samsung SerDes PHY driver"); | ||
249 | MODULE_LICENSE("GPL V2"); | ||
250 | MODULE_AUTHOR("Girish K S <ks.giri@samsung.com>"); | ||
251 | MODULE_AUTHOR("Yuvaraj C D <yuvaraj.cd@samsung.com>"); | ||
diff --git a/drivers/phy/phy-exynos5250-usb2.c b/drivers/phy/phy-exynos5250-usb2.c new file mode 100644 index 000000000000..94179afda951 --- /dev/null +++ b/drivers/phy/phy-exynos5250-usb2.c | |||
@@ -0,0 +1,404 @@ | |||
1 | /* | ||
2 | * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 5250 support | ||
3 | * | ||
4 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
5 | * Author: Kamil Debski <k.debski@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/delay.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/phy/phy.h> | ||
15 | #include <linux/regmap.h> | ||
16 | #include "phy-samsung-usb2.h" | ||
17 | |||
18 | /* Exynos USB PHY registers */ | ||
19 | #define EXYNOS_5250_REFCLKSEL_CRYSTAL 0x0 | ||
20 | #define EXYNOS_5250_REFCLKSEL_XO 0x1 | ||
21 | #define EXYNOS_5250_REFCLKSEL_CLKCORE 0x2 | ||
22 | |||
23 | #define EXYNOS_5250_FSEL_9MHZ6 0x0 | ||
24 | #define EXYNOS_5250_FSEL_10MHZ 0x1 | ||
25 | #define EXYNOS_5250_FSEL_12MHZ 0x2 | ||
26 | #define EXYNOS_5250_FSEL_19MHZ2 0x3 | ||
27 | #define EXYNOS_5250_FSEL_20MHZ 0x4 | ||
28 | #define EXYNOS_5250_FSEL_24MHZ 0x5 | ||
29 | #define EXYNOS_5250_FSEL_50MHZ 0x7 | ||
30 | |||
31 | /* Normal host */ | ||
32 | #define EXYNOS_5250_HOSTPHYCTRL0 0x0 | ||
33 | |||
34 | #define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL BIT(31) | ||
35 | #define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT 19 | ||
36 | #define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_MASK \ | ||
37 | (0x3 << EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT) | ||
38 | #define EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT 16 | ||
39 | #define EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK \ | ||
40 | (0x7 << EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT) | ||
41 | #define EXYNOS_5250_HOSTPHYCTRL0_TESTBURNIN BIT(11) | ||
42 | #define EXYNOS_5250_HOSTPHYCTRL0_RETENABLE BIT(10) | ||
43 | #define EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N BIT(9) | ||
44 | #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_MASK (0x3 << 7) | ||
45 | #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_DUAL (0x0 << 7) | ||
46 | #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ID0 (0x1 << 7) | ||
47 | #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ANALOGTEST (0x2 << 7) | ||
48 | #define EXYNOS_5250_HOSTPHYCTRL0_SIDDQ BIT(6) | ||
49 | #define EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP BIT(5) | ||
50 | #define EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND BIT(4) | ||
51 | #define EXYNOS_5250_HOSTPHYCTRL0_WORDINTERFACE BIT(3) | ||
52 | #define EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST BIT(2) | ||
53 | #define EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST BIT(1) | ||
54 | #define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST BIT(0) | ||
55 | |||
56 | /* HSIC0 & HSIC1 */ | ||
57 | #define EXYNOS_5250_HSICPHYCTRL1 0x10 | ||
58 | #define EXYNOS_5250_HSICPHYCTRL2 0x20 | ||
59 | |||
60 | #define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_MASK (0x3 << 23) | ||
61 | #define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT (0x2 << 23) | ||
62 | #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_MASK (0x7f << 16) | ||
63 | #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 (0x24 << 16) | ||
64 | #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_15 (0x1c << 16) | ||
65 | #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_16 (0x1a << 16) | ||
66 | #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_19_2 (0x15 << 16) | ||
67 | #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_20 (0x14 << 16) | ||
68 | #define EXYNOS_5250_HSICPHYCTRLX_SIDDQ BIT(6) | ||
69 | #define EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP BIT(5) | ||
70 | #define EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND BIT(4) | ||
71 | #define EXYNOS_5250_HSICPHYCTRLX_WORDINTERFACE BIT(3) | ||
72 | #define EXYNOS_5250_HSICPHYCTRLX_UTMISWRST BIT(2) | ||
73 | #define EXYNOS_5250_HSICPHYCTRLX_PHYSWRST BIT(0) | ||
74 | |||
75 | /* EHCI control */ | ||
76 | #define EXYNOS_5250_HOSTEHCICTRL 0x30 | ||
77 | #define EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN BIT(29) | ||
78 | #define EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 BIT(28) | ||
79 | #define EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 BIT(27) | ||
80 | #define EXYNOS_5250_HOSTEHCICTRL_ENAINCR16 BIT(26) | ||
81 | #define EXYNOS_5250_HOSTEHCICTRL_AUTOPPDONOVRCUREN BIT(25) | ||
82 | #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT 19 | ||
83 | #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK \ | ||
84 | (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT) | ||
85 | #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT 13 | ||
86 | #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_MASK \ | ||
87 | (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT) | ||
88 | #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL2_SHIFT 7 | ||
89 | #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK \ | ||
90 | (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT) | ||
91 | #define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT 1 | ||
92 | #define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_MASK \ | ||
93 | (0x1 << EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT) | ||
94 | #define EXYNOS_5250_HOSTEHCICTRL_SIMULATIONMODE BIT(0) | ||
95 | |||
96 | /* OHCI control */ | ||
97 | #define EXYNOS_5250_HOSTOHCICTRL 0x34 | ||
98 | #define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT 1 | ||
99 | #define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_MASK \ | ||
100 | (0x3ff << EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT) | ||
101 | #define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVALEN BIT(0) | ||
102 | |||
103 | /* USBOTG */ | ||
104 | #define EXYNOS_5250_USBOTGSYS 0x38 | ||
105 | #define EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET BIT(14) | ||
106 | #define EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG BIT(13) | ||
107 | #define EXYNOS_5250_USBOTGSYS_PHY_SW_RST BIT(12) | ||
108 | #define EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT 9 | ||
109 | #define EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK \ | ||
110 | (0x3 << EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT) | ||
111 | #define EXYNOS_5250_USBOTGSYS_ID_PULLUP BIT(8) | ||
112 | #define EXYNOS_5250_USBOTGSYS_COMMON_ON BIT(7) | ||
113 | #define EXYNOS_5250_USBOTGSYS_FSEL_SHIFT 4 | ||
114 | #define EXYNOS_5250_USBOTGSYS_FSEL_MASK \ | ||
115 | (0x3 << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT) | ||
116 | #define EXYNOS_5250_USBOTGSYS_FORCE_SLEEP BIT(3) | ||
117 | #define EXYNOS_5250_USBOTGSYS_OTGDISABLE BIT(2) | ||
118 | #define EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG BIT(1) | ||
119 | #define EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND BIT(0) | ||
120 | |||
121 | /* Isolation, configured in the power management unit */ | ||
122 | #define EXYNOS_5250_USB_ISOL_OTG_OFFSET 0x704 | ||
123 | #define EXYNOS_5250_USB_ISOL_OTG BIT(0) | ||
124 | #define EXYNOS_5250_USB_ISOL_HOST_OFFSET 0x708 | ||
125 | #define EXYNOS_5250_USB_ISOL_HOST BIT(0) | ||
126 | |||
127 | /* Mode swtich register */ | ||
128 | #define EXYNOS_5250_MODE_SWITCH_OFFSET 0x230 | ||
129 | #define EXYNOS_5250_MODE_SWITCH_MASK 1 | ||
130 | #define EXYNOS_5250_MODE_SWITCH_DEVICE 0 | ||
131 | #define EXYNOS_5250_MODE_SWITCH_HOST 1 | ||
132 | |||
133 | enum exynos4x12_phy_id { | ||
134 | EXYNOS5250_DEVICE, | ||
135 | EXYNOS5250_HOST, | ||
136 | EXYNOS5250_HSIC0, | ||
137 | EXYNOS5250_HSIC1, | ||
138 | EXYNOS5250_NUM_PHYS, | ||
139 | }; | ||
140 | |||
141 | /* | ||
142 | * exynos5250_rate_to_clk() converts the supplied clock rate to the value that | ||
143 | * can be written to the phy register. | ||
144 | */ | ||
145 | static int exynos5250_rate_to_clk(unsigned long rate, u32 *reg) | ||
146 | { | ||
147 | /* EXYNOS_5250_FSEL_MASK */ | ||
148 | |||
149 | switch (rate) { | ||
150 | case 9600 * KHZ: | ||
151 | *reg = EXYNOS_5250_FSEL_9MHZ6; | ||
152 | break; | ||
153 | case 10 * MHZ: | ||
154 | *reg = EXYNOS_5250_FSEL_10MHZ; | ||
155 | break; | ||
156 | case 12 * MHZ: | ||
157 | *reg = EXYNOS_5250_FSEL_12MHZ; | ||
158 | break; | ||
159 | case 19200 * KHZ: | ||
160 | *reg = EXYNOS_5250_FSEL_19MHZ2; | ||
161 | break; | ||
162 | case 20 * MHZ: | ||
163 | *reg = EXYNOS_5250_FSEL_20MHZ; | ||
164 | break; | ||
165 | case 24 * MHZ: | ||
166 | *reg = EXYNOS_5250_FSEL_24MHZ; | ||
167 | break; | ||
168 | case 50 * MHZ: | ||
169 | *reg = EXYNOS_5250_FSEL_50MHZ; | ||
170 | break; | ||
171 | default: | ||
172 | return -EINVAL; | ||
173 | } | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static void exynos5250_isol(struct samsung_usb2_phy_instance *inst, bool on) | ||
179 | { | ||
180 | struct samsung_usb2_phy_driver *drv = inst->drv; | ||
181 | u32 offset; | ||
182 | u32 mask; | ||
183 | |||
184 | switch (inst->cfg->id) { | ||
185 | case EXYNOS5250_DEVICE: | ||
186 | offset = EXYNOS_5250_USB_ISOL_OTG_OFFSET; | ||
187 | mask = EXYNOS_5250_USB_ISOL_OTG; | ||
188 | break; | ||
189 | case EXYNOS5250_HOST: | ||
190 | offset = EXYNOS_5250_USB_ISOL_HOST_OFFSET; | ||
191 | mask = EXYNOS_5250_USB_ISOL_HOST; | ||
192 | break; | ||
193 | default: | ||
194 | return; | ||
195 | }; | ||
196 | |||
197 | regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask); | ||
198 | } | ||
199 | |||
200 | static int exynos5250_power_on(struct samsung_usb2_phy_instance *inst) | ||
201 | { | ||
202 | struct samsung_usb2_phy_driver *drv = inst->drv; | ||
203 | u32 ctrl0; | ||
204 | u32 otg; | ||
205 | u32 ehci; | ||
206 | u32 ohci; | ||
207 | u32 hsic; | ||
208 | |||
209 | switch (inst->cfg->id) { | ||
210 | case EXYNOS5250_DEVICE: | ||
211 | regmap_update_bits(drv->reg_sys, | ||
212 | EXYNOS_5250_MODE_SWITCH_OFFSET, | ||
213 | EXYNOS_5250_MODE_SWITCH_MASK, | ||
214 | EXYNOS_5250_MODE_SWITCH_DEVICE); | ||
215 | |||
216 | /* OTG configuration */ | ||
217 | otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS); | ||
218 | /* The clock */ | ||
219 | otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK; | ||
220 | otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT; | ||
221 | /* Reset */ | ||
222 | otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND | | ||
223 | EXYNOS_5250_USBOTGSYS_FORCE_SLEEP | | ||
224 | EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG); | ||
225 | otg |= EXYNOS_5250_USBOTGSYS_PHY_SW_RST | | ||
226 | EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET | | ||
227 | EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG | | ||
228 | EXYNOS_5250_USBOTGSYS_OTGDISABLE; | ||
229 | /* Ref clock */ | ||
230 | otg &= ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK; | ||
231 | otg |= EXYNOS_5250_REFCLKSEL_CLKCORE << | ||
232 | EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT; | ||
233 | writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS); | ||
234 | udelay(100); | ||
235 | otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST | | ||
236 | EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG | | ||
237 | EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET | | ||
238 | EXYNOS_5250_USBOTGSYS_OTGDISABLE); | ||
239 | writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS); | ||
240 | |||
241 | |||
242 | break; | ||
243 | case EXYNOS5250_HOST: | ||
244 | case EXYNOS5250_HSIC0: | ||
245 | case EXYNOS5250_HSIC1: | ||
246 | /* Host registers configuration */ | ||
247 | ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0); | ||
248 | /* The clock */ | ||
249 | ctrl0 &= ~EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK; | ||
250 | ctrl0 |= drv->ref_reg_val << | ||
251 | EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT; | ||
252 | |||
253 | /* Reset */ | ||
254 | ctrl0 &= ~(EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST | | ||
255 | EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL | | ||
256 | EXYNOS_5250_HOSTPHYCTRL0_SIDDQ | | ||
257 | EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND | | ||
258 | EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP); | ||
259 | ctrl0 |= EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST | | ||
260 | EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST | | ||
261 | EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N; | ||
262 | writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0); | ||
263 | udelay(10); | ||
264 | ctrl0 &= ~(EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST | | ||
265 | EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST); | ||
266 | writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0); | ||
267 | |||
268 | /* OTG configuration */ | ||
269 | otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS); | ||
270 | /* The clock */ | ||
271 | otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK; | ||
272 | otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT; | ||
273 | /* Reset */ | ||
274 | otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND | | ||
275 | EXYNOS_5250_USBOTGSYS_FORCE_SLEEP | | ||
276 | EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG); | ||
277 | otg |= EXYNOS_5250_USBOTGSYS_PHY_SW_RST | | ||
278 | EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET | | ||
279 | EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG | | ||
280 | EXYNOS_5250_USBOTGSYS_OTGDISABLE; | ||
281 | /* Ref clock */ | ||
282 | otg &= ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK; | ||
283 | otg |= EXYNOS_5250_REFCLKSEL_CLKCORE << | ||
284 | EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT; | ||
285 | writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS); | ||
286 | udelay(10); | ||
287 | otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST | | ||
288 | EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG | | ||
289 | EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET); | ||
290 | |||
291 | /* HSIC phy configuration */ | ||
292 | hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 | | ||
293 | EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT | | ||
294 | EXYNOS_5250_HSICPHYCTRLX_PHYSWRST); | ||
295 | writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1); | ||
296 | writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2); | ||
297 | udelay(10); | ||
298 | hsic &= ~EXYNOS_5250_HSICPHYCTRLX_PHYSWRST; | ||
299 | writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1); | ||
300 | writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2); | ||
301 | /* The following delay is necessary for the reset sequence to be | ||
302 | * completed */ | ||
303 | udelay(80); | ||
304 | |||
305 | /* Enable EHCI DMA burst */ | ||
306 | ehci = readl(drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL); | ||
307 | ehci |= EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN | | ||
308 | EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 | | ||
309 | EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 | | ||
310 | EXYNOS_5250_HOSTEHCICTRL_ENAINCR16; | ||
311 | writel(ehci, drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL); | ||
312 | |||
313 | /* OHCI settings */ | ||
314 | ohci = readl(drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL); | ||
315 | /* Following code is based on the old driver */ | ||
316 | ohci |= 0x1 << 3; | ||
317 | writel(ohci, drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL); | ||
318 | |||
319 | break; | ||
320 | } | ||
321 | inst->enabled = 1; | ||
322 | exynos5250_isol(inst, 0); | ||
323 | |||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | static int exynos5250_power_off(struct samsung_usb2_phy_instance *inst) | ||
328 | { | ||
329 | struct samsung_usb2_phy_driver *drv = inst->drv; | ||
330 | u32 ctrl0; | ||
331 | u32 otg; | ||
332 | u32 hsic; | ||
333 | |||
334 | inst->enabled = 0; | ||
335 | exynos5250_isol(inst, 1); | ||
336 | |||
337 | switch (inst->cfg->id) { | ||
338 | case EXYNOS5250_DEVICE: | ||
339 | otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS); | ||
340 | otg |= (EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND | | ||
341 | EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG | | ||
342 | EXYNOS_5250_USBOTGSYS_FORCE_SLEEP); | ||
343 | writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS); | ||
344 | break; | ||
345 | case EXYNOS5250_HOST: | ||
346 | ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0); | ||
347 | ctrl0 |= (EXYNOS_5250_HOSTPHYCTRL0_SIDDQ | | ||
348 | EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND | | ||
349 | EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP | | ||
350 | EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST | | ||
351 | EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL); | ||
352 | writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0); | ||
353 | break; | ||
354 | case EXYNOS5250_HSIC0: | ||
355 | case EXYNOS5250_HSIC1: | ||
356 | hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 | | ||
357 | EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT | | ||
358 | EXYNOS_5250_HSICPHYCTRLX_SIDDQ | | ||
359 | EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP | | ||
360 | EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND | ||
361 | ); | ||
362 | writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1); | ||
363 | writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2); | ||
364 | break; | ||
365 | } | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | |||
371 | static const struct samsung_usb2_common_phy exynos5250_phys[] = { | ||
372 | { | ||
373 | .label = "device", | ||
374 | .id = EXYNOS5250_DEVICE, | ||
375 | .power_on = exynos5250_power_on, | ||
376 | .power_off = exynos5250_power_off, | ||
377 | }, | ||
378 | { | ||
379 | .label = "host", | ||
380 | .id = EXYNOS5250_HOST, | ||
381 | .power_on = exynos5250_power_on, | ||
382 | .power_off = exynos5250_power_off, | ||
383 | }, | ||
384 | { | ||
385 | .label = "hsic0", | ||
386 | .id = EXYNOS5250_HSIC0, | ||
387 | .power_on = exynos5250_power_on, | ||
388 | .power_off = exynos5250_power_off, | ||
389 | }, | ||
390 | { | ||
391 | .label = "hsic1", | ||
392 | .id = EXYNOS5250_HSIC1, | ||
393 | .power_on = exynos5250_power_on, | ||
394 | .power_off = exynos5250_power_off, | ||
395 | }, | ||
396 | {}, | ||
397 | }; | ||
398 | |||
399 | const struct samsung_usb2_phy_config exynos5250_usb2_phy_config = { | ||
400 | .has_mode_switch = 1, | ||
401 | .num_phys = EXYNOS5250_NUM_PHYS, | ||
402 | .phys = exynos5250_phys, | ||
403 | .rate_to_clk = exynos5250_rate_to_clk, | ||
404 | }; | ||
diff --git a/drivers/usb/phy/phy-omap-control.c b/drivers/phy/phy-omap-control.c index e7253182e47d..311b4f9a5132 100644 --- a/drivers/usb/phy/phy-omap-control.c +++ b/drivers/phy/phy-omap-control.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * omap-control-usb.c - The USB part of control module. | 2 | * omap-control-phy.c - The PHY part of control module. |
3 | * | 3 | * |
4 | * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com | 4 | * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
@@ -24,36 +24,36 @@ | |||
24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/clk.h> | 26 | #include <linux/clk.h> |
27 | #include <linux/usb/omap_control_usb.h> | 27 | #include <linux/phy/omap_control_phy.h> |
28 | 28 | ||
29 | /** | 29 | /** |
30 | * omap_control_usb_phy_power - power on/off the phy using control module reg | 30 | * omap_control_phy_power - power on/off the phy using control module reg |
31 | * @dev: the control module device | 31 | * @dev: the control module device |
32 | * @on: 0 or 1, based on powering on or off the PHY | 32 | * @on: 0 or 1, based on powering on or off the PHY |
33 | */ | 33 | */ |
34 | void omap_control_usb_phy_power(struct device *dev, int on) | 34 | void omap_control_phy_power(struct device *dev, int on) |
35 | { | 35 | { |
36 | u32 val; | 36 | u32 val; |
37 | unsigned long rate; | 37 | unsigned long rate; |
38 | struct omap_control_usb *control_usb; | 38 | struct omap_control_phy *control_phy; |
39 | 39 | ||
40 | if (IS_ERR(dev) || !dev) { | 40 | if (IS_ERR(dev) || !dev) { |
41 | pr_err("%s: invalid device\n", __func__); | 41 | pr_err("%s: invalid device\n", __func__); |
42 | return; | 42 | return; |
43 | } | 43 | } |
44 | 44 | ||
45 | control_usb = dev_get_drvdata(dev); | 45 | control_phy = dev_get_drvdata(dev); |
46 | if (!control_usb) { | 46 | if (!control_phy) { |
47 | dev_err(dev, "%s: invalid control usb device\n", __func__); | 47 | dev_err(dev, "%s: invalid control phy device\n", __func__); |
48 | return; | 48 | return; |
49 | } | 49 | } |
50 | 50 | ||
51 | if (control_usb->type == OMAP_CTRL_TYPE_OTGHS) | 51 | if (control_phy->type == OMAP_CTRL_TYPE_OTGHS) |
52 | return; | 52 | return; |
53 | 53 | ||
54 | val = readl(control_usb->power); | 54 | val = readl(control_phy->power); |
55 | 55 | ||
56 | switch (control_usb->type) { | 56 | switch (control_phy->type) { |
57 | case OMAP_CTRL_TYPE_USB2: | 57 | case OMAP_CTRL_TYPE_USB2: |
58 | if (on) | 58 | if (on) |
59 | val &= ~OMAP_CTRL_DEV_PHY_PD; | 59 | val &= ~OMAP_CTRL_DEV_PHY_PD; |
@@ -62,19 +62,20 @@ void omap_control_usb_phy_power(struct device *dev, int on) | |||
62 | break; | 62 | break; |
63 | 63 | ||
64 | case OMAP_CTRL_TYPE_PIPE3: | 64 | case OMAP_CTRL_TYPE_PIPE3: |
65 | rate = clk_get_rate(control_usb->sys_clk); | 65 | rate = clk_get_rate(control_phy->sys_clk); |
66 | rate = rate/1000000; | 66 | rate = rate/1000000; |
67 | 67 | ||
68 | if (on) { | 68 | if (on) { |
69 | val &= ~(OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK | | 69 | val &= ~(OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK | |
70 | OMAP_CTRL_USB_PWRCTL_CLK_FREQ_MASK); | 70 | OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK); |
71 | val |= OMAP_CTRL_USB3_PHY_TX_RX_POWERON << | 71 | val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON << |
72 | OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT; | 72 | OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT; |
73 | val |= rate << OMAP_CTRL_USB_PWRCTL_CLK_FREQ_SHIFT; | 73 | val |= rate << |
74 | OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT; | ||
74 | } else { | 75 | } else { |
75 | val &= ~OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK; | 76 | val &= ~OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK; |
76 | val |= OMAP_CTRL_USB3_PHY_TX_RX_POWEROFF << | 77 | val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF << |
77 | OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT; | 78 | OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT; |
78 | } | 79 | } |
79 | break; | 80 | break; |
80 | 81 | ||
@@ -100,66 +101,66 @@ void omap_control_usb_phy_power(struct device *dev, int on) | |||
100 | break; | 101 | break; |
101 | default: | 102 | default: |
102 | dev_err(dev, "%s: type %d not recognized\n", | 103 | dev_err(dev, "%s: type %d not recognized\n", |
103 | __func__, control_usb->type); | 104 | __func__, control_phy->type); |
104 | break; | 105 | break; |
105 | } | 106 | } |
106 | 107 | ||
107 | writel(val, control_usb->power); | 108 | writel(val, control_phy->power); |
108 | } | 109 | } |
109 | EXPORT_SYMBOL_GPL(omap_control_usb_phy_power); | 110 | EXPORT_SYMBOL_GPL(omap_control_phy_power); |
110 | 111 | ||
111 | /** | 112 | /** |
112 | * omap_control_usb_host_mode - set AVALID, VBUSVALID and ID pin in grounded | 113 | * omap_control_usb_host_mode - set AVALID, VBUSVALID and ID pin in grounded |
113 | * @ctrl_usb: struct omap_control_usb * | 114 | * @ctrl_phy: struct omap_control_phy * |
114 | * | 115 | * |
115 | * Writes to the mailbox register to notify the usb core that a usb | 116 | * Writes to the mailbox register to notify the usb core that a usb |
116 | * device has been connected. | 117 | * device has been connected. |
117 | */ | 118 | */ |
118 | static void omap_control_usb_host_mode(struct omap_control_usb *ctrl_usb) | 119 | static void omap_control_usb_host_mode(struct omap_control_phy *ctrl_phy) |
119 | { | 120 | { |
120 | u32 val; | 121 | u32 val; |
121 | 122 | ||
122 | val = readl(ctrl_usb->otghs_control); | 123 | val = readl(ctrl_phy->otghs_control); |
123 | val &= ~(OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND); | 124 | val &= ~(OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND); |
124 | val |= OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID; | 125 | val |= OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID; |
125 | writel(val, ctrl_usb->otghs_control); | 126 | writel(val, ctrl_phy->otghs_control); |
126 | } | 127 | } |
127 | 128 | ||
128 | /** | 129 | /** |
129 | * omap_control_usb_device_mode - set AVALID, VBUSVALID and ID pin in high | 130 | * omap_control_usb_device_mode - set AVALID, VBUSVALID and ID pin in high |
130 | * impedance | 131 | * impedance |
131 | * @ctrl_usb: struct omap_control_usb * | 132 | * @ctrl_phy: struct omap_control_phy * |
132 | * | 133 | * |
133 | * Writes to the mailbox register to notify the usb core that it has been | 134 | * Writes to the mailbox register to notify the usb core that it has been |
134 | * connected to a usb host. | 135 | * connected to a usb host. |
135 | */ | 136 | */ |
136 | static void omap_control_usb_device_mode(struct omap_control_usb *ctrl_usb) | 137 | static void omap_control_usb_device_mode(struct omap_control_phy *ctrl_phy) |
137 | { | 138 | { |
138 | u32 val; | 139 | u32 val; |
139 | 140 | ||
140 | val = readl(ctrl_usb->otghs_control); | 141 | val = readl(ctrl_phy->otghs_control); |
141 | val &= ~OMAP_CTRL_DEV_SESSEND; | 142 | val &= ~OMAP_CTRL_DEV_SESSEND; |
142 | val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_AVALID | | 143 | val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_AVALID | |
143 | OMAP_CTRL_DEV_VBUSVALID; | 144 | OMAP_CTRL_DEV_VBUSVALID; |
144 | writel(val, ctrl_usb->otghs_control); | 145 | writel(val, ctrl_phy->otghs_control); |
145 | } | 146 | } |
146 | 147 | ||
147 | /** | 148 | /** |
148 | * omap_control_usb_set_sessionend - Enable SESSIONEND and IDIG to high | 149 | * omap_control_usb_set_sessionend - Enable SESSIONEND and IDIG to high |
149 | * impedance | 150 | * impedance |
150 | * @ctrl_usb: struct omap_control_usb * | 151 | * @ctrl_phy: struct omap_control_phy * |
151 | * | 152 | * |
152 | * Writes to the mailbox register to notify the usb core it's now in | 153 | * Writes to the mailbox register to notify the usb core it's now in |
153 | * disconnected state. | 154 | * disconnected state. |
154 | */ | 155 | */ |
155 | static void omap_control_usb_set_sessionend(struct omap_control_usb *ctrl_usb) | 156 | static void omap_control_usb_set_sessionend(struct omap_control_phy *ctrl_phy) |
156 | { | 157 | { |
157 | u32 val; | 158 | u32 val; |
158 | 159 | ||
159 | val = readl(ctrl_usb->otghs_control); | 160 | val = readl(ctrl_phy->otghs_control); |
160 | val &= ~(OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID); | 161 | val &= ~(OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID); |
161 | val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND; | 162 | val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND; |
162 | writel(val, ctrl_usb->otghs_control); | 163 | writel(val, ctrl_phy->otghs_control); |
163 | } | 164 | } |
164 | 165 | ||
165 | /** | 166 | /** |
@@ -174,30 +175,30 @@ static void omap_control_usb_set_sessionend(struct omap_control_usb *ctrl_usb) | |||
174 | void omap_control_usb_set_mode(struct device *dev, | 175 | void omap_control_usb_set_mode(struct device *dev, |
175 | enum omap_control_usb_mode mode) | 176 | enum omap_control_usb_mode mode) |
176 | { | 177 | { |
177 | struct omap_control_usb *ctrl_usb; | 178 | struct omap_control_phy *ctrl_phy; |
178 | 179 | ||
179 | if (IS_ERR(dev) || !dev) | 180 | if (IS_ERR(dev) || !dev) |
180 | return; | 181 | return; |
181 | 182 | ||
182 | ctrl_usb = dev_get_drvdata(dev); | 183 | ctrl_phy = dev_get_drvdata(dev); |
183 | 184 | ||
184 | if (!ctrl_usb) { | 185 | if (!ctrl_phy) { |
185 | dev_err(dev, "Invalid control usb device\n"); | 186 | dev_err(dev, "Invalid control phy device\n"); |
186 | return; | 187 | return; |
187 | } | 188 | } |
188 | 189 | ||
189 | if (ctrl_usb->type != OMAP_CTRL_TYPE_OTGHS) | 190 | if (ctrl_phy->type != OMAP_CTRL_TYPE_OTGHS) |
190 | return; | 191 | return; |
191 | 192 | ||
192 | switch (mode) { | 193 | switch (mode) { |
193 | case USB_MODE_HOST: | 194 | case USB_MODE_HOST: |
194 | omap_control_usb_host_mode(ctrl_usb); | 195 | omap_control_usb_host_mode(ctrl_phy); |
195 | break; | 196 | break; |
196 | case USB_MODE_DEVICE: | 197 | case USB_MODE_DEVICE: |
197 | omap_control_usb_device_mode(ctrl_usb); | 198 | omap_control_usb_device_mode(ctrl_phy); |
198 | break; | 199 | break; |
199 | case USB_MODE_DISCONNECT: | 200 | case USB_MODE_DISCONNECT: |
200 | omap_control_usb_set_sessionend(ctrl_usb); | 201 | omap_control_usb_set_sessionend(ctrl_phy); |
201 | break; | 202 | break; |
202 | default: | 203 | default: |
203 | dev_vdbg(dev, "invalid omap control usb mode\n"); | 204 | dev_vdbg(dev, "invalid omap control usb mode\n"); |
@@ -207,13 +208,13 @@ EXPORT_SYMBOL_GPL(omap_control_usb_set_mode); | |||
207 | 208 | ||
208 | #ifdef CONFIG_OF | 209 | #ifdef CONFIG_OF |
209 | 210 | ||
210 | static const enum omap_control_usb_type otghs_data = OMAP_CTRL_TYPE_OTGHS; | 211 | static const enum omap_control_phy_type otghs_data = OMAP_CTRL_TYPE_OTGHS; |
211 | static const enum omap_control_usb_type usb2_data = OMAP_CTRL_TYPE_USB2; | 212 | static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2; |
212 | static const enum omap_control_usb_type pipe3_data = OMAP_CTRL_TYPE_PIPE3; | 213 | static const enum omap_control_phy_type pipe3_data = OMAP_CTRL_TYPE_PIPE3; |
213 | static const enum omap_control_usb_type dra7usb2_data = OMAP_CTRL_TYPE_DRA7USB2; | 214 | static const enum omap_control_phy_type dra7usb2_data = OMAP_CTRL_TYPE_DRA7USB2; |
214 | static const enum omap_control_usb_type am437usb2_data = OMAP_CTRL_TYPE_AM437USB2; | 215 | static const enum omap_control_phy_type am437usb2_data = OMAP_CTRL_TYPE_AM437USB2; |
215 | 216 | ||
216 | static const struct of_device_id omap_control_usb_id_table[] = { | 217 | static const struct of_device_id omap_control_phy_id_table[] = { |
217 | { | 218 | { |
218 | .compatible = "ti,control-phy-otghs", | 219 | .compatible = "ti,control-phy-otghs", |
219 | .data = &otghs_data, | 220 | .data = &otghs_data, |
@@ -227,93 +228,93 @@ static const struct of_device_id omap_control_usb_id_table[] = { | |||
227 | .data = &pipe3_data, | 228 | .data = &pipe3_data, |
228 | }, | 229 | }, |
229 | { | 230 | { |
230 | .compatible = "ti,control-phy-dra7usb2", | 231 | .compatible = "ti,control-phy-usb2-dra7", |
231 | .data = &dra7usb2_data, | 232 | .data = &dra7usb2_data, |
232 | }, | 233 | }, |
233 | { | 234 | { |
234 | .compatible = "ti,control-phy-am437usb2", | 235 | .compatible = "ti,control-phy-usb2-am437", |
235 | .data = &am437usb2_data, | 236 | .data = &am437usb2_data, |
236 | }, | 237 | }, |
237 | {}, | 238 | {}, |
238 | }; | 239 | }; |
239 | MODULE_DEVICE_TABLE(of, omap_control_usb_id_table); | 240 | MODULE_DEVICE_TABLE(of, omap_control_phy_id_table); |
240 | #endif | 241 | #endif |
241 | 242 | ||
242 | 243 | ||
243 | static int omap_control_usb_probe(struct platform_device *pdev) | 244 | static int omap_control_phy_probe(struct platform_device *pdev) |
244 | { | 245 | { |
245 | struct resource *res; | 246 | struct resource *res; |
246 | const struct of_device_id *of_id; | 247 | const struct of_device_id *of_id; |
247 | struct omap_control_usb *control_usb; | 248 | struct omap_control_phy *control_phy; |
248 | 249 | ||
249 | of_id = of_match_device(of_match_ptr(omap_control_usb_id_table), | 250 | of_id = of_match_device(of_match_ptr(omap_control_phy_id_table), |
250 | &pdev->dev); | 251 | &pdev->dev); |
251 | if (!of_id) | 252 | if (!of_id) |
252 | return -EINVAL; | 253 | return -EINVAL; |
253 | 254 | ||
254 | control_usb = devm_kzalloc(&pdev->dev, sizeof(*control_usb), | 255 | control_phy = devm_kzalloc(&pdev->dev, sizeof(*control_phy), |
255 | GFP_KERNEL); | 256 | GFP_KERNEL); |
256 | if (!control_usb) { | 257 | if (!control_phy) { |
257 | dev_err(&pdev->dev, "unable to alloc memory for control usb\n"); | 258 | dev_err(&pdev->dev, "unable to alloc memory for control phy\n"); |
258 | return -ENOMEM; | 259 | return -ENOMEM; |
259 | } | 260 | } |
260 | 261 | ||
261 | control_usb->dev = &pdev->dev; | 262 | control_phy->dev = &pdev->dev; |
262 | control_usb->type = *(enum omap_control_usb_type *)of_id->data; | 263 | control_phy->type = *(enum omap_control_phy_type *)of_id->data; |
263 | 264 | ||
264 | if (control_usb->type == OMAP_CTRL_TYPE_OTGHS) { | 265 | if (control_phy->type == OMAP_CTRL_TYPE_OTGHS) { |
265 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | 266 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
266 | "otghs_control"); | 267 | "otghs_control"); |
267 | control_usb->otghs_control = devm_ioremap_resource( | 268 | control_phy->otghs_control = devm_ioremap_resource( |
268 | &pdev->dev, res); | 269 | &pdev->dev, res); |
269 | if (IS_ERR(control_usb->otghs_control)) | 270 | if (IS_ERR(control_phy->otghs_control)) |
270 | return PTR_ERR(control_usb->otghs_control); | 271 | return PTR_ERR(control_phy->otghs_control); |
271 | } else { | 272 | } else { |
272 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | 273 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
273 | "power"); | 274 | "power"); |
274 | control_usb->power = devm_ioremap_resource(&pdev->dev, res); | 275 | control_phy->power = devm_ioremap_resource(&pdev->dev, res); |
275 | if (IS_ERR(control_usb->power)) { | 276 | if (IS_ERR(control_phy->power)) { |
276 | dev_err(&pdev->dev, "Couldn't get power register\n"); | 277 | dev_err(&pdev->dev, "Couldn't get power register\n"); |
277 | return PTR_ERR(control_usb->power); | 278 | return PTR_ERR(control_phy->power); |
278 | } | 279 | } |
279 | } | 280 | } |
280 | 281 | ||
281 | if (control_usb->type == OMAP_CTRL_TYPE_PIPE3) { | 282 | if (control_phy->type == OMAP_CTRL_TYPE_PIPE3) { |
282 | control_usb->sys_clk = devm_clk_get(control_usb->dev, | 283 | control_phy->sys_clk = devm_clk_get(control_phy->dev, |
283 | "sys_clkin"); | 284 | "sys_clkin"); |
284 | if (IS_ERR(control_usb->sys_clk)) { | 285 | if (IS_ERR(control_phy->sys_clk)) { |
285 | pr_err("%s: unable to get sys_clkin\n", __func__); | 286 | pr_err("%s: unable to get sys_clkin\n", __func__); |
286 | return -EINVAL; | 287 | return -EINVAL; |
287 | } | 288 | } |
288 | } | 289 | } |
289 | 290 | ||
290 | dev_set_drvdata(control_usb->dev, control_usb); | 291 | dev_set_drvdata(control_phy->dev, control_phy); |
291 | 292 | ||
292 | return 0; | 293 | return 0; |
293 | } | 294 | } |
294 | 295 | ||
295 | static struct platform_driver omap_control_usb_driver = { | 296 | static struct platform_driver omap_control_phy_driver = { |
296 | .probe = omap_control_usb_probe, | 297 | .probe = omap_control_phy_probe, |
297 | .driver = { | 298 | .driver = { |
298 | .name = "omap-control-usb", | 299 | .name = "omap-control-phy", |
299 | .owner = THIS_MODULE, | 300 | .owner = THIS_MODULE, |
300 | .of_match_table = of_match_ptr(omap_control_usb_id_table), | 301 | .of_match_table = of_match_ptr(omap_control_phy_id_table), |
301 | }, | 302 | }, |
302 | }; | 303 | }; |
303 | 304 | ||
304 | static int __init omap_control_usb_init(void) | 305 | static int __init omap_control_phy_init(void) |
305 | { | 306 | { |
306 | return platform_driver_register(&omap_control_usb_driver); | 307 | return platform_driver_register(&omap_control_phy_driver); |
307 | } | 308 | } |
308 | subsys_initcall(omap_control_usb_init); | 309 | subsys_initcall(omap_control_phy_init); |
309 | 310 | ||
310 | static void __exit omap_control_usb_exit(void) | 311 | static void __exit omap_control_phy_exit(void) |
311 | { | 312 | { |
312 | platform_driver_unregister(&omap_control_usb_driver); | 313 | platform_driver_unregister(&omap_control_phy_driver); |
313 | } | 314 | } |
314 | module_exit(omap_control_usb_exit); | 315 | module_exit(omap_control_phy_exit); |
315 | 316 | ||
316 | MODULE_ALIAS("platform: omap_control_usb"); | 317 | MODULE_ALIAS("platform: omap_control_phy"); |
317 | MODULE_AUTHOR("Texas Instruments Inc."); | 318 | MODULE_AUTHOR("Texas Instruments Inc."); |
318 | MODULE_DESCRIPTION("OMAP Control Module USB Driver"); | 319 | MODULE_DESCRIPTION("OMAP Control Module PHY Driver"); |
319 | MODULE_LICENSE("GPL v2"); | 320 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c index 7699752fba11..a2205a841e5e 100644 --- a/drivers/phy/phy-omap-usb2.c +++ b/drivers/phy/phy-omap-usb2.c | |||
@@ -21,16 +21,19 @@ | |||
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/of.h> | 22 | #include <linux/of.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/usb/omap_usb.h> | 24 | #include <linux/phy/omap_usb.h> |
25 | #include <linux/usb/phy_companion.h> | 25 | #include <linux/usb/phy_companion.h> |
26 | #include <linux/clk.h> | 26 | #include <linux/clk.h> |
27 | #include <linux/err.h> | 27 | #include <linux/err.h> |
28 | #include <linux/pm_runtime.h> | 28 | #include <linux/pm_runtime.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/usb/omap_control_usb.h> | 30 | #include <linux/phy/omap_control_phy.h> |
31 | #include <linux/phy/phy.h> | 31 | #include <linux/phy/phy.h> |
32 | #include <linux/of_platform.h> | 32 | #include <linux/of_platform.h> |
33 | 33 | ||
34 | #define USB2PHY_DISCON_BYP_LATCH (1 << 31) | ||
35 | #define USB2PHY_ANA_CONFIG1 0x4c | ||
36 | |||
34 | /** | 37 | /** |
35 | * omap_usb2_set_comparator - links the comparator present in the sytem with | 38 | * omap_usb2_set_comparator - links the comparator present in the sytem with |
36 | * this phy | 39 | * this phy |
@@ -98,65 +101,116 @@ static int omap_usb_set_peripheral(struct usb_otg *otg, | |||
98 | return 0; | 101 | return 0; |
99 | } | 102 | } |
100 | 103 | ||
101 | static int omap_usb2_suspend(struct usb_phy *x, int suspend) | 104 | static int omap_usb_power_off(struct phy *x) |
102 | { | 105 | { |
103 | struct omap_usb *phy = phy_to_omapusb(x); | 106 | struct omap_usb *phy = phy_get_drvdata(x); |
104 | int ret; | ||
105 | 107 | ||
106 | if (suspend && !phy->is_suspended) { | 108 | omap_control_phy_power(phy->control_dev, 0); |
107 | omap_control_usb_phy_power(phy->control_dev, 0); | ||
108 | pm_runtime_put_sync(phy->dev); | ||
109 | phy->is_suspended = 1; | ||
110 | } else if (!suspend && phy->is_suspended) { | ||
111 | ret = pm_runtime_get_sync(phy->dev); | ||
112 | if (ret < 0) { | ||
113 | dev_err(phy->dev, "get_sync failed with err %d\n", ret); | ||
114 | return ret; | ||
115 | } | ||
116 | omap_control_usb_phy_power(phy->control_dev, 1); | ||
117 | phy->is_suspended = 0; | ||
118 | } | ||
119 | 109 | ||
120 | return 0; | 110 | return 0; |
121 | } | 111 | } |
122 | 112 | ||
123 | static int omap_usb_power_off(struct phy *x) | 113 | static int omap_usb_power_on(struct phy *x) |
124 | { | 114 | { |
125 | struct omap_usb *phy = phy_get_drvdata(x); | 115 | struct omap_usb *phy = phy_get_drvdata(x); |
126 | 116 | ||
127 | omap_control_usb_phy_power(phy->control_dev, 0); | 117 | omap_control_phy_power(phy->control_dev, 1); |
128 | 118 | ||
129 | return 0; | 119 | return 0; |
130 | } | 120 | } |
131 | 121 | ||
132 | static int omap_usb_power_on(struct phy *x) | 122 | static int omap_usb_init(struct phy *x) |
133 | { | 123 | { |
134 | struct omap_usb *phy = phy_get_drvdata(x); | 124 | struct omap_usb *phy = phy_get_drvdata(x); |
135 | 125 | u32 val; | |
136 | omap_control_usb_phy_power(phy->control_dev, 1); | 126 | |
127 | if (phy->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) { | ||
128 | /* | ||
129 | * | ||
130 | * Reduce the sensitivity of internal PHY by enabling the | ||
131 | * DISCON_BYP_LATCH of the USB2PHY_ANA_CONFIG1 register. This | ||
132 | * resolves issues with certain devices which can otherwise | ||
133 | * be prone to false disconnects. | ||
134 | * | ||
135 | */ | ||
136 | val = omap_usb_readl(phy->phy_base, USB2PHY_ANA_CONFIG1); | ||
137 | val |= USB2PHY_DISCON_BYP_LATCH; | ||
138 | omap_usb_writel(phy->phy_base, USB2PHY_ANA_CONFIG1, val); | ||
139 | } | ||
137 | 140 | ||
138 | return 0; | 141 | return 0; |
139 | } | 142 | } |
140 | 143 | ||
141 | static struct phy_ops ops = { | 144 | static struct phy_ops ops = { |
145 | .init = omap_usb_init, | ||
142 | .power_on = omap_usb_power_on, | 146 | .power_on = omap_usb_power_on, |
143 | .power_off = omap_usb_power_off, | 147 | .power_off = omap_usb_power_off, |
144 | .owner = THIS_MODULE, | 148 | .owner = THIS_MODULE, |
145 | }; | 149 | }; |
146 | 150 | ||
151 | #ifdef CONFIG_OF | ||
152 | static const struct usb_phy_data omap_usb2_data = { | ||
153 | .label = "omap_usb2", | ||
154 | .flags = OMAP_USB2_HAS_START_SRP | OMAP_USB2_HAS_SET_VBUS, | ||
155 | }; | ||
156 | |||
157 | static const struct usb_phy_data omap5_usb2_data = { | ||
158 | .label = "omap5_usb2", | ||
159 | .flags = 0, | ||
160 | }; | ||
161 | |||
162 | static const struct usb_phy_data dra7x_usb2_data = { | ||
163 | .label = "dra7x_usb2", | ||
164 | .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT, | ||
165 | }; | ||
166 | |||
167 | static const struct usb_phy_data am437x_usb2_data = { | ||
168 | .label = "am437x_usb2", | ||
169 | .flags = 0, | ||
170 | }; | ||
171 | |||
172 | static const struct of_device_id omap_usb2_id_table[] = { | ||
173 | { | ||
174 | .compatible = "ti,omap-usb2", | ||
175 | .data = &omap_usb2_data, | ||
176 | }, | ||
177 | { | ||
178 | .compatible = "ti,omap5-usb2", | ||
179 | .data = &omap5_usb2_data, | ||
180 | }, | ||
181 | { | ||
182 | .compatible = "ti,dra7x-usb2", | ||
183 | .data = &dra7x_usb2_data, | ||
184 | }, | ||
185 | { | ||
186 | .compatible = "ti,am437x-usb2", | ||
187 | .data = &am437x_usb2_data, | ||
188 | }, | ||
189 | {}, | ||
190 | }; | ||
191 | MODULE_DEVICE_TABLE(of, omap_usb2_id_table); | ||
192 | #endif | ||
193 | |||
147 | static int omap_usb2_probe(struct platform_device *pdev) | 194 | static int omap_usb2_probe(struct platform_device *pdev) |
148 | { | 195 | { |
149 | struct omap_usb *phy; | 196 | struct omap_usb *phy; |
150 | struct phy *generic_phy; | 197 | struct phy *generic_phy; |
198 | struct resource *res; | ||
151 | struct phy_provider *phy_provider; | 199 | struct phy_provider *phy_provider; |
152 | struct usb_otg *otg; | 200 | struct usb_otg *otg; |
153 | struct device_node *node = pdev->dev.of_node; | 201 | struct device_node *node = pdev->dev.of_node; |
154 | struct device_node *control_node; | 202 | struct device_node *control_node; |
155 | struct platform_device *control_pdev; | 203 | struct platform_device *control_pdev; |
204 | const struct of_device_id *of_id; | ||
205 | struct usb_phy_data *phy_data; | ||
206 | |||
207 | of_id = of_match_device(of_match_ptr(omap_usb2_id_table), &pdev->dev); | ||
156 | 208 | ||
157 | if (!node) | 209 | if (!of_id) |
158 | return -EINVAL; | 210 | return -EINVAL; |
159 | 211 | ||
212 | phy_data = (struct usb_phy_data *)of_id->data; | ||
213 | |||
160 | phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); | 214 | phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); |
161 | if (!phy) { | 215 | if (!phy) { |
162 | dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n"); | 216 | dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n"); |
@@ -172,11 +226,18 @@ static int omap_usb2_probe(struct platform_device *pdev) | |||
172 | phy->dev = &pdev->dev; | 226 | phy->dev = &pdev->dev; |
173 | 227 | ||
174 | phy->phy.dev = phy->dev; | 228 | phy->phy.dev = phy->dev; |
175 | phy->phy.label = "omap-usb2"; | 229 | phy->phy.label = phy_data->label; |
176 | phy->phy.set_suspend = omap_usb2_suspend; | ||
177 | phy->phy.otg = otg; | 230 | phy->phy.otg = otg; |
178 | phy->phy.type = USB_PHY_TYPE_USB2; | 231 | phy->phy.type = USB_PHY_TYPE_USB2; |
179 | 232 | ||
233 | if (phy_data->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) { | ||
234 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
235 | phy->phy_base = devm_ioremap_resource(&pdev->dev, res); | ||
236 | if (!phy->phy_base) | ||
237 | return -ENOMEM; | ||
238 | phy->flags |= OMAP_USB2_CALIBRATE_FALSE_DISCONNECT; | ||
239 | } | ||
240 | |||
180 | control_node = of_parse_phandle(node, "ctrl-module", 0); | 241 | control_node = of_parse_phandle(node, "ctrl-module", 0); |
181 | if (!control_node) { | 242 | if (!control_node) { |
182 | dev_err(&pdev->dev, "Failed to get control device phandle\n"); | 243 | dev_err(&pdev->dev, "Failed to get control device phandle\n"); |
@@ -190,14 +251,14 @@ static int omap_usb2_probe(struct platform_device *pdev) | |||
190 | } | 251 | } |
191 | 252 | ||
192 | phy->control_dev = &control_pdev->dev; | 253 | phy->control_dev = &control_pdev->dev; |
193 | 254 | omap_control_phy_power(phy->control_dev, 0); | |
194 | phy->is_suspended = 1; | ||
195 | omap_control_usb_phy_power(phy->control_dev, 0); | ||
196 | 255 | ||
197 | otg->set_host = omap_usb_set_host; | 256 | otg->set_host = omap_usb_set_host; |
198 | otg->set_peripheral = omap_usb_set_peripheral; | 257 | otg->set_peripheral = omap_usb_set_peripheral; |
199 | otg->set_vbus = omap_usb_set_vbus; | 258 | if (phy_data->flags & OMAP_USB2_HAS_SET_VBUS) |
200 | otg->start_srp = omap_usb_start_srp; | 259 | otg->set_vbus = omap_usb_set_vbus; |
260 | if (phy_data->flags & OMAP_USB2_HAS_START_SRP) | ||
261 | otg->start_srp = omap_usb_start_srp; | ||
201 | otg->phy = &phy->phy; | 262 | otg->phy = &phy->phy; |
202 | 263 | ||
203 | platform_set_drvdata(pdev, phy); | 264 | platform_set_drvdata(pdev, phy); |
@@ -297,14 +358,6 @@ static const struct dev_pm_ops omap_usb2_pm_ops = { | |||
297 | #define DEV_PM_OPS NULL | 358 | #define DEV_PM_OPS NULL |
298 | #endif | 359 | #endif |
299 | 360 | ||
300 | #ifdef CONFIG_OF | ||
301 | static const struct of_device_id omap_usb2_id_table[] = { | ||
302 | { .compatible = "ti,omap-usb2" }, | ||
303 | {} | ||
304 | }; | ||
305 | MODULE_DEVICE_TABLE(of, omap_usb2_id_table); | ||
306 | #endif | ||
307 | |||
308 | static struct platform_driver omap_usb2_driver = { | 361 | static struct platform_driver omap_usb2_driver = { |
309 | .probe = omap_usb2_probe, | 362 | .probe = omap_usb2_probe, |
310 | .remove = omap_usb2_remove, | 363 | .remove = omap_usb2_remove, |
diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c new file mode 100644 index 000000000000..8a8c6bc8709a --- /dev/null +++ b/drivers/phy/phy-samsung-usb2.c | |||
@@ -0,0 +1,228 @@ | |||
1 | /* | ||
2 | * Samsung SoC USB 1.1/2.0 PHY driver | ||
3 | * | ||
4 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
5 | * Author: Kamil Debski <k.debski@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/mfd/syscon.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/of.h> | ||
16 | #include <linux/of_address.h> | ||
17 | #include <linux/phy/phy.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/spinlock.h> | ||
20 | #include "phy-samsung-usb2.h" | ||
21 | |||
22 | static int samsung_usb2_phy_power_on(struct phy *phy) | ||
23 | { | ||
24 | struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy); | ||
25 | struct samsung_usb2_phy_driver *drv = inst->drv; | ||
26 | int ret; | ||
27 | |||
28 | dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n", | ||
29 | inst->cfg->label); | ||
30 | ret = clk_prepare_enable(drv->clk); | ||
31 | if (ret) | ||
32 | goto err_main_clk; | ||
33 | ret = clk_prepare_enable(drv->ref_clk); | ||
34 | if (ret) | ||
35 | goto err_instance_clk; | ||
36 | if (inst->cfg->power_on) { | ||
37 | spin_lock(&drv->lock); | ||
38 | ret = inst->cfg->power_on(inst); | ||
39 | spin_unlock(&drv->lock); | ||
40 | } | ||
41 | |||
42 | return 0; | ||
43 | |||
44 | err_instance_clk: | ||
45 | clk_disable_unprepare(drv->clk); | ||
46 | err_main_clk: | ||
47 | return ret; | ||
48 | } | ||
49 | |||
50 | static int samsung_usb2_phy_power_off(struct phy *phy) | ||
51 | { | ||
52 | struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy); | ||
53 | struct samsung_usb2_phy_driver *drv = inst->drv; | ||
54 | int ret = 0; | ||
55 | |||
56 | dev_dbg(drv->dev, "Request to power_off \"%s\" usb phy\n", | ||
57 | inst->cfg->label); | ||
58 | if (inst->cfg->power_off) { | ||
59 | spin_lock(&drv->lock); | ||
60 | ret = inst->cfg->power_off(inst); | ||
61 | spin_unlock(&drv->lock); | ||
62 | } | ||
63 | clk_disable_unprepare(drv->ref_clk); | ||
64 | clk_disable_unprepare(drv->clk); | ||
65 | return ret; | ||
66 | } | ||
67 | |||
68 | static struct phy_ops samsung_usb2_phy_ops = { | ||
69 | .power_on = samsung_usb2_phy_power_on, | ||
70 | .power_off = samsung_usb2_phy_power_off, | ||
71 | .owner = THIS_MODULE, | ||
72 | }; | ||
73 | |||
74 | static struct phy *samsung_usb2_phy_xlate(struct device *dev, | ||
75 | struct of_phandle_args *args) | ||
76 | { | ||
77 | struct samsung_usb2_phy_driver *drv; | ||
78 | |||
79 | drv = dev_get_drvdata(dev); | ||
80 | if (!drv) | ||
81 | return ERR_PTR(-EINVAL); | ||
82 | |||
83 | if (WARN_ON(args->args[0] >= drv->cfg->num_phys)) | ||
84 | return ERR_PTR(-ENODEV); | ||
85 | |||
86 | return drv->instances[args->args[0]].phy; | ||
87 | } | ||
88 | |||
89 | static const struct of_device_id samsung_usb2_phy_of_match[] = { | ||
90 | #ifdef CONFIG_PHY_EXYNOS4210_USB2 | ||
91 | { | ||
92 | .compatible = "samsung,exynos4210-usb2-phy", | ||
93 | .data = &exynos4210_usb2_phy_config, | ||
94 | }, | ||
95 | #endif | ||
96 | #ifdef CONFIG_PHY_EXYNOS4X12_USB2 | ||
97 | { | ||
98 | .compatible = "samsung,exynos4x12-usb2-phy", | ||
99 | .data = &exynos4x12_usb2_phy_config, | ||
100 | }, | ||
101 | #endif | ||
102 | #ifdef CONFIG_PHY_EXYNOS5250_USB2 | ||
103 | { | ||
104 | .compatible = "samsung,exynos5250-usb2-phy", | ||
105 | .data = &exynos5250_usb2_phy_config, | ||
106 | }, | ||
107 | #endif | ||
108 | { }, | ||
109 | }; | ||
110 | |||
111 | static int samsung_usb2_phy_probe(struct platform_device *pdev) | ||
112 | { | ||
113 | const struct of_device_id *match; | ||
114 | const struct samsung_usb2_phy_config *cfg; | ||
115 | struct device *dev = &pdev->dev; | ||
116 | struct phy_provider *phy_provider; | ||
117 | struct resource *mem; | ||
118 | struct samsung_usb2_phy_driver *drv; | ||
119 | int i, ret; | ||
120 | |||
121 | if (!pdev->dev.of_node) { | ||
122 | dev_err(dev, "This driver is required to be instantiated from device tree\n"); | ||
123 | return -EINVAL; | ||
124 | } | ||
125 | |||
126 | match = of_match_node(samsung_usb2_phy_of_match, pdev->dev.of_node); | ||
127 | if (!match) { | ||
128 | dev_err(dev, "of_match_node() failed\n"); | ||
129 | return -EINVAL; | ||
130 | } | ||
131 | cfg = match->data; | ||
132 | |||
133 | drv = devm_kzalloc(dev, sizeof(struct samsung_usb2_phy_driver) + | ||
134 | cfg->num_phys * sizeof(struct samsung_usb2_phy_instance), | ||
135 | GFP_KERNEL); | ||
136 | if (!drv) | ||
137 | return -ENOMEM; | ||
138 | |||
139 | dev_set_drvdata(dev, drv); | ||
140 | spin_lock_init(&drv->lock); | ||
141 | |||
142 | drv->cfg = cfg; | ||
143 | drv->dev = dev; | ||
144 | |||
145 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
146 | drv->reg_phy = devm_ioremap_resource(dev, mem); | ||
147 | if (IS_ERR(drv->reg_phy)) { | ||
148 | dev_err(dev, "Failed to map register memory (phy)\n"); | ||
149 | return PTR_ERR(drv->reg_phy); | ||
150 | } | ||
151 | |||
152 | drv->reg_pmu = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, | ||
153 | "samsung,pmureg-phandle"); | ||
154 | if (IS_ERR(drv->reg_pmu)) { | ||
155 | dev_err(dev, "Failed to map PMU registers (via syscon)\n"); | ||
156 | return PTR_ERR(drv->reg_pmu); | ||
157 | } | ||
158 | |||
159 | if (drv->cfg->has_mode_switch) { | ||
160 | drv->reg_sys = syscon_regmap_lookup_by_phandle( | ||
161 | pdev->dev.of_node, "samsung,sysreg-phandle"); | ||
162 | if (IS_ERR(drv->reg_sys)) { | ||
163 | dev_err(dev, "Failed to map system registers (via syscon)\n"); | ||
164 | return PTR_ERR(drv->reg_sys); | ||
165 | } | ||
166 | } | ||
167 | |||
168 | drv->clk = devm_clk_get(dev, "phy"); | ||
169 | if (IS_ERR(drv->clk)) { | ||
170 | dev_err(dev, "Failed to get clock of phy controller\n"); | ||
171 | return PTR_ERR(drv->clk); | ||
172 | } | ||
173 | |||
174 | drv->ref_clk = devm_clk_get(dev, "ref"); | ||
175 | if (IS_ERR(drv->ref_clk)) { | ||
176 | dev_err(dev, "Failed to get reference clock for the phy controller\n"); | ||
177 | return PTR_ERR(drv->ref_clk); | ||
178 | } | ||
179 | |||
180 | drv->ref_rate = clk_get_rate(drv->ref_clk); | ||
181 | if (drv->cfg->rate_to_clk) { | ||
182 | ret = drv->cfg->rate_to_clk(drv->ref_rate, &drv->ref_reg_val); | ||
183 | if (ret) | ||
184 | return ret; | ||
185 | } | ||
186 | |||
187 | for (i = 0; i < drv->cfg->num_phys; i++) { | ||
188 | char *label = drv->cfg->phys[i].label; | ||
189 | struct samsung_usb2_phy_instance *p = &drv->instances[i]; | ||
190 | |||
191 | dev_dbg(dev, "Creating phy \"%s\"\n", label); | ||
192 | p->phy = devm_phy_create(dev, &samsung_usb2_phy_ops, NULL); | ||
193 | if (IS_ERR(p->phy)) { | ||
194 | dev_err(drv->dev, "Failed to create usb2_phy \"%s\"\n", | ||
195 | label); | ||
196 | return PTR_ERR(p->phy); | ||
197 | } | ||
198 | |||
199 | p->cfg = &drv->cfg->phys[i]; | ||
200 | p->drv = drv; | ||
201 | phy_set_bus_width(p->phy, 8); | ||
202 | phy_set_drvdata(p->phy, p); | ||
203 | } | ||
204 | |||
205 | phy_provider = devm_of_phy_provider_register(dev, | ||
206 | samsung_usb2_phy_xlate); | ||
207 | if (IS_ERR(phy_provider)) { | ||
208 | dev_err(drv->dev, "Failed to register phy provider\n"); | ||
209 | return PTR_ERR(phy_provider); | ||
210 | } | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static struct platform_driver samsung_usb2_phy_driver = { | ||
216 | .probe = samsung_usb2_phy_probe, | ||
217 | .driver = { | ||
218 | .of_match_table = samsung_usb2_phy_of_match, | ||
219 | .name = "samsung-usb2-phy", | ||
220 | .owner = THIS_MODULE, | ||
221 | } | ||
222 | }; | ||
223 | |||
224 | module_platform_driver(samsung_usb2_phy_driver); | ||
225 | MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC USB PHY driver"); | ||
226 | MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>"); | ||
227 | MODULE_LICENSE("GPL v2"); | ||
228 | MODULE_ALIAS("platform:samsung-usb2-phy"); | ||
diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/phy-samsung-usb2.h new file mode 100644 index 000000000000..45b3170652bd --- /dev/null +++ b/drivers/phy/phy-samsung-usb2.h | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * Samsung SoC USB 1.1/2.0 PHY driver | ||
3 | * | ||
4 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
5 | * Author: Kamil Debski <k.debski@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef _PHY_EXYNOS_USB2_H | ||
13 | #define _PHY_EXYNOS_USB2_H | ||
14 | |||
15 | #include <linux/clk.h> | ||
16 | #include <linux/phy/phy.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/regmap.h> | ||
19 | #include <linux/spinlock.h> | ||
20 | |||
21 | #define KHZ 1000 | ||
22 | #define MHZ (KHZ * KHZ) | ||
23 | |||
24 | struct samsung_usb2_phy_driver; | ||
25 | struct samsung_usb2_phy_instance; | ||
26 | struct samsung_usb2_phy_config; | ||
27 | |||
28 | struct samsung_usb2_phy_instance { | ||
29 | const struct samsung_usb2_common_phy *cfg; | ||
30 | struct phy *phy; | ||
31 | struct samsung_usb2_phy_driver *drv; | ||
32 | bool enabled; | ||
33 | }; | ||
34 | |||
35 | struct samsung_usb2_phy_driver { | ||
36 | const struct samsung_usb2_phy_config *cfg; | ||
37 | struct clk *clk; | ||
38 | struct clk *ref_clk; | ||
39 | unsigned long ref_rate; | ||
40 | u32 ref_reg_val; | ||
41 | struct device *dev; | ||
42 | void __iomem *reg_phy; | ||
43 | struct regmap *reg_pmu; | ||
44 | struct regmap *reg_sys; | ||
45 | spinlock_t lock; | ||
46 | struct samsung_usb2_phy_instance instances[0]; | ||
47 | }; | ||
48 | |||
49 | struct samsung_usb2_common_phy { | ||
50 | int (*power_on)(struct samsung_usb2_phy_instance *); | ||
51 | int (*power_off)(struct samsung_usb2_phy_instance *); | ||
52 | unsigned int id; | ||
53 | char *label; | ||
54 | }; | ||
55 | |||
56 | |||
57 | struct samsung_usb2_phy_config { | ||
58 | const struct samsung_usb2_common_phy *phys; | ||
59 | int (*rate_to_clk)(unsigned long, u32 *); | ||
60 | unsigned int num_phys; | ||
61 | bool has_mode_switch; | ||
62 | }; | ||
63 | |||
64 | extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config; | ||
65 | extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config; | ||
66 | extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config; | ||
67 | #endif | ||
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c new file mode 100644 index 000000000000..e6e6c4ba7145 --- /dev/null +++ b/drivers/phy/phy-sun4i-usb.c | |||
@@ -0,0 +1,331 @@ | |||
1 | /* | ||
2 | * Allwinner sun4i USB phy driver | ||
3 | * | ||
4 | * Copyright (C) 2014 Hans de Goede <hdegoede@redhat.com> | ||
5 | * | ||
6 | * Based on code from | ||
7 | * Allwinner Technology Co., Ltd. <www.allwinnertech.com> | ||
8 | * | ||
9 | * Modelled after: Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY driver | ||
10 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
11 | * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | */ | ||
23 | |||
24 | #include <linux/clk.h> | ||
25 | #include <linux/io.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/mutex.h> | ||
29 | #include <linux/of.h> | ||
30 | #include <linux/of_address.h> | ||
31 | #include <linux/phy/phy.h> | ||
32 | #include <linux/platform_device.h> | ||
33 | #include <linux/regulator/consumer.h> | ||
34 | #include <linux/reset.h> | ||
35 | |||
36 | #define REG_ISCR 0x00 | ||
37 | #define REG_PHYCTL 0x04 | ||
38 | #define REG_PHYBIST 0x08 | ||
39 | #define REG_PHYTUNE 0x0c | ||
40 | |||
41 | #define PHYCTL_DATA BIT(7) | ||
42 | |||
43 | #define SUNXI_AHB_ICHR8_EN BIT(10) | ||
44 | #define SUNXI_AHB_INCR4_BURST_EN BIT(9) | ||
45 | #define SUNXI_AHB_INCRX_ALIGN_EN BIT(8) | ||
46 | #define SUNXI_ULPI_BYPASS_EN BIT(0) | ||
47 | |||
48 | /* Common Control Bits for Both PHYs */ | ||
49 | #define PHY_PLL_BW 0x03 | ||
50 | #define PHY_RES45_CAL_EN 0x0c | ||
51 | |||
52 | /* Private Control Bits for Each PHY */ | ||
53 | #define PHY_TX_AMPLITUDE_TUNE 0x20 | ||
54 | #define PHY_TX_SLEWRATE_TUNE 0x22 | ||
55 | #define PHY_VBUSVALID_TH_SEL 0x25 | ||
56 | #define PHY_PULLUP_RES_SEL 0x27 | ||
57 | #define PHY_OTG_FUNC_EN 0x28 | ||
58 | #define PHY_VBUS_DET_EN 0x29 | ||
59 | #define PHY_DISCON_TH_SEL 0x2a | ||
60 | |||
61 | #define MAX_PHYS 3 | ||
62 | |||
63 | struct sun4i_usb_phy_data { | ||
64 | struct clk *clk; | ||
65 | void __iomem *base; | ||
66 | struct mutex mutex; | ||
67 | int num_phys; | ||
68 | u32 disc_thresh; | ||
69 | struct sun4i_usb_phy { | ||
70 | struct phy *phy; | ||
71 | void __iomem *pmu; | ||
72 | struct regulator *vbus; | ||
73 | struct reset_control *reset; | ||
74 | int index; | ||
75 | } phys[MAX_PHYS]; | ||
76 | }; | ||
77 | |||
78 | #define to_sun4i_usb_phy_data(phy) \ | ||
79 | container_of((phy), struct sun4i_usb_phy_data, phys[(phy)->index]) | ||
80 | |||
81 | static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data, | ||
82 | int len) | ||
83 | { | ||
84 | struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy); | ||
85 | u32 temp, usbc_bit = BIT(phy->index * 2); | ||
86 | int i; | ||
87 | |||
88 | mutex_lock(&phy_data->mutex); | ||
89 | |||
90 | for (i = 0; i < len; i++) { | ||
91 | temp = readl(phy_data->base + REG_PHYCTL); | ||
92 | |||
93 | /* clear the address portion */ | ||
94 | temp &= ~(0xff << 8); | ||
95 | |||
96 | /* set the address */ | ||
97 | temp |= ((addr + i) << 8); | ||
98 | writel(temp, phy_data->base + REG_PHYCTL); | ||
99 | |||
100 | /* set the data bit and clear usbc bit*/ | ||
101 | temp = readb(phy_data->base + REG_PHYCTL); | ||
102 | if (data & 0x1) | ||
103 | temp |= PHYCTL_DATA; | ||
104 | else | ||
105 | temp &= ~PHYCTL_DATA; | ||
106 | temp &= ~usbc_bit; | ||
107 | writeb(temp, phy_data->base + REG_PHYCTL); | ||
108 | |||
109 | /* pulse usbc_bit */ | ||
110 | temp = readb(phy_data->base + REG_PHYCTL); | ||
111 | temp |= usbc_bit; | ||
112 | writeb(temp, phy_data->base + REG_PHYCTL); | ||
113 | |||
114 | temp = readb(phy_data->base + REG_PHYCTL); | ||
115 | temp &= ~usbc_bit; | ||
116 | writeb(temp, phy_data->base + REG_PHYCTL); | ||
117 | |||
118 | data >>= 1; | ||
119 | } | ||
120 | mutex_unlock(&phy_data->mutex); | ||
121 | } | ||
122 | |||
123 | static void sun4i_usb_phy_passby(struct sun4i_usb_phy *phy, int enable) | ||
124 | { | ||
125 | u32 bits, reg_value; | ||
126 | |||
127 | if (!phy->pmu) | ||
128 | return; | ||
129 | |||
130 | bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN | | ||
131 | SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_EN; | ||
132 | |||
133 | reg_value = readl(phy->pmu); | ||
134 | |||
135 | if (enable) | ||
136 | reg_value |= bits; | ||
137 | else | ||
138 | reg_value &= ~bits; | ||
139 | |||
140 | writel(reg_value, phy->pmu); | ||
141 | } | ||
142 | |||
143 | static int sun4i_usb_phy_init(struct phy *_phy) | ||
144 | { | ||
145 | struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); | ||
146 | struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); | ||
147 | int ret; | ||
148 | |||
149 | ret = clk_prepare_enable(data->clk); | ||
150 | if (ret) | ||
151 | return ret; | ||
152 | |||
153 | ret = reset_control_deassert(phy->reset); | ||
154 | if (ret) { | ||
155 | clk_disable_unprepare(data->clk); | ||
156 | return ret; | ||
157 | } | ||
158 | |||
159 | /* Adjust PHY's magnitude and rate */ | ||
160 | sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5); | ||
161 | |||
162 | /* Disconnect threshold adjustment */ | ||
163 | sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, data->disc_thresh, 2); | ||
164 | |||
165 | sun4i_usb_phy_passby(phy, 1); | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | static int sun4i_usb_phy_exit(struct phy *_phy) | ||
171 | { | ||
172 | struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); | ||
173 | struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); | ||
174 | |||
175 | sun4i_usb_phy_passby(phy, 0); | ||
176 | reset_control_assert(phy->reset); | ||
177 | clk_disable_unprepare(data->clk); | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static int sun4i_usb_phy_power_on(struct phy *_phy) | ||
183 | { | ||
184 | struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); | ||
185 | int ret = 0; | ||
186 | |||
187 | if (phy->vbus) | ||
188 | ret = regulator_enable(phy->vbus); | ||
189 | |||
190 | return ret; | ||
191 | } | ||
192 | |||
193 | static int sun4i_usb_phy_power_off(struct phy *_phy) | ||
194 | { | ||
195 | struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); | ||
196 | |||
197 | if (phy->vbus) | ||
198 | regulator_disable(phy->vbus); | ||
199 | |||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | static struct phy_ops sun4i_usb_phy_ops = { | ||
204 | .init = sun4i_usb_phy_init, | ||
205 | .exit = sun4i_usb_phy_exit, | ||
206 | .power_on = sun4i_usb_phy_power_on, | ||
207 | .power_off = sun4i_usb_phy_power_off, | ||
208 | .owner = THIS_MODULE, | ||
209 | }; | ||
210 | |||
211 | static struct phy *sun4i_usb_phy_xlate(struct device *dev, | ||
212 | struct of_phandle_args *args) | ||
213 | { | ||
214 | struct sun4i_usb_phy_data *data = dev_get_drvdata(dev); | ||
215 | |||
216 | if (WARN_ON(args->args[0] == 0 || args->args[0] >= data->num_phys)) | ||
217 | return ERR_PTR(-ENODEV); | ||
218 | |||
219 | return data->phys[args->args[0]].phy; | ||
220 | } | ||
221 | |||
222 | static int sun4i_usb_phy_probe(struct platform_device *pdev) | ||
223 | { | ||
224 | struct sun4i_usb_phy_data *data; | ||
225 | struct device *dev = &pdev->dev; | ||
226 | struct device_node *np = dev->of_node; | ||
227 | void __iomem *pmu = NULL; | ||
228 | struct phy_provider *phy_provider; | ||
229 | struct reset_control *reset; | ||
230 | struct regulator *vbus; | ||
231 | struct resource *res; | ||
232 | struct phy *phy; | ||
233 | char name[16]; | ||
234 | int i; | ||
235 | |||
236 | data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); | ||
237 | if (!data) | ||
238 | return -ENOMEM; | ||
239 | |||
240 | mutex_init(&data->mutex); | ||
241 | |||
242 | if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy")) | ||
243 | data->num_phys = 2; | ||
244 | else | ||
245 | data->num_phys = 3; | ||
246 | |||
247 | if (of_device_is_compatible(np, "allwinner,sun4i-a10-usb-phy")) | ||
248 | data->disc_thresh = 3; | ||
249 | else | ||
250 | data->disc_thresh = 2; | ||
251 | |||
252 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl"); | ||
253 | data->base = devm_ioremap_resource(dev, res); | ||
254 | if (IS_ERR(data->base)) | ||
255 | return PTR_ERR(data->base); | ||
256 | |||
257 | data->clk = devm_clk_get(dev, "usb_phy"); | ||
258 | if (IS_ERR(data->clk)) { | ||
259 | dev_err(dev, "could not get usb_phy clock\n"); | ||
260 | return PTR_ERR(data->clk); | ||
261 | } | ||
262 | |||
263 | /* Skip 0, 0 is the phy for otg which is not yet supported. */ | ||
264 | for (i = 1; i < data->num_phys; i++) { | ||
265 | snprintf(name, sizeof(name), "usb%d_vbus", i); | ||
266 | vbus = devm_regulator_get_optional(dev, name); | ||
267 | if (IS_ERR(vbus)) { | ||
268 | if (PTR_ERR(vbus) == -EPROBE_DEFER) | ||
269 | return -EPROBE_DEFER; | ||
270 | vbus = NULL; | ||
271 | } | ||
272 | |||
273 | snprintf(name, sizeof(name), "usb%d_reset", i); | ||
274 | reset = devm_reset_control_get(dev, name); | ||
275 | if (IS_ERR(reset)) { | ||
276 | dev_err(dev, "failed to get reset %s\n", name); | ||
277 | return PTR_ERR(reset); | ||
278 | } | ||
279 | |||
280 | if (i) { /* No pmu for usbc0 */ | ||
281 | snprintf(name, sizeof(name), "pmu%d", i); | ||
282 | res = platform_get_resource_byname(pdev, | ||
283 | IORESOURCE_MEM, name); | ||
284 | pmu = devm_ioremap_resource(dev, res); | ||
285 | if (IS_ERR(pmu)) | ||
286 | return PTR_ERR(pmu); | ||
287 | } | ||
288 | |||
289 | phy = devm_phy_create(dev, &sun4i_usb_phy_ops, NULL); | ||
290 | if (IS_ERR(phy)) { | ||
291 | dev_err(dev, "failed to create PHY %d\n", i); | ||
292 | return PTR_ERR(phy); | ||
293 | } | ||
294 | |||
295 | data->phys[i].phy = phy; | ||
296 | data->phys[i].pmu = pmu; | ||
297 | data->phys[i].vbus = vbus; | ||
298 | data->phys[i].reset = reset; | ||
299 | data->phys[i].index = i; | ||
300 | phy_set_drvdata(phy, &data->phys[i]); | ||
301 | } | ||
302 | |||
303 | dev_set_drvdata(dev, data); | ||
304 | phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate); | ||
305 | if (IS_ERR(phy_provider)) | ||
306 | return PTR_ERR(phy_provider); | ||
307 | |||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | static const struct of_device_id sun4i_usb_phy_of_match[] = { | ||
312 | { .compatible = "allwinner,sun4i-a10-usb-phy" }, | ||
313 | { .compatible = "allwinner,sun5i-a13-usb-phy" }, | ||
314 | { .compatible = "allwinner,sun7i-a20-usb-phy" }, | ||
315 | { }, | ||
316 | }; | ||
317 | MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match); | ||
318 | |||
319 | static struct platform_driver sun4i_usb_phy_driver = { | ||
320 | .probe = sun4i_usb_phy_probe, | ||
321 | .driver = { | ||
322 | .of_match_table = sun4i_usb_phy_of_match, | ||
323 | .name = "sun4i-usb-phy", | ||
324 | .owner = THIS_MODULE, | ||
325 | } | ||
326 | }; | ||
327 | module_platform_driver(sun4i_usb_phy_driver); | ||
328 | |||
329 | MODULE_DESCRIPTION("Allwinner sun4i USB phy driver"); | ||
330 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); | ||
331 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c new file mode 100644 index 000000000000..591367654613 --- /dev/null +++ b/drivers/phy/phy-ti-pipe3.c | |||
@@ -0,0 +1,470 @@ | |||
1 | /* | ||
2 | * phy-ti-pipe3 - PIPE3 PHY driver. | ||
3 | * | ||
4 | * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * Author: Kishon Vijay Abraham I <kishon@ti.com> | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/phy/phy.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/clk.h> | ||
25 | #include <linux/err.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/pm_runtime.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/phy/omap_control_phy.h> | ||
30 | #include <linux/of_platform.h> | ||
31 | |||
32 | #define PLL_STATUS 0x00000004 | ||
33 | #define PLL_GO 0x00000008 | ||
34 | #define PLL_CONFIGURATION1 0x0000000C | ||
35 | #define PLL_CONFIGURATION2 0x00000010 | ||
36 | #define PLL_CONFIGURATION3 0x00000014 | ||
37 | #define PLL_CONFIGURATION4 0x00000020 | ||
38 | |||
39 | #define PLL_REGM_MASK 0x001FFE00 | ||
40 | #define PLL_REGM_SHIFT 0x9 | ||
41 | #define PLL_REGM_F_MASK 0x0003FFFF | ||
42 | #define PLL_REGM_F_SHIFT 0x0 | ||
43 | #define PLL_REGN_MASK 0x000001FE | ||
44 | #define PLL_REGN_SHIFT 0x1 | ||
45 | #define PLL_SELFREQDCO_MASK 0x0000000E | ||
46 | #define PLL_SELFREQDCO_SHIFT 0x1 | ||
47 | #define PLL_SD_MASK 0x0003FC00 | ||
48 | #define PLL_SD_SHIFT 10 | ||
49 | #define SET_PLL_GO 0x1 | ||
50 | #define PLL_LDOPWDN BIT(15) | ||
51 | #define PLL_TICOPWDN BIT(16) | ||
52 | #define PLL_LOCK 0x2 | ||
53 | #define PLL_IDLE 0x1 | ||
54 | |||
55 | /* | ||
56 | * This is an Empirical value that works, need to confirm the actual | ||
57 | * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status | ||
58 | * to be correctly reflected in the PIPE3PHY_PLL_STATUS register. | ||
59 | */ | ||
60 | #define PLL_IDLE_TIME 100 /* in milliseconds */ | ||
61 | #define PLL_LOCK_TIME 100 /* in milliseconds */ | ||
62 | |||
63 | struct pipe3_dpll_params { | ||
64 | u16 m; | ||
65 | u8 n; | ||
66 | u8 freq:3; | ||
67 | u8 sd; | ||
68 | u32 mf; | ||
69 | }; | ||
70 | |||
71 | struct pipe3_dpll_map { | ||
72 | unsigned long rate; | ||
73 | struct pipe3_dpll_params params; | ||
74 | }; | ||
75 | |||
76 | struct ti_pipe3 { | ||
77 | void __iomem *pll_ctrl_base; | ||
78 | struct device *dev; | ||
79 | struct device *control_dev; | ||
80 | struct clk *wkupclk; | ||
81 | struct clk *sys_clk; | ||
82 | struct clk *refclk; | ||
83 | struct pipe3_dpll_map *dpll_map; | ||
84 | }; | ||
85 | |||
86 | static struct pipe3_dpll_map dpll_map_usb[] = { | ||
87 | {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */ | ||
88 | {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */ | ||
89 | {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */ | ||
90 | {20000000, {1000, 7, 4, 10, 0} }, /* 20 MHz */ | ||
91 | {26000000, {1250, 12, 4, 20, 0} }, /* 26 MHz */ | ||
92 | {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */ | ||
93 | { }, /* Terminator */ | ||
94 | }; | ||
95 | |||
96 | static struct pipe3_dpll_map dpll_map_sata[] = { | ||
97 | {12000000, {1000, 7, 4, 6, 0} }, /* 12 MHz */ | ||
98 | {16800000, {714, 7, 4, 6, 0} }, /* 16.8 MHz */ | ||
99 | {19200000, {625, 7, 4, 6, 0} }, /* 19.2 MHz */ | ||
100 | {20000000, {600, 7, 4, 6, 0} }, /* 20 MHz */ | ||
101 | {26000000, {461, 7, 4, 6, 0} }, /* 26 MHz */ | ||
102 | {38400000, {312, 7, 4, 6, 0} }, /* 38.4 MHz */ | ||
103 | { }, /* Terminator */ | ||
104 | }; | ||
105 | |||
106 | static inline u32 ti_pipe3_readl(void __iomem *addr, unsigned offset) | ||
107 | { | ||
108 | return __raw_readl(addr + offset); | ||
109 | } | ||
110 | |||
111 | static inline void ti_pipe3_writel(void __iomem *addr, unsigned offset, | ||
112 | u32 data) | ||
113 | { | ||
114 | __raw_writel(data, addr + offset); | ||
115 | } | ||
116 | |||
117 | static struct pipe3_dpll_params *ti_pipe3_get_dpll_params(struct ti_pipe3 *phy) | ||
118 | { | ||
119 | unsigned long rate; | ||
120 | struct pipe3_dpll_map *dpll_map = phy->dpll_map; | ||
121 | |||
122 | rate = clk_get_rate(phy->sys_clk); | ||
123 | |||
124 | for (; dpll_map->rate; dpll_map++) { | ||
125 | if (rate == dpll_map->rate) | ||
126 | return &dpll_map->params; | ||
127 | } | ||
128 | |||
129 | dev_err(phy->dev, "No DPLL configuration for %lu Hz SYS CLK\n", rate); | ||
130 | |||
131 | return NULL; | ||
132 | } | ||
133 | |||
134 | static int ti_pipe3_power_off(struct phy *x) | ||
135 | { | ||
136 | struct ti_pipe3 *phy = phy_get_drvdata(x); | ||
137 | |||
138 | omap_control_phy_power(phy->control_dev, 0); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static int ti_pipe3_power_on(struct phy *x) | ||
144 | { | ||
145 | struct ti_pipe3 *phy = phy_get_drvdata(x); | ||
146 | |||
147 | omap_control_phy_power(phy->control_dev, 1); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int ti_pipe3_dpll_wait_lock(struct ti_pipe3 *phy) | ||
153 | { | ||
154 | u32 val; | ||
155 | unsigned long timeout; | ||
156 | |||
157 | timeout = jiffies + msecs_to_jiffies(PLL_LOCK_TIME); | ||
158 | do { | ||
159 | cpu_relax(); | ||
160 | val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS); | ||
161 | if (val & PLL_LOCK) | ||
162 | break; | ||
163 | } while (!time_after(jiffies, timeout)); | ||
164 | |||
165 | if (!(val & PLL_LOCK)) { | ||
166 | dev_err(phy->dev, "DPLL failed to lock\n"); | ||
167 | return -EBUSY; | ||
168 | } | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static int ti_pipe3_dpll_program(struct ti_pipe3 *phy) | ||
174 | { | ||
175 | u32 val; | ||
176 | struct pipe3_dpll_params *dpll_params; | ||
177 | |||
178 | dpll_params = ti_pipe3_get_dpll_params(phy); | ||
179 | if (!dpll_params) | ||
180 | return -EINVAL; | ||
181 | |||
182 | val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); | ||
183 | val &= ~PLL_REGN_MASK; | ||
184 | val |= dpll_params->n << PLL_REGN_SHIFT; | ||
185 | ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); | ||
186 | |||
187 | val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); | ||
188 | val &= ~PLL_SELFREQDCO_MASK; | ||
189 | val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT; | ||
190 | ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); | ||
191 | |||
192 | val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); | ||
193 | val &= ~PLL_REGM_MASK; | ||
194 | val |= dpll_params->m << PLL_REGM_SHIFT; | ||
195 | ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); | ||
196 | |||
197 | val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4); | ||
198 | val &= ~PLL_REGM_F_MASK; | ||
199 | val |= dpll_params->mf << PLL_REGM_F_SHIFT; | ||
200 | ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val); | ||
201 | |||
202 | val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3); | ||
203 | val &= ~PLL_SD_MASK; | ||
204 | val |= dpll_params->sd << PLL_SD_SHIFT; | ||
205 | ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val); | ||
206 | |||
207 | ti_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO); | ||
208 | |||
209 | return ti_pipe3_dpll_wait_lock(phy); | ||
210 | } | ||
211 | |||
212 | static int ti_pipe3_init(struct phy *x) | ||
213 | { | ||
214 | struct ti_pipe3 *phy = phy_get_drvdata(x); | ||
215 | u32 val; | ||
216 | int ret = 0; | ||
217 | |||
218 | /* Bring it out of IDLE if it is IDLE */ | ||
219 | val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); | ||
220 | if (val & PLL_IDLE) { | ||
221 | val &= ~PLL_IDLE; | ||
222 | ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); | ||
223 | ret = ti_pipe3_dpll_wait_lock(phy); | ||
224 | } | ||
225 | |||
226 | /* Program the DPLL only if not locked */ | ||
227 | val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS); | ||
228 | if (!(val & PLL_LOCK)) | ||
229 | if (ti_pipe3_dpll_program(phy)) | ||
230 | return -EINVAL; | ||
231 | |||
232 | return ret; | ||
233 | } | ||
234 | |||
235 | static int ti_pipe3_exit(struct phy *x) | ||
236 | { | ||
237 | struct ti_pipe3 *phy = phy_get_drvdata(x); | ||
238 | u32 val; | ||
239 | unsigned long timeout; | ||
240 | |||
241 | /* SATA DPLL can't be powered down due to Errata i783 */ | ||
242 | if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata")) | ||
243 | return 0; | ||
244 | |||
245 | /* Put DPLL in IDLE mode */ | ||
246 | val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); | ||
247 | val |= PLL_IDLE; | ||
248 | ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); | ||
249 | |||
250 | /* wait for LDO and Oscillator to power down */ | ||
251 | timeout = jiffies + msecs_to_jiffies(PLL_IDLE_TIME); | ||
252 | do { | ||
253 | cpu_relax(); | ||
254 | val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS); | ||
255 | if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN)) | ||
256 | break; | ||
257 | } while (!time_after(jiffies, timeout)); | ||
258 | |||
259 | if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) { | ||
260 | dev_err(phy->dev, "Failed to power down: PLL_STATUS 0x%x\n", | ||
261 | val); | ||
262 | return -EBUSY; | ||
263 | } | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | static struct phy_ops ops = { | ||
268 | .init = ti_pipe3_init, | ||
269 | .exit = ti_pipe3_exit, | ||
270 | .power_on = ti_pipe3_power_on, | ||
271 | .power_off = ti_pipe3_power_off, | ||
272 | .owner = THIS_MODULE, | ||
273 | }; | ||
274 | |||
275 | #ifdef CONFIG_OF | ||
276 | static const struct of_device_id ti_pipe3_id_table[]; | ||
277 | #endif | ||
278 | |||
279 | static int ti_pipe3_probe(struct platform_device *pdev) | ||
280 | { | ||
281 | struct ti_pipe3 *phy; | ||
282 | struct phy *generic_phy; | ||
283 | struct phy_provider *phy_provider; | ||
284 | struct resource *res; | ||
285 | struct device_node *node = pdev->dev.of_node; | ||
286 | struct device_node *control_node; | ||
287 | struct platform_device *control_pdev; | ||
288 | const struct of_device_id *match; | ||
289 | |||
290 | match = of_match_device(of_match_ptr(ti_pipe3_id_table), &pdev->dev); | ||
291 | if (!match) | ||
292 | return -EINVAL; | ||
293 | |||
294 | phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); | ||
295 | if (!phy) { | ||
296 | dev_err(&pdev->dev, "unable to alloc mem for TI PIPE3 PHY\n"); | ||
297 | return -ENOMEM; | ||
298 | } | ||
299 | |||
300 | phy->dpll_map = (struct pipe3_dpll_map *)match->data; | ||
301 | if (!phy->dpll_map) { | ||
302 | dev_err(&pdev->dev, "no DPLL data\n"); | ||
303 | return -EINVAL; | ||
304 | } | ||
305 | |||
306 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl"); | ||
307 | phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res); | ||
308 | if (IS_ERR(phy->pll_ctrl_base)) | ||
309 | return PTR_ERR(phy->pll_ctrl_base); | ||
310 | |||
311 | phy->dev = &pdev->dev; | ||
312 | |||
313 | if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) { | ||
314 | |||
315 | phy->wkupclk = devm_clk_get(phy->dev, "wkupclk"); | ||
316 | if (IS_ERR(phy->wkupclk)) { | ||
317 | dev_err(&pdev->dev, "unable to get wkupclk\n"); | ||
318 | return PTR_ERR(phy->wkupclk); | ||
319 | } | ||
320 | |||
321 | phy->refclk = devm_clk_get(phy->dev, "refclk"); | ||
322 | if (IS_ERR(phy->refclk)) { | ||
323 | dev_err(&pdev->dev, "unable to get refclk\n"); | ||
324 | return PTR_ERR(phy->refclk); | ||
325 | } | ||
326 | } else { | ||
327 | phy->wkupclk = ERR_PTR(-ENODEV); | ||
328 | phy->refclk = ERR_PTR(-ENODEV); | ||
329 | } | ||
330 | |||
331 | phy->sys_clk = devm_clk_get(phy->dev, "sysclk"); | ||
332 | if (IS_ERR(phy->sys_clk)) { | ||
333 | dev_err(&pdev->dev, "unable to get sysclk\n"); | ||
334 | return -EINVAL; | ||
335 | } | ||
336 | |||
337 | control_node = of_parse_phandle(node, "ctrl-module", 0); | ||
338 | if (!control_node) { | ||
339 | dev_err(&pdev->dev, "Failed to get control device phandle\n"); | ||
340 | return -EINVAL; | ||
341 | } | ||
342 | |||
343 | control_pdev = of_find_device_by_node(control_node); | ||
344 | if (!control_pdev) { | ||
345 | dev_err(&pdev->dev, "Failed to get control device\n"); | ||
346 | return -EINVAL; | ||
347 | } | ||
348 | |||
349 | phy->control_dev = &control_pdev->dev; | ||
350 | |||
351 | omap_control_phy_power(phy->control_dev, 0); | ||
352 | |||
353 | platform_set_drvdata(pdev, phy); | ||
354 | pm_runtime_enable(phy->dev); | ||
355 | |||
356 | generic_phy = devm_phy_create(phy->dev, &ops, NULL); | ||
357 | if (IS_ERR(generic_phy)) | ||
358 | return PTR_ERR(generic_phy); | ||
359 | |||
360 | phy_set_drvdata(generic_phy, phy); | ||
361 | phy_provider = devm_of_phy_provider_register(phy->dev, | ||
362 | of_phy_simple_xlate); | ||
363 | if (IS_ERR(phy_provider)) | ||
364 | return PTR_ERR(phy_provider); | ||
365 | |||
366 | pm_runtime_get(&pdev->dev); | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static int ti_pipe3_remove(struct platform_device *pdev) | ||
372 | { | ||
373 | if (!pm_runtime_suspended(&pdev->dev)) | ||
374 | pm_runtime_put(&pdev->dev); | ||
375 | pm_runtime_disable(&pdev->dev); | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | #ifdef CONFIG_PM_RUNTIME | ||
381 | |||
382 | static int ti_pipe3_runtime_suspend(struct device *dev) | ||
383 | { | ||
384 | struct ti_pipe3 *phy = dev_get_drvdata(dev); | ||
385 | |||
386 | if (!IS_ERR(phy->wkupclk)) | ||
387 | clk_disable_unprepare(phy->wkupclk); | ||
388 | if (!IS_ERR(phy->refclk)) | ||
389 | clk_disable_unprepare(phy->refclk); | ||
390 | |||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | static int ti_pipe3_runtime_resume(struct device *dev) | ||
395 | { | ||
396 | u32 ret = 0; | ||
397 | struct ti_pipe3 *phy = dev_get_drvdata(dev); | ||
398 | |||
399 | if (!IS_ERR(phy->refclk)) { | ||
400 | ret = clk_prepare_enable(phy->refclk); | ||
401 | if (ret) { | ||
402 | dev_err(phy->dev, "Failed to enable refclk %d\n", ret); | ||
403 | goto err1; | ||
404 | } | ||
405 | } | ||
406 | |||
407 | if (!IS_ERR(phy->wkupclk)) { | ||
408 | ret = clk_prepare_enable(phy->wkupclk); | ||
409 | if (ret) { | ||
410 | dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret); | ||
411 | goto err2; | ||
412 | } | ||
413 | } | ||
414 | |||
415 | return 0; | ||
416 | |||
417 | err2: | ||
418 | if (!IS_ERR(phy->refclk)) | ||
419 | clk_disable_unprepare(phy->refclk); | ||
420 | |||
421 | err1: | ||
422 | return ret; | ||
423 | } | ||
424 | |||
425 | static const struct dev_pm_ops ti_pipe3_pm_ops = { | ||
426 | SET_RUNTIME_PM_OPS(ti_pipe3_runtime_suspend, | ||
427 | ti_pipe3_runtime_resume, NULL) | ||
428 | }; | ||
429 | |||
430 | #define DEV_PM_OPS (&ti_pipe3_pm_ops) | ||
431 | #else | ||
432 | #define DEV_PM_OPS NULL | ||
433 | #endif | ||
434 | |||
435 | #ifdef CONFIG_OF | ||
436 | static const struct of_device_id ti_pipe3_id_table[] = { | ||
437 | { | ||
438 | .compatible = "ti,phy-usb3", | ||
439 | .data = dpll_map_usb, | ||
440 | }, | ||
441 | { | ||
442 | .compatible = "ti,omap-usb3", | ||
443 | .data = dpll_map_usb, | ||
444 | }, | ||
445 | { | ||
446 | .compatible = "ti,phy-pipe3-sata", | ||
447 | .data = dpll_map_sata, | ||
448 | }, | ||
449 | {} | ||
450 | }; | ||
451 | MODULE_DEVICE_TABLE(of, ti_pipe3_id_table); | ||
452 | #endif | ||
453 | |||
454 | static struct platform_driver ti_pipe3_driver = { | ||
455 | .probe = ti_pipe3_probe, | ||
456 | .remove = ti_pipe3_remove, | ||
457 | .driver = { | ||
458 | .name = "ti-pipe3", | ||
459 | .owner = THIS_MODULE, | ||
460 | .pm = DEV_PM_OPS, | ||
461 | .of_match_table = of_match_ptr(ti_pipe3_id_table), | ||
462 | }, | ||
463 | }; | ||
464 | |||
465 | module_platform_driver(ti_pipe3_driver); | ||
466 | |||
467 | MODULE_ALIAS("platform: ti_pipe3"); | ||
468 | MODULE_AUTHOR("Texas Instruments Inc."); | ||
469 | MODULE_DESCRIPTION("TI PIPE3 phy driver"); | ||
470 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c index c3ace1db8136..2e0e9b3774c8 100644 --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c | |||
@@ -338,7 +338,7 @@ static void twl4030_usb_set_mode(struct twl4030_usb *twl, int mode) | |||
338 | dev_err(twl->dev, "unsupported T2 transceiver mode %d\n", | 338 | dev_err(twl->dev, "unsupported T2 transceiver mode %d\n", |
339 | mode); | 339 | mode); |
340 | break; | 340 | break; |
341 | }; | 341 | } |
342 | } | 342 | } |
343 | 343 | ||
344 | static void twl4030_i2c_access(struct twl4030_usb *twl, int on) | 344 | static void twl4030_i2c_access(struct twl4030_usb *twl, int on) |
@@ -661,7 +661,7 @@ static int twl4030_usb_probe(struct platform_device *pdev) | |||
661 | struct phy_provider *phy_provider; | 661 | struct phy_provider *phy_provider; |
662 | struct phy_init_data *init_data = NULL; | 662 | struct phy_init_data *init_data = NULL; |
663 | 663 | ||
664 | twl = devm_kzalloc(&pdev->dev, sizeof *twl, GFP_KERNEL); | 664 | twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL); |
665 | if (!twl) | 665 | if (!twl) |
666 | return -ENOMEM; | 666 | return -ENOMEM; |
667 | 667 | ||
@@ -676,7 +676,7 @@ static int twl4030_usb_probe(struct platform_device *pdev) | |||
676 | return -EINVAL; | 676 | return -EINVAL; |
677 | } | 677 | } |
678 | 678 | ||
679 | otg = devm_kzalloc(&pdev->dev, sizeof *otg, GFP_KERNEL); | 679 | otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL); |
680 | if (!otg) | 680 | if (!otg) |
681 | return -ENOMEM; | 681 | return -ENOMEM; |
682 | 682 | ||
diff --git a/drivers/phy/phy-xgene.c b/drivers/phy/phy-xgene.c new file mode 100644 index 000000000000..4aa1ccd1511f --- /dev/null +++ b/drivers/phy/phy-xgene.c | |||
@@ -0,0 +1,1750 @@ | |||
1 | /* | ||
2 | * AppliedMicro X-Gene Multi-purpose PHY driver | ||
3 | * | ||
4 | * Copyright (c) 2014, Applied Micro Circuits Corporation | ||
5 | * Author: Loc Ho <lho@apm.com> | ||
6 | * Tuan Phan <tphan@apm.com> | ||
7 | * Suman Tripathi <stripathi@apm.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
21 | * | ||
22 | * The APM X-Gene PHY consists of two PLL clock macro's (CMU) and lanes. | ||
23 | * The first PLL clock macro is used for internal reference clock. The second | ||
24 | * PLL clock macro is used to generate the clock for the PHY. This driver | ||
25 | * configures the first PLL CMU, the second PLL CMU, and programs the PHY to | ||
26 | * operate according to the mode of operation. The first PLL CMU is only | ||
27 | * required if internal clock is enabled. | ||
28 | * | ||
29 | * Logical Layer Out Of HW module units: | ||
30 | * | ||
31 | * ----------------- | ||
32 | * | Internal | |------| | ||
33 | * | Ref PLL CMU |----| | ------------- --------- | ||
34 | * ------------ ---- | MUX |-----|PHY PLL CMU|----| Serdes| | ||
35 | * | | | | --------- | ||
36 | * External Clock ------| | ------------- | ||
37 | * |------| | ||
38 | * | ||
39 | * The Ref PLL CMU CSR (Configuration System Registers) is accessed | ||
40 | * indirectly from the SDS offset at 0x2000. It is only required for | ||
41 | * internal reference clock. | ||
42 | * The PHY PLL CMU CSR is accessed indirectly from the SDS offset at 0x0000. | ||
43 | * The Serdes CSR is accessed indirectly from the SDS offset at 0x0400. | ||
44 | * | ||
45 | * The Ref PLL CMU can be located within the same PHY IP or outside the PHY IP | ||
46 | * due to shared Ref PLL CMU. For PHY with Ref PLL CMU shared with another IP, | ||
47 | * it is located outside the PHY IP. This is the case for the PHY located | ||
48 | * at 0x1f23a000 (SATA Port 4/5). For such PHY, another resource is required | ||
49 | * to located the SDS/Ref PLL CMU module and its clock for that IP enabled. | ||
50 | * | ||
51 | * Currently, this driver only supports Gen3 SATA mode with external clock. | ||
52 | */ | ||
53 | #include <linux/module.h> | ||
54 | #include <linux/platform_device.h> | ||
55 | #include <linux/io.h> | ||
56 | #include <linux/delay.h> | ||
57 | #include <linux/phy/phy.h> | ||
58 | #include <linux/clk.h> | ||
59 | |||
60 | /* Max 2 lanes per a PHY unit */ | ||
61 | #define MAX_LANE 2 | ||
62 | |||
63 | /* Register offset inside the PHY */ | ||
64 | #define SERDES_PLL_INDIRECT_OFFSET 0x0000 | ||
65 | #define SERDES_PLL_REF_INDIRECT_OFFSET 0x2000 | ||
66 | #define SERDES_INDIRECT_OFFSET 0x0400 | ||
67 | #define SERDES_LANE_STRIDE 0x0200 | ||
68 | |||
69 | /* Some default Serdes parameters */ | ||
70 | #define DEFAULT_SATA_TXBOOST_GAIN { 0x1e, 0x1e, 0x1e } | ||
71 | #define DEFAULT_SATA_TXEYEDIRECTION { 0x0, 0x0, 0x0 } | ||
72 | #define DEFAULT_SATA_TXEYETUNING { 0xa, 0xa, 0xa } | ||
73 | #define DEFAULT_SATA_SPD_SEL { 0x1, 0x3, 0x7 } | ||
74 | #define DEFAULT_SATA_TXAMP { 0x8, 0x8, 0x8 } | ||
75 | #define DEFAULT_SATA_TXCN1 { 0x2, 0x2, 0x2 } | ||
76 | #define DEFAULT_SATA_TXCN2 { 0x0, 0x0, 0x0 } | ||
77 | #define DEFAULT_SATA_TXCP1 { 0xa, 0xa, 0xa } | ||
78 | |||
79 | #define SATA_SPD_SEL_GEN3 0x7 | ||
80 | #define SATA_SPD_SEL_GEN2 0x3 | ||
81 | #define SATA_SPD_SEL_GEN1 0x1 | ||
82 | |||
83 | #define SSC_DISABLE 0 | ||
84 | #define SSC_ENABLE 1 | ||
85 | |||
86 | #define FBDIV_VAL_50M 0x77 | ||
87 | #define REFDIV_VAL_50M 0x1 | ||
88 | #define FBDIV_VAL_100M 0x3B | ||
89 | #define REFDIV_VAL_100M 0x0 | ||
90 | |||
91 | /* SATA Clock/Reset CSR */ | ||
92 | #define SATACLKENREG 0x00000000 | ||
93 | #define SATA0_CORE_CLKEN 0x00000002 | ||
94 | #define SATA1_CORE_CLKEN 0x00000004 | ||
95 | #define SATASRESETREG 0x00000004 | ||
96 | #define SATA_MEM_RESET_MASK 0x00000020 | ||
97 | #define SATA_MEM_RESET_RD(src) (((src) & 0x00000020) >> 5) | ||
98 | #define SATA_SDS_RESET_MASK 0x00000004 | ||
99 | #define SATA_CSR_RESET_MASK 0x00000001 | ||
100 | #define SATA_CORE_RESET_MASK 0x00000002 | ||
101 | #define SATA_PMCLK_RESET_MASK 0x00000010 | ||
102 | #define SATA_PCLK_RESET_MASK 0x00000008 | ||
103 | |||
104 | /* SDS CSR used for PHY Indirect access */ | ||
105 | #define SATA_ENET_SDS_PCS_CTL0 0x00000000 | ||
106 | #define REGSPEC_CFG_I_TX_WORDMODE0_SET(dst, src) \ | ||
107 | (((dst) & ~0x00070000) | (((u32) (src) << 16) & 0x00070000)) | ||
108 | #define REGSPEC_CFG_I_RX_WORDMODE0_SET(dst, src) \ | ||
109 | (((dst) & ~0x00e00000) | (((u32) (src) << 21) & 0x00e00000)) | ||
110 | #define SATA_ENET_SDS_CTL0 0x0000000c | ||
111 | #define REGSPEC_CFG_I_CUSTOMER_PIN_MODE0_SET(dst, src) \ | ||
112 | (((dst) & ~0x00007fff) | (((u32) (src)) & 0x00007fff)) | ||
113 | #define SATA_ENET_SDS_CTL1 0x00000010 | ||
114 | #define CFG_I_SPD_SEL_CDR_OVR1_SET(dst, src) \ | ||
115 | (((dst) & ~0x0000000f) | (((u32) (src)) & 0x0000000f)) | ||
116 | #define SATA_ENET_SDS_RST_CTL 0x00000024 | ||
117 | #define SATA_ENET_SDS_IND_CMD_REG 0x0000003c | ||
118 | #define CFG_IND_WR_CMD_MASK 0x00000001 | ||
119 | #define CFG_IND_RD_CMD_MASK 0x00000002 | ||
120 | #define CFG_IND_CMD_DONE_MASK 0x00000004 | ||
121 | #define CFG_IND_ADDR_SET(dst, src) \ | ||
122 | (((dst) & ~0x003ffff0) | (((u32) (src) << 4) & 0x003ffff0)) | ||
123 | #define SATA_ENET_SDS_IND_RDATA_REG 0x00000040 | ||
124 | #define SATA_ENET_SDS_IND_WDATA_REG 0x00000044 | ||
125 | #define SATA_ENET_CLK_MACRO_REG 0x0000004c | ||
126 | #define I_RESET_B_SET(dst, src) \ | ||
127 | (((dst) & ~0x00000001) | (((u32) (src)) & 0x00000001)) | ||
128 | #define I_PLL_FBDIV_SET(dst, src) \ | ||
129 | (((dst) & ~0x001ff000) | (((u32) (src) << 12) & 0x001ff000)) | ||
130 | #define I_CUSTOMEROV_SET(dst, src) \ | ||
131 | (((dst) & ~0x00000f80) | (((u32) (src) << 7) & 0x00000f80)) | ||
132 | #define O_PLL_LOCK_RD(src) (((src) & 0x40000000) >> 30) | ||
133 | #define O_PLL_READY_RD(src) (((src) & 0x80000000) >> 31) | ||
134 | |||
135 | /* PLL Clock Macro Unit (CMU) CSR accessing from SDS indirectly */ | ||
136 | #define CMU_REG0 0x00000 | ||
137 | #define CMU_REG0_PLL_REF_SEL_MASK 0x00002000 | ||
138 | #define CMU_REG0_PLL_REF_SEL_SET(dst, src) \ | ||
139 | (((dst) & ~0x00002000) | (((u32) (src) << 13) & 0x00002000)) | ||
140 | #define CMU_REG0_PDOWN_MASK 0x00004000 | ||
141 | #define CMU_REG0_CAL_COUNT_RESOL_SET(dst, src) \ | ||
142 | (((dst) & ~0x000000e0) | (((u32) (src) << 5) & 0x000000e0)) | ||
143 | #define CMU_REG1 0x00002 | ||
144 | #define CMU_REG1_PLL_CP_SET(dst, src) \ | ||
145 | (((dst) & ~0x00003c00) | (((u32) (src) << 10) & 0x00003c00)) | ||
146 | #define CMU_REG1_PLL_MANUALCAL_SET(dst, src) \ | ||
147 | (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008)) | ||
148 | #define CMU_REG1_PLL_CP_SEL_SET(dst, src) \ | ||
149 | (((dst) & ~0x000003e0) | (((u32) (src) << 5) & 0x000003e0)) | ||
150 | #define CMU_REG1_REFCLK_CMOS_SEL_MASK 0x00000001 | ||
151 | #define CMU_REG1_REFCLK_CMOS_SEL_SET(dst, src) \ | ||
152 | (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001)) | ||
153 | #define CMU_REG2 0x00004 | ||
154 | #define CMU_REG2_PLL_REFDIV_SET(dst, src) \ | ||
155 | (((dst) & ~0x0000c000) | (((u32) (src) << 14) & 0x0000c000)) | ||
156 | #define CMU_REG2_PLL_LFRES_SET(dst, src) \ | ||
157 | (((dst) & ~0x0000001e) | (((u32) (src) << 1) & 0x0000001e)) | ||
158 | #define CMU_REG2_PLL_FBDIV_SET(dst, src) \ | ||
159 | (((dst) & ~0x00003fe0) | (((u32) (src) << 5) & 0x00003fe0)) | ||
160 | #define CMU_REG3 0x00006 | ||
161 | #define CMU_REG3_VCOVARSEL_SET(dst, src) \ | ||
162 | (((dst) & ~0x0000000f) | (((u32) (src) << 0) & 0x0000000f)) | ||
163 | #define CMU_REG3_VCO_MOMSEL_INIT_SET(dst, src) \ | ||
164 | (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0)) | ||
165 | #define CMU_REG3_VCO_MANMOMSEL_SET(dst, src) \ | ||
166 | (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00)) | ||
167 | #define CMU_REG4 0x00008 | ||
168 | #define CMU_REG5 0x0000a | ||
169 | #define CMU_REG5_PLL_LFSMCAP_SET(dst, src) \ | ||
170 | (((dst) & ~0x0000c000) | (((u32) (src) << 14) & 0x0000c000)) | ||
171 | #define CMU_REG5_PLL_LOCK_RESOLUTION_SET(dst, src) \ | ||
172 | (((dst) & ~0x0000000e) | (((u32) (src) << 1) & 0x0000000e)) | ||
173 | #define CMU_REG5_PLL_LFCAP_SET(dst, src) \ | ||
174 | (((dst) & ~0x00003000) | (((u32) (src) << 12) & 0x00003000)) | ||
175 | #define CMU_REG5_PLL_RESETB_MASK 0x00000001 | ||
176 | #define CMU_REG6 0x0000c | ||
177 | #define CMU_REG6_PLL_VREGTRIM_SET(dst, src) \ | ||
178 | (((dst) & ~0x00000600) | (((u32) (src) << 9) & 0x00000600)) | ||
179 | #define CMU_REG6_MAN_PVT_CAL_SET(dst, src) \ | ||
180 | (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004)) | ||
181 | #define CMU_REG7 0x0000e | ||
182 | #define CMU_REG7_PLL_CALIB_DONE_RD(src) ((0x00004000 & (u32) (src)) >> 14) | ||
183 | #define CMU_REG7_VCO_CAL_FAIL_RD(src) ((0x00000c00 & (u32) (src)) >> 10) | ||
184 | #define CMU_REG8 0x00010 | ||
185 | #define CMU_REG9 0x00012 | ||
186 | #define CMU_REG9_WORD_LEN_8BIT 0x000 | ||
187 | #define CMU_REG9_WORD_LEN_10BIT 0x001 | ||
188 | #define CMU_REG9_WORD_LEN_16BIT 0x002 | ||
189 | #define CMU_REG9_WORD_LEN_20BIT 0x003 | ||
190 | #define CMU_REG9_WORD_LEN_32BIT 0x004 | ||
191 | #define CMU_REG9_WORD_LEN_40BIT 0x005 | ||
192 | #define CMU_REG9_WORD_LEN_64BIT 0x006 | ||
193 | #define CMU_REG9_WORD_LEN_66BIT 0x007 | ||
194 | #define CMU_REG9_TX_WORD_MODE_CH1_SET(dst, src) \ | ||
195 | (((dst) & ~0x00000380) | (((u32) (src) << 7) & 0x00000380)) | ||
196 | #define CMU_REG9_TX_WORD_MODE_CH0_SET(dst, src) \ | ||
197 | (((dst) & ~0x00000070) | (((u32) (src) << 4) & 0x00000070)) | ||
198 | #define CMU_REG9_PLL_POST_DIVBY2_SET(dst, src) \ | ||
199 | (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008)) | ||
200 | #define CMU_REG9_VBG_BYPASSB_SET(dst, src) \ | ||
201 | (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004)) | ||
202 | #define CMU_REG9_IGEN_BYPASS_SET(dst, src) \ | ||
203 | (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002)) | ||
204 | #define CMU_REG10 0x00014 | ||
205 | #define CMU_REG10_VREG_REFSEL_SET(dst, src) \ | ||
206 | (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001)) | ||
207 | #define CMU_REG11 0x00016 | ||
208 | #define CMU_REG12 0x00018 | ||
209 | #define CMU_REG12_STATE_DELAY9_SET(dst, src) \ | ||
210 | (((dst) & ~0x000000f0) | (((u32) (src) << 4) & 0x000000f0)) | ||
211 | #define CMU_REG13 0x0001a | ||
212 | #define CMU_REG14 0x0001c | ||
213 | #define CMU_REG15 0x0001e | ||
214 | #define CMU_REG16 0x00020 | ||
215 | #define CMU_REG16_PVT_DN_MAN_ENA_MASK 0x00000001 | ||
216 | #define CMU_REG16_PVT_UP_MAN_ENA_MASK 0x00000002 | ||
217 | #define CMU_REG16_VCOCAL_WAIT_BTW_CODE_SET(dst, src) \ | ||
218 | (((dst) & ~0x0000001c) | (((u32) (src) << 2) & 0x0000001c)) | ||
219 | #define CMU_REG16_CALIBRATION_DONE_OVERRIDE_SET(dst, src) \ | ||
220 | (((dst) & ~0x00000040) | (((u32) (src) << 6) & 0x00000040)) | ||
221 | #define CMU_REG16_BYPASS_PLL_LOCK_SET(dst, src) \ | ||
222 | (((dst) & ~0x00000020) | (((u32) (src) << 5) & 0x00000020)) | ||
223 | #define CMU_REG17 0x00022 | ||
224 | #define CMU_REG17_PVT_CODE_R2A_SET(dst, src) \ | ||
225 | (((dst) & ~0x00007f00) | (((u32) (src) << 8) & 0x00007f00)) | ||
226 | #define CMU_REG17_RESERVED_7_SET(dst, src) \ | ||
227 | (((dst) & ~0x000000e0) | (((u32) (src) << 5) & 0x000000e0)) | ||
228 | #define CMU_REG17_PVT_TERM_MAN_ENA_MASK 0x00008000 | ||
229 | #define CMU_REG18 0x00024 | ||
230 | #define CMU_REG19 0x00026 | ||
231 | #define CMU_REG20 0x00028 | ||
232 | #define CMU_REG21 0x0002a | ||
233 | #define CMU_REG22 0x0002c | ||
234 | #define CMU_REG23 0x0002e | ||
235 | #define CMU_REG24 0x00030 | ||
236 | #define CMU_REG25 0x00032 | ||
237 | #define CMU_REG26 0x00034 | ||
238 | #define CMU_REG26_FORCE_PLL_LOCK_SET(dst, src) \ | ||
239 | (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001)) | ||
240 | #define CMU_REG27 0x00036 | ||
241 | #define CMU_REG28 0x00038 | ||
242 | #define CMU_REG29 0x0003a | ||
243 | #define CMU_REG30 0x0003c | ||
244 | #define CMU_REG30_LOCK_COUNT_SET(dst, src) \ | ||
245 | (((dst) & ~0x00000006) | (((u32) (src) << 1) & 0x00000006)) | ||
246 | #define CMU_REG30_PCIE_MODE_SET(dst, src) \ | ||
247 | (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008)) | ||
248 | #define CMU_REG31 0x0003e | ||
249 | #define CMU_REG32 0x00040 | ||
250 | #define CMU_REG32_FORCE_VCOCAL_START_MASK 0x00004000 | ||
251 | #define CMU_REG32_PVT_CAL_WAIT_SEL_SET(dst, src) \ | ||
252 | (((dst) & ~0x00000006) | (((u32) (src) << 1) & 0x00000006)) | ||
253 | #define CMU_REG32_IREF_ADJ_SET(dst, src) \ | ||
254 | (((dst) & ~0x00000180) | (((u32) (src) << 7) & 0x00000180)) | ||
255 | #define CMU_REG33 0x00042 | ||
256 | #define CMU_REG34 0x00044 | ||
257 | #define CMU_REG34_VCO_CAL_VTH_LO_MAX_SET(dst, src) \ | ||
258 | (((dst) & ~0x0000000f) | (((u32) (src) << 0) & 0x0000000f)) | ||
259 | #define CMU_REG34_VCO_CAL_VTH_HI_MAX_SET(dst, src) \ | ||
260 | (((dst) & ~0x00000f00) | (((u32) (src) << 8) & 0x00000f00)) | ||
261 | #define CMU_REG34_VCO_CAL_VTH_LO_MIN_SET(dst, src) \ | ||
262 | (((dst) & ~0x000000f0) | (((u32) (src) << 4) & 0x000000f0)) | ||
263 | #define CMU_REG34_VCO_CAL_VTH_HI_MIN_SET(dst, src) \ | ||
264 | (((dst) & ~0x0000f000) | (((u32) (src) << 12) & 0x0000f000)) | ||
265 | #define CMU_REG35 0x00046 | ||
266 | #define CMU_REG35_PLL_SSC_MOD_SET(dst, src) \ | ||
267 | (((dst) & ~0x0000fe00) | (((u32) (src) << 9) & 0x0000fe00)) | ||
268 | #define CMU_REG36 0x00048 | ||
269 | #define CMU_REG36_PLL_SSC_EN_SET(dst, src) \ | ||
270 | (((dst) & ~0x00000010) | (((u32) (src) << 4) & 0x00000010)) | ||
271 | #define CMU_REG36_PLL_SSC_VSTEP_SET(dst, src) \ | ||
272 | (((dst) & ~0x0000ffc0) | (((u32) (src) << 6) & 0x0000ffc0)) | ||
273 | #define CMU_REG36_PLL_SSC_DSMSEL_SET(dst, src) \ | ||
274 | (((dst) & ~0x00000020) | (((u32) (src) << 5) & 0x00000020)) | ||
275 | #define CMU_REG37 0x0004a | ||
276 | #define CMU_REG38 0x0004c | ||
277 | #define CMU_REG39 0x0004e | ||
278 | |||
279 | /* PHY lane CSR accessing from SDS indirectly */ | ||
280 | #define RXTX_REG0 0x000 | ||
281 | #define RXTX_REG0_CTLE_EQ_HR_SET(dst, src) \ | ||
282 | (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800)) | ||
283 | #define RXTX_REG0_CTLE_EQ_QR_SET(dst, src) \ | ||
284 | (((dst) & ~0x000007c0) | (((u32) (src) << 6) & 0x000007c0)) | ||
285 | #define RXTX_REG0_CTLE_EQ_FR_SET(dst, src) \ | ||
286 | (((dst) & ~0x0000003e) | (((u32) (src) << 1) & 0x0000003e)) | ||
287 | #define RXTX_REG1 0x002 | ||
288 | #define RXTX_REG1_RXACVCM_SET(dst, src) \ | ||
289 | (((dst) & ~0x0000f000) | (((u32) (src) << 12) & 0x0000f000)) | ||
290 | #define RXTX_REG1_CTLE_EQ_SET(dst, src) \ | ||
291 | (((dst) & ~0x00000f80) | (((u32) (src) << 7) & 0x00000f80)) | ||
292 | #define RXTX_REG1_RXVREG1_SET(dst, src) \ | ||
293 | (((dst) & ~0x00000060) | (((u32) (src) << 5) & 0x00000060)) | ||
294 | #define RXTX_REG1_RXIREF_ADJ_SET(dst, src) \ | ||
295 | (((dst) & ~0x00000006) | (((u32) (src) << 1) & 0x00000006)) | ||
296 | #define RXTX_REG2 0x004 | ||
297 | #define RXTX_REG2_VTT_ENA_SET(dst, src) \ | ||
298 | (((dst) & ~0x00000100) | (((u32) (src) << 8) & 0x00000100)) | ||
299 | #define RXTX_REG2_TX_FIFO_ENA_SET(dst, src) \ | ||
300 | (((dst) & ~0x00000020) | (((u32) (src) << 5) & 0x00000020)) | ||
301 | #define RXTX_REG2_VTT_SEL_SET(dst, src) \ | ||
302 | (((dst) & ~0x000000c0) | (((u32) (src) << 6) & 0x000000c0)) | ||
303 | #define RXTX_REG4 0x008 | ||
304 | #define RXTX_REG4_TX_LOOPBACK_BUF_EN_MASK 0x00000040 | ||
305 | #define RXTX_REG4_TX_DATA_RATE_SET(dst, src) \ | ||
306 | (((dst) & ~0x0000c000) | (((u32) (src) << 14) & 0x0000c000)) | ||
307 | #define RXTX_REG4_TX_WORD_MODE_SET(dst, src) \ | ||
308 | (((dst) & ~0x00003800) | (((u32) (src) << 11) & 0x00003800)) | ||
309 | #define RXTX_REG5 0x00a | ||
310 | #define RXTX_REG5_TX_CN1_SET(dst, src) \ | ||
311 | (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800)) | ||
312 | #define RXTX_REG5_TX_CP1_SET(dst, src) \ | ||
313 | (((dst) & ~0x000007e0) | (((u32) (src) << 5) & 0x000007e0)) | ||
314 | #define RXTX_REG5_TX_CN2_SET(dst, src) \ | ||
315 | (((dst) & ~0x0000001f) | (((u32) (src) << 0) & 0x0000001f)) | ||
316 | #define RXTX_REG6 0x00c | ||
317 | #define RXTX_REG6_TXAMP_CNTL_SET(dst, src) \ | ||
318 | (((dst) & ~0x00000780) | (((u32) (src) << 7) & 0x00000780)) | ||
319 | #define RXTX_REG6_TXAMP_ENA_SET(dst, src) \ | ||
320 | (((dst) & ~0x00000040) | (((u32) (src) << 6) & 0x00000040)) | ||
321 | #define RXTX_REG6_RX_BIST_ERRCNT_RD_SET(dst, src) \ | ||
322 | (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001)) | ||
323 | #define RXTX_REG6_TX_IDLE_SET(dst, src) \ | ||
324 | (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008)) | ||
325 | #define RXTX_REG6_RX_BIST_RESYNC_SET(dst, src) \ | ||
326 | (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002)) | ||
327 | #define RXTX_REG7 0x00e | ||
328 | #define RXTX_REG7_RESETB_RXD_MASK 0x00000100 | ||
329 | #define RXTX_REG7_RESETB_RXA_MASK 0x00000080 | ||
330 | #define RXTX_REG7_BIST_ENA_RX_SET(dst, src) \ | ||
331 | (((dst) & ~0x00000040) | (((u32) (src) << 6) & 0x00000040)) | ||
332 | #define RXTX_REG7_RX_WORD_MODE_SET(dst, src) \ | ||
333 | (((dst) & ~0x00003800) | (((u32) (src) << 11) & 0x00003800)) | ||
334 | #define RXTX_REG8 0x010 | ||
335 | #define RXTX_REG8_CDR_LOOP_ENA_SET(dst, src) \ | ||
336 | (((dst) & ~0x00004000) | (((u32) (src) << 14) & 0x00004000)) | ||
337 | #define RXTX_REG8_CDR_BYPASS_RXLOS_SET(dst, src) \ | ||
338 | (((dst) & ~0x00000800) | (((u32) (src) << 11) & 0x00000800)) | ||
339 | #define RXTX_REG8_SSC_ENABLE_SET(dst, src) \ | ||
340 | (((dst) & ~0x00000200) | (((u32) (src) << 9) & 0x00000200)) | ||
341 | #define RXTX_REG8_SD_VREF_SET(dst, src) \ | ||
342 | (((dst) & ~0x000000f0) | (((u32) (src) << 4) & 0x000000f0)) | ||
343 | #define RXTX_REG8_SD_DISABLE_SET(dst, src) \ | ||
344 | (((dst) & ~0x00000100) | (((u32) (src) << 8) & 0x00000100)) | ||
345 | #define RXTX_REG7 0x00e | ||
346 | #define RXTX_REG7_RESETB_RXD_SET(dst, src) \ | ||
347 | (((dst) & ~0x00000100) | (((u32) (src) << 8) & 0x00000100)) | ||
348 | #define RXTX_REG7_RESETB_RXA_SET(dst, src) \ | ||
349 | (((dst) & ~0x00000080) | (((u32) (src) << 7) & 0x00000080)) | ||
350 | #define RXTX_REG7_LOOP_BACK_ENA_CTLE_MASK 0x00004000 | ||
351 | #define RXTX_REG7_LOOP_BACK_ENA_CTLE_SET(dst, src) \ | ||
352 | (((dst) & ~0x00004000) | (((u32) (src) << 14) & 0x00004000)) | ||
353 | #define RXTX_REG11 0x016 | ||
354 | #define RXTX_REG11_PHASE_ADJUST_LIMIT_SET(dst, src) \ | ||
355 | (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800)) | ||
356 | #define RXTX_REG12 0x018 | ||
357 | #define RXTX_REG12_LATCH_OFF_ENA_SET(dst, src) \ | ||
358 | (((dst) & ~0x00002000) | (((u32) (src) << 13) & 0x00002000)) | ||
359 | #define RXTX_REG12_SUMOS_ENABLE_SET(dst, src) \ | ||
360 | (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004)) | ||
361 | #define RXTX_REG12_RX_DET_TERM_ENABLE_MASK 0x00000002 | ||
362 | #define RXTX_REG12_RX_DET_TERM_ENABLE_SET(dst, src) \ | ||
363 | (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002)) | ||
364 | #define RXTX_REG13 0x01a | ||
365 | #define RXTX_REG14 0x01c | ||
366 | #define RXTX_REG14_CLTE_LATCAL_MAN_PROG_SET(dst, src) \ | ||
367 | (((dst) & ~0x0000003f) | (((u32) (src) << 0) & 0x0000003f)) | ||
368 | #define RXTX_REG14_CTLE_LATCAL_MAN_ENA_SET(dst, src) \ | ||
369 | (((dst) & ~0x00000040) | (((u32) (src) << 6) & 0x00000040)) | ||
370 | #define RXTX_REG26 0x034 | ||
371 | #define RXTX_REG26_PERIOD_ERROR_LATCH_SET(dst, src) \ | ||
372 | (((dst) & ~0x00003800) | (((u32) (src) << 11) & 0x00003800)) | ||
373 | #define RXTX_REG26_BLWC_ENA_SET(dst, src) \ | ||
374 | (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008)) | ||
375 | #define RXTX_REG21 0x02a | ||
376 | #define RXTX_REG21_DO_LATCH_CALOUT_RD(src) ((0x0000fc00 & (u32) (src)) >> 10) | ||
377 | #define RXTX_REG21_XO_LATCH_CALOUT_RD(src) ((0x000003f0 & (u32) (src)) >> 4) | ||
378 | #define RXTX_REG21_LATCH_CAL_FAIL_ODD_RD(src) ((0x0000000f & (u32)(src))) | ||
379 | #define RXTX_REG22 0x02c | ||
380 | #define RXTX_REG22_SO_LATCH_CALOUT_RD(src) ((0x000003f0 & (u32) (src)) >> 4) | ||
381 | #define RXTX_REG22_EO_LATCH_CALOUT_RD(src) ((0x0000fc00 & (u32) (src)) >> 10) | ||
382 | #define RXTX_REG22_LATCH_CAL_FAIL_EVEN_RD(src) ((0x0000000f & (u32)(src))) | ||
383 | #define RXTX_REG23 0x02e | ||
384 | #define RXTX_REG23_DE_LATCH_CALOUT_RD(src) ((0x0000fc00 & (u32) (src)) >> 10) | ||
385 | #define RXTX_REG23_XE_LATCH_CALOUT_RD(src) ((0x000003f0 & (u32) (src)) >> 4) | ||
386 | #define RXTX_REG24 0x030 | ||
387 | #define RXTX_REG24_EE_LATCH_CALOUT_RD(src) ((0x0000fc00 & (u32) (src)) >> 10) | ||
388 | #define RXTX_REG24_SE_LATCH_CALOUT_RD(src) ((0x000003f0 & (u32) (src)) >> 4) | ||
389 | #define RXTX_REG27 0x036 | ||
390 | #define RXTX_REG28 0x038 | ||
391 | #define RXTX_REG31 0x03e | ||
392 | #define RXTX_REG38 0x04c | ||
393 | #define RXTX_REG38_CUSTOMER_PINMODE_INV_SET(dst, src) \ | ||
394 | (((dst) & 0x0000fffe) | (((u32) (src) << 1) & 0x0000fffe)) | ||
395 | #define RXTX_REG39 0x04e | ||
396 | #define RXTX_REG40 0x050 | ||
397 | #define RXTX_REG41 0x052 | ||
398 | #define RXTX_REG42 0x054 | ||
399 | #define RXTX_REG43 0x056 | ||
400 | #define RXTX_REG44 0x058 | ||
401 | #define RXTX_REG45 0x05a | ||
402 | #define RXTX_REG46 0x05c | ||
403 | #define RXTX_REG47 0x05e | ||
404 | #define RXTX_REG48 0x060 | ||
405 | #define RXTX_REG49 0x062 | ||
406 | #define RXTX_REG50 0x064 | ||
407 | #define RXTX_REG51 0x066 | ||
408 | #define RXTX_REG52 0x068 | ||
409 | #define RXTX_REG53 0x06a | ||
410 | #define RXTX_REG54 0x06c | ||
411 | #define RXTX_REG55 0x06e | ||
412 | #define RXTX_REG61 0x07a | ||
413 | #define RXTX_REG61_ISCAN_INBERT_SET(dst, src) \ | ||
414 | (((dst) & ~0x00000010) | (((u32) (src) << 4) & 0x00000010)) | ||
415 | #define RXTX_REG61_LOADFREQ_SHIFT_SET(dst, src) \ | ||
416 | (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008)) | ||
417 | #define RXTX_REG61_EYE_COUNT_WIDTH_SEL_SET(dst, src) \ | ||
418 | (((dst) & ~0x000000c0) | (((u32) (src) << 6) & 0x000000c0)) | ||
419 | #define RXTX_REG61_SPD_SEL_CDR_SET(dst, src) \ | ||
420 | (((dst) & ~0x00003c00) | (((u32) (src) << 10) & 0x00003c00)) | ||
421 | #define RXTX_REG62 0x07c | ||
422 | #define RXTX_REG62_PERIOD_H1_QLATCH_SET(dst, src) \ | ||
423 | (((dst) & ~0x00003800) | (((u32) (src) << 11) & 0x00003800)) | ||
424 | #define RXTX_REG81 0x0a2 | ||
425 | #define RXTX_REG89_MU_TH7_SET(dst, src) \ | ||
426 | (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800)) | ||
427 | #define RXTX_REG89_MU_TH8_SET(dst, src) \ | ||
428 | (((dst) & ~0x000007c0) | (((u32) (src) << 6) & 0x000007c0)) | ||
429 | #define RXTX_REG89_MU_TH9_SET(dst, src) \ | ||
430 | (((dst) & ~0x0000003e) | (((u32) (src) << 1) & 0x0000003e)) | ||
431 | #define RXTX_REG96 0x0c0 | ||
432 | #define RXTX_REG96_MU_FREQ1_SET(dst, src) \ | ||
433 | (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800)) | ||
434 | #define RXTX_REG96_MU_FREQ2_SET(dst, src) \ | ||
435 | (((dst) & ~0x000007c0) | (((u32) (src) << 6) & 0x000007c0)) | ||
436 | #define RXTX_REG96_MU_FREQ3_SET(dst, src) \ | ||
437 | (((dst) & ~0x0000003e) | (((u32) (src) << 1) & 0x0000003e)) | ||
438 | #define RXTX_REG99 0x0c6 | ||
439 | #define RXTX_REG99_MU_PHASE1_SET(dst, src) \ | ||
440 | (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800)) | ||
441 | #define RXTX_REG99_MU_PHASE2_SET(dst, src) \ | ||
442 | (((dst) & ~0x000007c0) | (((u32) (src) << 6) & 0x000007c0)) | ||
443 | #define RXTX_REG99_MU_PHASE3_SET(dst, src) \ | ||
444 | (((dst) & ~0x0000003e) | (((u32) (src) << 1) & 0x0000003e)) | ||
445 | #define RXTX_REG102 0x0cc | ||
446 | #define RXTX_REG102_FREQLOOP_LIMIT_SET(dst, src) \ | ||
447 | (((dst) & ~0x00000060) | (((u32) (src) << 5) & 0x00000060)) | ||
448 | #define RXTX_REG114 0x0e4 | ||
449 | #define RXTX_REG121 0x0f2 | ||
450 | #define RXTX_REG121_SUMOS_CAL_CODE_RD(src) ((0x0000003e & (u32)(src)) >> 0x1) | ||
451 | #define RXTX_REG125 0x0fa | ||
452 | #define RXTX_REG125_PQ_REG_SET(dst, src) \ | ||
453 | (((dst) & ~0x0000fe00) | (((u32) (src) << 9) & 0x0000fe00)) | ||
454 | #define RXTX_REG125_SIGN_PQ_SET(dst, src) \ | ||
455 | (((dst) & ~0x00000100) | (((u32) (src) << 8) & 0x00000100)) | ||
456 | #define RXTX_REG125_SIGN_PQ_2C_SET(dst, src) \ | ||
457 | (((dst) & ~0x00000080) | (((u32) (src) << 7) & 0x00000080)) | ||
458 | #define RXTX_REG125_PHZ_MANUALCODE_SET(dst, src) \ | ||
459 | (((dst) & ~0x0000007c) | (((u32) (src) << 2) & 0x0000007c)) | ||
460 | #define RXTX_REG125_PHZ_MANUAL_SET(dst, src) \ | ||
461 | (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002)) | ||
462 | #define RXTX_REG127 0x0fe | ||
463 | #define RXTX_REG127_FORCE_SUM_CAL_START_MASK 0x00000002 | ||
464 | #define RXTX_REG127_FORCE_LAT_CAL_START_MASK 0x00000004 | ||
465 | #define RXTX_REG127_FORCE_SUM_CAL_START_SET(dst, src) \ | ||
466 | (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002)) | ||
467 | #define RXTX_REG127_FORCE_LAT_CAL_START_SET(dst, src) \ | ||
468 | (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004)) | ||
469 | #define RXTX_REG127_LATCH_MAN_CAL_ENA_SET(dst, src) \ | ||
470 | (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008)) | ||
471 | #define RXTX_REG127_DO_LATCH_MANCAL_SET(dst, src) \ | ||
472 | (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00)) | ||
473 | #define RXTX_REG127_XO_LATCH_MANCAL_SET(dst, src) \ | ||
474 | (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0)) | ||
475 | #define RXTX_REG128 0x100 | ||
476 | #define RXTX_REG128_LATCH_CAL_WAIT_SEL_SET(dst, src) \ | ||
477 | (((dst) & ~0x0000000c) | (((u32) (src) << 2) & 0x0000000c)) | ||
478 | #define RXTX_REG128_EO_LATCH_MANCAL_SET(dst, src) \ | ||
479 | (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00)) | ||
480 | #define RXTX_REG128_SO_LATCH_MANCAL_SET(dst, src) \ | ||
481 | (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0)) | ||
482 | #define RXTX_REG129 0x102 | ||
483 | #define RXTX_REG129_DE_LATCH_MANCAL_SET(dst, src) \ | ||
484 | (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00)) | ||
485 | #define RXTX_REG129_XE_LATCH_MANCAL_SET(dst, src) \ | ||
486 | (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0)) | ||
487 | #define RXTX_REG130 0x104 | ||
488 | #define RXTX_REG130_EE_LATCH_MANCAL_SET(dst, src) \ | ||
489 | (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00)) | ||
490 | #define RXTX_REG130_SE_LATCH_MANCAL_SET(dst, src) \ | ||
491 | (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0)) | ||
492 | #define RXTX_REG145 0x122 | ||
493 | #define RXTX_REG145_TX_IDLE_SATA_SET(dst, src) \ | ||
494 | (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001)) | ||
495 | #define RXTX_REG145_RXES_ENA_SET(dst, src) \ | ||
496 | (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002)) | ||
497 | #define RXTX_REG145_RXDFE_CONFIG_SET(dst, src) \ | ||
498 | (((dst) & ~0x0000c000) | (((u32) (src) << 14) & 0x0000c000)) | ||
499 | #define RXTX_REG145_RXVWES_LATENA_SET(dst, src) \ | ||
500 | (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004)) | ||
501 | #define RXTX_REG147 0x126 | ||
502 | #define RXTX_REG148 0x128 | ||
503 | |||
504 | /* Clock macro type */ | ||
505 | enum cmu_type_t { | ||
506 | REF_CMU = 0, /* Clock macro is the internal reference clock */ | ||
507 | PHY_CMU = 1, /* Clock macro is the PLL for the Serdes */ | ||
508 | }; | ||
509 | |||
510 | enum mux_type_t { | ||
511 | MUX_SELECT_ATA = 0, /* Switch the MUX to ATA */ | ||
512 | MUX_SELECT_SGMMII = 0, /* Switch the MUX to SGMII */ | ||
513 | }; | ||
514 | |||
515 | enum clk_type_t { | ||
516 | CLK_EXT_DIFF = 0, /* External differential */ | ||
517 | CLK_INT_DIFF = 1, /* Internal differential */ | ||
518 | CLK_INT_SING = 2, /* Internal single ended */ | ||
519 | }; | ||
520 | |||
521 | enum phy_mode { | ||
522 | MODE_SATA = 0, /* List them for simple reference */ | ||
523 | MODE_SGMII = 1, | ||
524 | MODE_PCIE = 2, | ||
525 | MODE_USB = 3, | ||
526 | MODE_XFI = 4, | ||
527 | MODE_MAX | ||
528 | }; | ||
529 | |||
530 | struct xgene_sata_override_param { | ||
531 | u32 speed[MAX_LANE]; /* Index for override parameter per lane */ | ||
532 | u32 txspeed[3]; /* Tx speed */ | ||
533 | u32 txboostgain[MAX_LANE*3]; /* Tx freq boost and gain control */ | ||
534 | u32 txeyetuning[MAX_LANE*3]; /* Tx eye tuning */ | ||
535 | u32 txeyedirection[MAX_LANE*3]; /* Tx eye tuning direction */ | ||
536 | u32 txamplitude[MAX_LANE*3]; /* Tx amplitude control */ | ||
537 | u32 txprecursor_cn1[MAX_LANE*3]; /* Tx emphasis taps 1st pre-cursor */ | ||
538 | u32 txprecursor_cn2[MAX_LANE*3]; /* Tx emphasis taps 2nd pre-cursor */ | ||
539 | u32 txpostcursor_cp1[MAX_LANE*3]; /* Tx emphasis taps post-cursor */ | ||
540 | }; | ||
541 | |||
542 | struct xgene_phy_ctx { | ||
543 | struct device *dev; | ||
544 | struct phy *phy; | ||
545 | enum phy_mode mode; /* Mode of operation */ | ||
546 | enum clk_type_t clk_type; /* Input clock selection */ | ||
547 | void __iomem *sds_base; /* PHY CSR base addr */ | ||
548 | struct clk *clk; /* Optional clock */ | ||
549 | |||
550 | /* Override Serdes parameters */ | ||
551 | struct xgene_sata_override_param sata_param; | ||
552 | }; | ||
553 | |||
554 | /* | ||
555 | * For chip earlier than A3 version, enable this flag. | ||
556 | * To enable, pass boot argument phy_xgene.preA3Chip=1 | ||
557 | */ | ||
558 | static int preA3Chip; | ||
559 | MODULE_PARM_DESC(preA3Chip, "Enable pre-A3 chip support (1=enable 0=disable)"); | ||
560 | module_param_named(preA3Chip, preA3Chip, int, 0444); | ||
561 | |||
562 | static void sds_wr(void __iomem *csr_base, u32 indirect_cmd_reg, | ||
563 | u32 indirect_data_reg, u32 addr, u32 data) | ||
564 | { | ||
565 | unsigned long deadline = jiffies + HZ; | ||
566 | u32 val; | ||
567 | u32 cmd; | ||
568 | |||
569 | cmd = CFG_IND_WR_CMD_MASK | CFG_IND_CMD_DONE_MASK; | ||
570 | cmd = CFG_IND_ADDR_SET(cmd, addr); | ||
571 | writel(data, csr_base + indirect_data_reg); | ||
572 | readl(csr_base + indirect_data_reg); /* Force a barrier */ | ||
573 | writel(cmd, csr_base + indirect_cmd_reg); | ||
574 | readl(csr_base + indirect_cmd_reg); /* Force a barrier */ | ||
575 | do { | ||
576 | val = readl(csr_base + indirect_cmd_reg); | ||
577 | } while (!(val & CFG_IND_CMD_DONE_MASK) && | ||
578 | time_before(jiffies, deadline)); | ||
579 | if (!(val & CFG_IND_CMD_DONE_MASK)) | ||
580 | pr_err("SDS WR timeout at 0x%p offset 0x%08X value 0x%08X\n", | ||
581 | csr_base + indirect_cmd_reg, addr, data); | ||
582 | } | ||
583 | |||
584 | static void sds_rd(void __iomem *csr_base, u32 indirect_cmd_reg, | ||
585 | u32 indirect_data_reg, u32 addr, u32 *data) | ||
586 | { | ||
587 | unsigned long deadline = jiffies + HZ; | ||
588 | u32 val; | ||
589 | u32 cmd; | ||
590 | |||
591 | cmd = CFG_IND_RD_CMD_MASK | CFG_IND_CMD_DONE_MASK; | ||
592 | cmd = CFG_IND_ADDR_SET(cmd, addr); | ||
593 | writel(cmd, csr_base + indirect_cmd_reg); | ||
594 | readl(csr_base + indirect_cmd_reg); /* Force a barrier */ | ||
595 | do { | ||
596 | val = readl(csr_base + indirect_cmd_reg); | ||
597 | } while (!(val & CFG_IND_CMD_DONE_MASK) && | ||
598 | time_before(jiffies, deadline)); | ||
599 | *data = readl(csr_base + indirect_data_reg); | ||
600 | if (!(val & CFG_IND_CMD_DONE_MASK)) | ||
601 | pr_err("SDS WR timeout at 0x%p offset 0x%08X value 0x%08X\n", | ||
602 | csr_base + indirect_cmd_reg, addr, *data); | ||
603 | } | ||
604 | |||
605 | static void cmu_wr(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type, | ||
606 | u32 reg, u32 data) | ||
607 | { | ||
608 | void __iomem *sds_base = ctx->sds_base; | ||
609 | u32 val; | ||
610 | |||
611 | if (cmu_type == REF_CMU) | ||
612 | reg += SERDES_PLL_REF_INDIRECT_OFFSET; | ||
613 | else | ||
614 | reg += SERDES_PLL_INDIRECT_OFFSET; | ||
615 | sds_wr(sds_base, SATA_ENET_SDS_IND_CMD_REG, | ||
616 | SATA_ENET_SDS_IND_WDATA_REG, reg, data); | ||
617 | sds_rd(sds_base, SATA_ENET_SDS_IND_CMD_REG, | ||
618 | SATA_ENET_SDS_IND_RDATA_REG, reg, &val); | ||
619 | pr_debug("CMU WR addr 0x%X value 0x%08X <-> 0x%08X\n", reg, data, val); | ||
620 | } | ||
621 | |||
622 | static void cmu_rd(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type, | ||
623 | u32 reg, u32 *data) | ||
624 | { | ||
625 | void __iomem *sds_base = ctx->sds_base; | ||
626 | |||
627 | if (cmu_type == REF_CMU) | ||
628 | reg += SERDES_PLL_REF_INDIRECT_OFFSET; | ||
629 | else | ||
630 | reg += SERDES_PLL_INDIRECT_OFFSET; | ||
631 | sds_rd(sds_base, SATA_ENET_SDS_IND_CMD_REG, | ||
632 | SATA_ENET_SDS_IND_RDATA_REG, reg, data); | ||
633 | pr_debug("CMU RD addr 0x%X value 0x%08X\n", reg, *data); | ||
634 | } | ||
635 | |||
636 | static void cmu_toggle1to0(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type, | ||
637 | u32 reg, u32 bits) | ||
638 | { | ||
639 | u32 val; | ||
640 | |||
641 | cmu_rd(ctx, cmu_type, reg, &val); | ||
642 | val |= bits; | ||
643 | cmu_wr(ctx, cmu_type, reg, val); | ||
644 | cmu_rd(ctx, cmu_type, reg, &val); | ||
645 | val &= ~bits; | ||
646 | cmu_wr(ctx, cmu_type, reg, val); | ||
647 | } | ||
648 | |||
649 | static void cmu_clrbits(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type, | ||
650 | u32 reg, u32 bits) | ||
651 | { | ||
652 | u32 val; | ||
653 | |||
654 | cmu_rd(ctx, cmu_type, reg, &val); | ||
655 | val &= ~bits; | ||
656 | cmu_wr(ctx, cmu_type, reg, val); | ||
657 | } | ||
658 | |||
659 | static void cmu_setbits(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type, | ||
660 | u32 reg, u32 bits) | ||
661 | { | ||
662 | u32 val; | ||
663 | |||
664 | cmu_rd(ctx, cmu_type, reg, &val); | ||
665 | val |= bits; | ||
666 | cmu_wr(ctx, cmu_type, reg, val); | ||
667 | } | ||
668 | |||
669 | static void serdes_wr(struct xgene_phy_ctx *ctx, int lane, u32 reg, u32 data) | ||
670 | { | ||
671 | void __iomem *sds_base = ctx->sds_base; | ||
672 | u32 val; | ||
673 | |||
674 | reg += SERDES_INDIRECT_OFFSET; | ||
675 | reg += lane * SERDES_LANE_STRIDE; | ||
676 | sds_wr(sds_base, SATA_ENET_SDS_IND_CMD_REG, | ||
677 | SATA_ENET_SDS_IND_WDATA_REG, reg, data); | ||
678 | sds_rd(sds_base, SATA_ENET_SDS_IND_CMD_REG, | ||
679 | SATA_ENET_SDS_IND_RDATA_REG, reg, &val); | ||
680 | pr_debug("SERDES WR addr 0x%X value 0x%08X <-> 0x%08X\n", reg, data, | ||
681 | val); | ||
682 | } | ||
683 | |||
684 | static void serdes_rd(struct xgene_phy_ctx *ctx, int lane, u32 reg, u32 *data) | ||
685 | { | ||
686 | void __iomem *sds_base = ctx->sds_base; | ||
687 | |||
688 | reg += SERDES_INDIRECT_OFFSET; | ||
689 | reg += lane * SERDES_LANE_STRIDE; | ||
690 | sds_rd(sds_base, SATA_ENET_SDS_IND_CMD_REG, | ||
691 | SATA_ENET_SDS_IND_RDATA_REG, reg, data); | ||
692 | pr_debug("SERDES RD addr 0x%X value 0x%08X\n", reg, *data); | ||
693 | } | ||
694 | |||
695 | static void serdes_clrbits(struct xgene_phy_ctx *ctx, int lane, u32 reg, | ||
696 | u32 bits) | ||
697 | { | ||
698 | u32 val; | ||
699 | |||
700 | serdes_rd(ctx, lane, reg, &val); | ||
701 | val &= ~bits; | ||
702 | serdes_wr(ctx, lane, reg, val); | ||
703 | } | ||
704 | |||
705 | static void serdes_setbits(struct xgene_phy_ctx *ctx, int lane, u32 reg, | ||
706 | u32 bits) | ||
707 | { | ||
708 | u32 val; | ||
709 | |||
710 | serdes_rd(ctx, lane, reg, &val); | ||
711 | val |= bits; | ||
712 | serdes_wr(ctx, lane, reg, val); | ||
713 | } | ||
714 | |||
715 | static void xgene_phy_cfg_cmu_clk_type(struct xgene_phy_ctx *ctx, | ||
716 | enum cmu_type_t cmu_type, | ||
717 | enum clk_type_t clk_type) | ||
718 | { | ||
719 | u32 val; | ||
720 | |||
721 | /* Set the reset sequence delay for TX ready assertion */ | ||
722 | cmu_rd(ctx, cmu_type, CMU_REG12, &val); | ||
723 | val = CMU_REG12_STATE_DELAY9_SET(val, 0x1); | ||
724 | cmu_wr(ctx, cmu_type, CMU_REG12, val); | ||
725 | /* Set the programmable stage delays between various enable stages */ | ||
726 | cmu_wr(ctx, cmu_type, CMU_REG13, 0x0222); | ||
727 | cmu_wr(ctx, cmu_type, CMU_REG14, 0x2225); | ||
728 | |||
729 | /* Configure clock type */ | ||
730 | if (clk_type == CLK_EXT_DIFF) { | ||
731 | /* Select external clock mux */ | ||
732 | cmu_rd(ctx, cmu_type, CMU_REG0, &val); | ||
733 | val = CMU_REG0_PLL_REF_SEL_SET(val, 0x0); | ||
734 | cmu_wr(ctx, cmu_type, CMU_REG0, val); | ||
735 | /* Select CMOS as reference clock */ | ||
736 | cmu_rd(ctx, cmu_type, CMU_REG1, &val); | ||
737 | val = CMU_REG1_REFCLK_CMOS_SEL_SET(val, 0x0); | ||
738 | cmu_wr(ctx, cmu_type, CMU_REG1, val); | ||
739 | dev_dbg(ctx->dev, "Set external reference clock\n"); | ||
740 | } else if (clk_type == CLK_INT_DIFF) { | ||
741 | /* Select internal clock mux */ | ||
742 | cmu_rd(ctx, cmu_type, CMU_REG0, &val); | ||
743 | val = CMU_REG0_PLL_REF_SEL_SET(val, 0x1); | ||
744 | cmu_wr(ctx, cmu_type, CMU_REG0, val); | ||
745 | /* Select CMOS as reference clock */ | ||
746 | cmu_rd(ctx, cmu_type, CMU_REG1, &val); | ||
747 | val = CMU_REG1_REFCLK_CMOS_SEL_SET(val, 0x1); | ||
748 | cmu_wr(ctx, cmu_type, CMU_REG1, val); | ||
749 | dev_dbg(ctx->dev, "Set internal reference clock\n"); | ||
750 | } else if (clk_type == CLK_INT_SING) { | ||
751 | /* | ||
752 | * NOTE: This clock type is NOT support for controller | ||
753 | * whose internal clock shared in the PCIe controller | ||
754 | * | ||
755 | * Select internal clock mux | ||
756 | */ | ||
757 | cmu_rd(ctx, cmu_type, CMU_REG1, &val); | ||
758 | val = CMU_REG1_REFCLK_CMOS_SEL_SET(val, 0x1); | ||
759 | cmu_wr(ctx, cmu_type, CMU_REG1, val); | ||
760 | /* Select CML as reference clock */ | ||
761 | cmu_rd(ctx, cmu_type, CMU_REG1, &val); | ||
762 | val = CMU_REG1_REFCLK_CMOS_SEL_SET(val, 0x0); | ||
763 | cmu_wr(ctx, cmu_type, CMU_REG1, val); | ||
764 | dev_dbg(ctx->dev, | ||
765 | "Set internal single ended reference clock\n"); | ||
766 | } | ||
767 | } | ||
768 | |||
769 | static void xgene_phy_sata_cfg_cmu_core(struct xgene_phy_ctx *ctx, | ||
770 | enum cmu_type_t cmu_type, | ||
771 | enum clk_type_t clk_type) | ||
772 | { | ||
773 | u32 val; | ||
774 | int ref_100MHz; | ||
775 | |||
776 | if (cmu_type == REF_CMU) { | ||
777 | /* Set VCO calibration voltage threshold */ | ||
778 | cmu_rd(ctx, cmu_type, CMU_REG34, &val); | ||
779 | val = CMU_REG34_VCO_CAL_VTH_LO_MAX_SET(val, 0x7); | ||
780 | val = CMU_REG34_VCO_CAL_VTH_HI_MAX_SET(val, 0xc); | ||
781 | val = CMU_REG34_VCO_CAL_VTH_LO_MIN_SET(val, 0x3); | ||
782 | val = CMU_REG34_VCO_CAL_VTH_HI_MIN_SET(val, 0x8); | ||
783 | cmu_wr(ctx, cmu_type, CMU_REG34, val); | ||
784 | } | ||
785 | |||
786 | /* Set the VCO calibration counter */ | ||
787 | cmu_rd(ctx, cmu_type, CMU_REG0, &val); | ||
788 | if (cmu_type == REF_CMU || preA3Chip) | ||
789 | val = CMU_REG0_CAL_COUNT_RESOL_SET(val, 0x4); | ||
790 | else | ||
791 | val = CMU_REG0_CAL_COUNT_RESOL_SET(val, 0x7); | ||
792 | cmu_wr(ctx, cmu_type, CMU_REG0, val); | ||
793 | |||
794 | /* Configure PLL for calibration */ | ||
795 | cmu_rd(ctx, cmu_type, CMU_REG1, &val); | ||
796 | val = CMU_REG1_PLL_CP_SET(val, 0x1); | ||
797 | if (cmu_type == REF_CMU || preA3Chip) | ||
798 | val = CMU_REG1_PLL_CP_SEL_SET(val, 0x5); | ||
799 | else | ||
800 | val = CMU_REG1_PLL_CP_SEL_SET(val, 0x3); | ||
801 | if (cmu_type == REF_CMU) | ||
802 | val = CMU_REG1_PLL_MANUALCAL_SET(val, 0x0); | ||
803 | else | ||
804 | val = CMU_REG1_PLL_MANUALCAL_SET(val, 0x1); | ||
805 | cmu_wr(ctx, cmu_type, CMU_REG1, val); | ||
806 | |||
807 | if (cmu_type != REF_CMU) | ||
808 | cmu_clrbits(ctx, cmu_type, CMU_REG5, CMU_REG5_PLL_RESETB_MASK); | ||
809 | |||
810 | /* Configure the PLL for either 100MHz or 50MHz */ | ||
811 | cmu_rd(ctx, cmu_type, CMU_REG2, &val); | ||
812 | if (cmu_type == REF_CMU) { | ||
813 | val = CMU_REG2_PLL_LFRES_SET(val, 0xa); | ||
814 | ref_100MHz = 1; | ||
815 | } else { | ||
816 | val = CMU_REG2_PLL_LFRES_SET(val, 0x3); | ||
817 | if (clk_type == CLK_EXT_DIFF) | ||
818 | ref_100MHz = 0; | ||
819 | else | ||
820 | ref_100MHz = 1; | ||
821 | } | ||
822 | if (ref_100MHz) { | ||
823 | val = CMU_REG2_PLL_FBDIV_SET(val, FBDIV_VAL_100M); | ||
824 | val = CMU_REG2_PLL_REFDIV_SET(val, REFDIV_VAL_100M); | ||
825 | } else { | ||
826 | val = CMU_REG2_PLL_FBDIV_SET(val, FBDIV_VAL_50M); | ||
827 | val = CMU_REG2_PLL_REFDIV_SET(val, REFDIV_VAL_50M); | ||
828 | } | ||
829 | cmu_wr(ctx, cmu_type, CMU_REG2, val); | ||
830 | |||
831 | /* Configure the VCO */ | ||
832 | cmu_rd(ctx, cmu_type, CMU_REG3, &val); | ||
833 | if (cmu_type == REF_CMU) { | ||
834 | val = CMU_REG3_VCOVARSEL_SET(val, 0x3); | ||
835 | val = CMU_REG3_VCO_MOMSEL_INIT_SET(val, 0x10); | ||
836 | } else { | ||
837 | val = CMU_REG3_VCOVARSEL_SET(val, 0xF); | ||
838 | if (preA3Chip) | ||
839 | val = CMU_REG3_VCO_MOMSEL_INIT_SET(val, 0x15); | ||
840 | else | ||
841 | val = CMU_REG3_VCO_MOMSEL_INIT_SET(val, 0x1a); | ||
842 | val = CMU_REG3_VCO_MANMOMSEL_SET(val, 0x15); | ||
843 | } | ||
844 | cmu_wr(ctx, cmu_type, CMU_REG3, val); | ||
845 | |||
846 | /* Disable force PLL lock */ | ||
847 | cmu_rd(ctx, cmu_type, CMU_REG26, &val); | ||
848 | val = CMU_REG26_FORCE_PLL_LOCK_SET(val, 0x0); | ||
849 | cmu_wr(ctx, cmu_type, CMU_REG26, val); | ||
850 | |||
851 | /* Setup PLL loop filter */ | ||
852 | cmu_rd(ctx, cmu_type, CMU_REG5, &val); | ||
853 | val = CMU_REG5_PLL_LFSMCAP_SET(val, 0x3); | ||
854 | val = CMU_REG5_PLL_LFCAP_SET(val, 0x3); | ||
855 | if (cmu_type == REF_CMU || !preA3Chip) | ||
856 | val = CMU_REG5_PLL_LOCK_RESOLUTION_SET(val, 0x7); | ||
857 | else | ||
858 | val = CMU_REG5_PLL_LOCK_RESOLUTION_SET(val, 0x4); | ||
859 | cmu_wr(ctx, cmu_type, CMU_REG5, val); | ||
860 | |||
861 | /* Enable or disable manual calibration */ | ||
862 | cmu_rd(ctx, cmu_type, CMU_REG6, &val); | ||
863 | val = CMU_REG6_PLL_VREGTRIM_SET(val, preA3Chip ? 0x0 : 0x2); | ||
864 | val = CMU_REG6_MAN_PVT_CAL_SET(val, preA3Chip ? 0x1 : 0x0); | ||
865 | cmu_wr(ctx, cmu_type, CMU_REG6, val); | ||
866 | |||
867 | /* Configure lane for 20-bits */ | ||
868 | if (cmu_type == PHY_CMU) { | ||
869 | cmu_rd(ctx, cmu_type, CMU_REG9, &val); | ||
870 | val = CMU_REG9_TX_WORD_MODE_CH1_SET(val, | ||
871 | CMU_REG9_WORD_LEN_20BIT); | ||
872 | val = CMU_REG9_TX_WORD_MODE_CH0_SET(val, | ||
873 | CMU_REG9_WORD_LEN_20BIT); | ||
874 | val = CMU_REG9_PLL_POST_DIVBY2_SET(val, 0x1); | ||
875 | if (!preA3Chip) { | ||
876 | val = CMU_REG9_VBG_BYPASSB_SET(val, 0x0); | ||
877 | val = CMU_REG9_IGEN_BYPASS_SET(val , 0x0); | ||
878 | } | ||
879 | cmu_wr(ctx, cmu_type, CMU_REG9, val); | ||
880 | |||
881 | if (!preA3Chip) { | ||
882 | cmu_rd(ctx, cmu_type, CMU_REG10, &val); | ||
883 | val = CMU_REG10_VREG_REFSEL_SET(val, 0x1); | ||
884 | cmu_wr(ctx, cmu_type, CMU_REG10, val); | ||
885 | } | ||
886 | } | ||
887 | |||
888 | cmu_rd(ctx, cmu_type, CMU_REG16, &val); | ||
889 | val = CMU_REG16_CALIBRATION_DONE_OVERRIDE_SET(val, 0x1); | ||
890 | val = CMU_REG16_BYPASS_PLL_LOCK_SET(val, 0x1); | ||
891 | if (cmu_type == REF_CMU || preA3Chip) | ||
892 | val = CMU_REG16_VCOCAL_WAIT_BTW_CODE_SET(val, 0x4); | ||
893 | else | ||
894 | val = CMU_REG16_VCOCAL_WAIT_BTW_CODE_SET(val, 0x7); | ||
895 | cmu_wr(ctx, cmu_type, CMU_REG16, val); | ||
896 | |||
897 | /* Configure for SATA */ | ||
898 | cmu_rd(ctx, cmu_type, CMU_REG30, &val); | ||
899 | val = CMU_REG30_PCIE_MODE_SET(val, 0x0); | ||
900 | val = CMU_REG30_LOCK_COUNT_SET(val, 0x3); | ||
901 | cmu_wr(ctx, cmu_type, CMU_REG30, val); | ||
902 | |||
903 | /* Disable state machine bypass */ | ||
904 | cmu_wr(ctx, cmu_type, CMU_REG31, 0xF); | ||
905 | |||
906 | cmu_rd(ctx, cmu_type, CMU_REG32, &val); | ||
907 | val = CMU_REG32_PVT_CAL_WAIT_SEL_SET(val, 0x3); | ||
908 | if (cmu_type == REF_CMU || preA3Chip) | ||
909 | val = CMU_REG32_IREF_ADJ_SET(val, 0x3); | ||
910 | else | ||
911 | val = CMU_REG32_IREF_ADJ_SET(val, 0x1); | ||
912 | cmu_wr(ctx, cmu_type, CMU_REG32, val); | ||
913 | |||
914 | /* Set VCO calibration threshold */ | ||
915 | if (cmu_type != REF_CMU && preA3Chip) | ||
916 | cmu_wr(ctx, cmu_type, CMU_REG34, 0x8d27); | ||
917 | else | ||
918 | cmu_wr(ctx, cmu_type, CMU_REG34, 0x873c); | ||
919 | |||
920 | /* Set CTLE Override and override waiting from state machine */ | ||
921 | cmu_wr(ctx, cmu_type, CMU_REG37, 0xF00F); | ||
922 | } | ||
923 | |||
924 | static void xgene_phy_ssc_enable(struct xgene_phy_ctx *ctx, | ||
925 | enum cmu_type_t cmu_type) | ||
926 | { | ||
927 | u32 val; | ||
928 | |||
929 | /* Set SSC modulation value */ | ||
930 | cmu_rd(ctx, cmu_type, CMU_REG35, &val); | ||
931 | val = CMU_REG35_PLL_SSC_MOD_SET(val, 98); | ||
932 | cmu_wr(ctx, cmu_type, CMU_REG35, val); | ||
933 | |||
934 | /* Enable SSC, set vertical step and DSM value */ | ||
935 | cmu_rd(ctx, cmu_type, CMU_REG36, &val); | ||
936 | val = CMU_REG36_PLL_SSC_VSTEP_SET(val, 30); | ||
937 | val = CMU_REG36_PLL_SSC_EN_SET(val, 1); | ||
938 | val = CMU_REG36_PLL_SSC_DSMSEL_SET(val, 1); | ||
939 | cmu_wr(ctx, cmu_type, CMU_REG36, val); | ||
940 | |||
941 | /* Reset the PLL */ | ||
942 | cmu_clrbits(ctx, cmu_type, CMU_REG5, CMU_REG5_PLL_RESETB_MASK); | ||
943 | cmu_setbits(ctx, cmu_type, CMU_REG5, CMU_REG5_PLL_RESETB_MASK); | ||
944 | |||
945 | /* Force VCO calibration to restart */ | ||
946 | cmu_toggle1to0(ctx, cmu_type, CMU_REG32, | ||
947 | CMU_REG32_FORCE_VCOCAL_START_MASK); | ||
948 | } | ||
949 | |||
950 | static void xgene_phy_sata_cfg_lanes(struct xgene_phy_ctx *ctx) | ||
951 | { | ||
952 | u32 val; | ||
953 | u32 reg; | ||
954 | int i; | ||
955 | int lane; | ||
956 | |||
957 | for (lane = 0; lane < MAX_LANE; lane++) { | ||
958 | serdes_wr(ctx, lane, RXTX_REG147, 0x6); | ||
959 | |||
960 | /* Set boost control for quarter, half, and full rate */ | ||
961 | serdes_rd(ctx, lane, RXTX_REG0, &val); | ||
962 | val = RXTX_REG0_CTLE_EQ_HR_SET(val, 0x10); | ||
963 | val = RXTX_REG0_CTLE_EQ_QR_SET(val, 0x10); | ||
964 | val = RXTX_REG0_CTLE_EQ_FR_SET(val, 0x10); | ||
965 | serdes_wr(ctx, lane, RXTX_REG0, val); | ||
966 | |||
967 | /* Set boost control value */ | ||
968 | serdes_rd(ctx, lane, RXTX_REG1, &val); | ||
969 | val = RXTX_REG1_RXACVCM_SET(val, 0x7); | ||
970 | val = RXTX_REG1_CTLE_EQ_SET(val, | ||
971 | ctx->sata_param.txboostgain[lane * 3 + | ||
972 | ctx->sata_param.speed[lane]]); | ||
973 | serdes_wr(ctx, lane, RXTX_REG1, val); | ||
974 | |||
975 | /* Latch VTT value based on the termination to ground and | ||
976 | enable TX FIFO */ | ||
977 | serdes_rd(ctx, lane, RXTX_REG2, &val); | ||
978 | val = RXTX_REG2_VTT_ENA_SET(val, 0x1); | ||
979 | val = RXTX_REG2_VTT_SEL_SET(val, 0x1); | ||
980 | val = RXTX_REG2_TX_FIFO_ENA_SET(val, 0x1); | ||
981 | serdes_wr(ctx, lane, RXTX_REG2, val); | ||
982 | |||
983 | /* Configure Tx for 20-bits */ | ||
984 | serdes_rd(ctx, lane, RXTX_REG4, &val); | ||
985 | val = RXTX_REG4_TX_WORD_MODE_SET(val, CMU_REG9_WORD_LEN_20BIT); | ||
986 | serdes_wr(ctx, lane, RXTX_REG4, val); | ||
987 | |||
988 | if (!preA3Chip) { | ||
989 | serdes_rd(ctx, lane, RXTX_REG1, &val); | ||
990 | val = RXTX_REG1_RXVREG1_SET(val, 0x2); | ||
991 | val = RXTX_REG1_RXIREF_ADJ_SET(val, 0x2); | ||
992 | serdes_wr(ctx, lane, RXTX_REG1, val); | ||
993 | } | ||
994 | |||
995 | /* Set pre-emphasis first 1 and 2, and post-emphasis values */ | ||
996 | serdes_rd(ctx, lane, RXTX_REG5, &val); | ||
997 | val = RXTX_REG5_TX_CN1_SET(val, | ||
998 | ctx->sata_param.txprecursor_cn1[lane * 3 + | ||
999 | ctx->sata_param.speed[lane]]); | ||
1000 | val = RXTX_REG5_TX_CP1_SET(val, | ||
1001 | ctx->sata_param.txpostcursor_cp1[lane * 3 + | ||
1002 | ctx->sata_param.speed[lane]]); | ||
1003 | val = RXTX_REG5_TX_CN2_SET(val, | ||
1004 | ctx->sata_param.txprecursor_cn2[lane * 3 + | ||
1005 | ctx->sata_param.speed[lane]]); | ||
1006 | serdes_wr(ctx, lane, RXTX_REG5, val); | ||
1007 | |||
1008 | /* Set TX amplitude value */ | ||
1009 | serdes_rd(ctx, lane, RXTX_REG6, &val); | ||
1010 | val = RXTX_REG6_TXAMP_CNTL_SET(val, | ||
1011 | ctx->sata_param.txamplitude[lane * 3 + | ||
1012 | ctx->sata_param.speed[lane]]); | ||
1013 | val = RXTX_REG6_TXAMP_ENA_SET(val, 0x1); | ||
1014 | val = RXTX_REG6_TX_IDLE_SET(val, 0x0); | ||
1015 | val = RXTX_REG6_RX_BIST_RESYNC_SET(val, 0x0); | ||
1016 | val = RXTX_REG6_RX_BIST_ERRCNT_RD_SET(val, 0x0); | ||
1017 | serdes_wr(ctx, lane, RXTX_REG6, val); | ||
1018 | |||
1019 | /* Configure Rx for 20-bits */ | ||
1020 | serdes_rd(ctx, lane, RXTX_REG7, &val); | ||
1021 | val = RXTX_REG7_BIST_ENA_RX_SET(val, 0x0); | ||
1022 | val = RXTX_REG7_RX_WORD_MODE_SET(val, CMU_REG9_WORD_LEN_20BIT); | ||
1023 | serdes_wr(ctx, lane, RXTX_REG7, val); | ||
1024 | |||
1025 | /* Set CDR and LOS values and enable Rx SSC */ | ||
1026 | serdes_rd(ctx, lane, RXTX_REG8, &val); | ||
1027 | val = RXTX_REG8_CDR_LOOP_ENA_SET(val, 0x1); | ||
1028 | val = RXTX_REG8_CDR_BYPASS_RXLOS_SET(val, 0x0); | ||
1029 | val = RXTX_REG8_SSC_ENABLE_SET(val, 0x1); | ||
1030 | val = RXTX_REG8_SD_DISABLE_SET(val, 0x0); | ||
1031 | val = RXTX_REG8_SD_VREF_SET(val, 0x4); | ||
1032 | serdes_wr(ctx, lane, RXTX_REG8, val); | ||
1033 | |||
1034 | /* Set phase adjust upper/lower limits */ | ||
1035 | serdes_rd(ctx, lane, RXTX_REG11, &val); | ||
1036 | val = RXTX_REG11_PHASE_ADJUST_LIMIT_SET(val, 0x0); | ||
1037 | serdes_wr(ctx, lane, RXTX_REG11, val); | ||
1038 | |||
1039 | /* Enable Latch Off; disable SUMOS and Tx termination */ | ||
1040 | serdes_rd(ctx, lane, RXTX_REG12, &val); | ||
1041 | val = RXTX_REG12_LATCH_OFF_ENA_SET(val, 0x1); | ||
1042 | val = RXTX_REG12_SUMOS_ENABLE_SET(val, 0x0); | ||
1043 | val = RXTX_REG12_RX_DET_TERM_ENABLE_SET(val, 0x0); | ||
1044 | serdes_wr(ctx, lane, RXTX_REG12, val); | ||
1045 | |||
1046 | /* Set period error latch to 512T and enable BWL */ | ||
1047 | serdes_rd(ctx, lane, RXTX_REG26, &val); | ||
1048 | val = RXTX_REG26_PERIOD_ERROR_LATCH_SET(val, 0x0); | ||
1049 | val = RXTX_REG26_BLWC_ENA_SET(val, 0x1); | ||
1050 | serdes_wr(ctx, lane, RXTX_REG26, val); | ||
1051 | |||
1052 | serdes_wr(ctx, lane, RXTX_REG28, 0x0); | ||
1053 | |||
1054 | /* Set DFE loop preset value */ | ||
1055 | serdes_wr(ctx, lane, RXTX_REG31, 0x0); | ||
1056 | |||
1057 | /* Set Eye Monitor counter width to 12-bit */ | ||
1058 | serdes_rd(ctx, lane, RXTX_REG61, &val); | ||
1059 | val = RXTX_REG61_ISCAN_INBERT_SET(val, 0x1); | ||
1060 | val = RXTX_REG61_LOADFREQ_SHIFT_SET(val, 0x0); | ||
1061 | val = RXTX_REG61_EYE_COUNT_WIDTH_SEL_SET(val, 0x0); | ||
1062 | serdes_wr(ctx, lane, RXTX_REG61, val); | ||
1063 | |||
1064 | serdes_rd(ctx, lane, RXTX_REG62, &val); | ||
1065 | val = RXTX_REG62_PERIOD_H1_QLATCH_SET(val, 0x0); | ||
1066 | serdes_wr(ctx, lane, RXTX_REG62, val); | ||
1067 | |||
1068 | /* Set BW select tap X for DFE loop */ | ||
1069 | for (i = 0; i < 9; i++) { | ||
1070 | reg = RXTX_REG81 + i * 2; | ||
1071 | serdes_rd(ctx, lane, reg, &val); | ||
1072 | val = RXTX_REG89_MU_TH7_SET(val, 0xe); | ||
1073 | val = RXTX_REG89_MU_TH8_SET(val, 0xe); | ||
1074 | val = RXTX_REG89_MU_TH9_SET(val, 0xe); | ||
1075 | serdes_wr(ctx, lane, reg, val); | ||
1076 | } | ||
1077 | |||
1078 | /* Set BW select tap X for frequency adjust loop */ | ||
1079 | for (i = 0; i < 3; i++) { | ||
1080 | reg = RXTX_REG96 + i * 2; | ||
1081 | serdes_rd(ctx, lane, reg, &val); | ||
1082 | val = RXTX_REG96_MU_FREQ1_SET(val, 0x10); | ||
1083 | val = RXTX_REG96_MU_FREQ2_SET(val, 0x10); | ||
1084 | val = RXTX_REG96_MU_FREQ3_SET(val, 0x10); | ||
1085 | serdes_wr(ctx, lane, reg, val); | ||
1086 | } | ||
1087 | |||
1088 | /* Set BW select tap X for phase adjust loop */ | ||
1089 | for (i = 0; i < 3; i++) { | ||
1090 | reg = RXTX_REG99 + i * 2; | ||
1091 | serdes_rd(ctx, lane, reg, &val); | ||
1092 | val = RXTX_REG99_MU_PHASE1_SET(val, 0x7); | ||
1093 | val = RXTX_REG99_MU_PHASE2_SET(val, 0x7); | ||
1094 | val = RXTX_REG99_MU_PHASE3_SET(val, 0x7); | ||
1095 | serdes_wr(ctx, lane, reg, val); | ||
1096 | } | ||
1097 | |||
1098 | serdes_rd(ctx, lane, RXTX_REG102, &val); | ||
1099 | val = RXTX_REG102_FREQLOOP_LIMIT_SET(val, 0x0); | ||
1100 | serdes_wr(ctx, lane, RXTX_REG102, val); | ||
1101 | |||
1102 | serdes_wr(ctx, lane, RXTX_REG114, 0xffe0); | ||
1103 | |||
1104 | serdes_rd(ctx, lane, RXTX_REG125, &val); | ||
1105 | val = RXTX_REG125_SIGN_PQ_SET(val, | ||
1106 | ctx->sata_param.txeyedirection[lane * 3 + | ||
1107 | ctx->sata_param.speed[lane]]); | ||
1108 | val = RXTX_REG125_PQ_REG_SET(val, | ||
1109 | ctx->sata_param.txeyetuning[lane * 3 + | ||
1110 | ctx->sata_param.speed[lane]]); | ||
1111 | val = RXTX_REG125_PHZ_MANUAL_SET(val, 0x1); | ||
1112 | serdes_wr(ctx, lane, RXTX_REG125, val); | ||
1113 | |||
1114 | serdes_rd(ctx, lane, RXTX_REG127, &val); | ||
1115 | val = RXTX_REG127_LATCH_MAN_CAL_ENA_SET(val, 0x0); | ||
1116 | serdes_wr(ctx, lane, RXTX_REG127, val); | ||
1117 | |||
1118 | serdes_rd(ctx, lane, RXTX_REG128, &val); | ||
1119 | val = RXTX_REG128_LATCH_CAL_WAIT_SEL_SET(val, 0x3); | ||
1120 | serdes_wr(ctx, lane, RXTX_REG128, val); | ||
1121 | |||
1122 | serdes_rd(ctx, lane, RXTX_REG145, &val); | ||
1123 | val = RXTX_REG145_RXDFE_CONFIG_SET(val, 0x3); | ||
1124 | val = RXTX_REG145_TX_IDLE_SATA_SET(val, 0x0); | ||
1125 | if (preA3Chip) { | ||
1126 | val = RXTX_REG145_RXES_ENA_SET(val, 0x1); | ||
1127 | val = RXTX_REG145_RXVWES_LATENA_SET(val, 0x1); | ||
1128 | } else { | ||
1129 | val = RXTX_REG145_RXES_ENA_SET(val, 0x0); | ||
1130 | val = RXTX_REG145_RXVWES_LATENA_SET(val, 0x0); | ||
1131 | } | ||
1132 | serdes_wr(ctx, lane, RXTX_REG145, val); | ||
1133 | |||
1134 | /* | ||
1135 | * Set Rx LOS filter clock rate, sample rate, and threshold | ||
1136 | * windows | ||
1137 | */ | ||
1138 | for (i = 0; i < 4; i++) { | ||
1139 | reg = RXTX_REG148 + i * 2; | ||
1140 | serdes_wr(ctx, lane, reg, 0xFFFF); | ||
1141 | } | ||
1142 | } | ||
1143 | } | ||
1144 | |||
1145 | static int xgene_phy_cal_rdy_chk(struct xgene_phy_ctx *ctx, | ||
1146 | enum cmu_type_t cmu_type, | ||
1147 | enum clk_type_t clk_type) | ||
1148 | { | ||
1149 | void __iomem *csr_serdes = ctx->sds_base; | ||
1150 | int loop; | ||
1151 | u32 val; | ||
1152 | |||
1153 | /* Release PHY main reset */ | ||
1154 | writel(0xdf, csr_serdes + SATA_ENET_SDS_RST_CTL); | ||
1155 | readl(csr_serdes + SATA_ENET_SDS_RST_CTL); /* Force a barrier */ | ||
1156 | |||
1157 | if (cmu_type != REF_CMU) { | ||
1158 | cmu_setbits(ctx, cmu_type, CMU_REG5, CMU_REG5_PLL_RESETB_MASK); | ||
1159 | /* | ||
1160 | * As per PHY design spec, the PLL reset requires a minimum | ||
1161 | * of 800us. | ||
1162 | */ | ||
1163 | usleep_range(800, 1000); | ||
1164 | |||
1165 | cmu_rd(ctx, cmu_type, CMU_REG1, &val); | ||
1166 | val = CMU_REG1_PLL_MANUALCAL_SET(val, 0x0); | ||
1167 | cmu_wr(ctx, cmu_type, CMU_REG1, val); | ||
1168 | /* | ||
1169 | * As per PHY design spec, the PLL auto calibration requires | ||
1170 | * a minimum of 800us. | ||
1171 | */ | ||
1172 | usleep_range(800, 1000); | ||
1173 | |||
1174 | cmu_toggle1to0(ctx, cmu_type, CMU_REG32, | ||
1175 | CMU_REG32_FORCE_VCOCAL_START_MASK); | ||
1176 | /* | ||
1177 | * As per PHY design spec, the PLL requires a minimum of | ||
1178 | * 800us to settle. | ||
1179 | */ | ||
1180 | usleep_range(800, 1000); | ||
1181 | } | ||
1182 | |||
1183 | if (!preA3Chip) | ||
1184 | goto skip_manual_cal; | ||
1185 | |||
1186 | /* | ||
1187 | * Configure the termination resister calibration | ||
1188 | * The serial receive pins, RXP/RXN, have TERMination resistor | ||
1189 | * that is required to be calibrated. | ||
1190 | */ | ||
1191 | cmu_rd(ctx, cmu_type, CMU_REG17, &val); | ||
1192 | val = CMU_REG17_PVT_CODE_R2A_SET(val, 0x12); | ||
1193 | val = CMU_REG17_RESERVED_7_SET(val, 0x0); | ||
1194 | cmu_wr(ctx, cmu_type, CMU_REG17, val); | ||
1195 | cmu_toggle1to0(ctx, cmu_type, CMU_REG17, | ||
1196 | CMU_REG17_PVT_TERM_MAN_ENA_MASK); | ||
1197 | /* | ||
1198 | * The serial transmit pins, TXP/TXN, have Pull-UP and Pull-DOWN | ||
1199 | * resistors that are required to the calibrated. | ||
1200 | * Configure the pull DOWN calibration | ||
1201 | */ | ||
1202 | cmu_rd(ctx, cmu_type, CMU_REG17, &val); | ||
1203 | val = CMU_REG17_PVT_CODE_R2A_SET(val, 0x29); | ||
1204 | val = CMU_REG17_RESERVED_7_SET(val, 0x0); | ||
1205 | cmu_wr(ctx, cmu_type, CMU_REG17, val); | ||
1206 | cmu_toggle1to0(ctx, cmu_type, CMU_REG16, | ||
1207 | CMU_REG16_PVT_DN_MAN_ENA_MASK); | ||
1208 | /* Configure the pull UP calibration */ | ||
1209 | cmu_rd(ctx, cmu_type, CMU_REG17, &val); | ||
1210 | val = CMU_REG17_PVT_CODE_R2A_SET(val, 0x28); | ||
1211 | val = CMU_REG17_RESERVED_7_SET(val, 0x0); | ||
1212 | cmu_wr(ctx, cmu_type, CMU_REG17, val); | ||
1213 | cmu_toggle1to0(ctx, cmu_type, CMU_REG16, | ||
1214 | CMU_REG16_PVT_UP_MAN_ENA_MASK); | ||
1215 | |||
1216 | skip_manual_cal: | ||
1217 | /* Poll the PLL calibration completion status for at least 1 ms */ | ||
1218 | loop = 100; | ||
1219 | do { | ||
1220 | cmu_rd(ctx, cmu_type, CMU_REG7, &val); | ||
1221 | if (CMU_REG7_PLL_CALIB_DONE_RD(val)) | ||
1222 | break; | ||
1223 | /* | ||
1224 | * As per PHY design spec, PLL calibration status requires | ||
1225 | * a minimum of 10us to be updated. | ||
1226 | */ | ||
1227 | usleep_range(10, 100); | ||
1228 | } while (--loop > 0); | ||
1229 | |||
1230 | cmu_rd(ctx, cmu_type, CMU_REG7, &val); | ||
1231 | dev_dbg(ctx->dev, "PLL calibration %s\n", | ||
1232 | CMU_REG7_PLL_CALIB_DONE_RD(val) ? "done" : "failed"); | ||
1233 | if (CMU_REG7_VCO_CAL_FAIL_RD(val)) { | ||
1234 | dev_err(ctx->dev, | ||
1235 | "PLL calibration failed due to VCO failure\n"); | ||
1236 | return -1; | ||
1237 | } | ||
1238 | dev_dbg(ctx->dev, "PLL calibration successful\n"); | ||
1239 | |||
1240 | cmu_rd(ctx, cmu_type, CMU_REG15, &val); | ||
1241 | dev_dbg(ctx->dev, "PHY Tx is %sready\n", val & 0x300 ? "" : "not "); | ||
1242 | return 0; | ||
1243 | } | ||
1244 | |||
1245 | static void xgene_phy_pdwn_force_vco(struct xgene_phy_ctx *ctx, | ||
1246 | enum cmu_type_t cmu_type, | ||
1247 | enum clk_type_t clk_type) | ||
1248 | { | ||
1249 | u32 val; | ||
1250 | |||
1251 | dev_dbg(ctx->dev, "Reset VCO and re-start again\n"); | ||
1252 | if (cmu_type == PHY_CMU) { | ||
1253 | cmu_rd(ctx, cmu_type, CMU_REG16, &val); | ||
1254 | val = CMU_REG16_VCOCAL_WAIT_BTW_CODE_SET(val, 0x7); | ||
1255 | cmu_wr(ctx, cmu_type, CMU_REG16, val); | ||
1256 | } | ||
1257 | |||
1258 | cmu_toggle1to0(ctx, cmu_type, CMU_REG0, CMU_REG0_PDOWN_MASK); | ||
1259 | cmu_toggle1to0(ctx, cmu_type, CMU_REG32, | ||
1260 | CMU_REG32_FORCE_VCOCAL_START_MASK); | ||
1261 | } | ||
1262 | |||
1263 | static int xgene_phy_hw_init_sata(struct xgene_phy_ctx *ctx, | ||
1264 | enum clk_type_t clk_type, int ssc_enable) | ||
1265 | { | ||
1266 | void __iomem *sds_base = ctx->sds_base; | ||
1267 | u32 val; | ||
1268 | int i; | ||
1269 | |||
1270 | /* Configure the PHY for operation */ | ||
1271 | dev_dbg(ctx->dev, "Reset PHY\n"); | ||
1272 | /* Place PHY into reset */ | ||
1273 | writel(0x0, sds_base + SATA_ENET_SDS_RST_CTL); | ||
1274 | val = readl(sds_base + SATA_ENET_SDS_RST_CTL); /* Force a barrier */ | ||
1275 | /* Release PHY lane from reset (active high) */ | ||
1276 | writel(0x20, sds_base + SATA_ENET_SDS_RST_CTL); | ||
1277 | readl(sds_base + SATA_ENET_SDS_RST_CTL); /* Force a barrier */ | ||
1278 | /* Release all PHY module out of reset except PHY main reset */ | ||
1279 | writel(0xde, sds_base + SATA_ENET_SDS_RST_CTL); | ||
1280 | readl(sds_base + SATA_ENET_SDS_RST_CTL); /* Force a barrier */ | ||
1281 | |||
1282 | /* Set the operation speed */ | ||
1283 | val = readl(sds_base + SATA_ENET_SDS_CTL1); | ||
1284 | val = CFG_I_SPD_SEL_CDR_OVR1_SET(val, | ||
1285 | ctx->sata_param.txspeed[ctx->sata_param.speed[0]]); | ||
1286 | writel(val, sds_base + SATA_ENET_SDS_CTL1); | ||
1287 | |||
1288 | dev_dbg(ctx->dev, "Set the customer pin mode to SATA\n"); | ||
1289 | val = readl(sds_base + SATA_ENET_SDS_CTL0); | ||
1290 | val = REGSPEC_CFG_I_CUSTOMER_PIN_MODE0_SET(val, 0x4421); | ||
1291 | writel(val, sds_base + SATA_ENET_SDS_CTL0); | ||
1292 | |||
1293 | /* Configure the clock macro unit (CMU) clock type */ | ||
1294 | xgene_phy_cfg_cmu_clk_type(ctx, PHY_CMU, clk_type); | ||
1295 | |||
1296 | /* Configure the clock macro */ | ||
1297 | xgene_phy_sata_cfg_cmu_core(ctx, PHY_CMU, clk_type); | ||
1298 | |||
1299 | /* Enable SSC if enabled */ | ||
1300 | if (ssc_enable) | ||
1301 | xgene_phy_ssc_enable(ctx, PHY_CMU); | ||
1302 | |||
1303 | /* Configure PHY lanes */ | ||
1304 | xgene_phy_sata_cfg_lanes(ctx); | ||
1305 | |||
1306 | /* Set Rx/Tx 20-bit */ | ||
1307 | val = readl(sds_base + SATA_ENET_SDS_PCS_CTL0); | ||
1308 | val = REGSPEC_CFG_I_RX_WORDMODE0_SET(val, 0x3); | ||
1309 | val = REGSPEC_CFG_I_TX_WORDMODE0_SET(val, 0x3); | ||
1310 | writel(val, sds_base + SATA_ENET_SDS_PCS_CTL0); | ||
1311 | |||
1312 | /* Start PLL calibration and try for three times */ | ||
1313 | i = 10; | ||
1314 | do { | ||
1315 | if (!xgene_phy_cal_rdy_chk(ctx, PHY_CMU, clk_type)) | ||
1316 | break; | ||
1317 | /* If failed, toggle the VCO power signal and start again */ | ||
1318 | xgene_phy_pdwn_force_vco(ctx, PHY_CMU, clk_type); | ||
1319 | } while (--i > 0); | ||
1320 | /* Even on failure, allow to continue any way */ | ||
1321 | if (i <= 0) | ||
1322 | dev_err(ctx->dev, "PLL calibration failed\n"); | ||
1323 | |||
1324 | return 0; | ||
1325 | } | ||
1326 | |||
1327 | static int xgene_phy_hw_initialize(struct xgene_phy_ctx *ctx, | ||
1328 | enum clk_type_t clk_type, | ||
1329 | int ssc_enable) | ||
1330 | { | ||
1331 | int rc; | ||
1332 | |||
1333 | dev_dbg(ctx->dev, "PHY init clk type %d\n", clk_type); | ||
1334 | |||
1335 | if (ctx->mode == MODE_SATA) { | ||
1336 | rc = xgene_phy_hw_init_sata(ctx, clk_type, ssc_enable); | ||
1337 | if (rc) | ||
1338 | return rc; | ||
1339 | } else { | ||
1340 | dev_err(ctx->dev, "Un-supported customer pin mode %d\n", | ||
1341 | ctx->mode); | ||
1342 | return -ENODEV; | ||
1343 | } | ||
1344 | |||
1345 | return 0; | ||
1346 | } | ||
1347 | |||
1348 | /* | ||
1349 | * Receiver Offset Calibration: | ||
1350 | * | ||
1351 | * Calibrate the receiver signal path offset in two steps - summar and | ||
1352 | * latch calibrations | ||
1353 | */ | ||
1354 | static void xgene_phy_force_lat_summer_cal(struct xgene_phy_ctx *ctx, int lane) | ||
1355 | { | ||
1356 | int i; | ||
1357 | struct { | ||
1358 | u32 reg; | ||
1359 | u32 val; | ||
1360 | } serdes_reg[] = { | ||
1361 | {RXTX_REG38, 0x0}, | ||
1362 | {RXTX_REG39, 0xff00}, | ||
1363 | {RXTX_REG40, 0xffff}, | ||
1364 | {RXTX_REG41, 0xffff}, | ||
1365 | {RXTX_REG42, 0xffff}, | ||
1366 | {RXTX_REG43, 0xffff}, | ||
1367 | {RXTX_REG44, 0xffff}, | ||
1368 | {RXTX_REG45, 0xffff}, | ||
1369 | {RXTX_REG46, 0xffff}, | ||
1370 | {RXTX_REG47, 0xfffc}, | ||
1371 | {RXTX_REG48, 0x0}, | ||
1372 | {RXTX_REG49, 0x0}, | ||
1373 | {RXTX_REG50, 0x0}, | ||
1374 | {RXTX_REG51, 0x0}, | ||
1375 | {RXTX_REG52, 0x0}, | ||
1376 | {RXTX_REG53, 0x0}, | ||
1377 | {RXTX_REG54, 0x0}, | ||
1378 | {RXTX_REG55, 0x0}, | ||
1379 | }; | ||
1380 | |||
1381 | /* Start SUMMER calibration */ | ||
1382 | serdes_setbits(ctx, lane, RXTX_REG127, | ||
1383 | RXTX_REG127_FORCE_SUM_CAL_START_MASK); | ||
1384 | /* | ||
1385 | * As per PHY design spec, the Summer calibration requires a minimum | ||
1386 | * of 100us to complete. | ||
1387 | */ | ||
1388 | usleep_range(100, 500); | ||
1389 | serdes_clrbits(ctx, lane, RXTX_REG127, | ||
1390 | RXTX_REG127_FORCE_SUM_CAL_START_MASK); | ||
1391 | /* | ||
1392 | * As per PHY design spec, the auto calibration requires a minimum | ||
1393 | * of 100us to complete. | ||
1394 | */ | ||
1395 | usleep_range(100, 500); | ||
1396 | |||
1397 | /* Start latch calibration */ | ||
1398 | serdes_setbits(ctx, lane, RXTX_REG127, | ||
1399 | RXTX_REG127_FORCE_LAT_CAL_START_MASK); | ||
1400 | /* | ||
1401 | * As per PHY design spec, the latch calibration requires a minimum | ||
1402 | * of 100us to complete. | ||
1403 | */ | ||
1404 | usleep_range(100, 500); | ||
1405 | serdes_clrbits(ctx, lane, RXTX_REG127, | ||
1406 | RXTX_REG127_FORCE_LAT_CAL_START_MASK); | ||
1407 | |||
1408 | /* Configure the PHY lane for calibration */ | ||
1409 | serdes_wr(ctx, lane, RXTX_REG28, 0x7); | ||
1410 | serdes_wr(ctx, lane, RXTX_REG31, 0x7e00); | ||
1411 | serdes_clrbits(ctx, lane, RXTX_REG4, | ||
1412 | RXTX_REG4_TX_LOOPBACK_BUF_EN_MASK); | ||
1413 | serdes_clrbits(ctx, lane, RXTX_REG7, | ||
1414 | RXTX_REG7_LOOP_BACK_ENA_CTLE_MASK); | ||
1415 | for (i = 0; i < ARRAY_SIZE(serdes_reg); i++) | ||
1416 | serdes_wr(ctx, lane, serdes_reg[i].reg, | ||
1417 | serdes_reg[i].val); | ||
1418 | } | ||
1419 | |||
1420 | static void xgene_phy_reset_rxd(struct xgene_phy_ctx *ctx, int lane) | ||
1421 | { | ||
1422 | /* Reset digital Rx */ | ||
1423 | serdes_clrbits(ctx, lane, RXTX_REG7, RXTX_REG7_RESETB_RXD_MASK); | ||
1424 | /* As per PHY design spec, the reset requires a minimum of 100us. */ | ||
1425 | usleep_range(100, 150); | ||
1426 | serdes_setbits(ctx, lane, RXTX_REG7, RXTX_REG7_RESETB_RXD_MASK); | ||
1427 | } | ||
1428 | |||
1429 | static int xgene_phy_get_avg(int accum, int samples) | ||
1430 | { | ||
1431 | return (accum + (samples / 2)) / samples; | ||
1432 | } | ||
1433 | |||
1434 | static void xgene_phy_gen_avg_val(struct xgene_phy_ctx *ctx, int lane) | ||
1435 | { | ||
1436 | int max_loop = 10; | ||
1437 | int avg_loop = 0; | ||
1438 | int lat_do = 0, lat_xo = 0, lat_eo = 0, lat_so = 0; | ||
1439 | int lat_de = 0, lat_xe = 0, lat_ee = 0, lat_se = 0; | ||
1440 | int sum_cal = 0; | ||
1441 | int lat_do_itr, lat_xo_itr, lat_eo_itr, lat_so_itr; | ||
1442 | int lat_de_itr, lat_xe_itr, lat_ee_itr, lat_se_itr; | ||
1443 | int sum_cal_itr; | ||
1444 | int fail_even; | ||
1445 | int fail_odd; | ||
1446 | u32 val; | ||
1447 | |||
1448 | dev_dbg(ctx->dev, "Generating avg calibration value for lane %d\n", | ||
1449 | lane); | ||
1450 | |||
1451 | /* Enable RX Hi-Z termination */ | ||
1452 | serdes_setbits(ctx, lane, RXTX_REG12, | ||
1453 | RXTX_REG12_RX_DET_TERM_ENABLE_MASK); | ||
1454 | /* Turn off DFE */ | ||
1455 | serdes_wr(ctx, lane, RXTX_REG28, 0x0000); | ||
1456 | /* DFE Presets to zero */ | ||
1457 | serdes_wr(ctx, lane, RXTX_REG31, 0x0000); | ||
1458 | |||
1459 | /* | ||
1460 | * Receiver Offset Calibration: | ||
1461 | * Calibrate the receiver signal path offset in two steps - summar | ||
1462 | * and latch calibration. | ||
1463 | * Runs the "Receiver Offset Calibration multiple times to determine | ||
1464 | * the average value to use. | ||
1465 | */ | ||
1466 | while (avg_loop < max_loop) { | ||
1467 | /* Start the calibration */ | ||
1468 | xgene_phy_force_lat_summer_cal(ctx, lane); | ||
1469 | |||
1470 | serdes_rd(ctx, lane, RXTX_REG21, &val); | ||
1471 | lat_do_itr = RXTX_REG21_DO_LATCH_CALOUT_RD(val); | ||
1472 | lat_xo_itr = RXTX_REG21_XO_LATCH_CALOUT_RD(val); | ||
1473 | fail_odd = RXTX_REG21_LATCH_CAL_FAIL_ODD_RD(val); | ||
1474 | |||
1475 | serdes_rd(ctx, lane, RXTX_REG22, &val); | ||
1476 | lat_eo_itr = RXTX_REG22_EO_LATCH_CALOUT_RD(val); | ||
1477 | lat_so_itr = RXTX_REG22_SO_LATCH_CALOUT_RD(val); | ||
1478 | fail_even = RXTX_REG22_LATCH_CAL_FAIL_EVEN_RD(val); | ||
1479 | |||
1480 | serdes_rd(ctx, lane, RXTX_REG23, &val); | ||
1481 | lat_de_itr = RXTX_REG23_DE_LATCH_CALOUT_RD(val); | ||
1482 | lat_xe_itr = RXTX_REG23_XE_LATCH_CALOUT_RD(val); | ||
1483 | |||
1484 | serdes_rd(ctx, lane, RXTX_REG24, &val); | ||
1485 | lat_ee_itr = RXTX_REG24_EE_LATCH_CALOUT_RD(val); | ||
1486 | lat_se_itr = RXTX_REG24_SE_LATCH_CALOUT_RD(val); | ||
1487 | |||
1488 | serdes_rd(ctx, lane, RXTX_REG121, &val); | ||
1489 | sum_cal_itr = RXTX_REG121_SUMOS_CAL_CODE_RD(val); | ||
1490 | |||
1491 | /* Check for failure. If passed, sum them for averaging */ | ||
1492 | if ((fail_even == 0 || fail_even == 1) && | ||
1493 | (fail_odd == 0 || fail_odd == 1)) { | ||
1494 | lat_do += lat_do_itr; | ||
1495 | lat_xo += lat_xo_itr; | ||
1496 | lat_eo += lat_eo_itr; | ||
1497 | lat_so += lat_so_itr; | ||
1498 | lat_de += lat_de_itr; | ||
1499 | lat_xe += lat_xe_itr; | ||
1500 | lat_ee += lat_ee_itr; | ||
1501 | lat_se += lat_se_itr; | ||
1502 | sum_cal += sum_cal_itr; | ||
1503 | |||
1504 | dev_dbg(ctx->dev, "Iteration %d:\n", avg_loop); | ||
1505 | dev_dbg(ctx->dev, "DO 0x%x XO 0x%x EO 0x%x SO 0x%x\n", | ||
1506 | lat_do_itr, lat_xo_itr, lat_eo_itr, | ||
1507 | lat_so_itr); | ||
1508 | dev_dbg(ctx->dev, "DE 0x%x XE 0x%x EE 0x%x SE 0x%x\n", | ||
1509 | lat_de_itr, lat_xe_itr, lat_ee_itr, | ||
1510 | lat_se_itr); | ||
1511 | dev_dbg(ctx->dev, "SUM 0x%x\n", sum_cal_itr); | ||
1512 | ++avg_loop; | ||
1513 | } else { | ||
1514 | dev_err(ctx->dev, | ||
1515 | "Receiver calibration failed at %d loop\n", | ||
1516 | avg_loop); | ||
1517 | } | ||
1518 | xgene_phy_reset_rxd(ctx, lane); | ||
1519 | } | ||
1520 | |||
1521 | /* Update latch manual calibration with average value */ | ||
1522 | serdes_rd(ctx, lane, RXTX_REG127, &val); | ||
1523 | val = RXTX_REG127_DO_LATCH_MANCAL_SET(val, | ||
1524 | xgene_phy_get_avg(lat_do, max_loop)); | ||
1525 | val = RXTX_REG127_XO_LATCH_MANCAL_SET(val, | ||
1526 | xgene_phy_get_avg(lat_xo, max_loop)); | ||
1527 | serdes_wr(ctx, lane, RXTX_REG127, val); | ||
1528 | |||
1529 | serdes_rd(ctx, lane, RXTX_REG128, &val); | ||
1530 | val = RXTX_REG128_EO_LATCH_MANCAL_SET(val, | ||
1531 | xgene_phy_get_avg(lat_eo, max_loop)); | ||
1532 | val = RXTX_REG128_SO_LATCH_MANCAL_SET(val, | ||
1533 | xgene_phy_get_avg(lat_so, max_loop)); | ||
1534 | serdes_wr(ctx, lane, RXTX_REG128, val); | ||
1535 | |||
1536 | serdes_rd(ctx, lane, RXTX_REG129, &val); | ||
1537 | val = RXTX_REG129_DE_LATCH_MANCAL_SET(val, | ||
1538 | xgene_phy_get_avg(lat_de, max_loop)); | ||
1539 | val = RXTX_REG129_XE_LATCH_MANCAL_SET(val, | ||
1540 | xgene_phy_get_avg(lat_xe, max_loop)); | ||
1541 | serdes_wr(ctx, lane, RXTX_REG129, val); | ||
1542 | |||
1543 | serdes_rd(ctx, lane, RXTX_REG130, &val); | ||
1544 | val = RXTX_REG130_EE_LATCH_MANCAL_SET(val, | ||
1545 | xgene_phy_get_avg(lat_ee, max_loop)); | ||
1546 | val = RXTX_REG130_SE_LATCH_MANCAL_SET(val, | ||
1547 | xgene_phy_get_avg(lat_se, max_loop)); | ||
1548 | serdes_wr(ctx, lane, RXTX_REG130, val); | ||
1549 | |||
1550 | /* Update SUMMER calibration with average value */ | ||
1551 | serdes_rd(ctx, lane, RXTX_REG14, &val); | ||
1552 | val = RXTX_REG14_CLTE_LATCAL_MAN_PROG_SET(val, | ||
1553 | xgene_phy_get_avg(sum_cal, max_loop)); | ||
1554 | serdes_wr(ctx, lane, RXTX_REG14, val); | ||
1555 | |||
1556 | dev_dbg(ctx->dev, "Average Value:\n"); | ||
1557 | dev_dbg(ctx->dev, "DO 0x%x XO 0x%x EO 0x%x SO 0x%x\n", | ||
1558 | xgene_phy_get_avg(lat_do, max_loop), | ||
1559 | xgene_phy_get_avg(lat_xo, max_loop), | ||
1560 | xgene_phy_get_avg(lat_eo, max_loop), | ||
1561 | xgene_phy_get_avg(lat_so, max_loop)); | ||
1562 | dev_dbg(ctx->dev, "DE 0x%x XE 0x%x EE 0x%x SE 0x%x\n", | ||
1563 | xgene_phy_get_avg(lat_de, max_loop), | ||
1564 | xgene_phy_get_avg(lat_xe, max_loop), | ||
1565 | xgene_phy_get_avg(lat_ee, max_loop), | ||
1566 | xgene_phy_get_avg(lat_se, max_loop)); | ||
1567 | dev_dbg(ctx->dev, "SUM 0x%x\n", | ||
1568 | xgene_phy_get_avg(sum_cal, max_loop)); | ||
1569 | |||
1570 | serdes_rd(ctx, lane, RXTX_REG14, &val); | ||
1571 | val = RXTX_REG14_CTLE_LATCAL_MAN_ENA_SET(val, 0x1); | ||
1572 | serdes_wr(ctx, lane, RXTX_REG14, val); | ||
1573 | dev_dbg(ctx->dev, "Enable Manual Summer calibration\n"); | ||
1574 | |||
1575 | serdes_rd(ctx, lane, RXTX_REG127, &val); | ||
1576 | val = RXTX_REG127_LATCH_MAN_CAL_ENA_SET(val, 0x1); | ||
1577 | dev_dbg(ctx->dev, "Enable Manual Latch calibration\n"); | ||
1578 | serdes_wr(ctx, lane, RXTX_REG127, val); | ||
1579 | |||
1580 | /* Disable RX Hi-Z termination */ | ||
1581 | serdes_rd(ctx, lane, RXTX_REG12, &val); | ||
1582 | val = RXTX_REG12_RX_DET_TERM_ENABLE_SET(val, 0); | ||
1583 | serdes_wr(ctx, lane, RXTX_REG12, val); | ||
1584 | /* Turn on DFE */ | ||
1585 | serdes_wr(ctx, lane, RXTX_REG28, 0x0007); | ||
1586 | /* Set DFE preset */ | ||
1587 | serdes_wr(ctx, lane, RXTX_REG31, 0x7e00); | ||
1588 | } | ||
1589 | |||
1590 | static int xgene_phy_hw_init(struct phy *phy) | ||
1591 | { | ||
1592 | struct xgene_phy_ctx *ctx = phy_get_drvdata(phy); | ||
1593 | int rc; | ||
1594 | int i; | ||
1595 | |||
1596 | rc = xgene_phy_hw_initialize(ctx, CLK_EXT_DIFF, SSC_DISABLE); | ||
1597 | if (rc) { | ||
1598 | dev_err(ctx->dev, "PHY initialize failed %d\n", rc); | ||
1599 | return rc; | ||
1600 | } | ||
1601 | |||
1602 | /* Setup clock properly after PHY configuration */ | ||
1603 | if (!IS_ERR(ctx->clk)) { | ||
1604 | /* HW requires an toggle of the clock */ | ||
1605 | clk_prepare_enable(ctx->clk); | ||
1606 | clk_disable_unprepare(ctx->clk); | ||
1607 | clk_prepare_enable(ctx->clk); | ||
1608 | } | ||
1609 | |||
1610 | /* Compute average value */ | ||
1611 | for (i = 0; i < MAX_LANE; i++) | ||
1612 | xgene_phy_gen_avg_val(ctx, i); | ||
1613 | |||
1614 | dev_dbg(ctx->dev, "PHY initialized\n"); | ||
1615 | return 0; | ||
1616 | } | ||
1617 | |||
1618 | static const struct phy_ops xgene_phy_ops = { | ||
1619 | .init = xgene_phy_hw_init, | ||
1620 | .owner = THIS_MODULE, | ||
1621 | }; | ||
1622 | |||
1623 | static struct phy *xgene_phy_xlate(struct device *dev, | ||
1624 | struct of_phandle_args *args) | ||
1625 | { | ||
1626 | struct xgene_phy_ctx *ctx = dev_get_drvdata(dev); | ||
1627 | |||
1628 | if (args->args_count <= 0) | ||
1629 | return ERR_PTR(-EINVAL); | ||
1630 | if (args->args[0] < MODE_SATA || args->args[0] >= MODE_MAX) | ||
1631 | return ERR_PTR(-EINVAL); | ||
1632 | |||
1633 | ctx->mode = args->args[0]; | ||
1634 | return ctx->phy; | ||
1635 | } | ||
1636 | |||
1637 | static void xgene_phy_get_param(struct platform_device *pdev, | ||
1638 | const char *name, u32 *buffer, | ||
1639 | int count, u32 *default_val, | ||
1640 | u32 conv_factor) | ||
1641 | { | ||
1642 | int i; | ||
1643 | |||
1644 | if (!of_property_read_u32_array(pdev->dev.of_node, name, buffer, | ||
1645 | count)) { | ||
1646 | for (i = 0; i < count; i++) | ||
1647 | buffer[i] /= conv_factor; | ||
1648 | return; | ||
1649 | } | ||
1650 | /* Does not exist, load default */ | ||
1651 | for (i = 0; i < count; i++) | ||
1652 | buffer[i] = default_val[i % 3]; | ||
1653 | } | ||
1654 | |||
1655 | static int xgene_phy_probe(struct platform_device *pdev) | ||
1656 | { | ||
1657 | struct phy_provider *phy_provider; | ||
1658 | struct xgene_phy_ctx *ctx; | ||
1659 | struct resource *res; | ||
1660 | int rc = 0; | ||
1661 | u32 default_spd[] = DEFAULT_SATA_SPD_SEL; | ||
1662 | u32 default_txboost_gain[] = DEFAULT_SATA_TXBOOST_GAIN; | ||
1663 | u32 default_txeye_direction[] = DEFAULT_SATA_TXEYEDIRECTION; | ||
1664 | u32 default_txeye_tuning[] = DEFAULT_SATA_TXEYETUNING; | ||
1665 | u32 default_txamp[] = DEFAULT_SATA_TXAMP; | ||
1666 | u32 default_txcn1[] = DEFAULT_SATA_TXCN1; | ||
1667 | u32 default_txcn2[] = DEFAULT_SATA_TXCN2; | ||
1668 | u32 default_txcp1[] = DEFAULT_SATA_TXCP1; | ||
1669 | int i; | ||
1670 | |||
1671 | ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); | ||
1672 | if (!ctx) | ||
1673 | return -ENOMEM; | ||
1674 | |||
1675 | ctx->dev = &pdev->dev; | ||
1676 | |||
1677 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1678 | ctx->sds_base = devm_ioremap_resource(&pdev->dev, res); | ||
1679 | if (IS_ERR(ctx->sds_base)) { | ||
1680 | rc = PTR_ERR(ctx->sds_base); | ||
1681 | goto error; | ||
1682 | } | ||
1683 | |||
1684 | /* Retrieve optional clock */ | ||
1685 | ctx->clk = clk_get(&pdev->dev, NULL); | ||
1686 | |||
1687 | /* Load override paramaters */ | ||
1688 | xgene_phy_get_param(pdev, "apm,tx-eye-tuning", | ||
1689 | ctx->sata_param.txeyetuning, 6, default_txeye_tuning, 1); | ||
1690 | xgene_phy_get_param(pdev, "apm,tx-eye-direction", | ||
1691 | ctx->sata_param.txeyedirection, 6, default_txeye_direction, 1); | ||
1692 | xgene_phy_get_param(pdev, "apm,tx-boost-gain", | ||
1693 | ctx->sata_param.txboostgain, 6, default_txboost_gain, 1); | ||
1694 | xgene_phy_get_param(pdev, "apm,tx-amplitude", | ||
1695 | ctx->sata_param.txamplitude, 6, default_txamp, 13300); | ||
1696 | xgene_phy_get_param(pdev, "apm,tx-pre-cursor1", | ||
1697 | ctx->sata_param.txprecursor_cn1, 6, default_txcn1, 18200); | ||
1698 | xgene_phy_get_param(pdev, "apm,tx-pre-cursor2", | ||
1699 | ctx->sata_param.txprecursor_cn2, 6, default_txcn2, 18200); | ||
1700 | xgene_phy_get_param(pdev, "apm,tx-post-cursor", | ||
1701 | ctx->sata_param.txpostcursor_cp1, 6, default_txcp1, 18200); | ||
1702 | xgene_phy_get_param(pdev, "apm,tx-speed", | ||
1703 | ctx->sata_param.txspeed, 3, default_spd, 1); | ||
1704 | for (i = 0; i < MAX_LANE; i++) | ||
1705 | ctx->sata_param.speed[i] = 2; /* Default to Gen3 */ | ||
1706 | |||
1707 | ctx->dev = &pdev->dev; | ||
1708 | platform_set_drvdata(pdev, ctx); | ||
1709 | |||
1710 | ctx->phy = devm_phy_create(ctx->dev, &xgene_phy_ops, NULL); | ||
1711 | if (IS_ERR(ctx->phy)) { | ||
1712 | dev_dbg(&pdev->dev, "Failed to create PHY\n"); | ||
1713 | rc = PTR_ERR(ctx->phy); | ||
1714 | goto error; | ||
1715 | } | ||
1716 | phy_set_drvdata(ctx->phy, ctx); | ||
1717 | |||
1718 | phy_provider = devm_of_phy_provider_register(ctx->dev, | ||
1719 | xgene_phy_xlate); | ||
1720 | if (IS_ERR(phy_provider)) { | ||
1721 | rc = PTR_ERR(phy_provider); | ||
1722 | goto error; | ||
1723 | } | ||
1724 | |||
1725 | return 0; | ||
1726 | |||
1727 | error: | ||
1728 | return rc; | ||
1729 | } | ||
1730 | |||
1731 | static const struct of_device_id xgene_phy_of_match[] = { | ||
1732 | {.compatible = "apm,xgene-phy",}, | ||
1733 | {}, | ||
1734 | }; | ||
1735 | MODULE_DEVICE_TABLE(of, xgene_phy_of_match); | ||
1736 | |||
1737 | static struct platform_driver xgene_phy_driver = { | ||
1738 | .probe = xgene_phy_probe, | ||
1739 | .driver = { | ||
1740 | .name = "xgene-phy", | ||
1741 | .owner = THIS_MODULE, | ||
1742 | .of_match_table = xgene_phy_of_match, | ||
1743 | }, | ||
1744 | }; | ||
1745 | module_platform_driver(xgene_phy_driver); | ||
1746 | |||
1747 | MODULE_DESCRIPTION("APM X-Gene Multi-Purpose PHY driver"); | ||
1748 | MODULE_AUTHOR("Loc Ho <lho@apm.com>"); | ||
1749 | MODULE_LICENSE("GPL v2"); | ||
1750 | MODULE_VERSION("0.1"); | ||
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 8aa59a2c5eb2..d341c149a2f9 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c | |||
@@ -37,7 +37,7 @@ | |||
37 | #include <linux/err.h> | 37 | #include <linux/err.h> |
38 | #include <linux/delay.h> | 38 | #include <linux/delay.h> |
39 | #include <linux/usb/musb-omap.h> | 39 | #include <linux/usb/musb-omap.h> |
40 | #include <linux/usb/omap_control_usb.h> | 40 | #include <linux/phy/omap_control_phy.h> |
41 | #include <linux/of_platform.h> | 41 | #include <linux/of_platform.h> |
42 | 42 | ||
43 | #include "musb_core.h" | 43 | #include "musb_core.h" |
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 7d1451d5bbea..416e0c8cf6ff 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig | |||
@@ -75,27 +75,6 @@ config NOP_USB_XCEIV | |||
75 | built-in with usb ip or which are autonomous and doesn't require any | 75 | built-in with usb ip or which are autonomous and doesn't require any |
76 | phy programming such as ISP1x04 etc. | 76 | phy programming such as ISP1x04 etc. |
77 | 77 | ||
78 | config OMAP_CONTROL_USB | ||
79 | tristate "OMAP CONTROL USB Driver" | ||
80 | depends on ARCH_OMAP2PLUS || COMPILE_TEST | ||
81 | help | ||
82 | Enable this to add support for the USB part present in the control | ||
83 | module. This driver has API to power on the USB2 PHY and to write to | ||
84 | the mailbox. The mailbox is present only in omap4 and the register to | ||
85 | power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an | ||
86 | additional register to power on USB3 PHY. | ||
87 | |||
88 | config OMAP_USB3 | ||
89 | tristate "OMAP USB3 PHY Driver" | ||
90 | depends on ARCH_OMAP2PLUS || COMPILE_TEST | ||
91 | select OMAP_CONTROL_USB | ||
92 | select USB_PHY | ||
93 | help | ||
94 | Enable this to support the USB3 PHY that is part of SOC. This | ||
95 | driver takes care of all the PHY functionality apart from comparator. | ||
96 | This driver interacts with the "OMAP Control USB Driver" to power | ||
97 | on/off the PHY. | ||
98 | |||
99 | config AM335X_CONTROL_USB | 78 | config AM335X_CONTROL_USB |
100 | tristate | 79 | tristate |
101 | 80 | ||
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index be58adae3496..f8fa719a31b9 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile | |||
@@ -13,11 +13,9 @@ obj-$(CONFIG_ISP1301_OMAP) += phy-isp1301-omap.o | |||
13 | obj-$(CONFIG_MV_U3D_PHY) += phy-mv-u3d-usb.o | 13 | obj-$(CONFIG_MV_U3D_PHY) += phy-mv-u3d-usb.o |
14 | obj-$(CONFIG_NOP_USB_XCEIV) += phy-generic.o | 14 | obj-$(CONFIG_NOP_USB_XCEIV) += phy-generic.o |
15 | obj-$(CONFIG_TAHVO_USB) += phy-tahvo.o | 15 | obj-$(CONFIG_TAHVO_USB) += phy-tahvo.o |
16 | obj-$(CONFIG_OMAP_CONTROL_USB) += phy-omap-control.o | ||
17 | obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o | 16 | obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o |
18 | obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o | 17 | obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o |
19 | obj-$(CONFIG_OMAP_OTG) += phy-omap-otg.o | 18 | obj-$(CONFIG_OMAP_OTG) += phy-omap-otg.o |
20 | obj-$(CONFIG_OMAP_USB3) += phy-omap-usb3.o | ||
21 | obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o | 19 | obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o |
22 | obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o | 20 | obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o |
23 | obj-$(CONFIG_SAMSUNG_USB3PHY) += phy-samsung-usb3.o | 21 | obj-$(CONFIG_SAMSUNG_USB3PHY) += phy-samsung-usb3.o |
diff --git a/drivers/usb/phy/phy-omap-usb3.c b/drivers/usb/phy/phy-omap-usb3.c deleted file mode 100644 index 0c6ba29bdddd..000000000000 --- a/drivers/usb/phy/phy-omap-usb3.c +++ /dev/null | |||
@@ -1,361 +0,0 @@ | |||
1 | /* | ||
2 | * omap-usb3 - USB PHY, talking to dwc3 controller in OMAP. | ||
3 | * | ||
4 | * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * Author: Kishon Vijay Abraham I <kishon@ti.com> | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/usb/omap_usb.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/clk.h> | ||
25 | #include <linux/err.h> | ||
26 | #include <linux/pm_runtime.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/usb/omap_control_usb.h> | ||
29 | #include <linux/of_platform.h> | ||
30 | |||
31 | #define PLL_STATUS 0x00000004 | ||
32 | #define PLL_GO 0x00000008 | ||
33 | #define PLL_CONFIGURATION1 0x0000000C | ||
34 | #define PLL_CONFIGURATION2 0x00000010 | ||
35 | #define PLL_CONFIGURATION3 0x00000014 | ||
36 | #define PLL_CONFIGURATION4 0x00000020 | ||
37 | |||
38 | #define PLL_REGM_MASK 0x001FFE00 | ||
39 | #define PLL_REGM_SHIFT 0x9 | ||
40 | #define PLL_REGM_F_MASK 0x0003FFFF | ||
41 | #define PLL_REGM_F_SHIFT 0x0 | ||
42 | #define PLL_REGN_MASK 0x000001FE | ||
43 | #define PLL_REGN_SHIFT 0x1 | ||
44 | #define PLL_SELFREQDCO_MASK 0x0000000E | ||
45 | #define PLL_SELFREQDCO_SHIFT 0x1 | ||
46 | #define PLL_SD_MASK 0x0003FC00 | ||
47 | #define PLL_SD_SHIFT 0x9 | ||
48 | #define SET_PLL_GO 0x1 | ||
49 | #define PLL_TICOPWDN 0x10000 | ||
50 | #define PLL_LOCK 0x2 | ||
51 | #define PLL_IDLE 0x1 | ||
52 | |||
53 | /* | ||
54 | * This is an Empirical value that works, need to confirm the actual | ||
55 | * value required for the USB3PHY_PLL_CONFIGURATION2.PLL_IDLE status | ||
56 | * to be correctly reflected in the USB3PHY_PLL_STATUS register. | ||
57 | */ | ||
58 | # define PLL_IDLE_TIME 100; | ||
59 | |||
60 | struct usb_dpll_map { | ||
61 | unsigned long rate; | ||
62 | struct usb_dpll_params params; | ||
63 | }; | ||
64 | |||
65 | static struct usb_dpll_map dpll_map[] = { | ||
66 | {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */ | ||
67 | {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */ | ||
68 | {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */ | ||
69 | {20000000, {1000, 7, 4, 10, 0} }, /* 20 MHz */ | ||
70 | {26000000, {1250, 12, 4, 20, 0} }, /* 26 MHz */ | ||
71 | {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */ | ||
72 | }; | ||
73 | |||
74 | static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate) | ||
75 | { | ||
76 | int i; | ||
77 | |||
78 | for (i = 0; i < ARRAY_SIZE(dpll_map); i++) { | ||
79 | if (rate == dpll_map[i].rate) | ||
80 | return &dpll_map[i].params; | ||
81 | } | ||
82 | |||
83 | return NULL; | ||
84 | } | ||
85 | |||
86 | static int omap_usb3_suspend(struct usb_phy *x, int suspend) | ||
87 | { | ||
88 | struct omap_usb *phy = phy_to_omapusb(x); | ||
89 | int val; | ||
90 | int timeout = PLL_IDLE_TIME; | ||
91 | |||
92 | if (suspend && !phy->is_suspended) { | ||
93 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); | ||
94 | val |= PLL_IDLE; | ||
95 | omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); | ||
96 | |||
97 | do { | ||
98 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS); | ||
99 | if (val & PLL_TICOPWDN) | ||
100 | break; | ||
101 | udelay(1); | ||
102 | } while (--timeout); | ||
103 | |||
104 | omap_control_usb_phy_power(phy->control_dev, 0); | ||
105 | |||
106 | phy->is_suspended = 1; | ||
107 | } else if (!suspend && phy->is_suspended) { | ||
108 | phy->is_suspended = 0; | ||
109 | |||
110 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); | ||
111 | val &= ~PLL_IDLE; | ||
112 | omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); | ||
113 | |||
114 | do { | ||
115 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS); | ||
116 | if (!(val & PLL_TICOPWDN)) | ||
117 | break; | ||
118 | udelay(1); | ||
119 | } while (--timeout); | ||
120 | } | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static void omap_usb_dpll_relock(struct omap_usb *phy) | ||
126 | { | ||
127 | u32 val; | ||
128 | unsigned long timeout; | ||
129 | |||
130 | omap_usb_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO); | ||
131 | |||
132 | timeout = jiffies + msecs_to_jiffies(20); | ||
133 | do { | ||
134 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS); | ||
135 | if (val & PLL_LOCK) | ||
136 | break; | ||
137 | } while (!WARN_ON(time_after(jiffies, timeout))); | ||
138 | } | ||
139 | |||
140 | static int omap_usb_dpll_lock(struct omap_usb *phy) | ||
141 | { | ||
142 | u32 val; | ||
143 | unsigned long rate; | ||
144 | struct usb_dpll_params *dpll_params; | ||
145 | |||
146 | rate = clk_get_rate(phy->sys_clk); | ||
147 | dpll_params = omap_usb3_get_dpll_params(rate); | ||
148 | if (!dpll_params) { | ||
149 | dev_err(phy->dev, | ||
150 | "No DPLL configuration for %lu Hz SYS CLK\n", rate); | ||
151 | return -EINVAL; | ||
152 | } | ||
153 | |||
154 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); | ||
155 | val &= ~PLL_REGN_MASK; | ||
156 | val |= dpll_params->n << PLL_REGN_SHIFT; | ||
157 | omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); | ||
158 | |||
159 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); | ||
160 | val &= ~PLL_SELFREQDCO_MASK; | ||
161 | val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT; | ||
162 | omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); | ||
163 | |||
164 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); | ||
165 | val &= ~PLL_REGM_MASK; | ||
166 | val |= dpll_params->m << PLL_REGM_SHIFT; | ||
167 | omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); | ||
168 | |||
169 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4); | ||
170 | val &= ~PLL_REGM_F_MASK; | ||
171 | val |= dpll_params->mf << PLL_REGM_F_SHIFT; | ||
172 | omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val); | ||
173 | |||
174 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3); | ||
175 | val &= ~PLL_SD_MASK; | ||
176 | val |= dpll_params->sd << PLL_SD_SHIFT; | ||
177 | omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val); | ||
178 | |||
179 | omap_usb_dpll_relock(phy); | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int omap_usb3_init(struct usb_phy *x) | ||
185 | { | ||
186 | struct omap_usb *phy = phy_to_omapusb(x); | ||
187 | int ret; | ||
188 | |||
189 | ret = omap_usb_dpll_lock(phy); | ||
190 | if (ret) | ||
191 | return ret; | ||
192 | |||
193 | omap_control_usb_phy_power(phy->control_dev, 1); | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static int omap_usb3_probe(struct platform_device *pdev) | ||
199 | { | ||
200 | struct omap_usb *phy; | ||
201 | struct resource *res; | ||
202 | struct device_node *node = pdev->dev.of_node; | ||
203 | struct device_node *control_node; | ||
204 | struct platform_device *control_pdev; | ||
205 | |||
206 | if (!node) | ||
207 | return -EINVAL; | ||
208 | |||
209 | phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); | ||
210 | if (!phy) { | ||
211 | dev_err(&pdev->dev, "unable to alloc mem for OMAP USB3 PHY\n"); | ||
212 | return -ENOMEM; | ||
213 | } | ||
214 | |||
215 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl"); | ||
216 | phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res); | ||
217 | if (IS_ERR(phy->pll_ctrl_base)) | ||
218 | return PTR_ERR(phy->pll_ctrl_base); | ||
219 | |||
220 | phy->dev = &pdev->dev; | ||
221 | |||
222 | phy->phy.dev = phy->dev; | ||
223 | phy->phy.label = "omap-usb3"; | ||
224 | phy->phy.init = omap_usb3_init; | ||
225 | phy->phy.set_suspend = omap_usb3_suspend; | ||
226 | phy->phy.type = USB_PHY_TYPE_USB3; | ||
227 | |||
228 | phy->is_suspended = 1; | ||
229 | phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k"); | ||
230 | if (IS_ERR(phy->wkupclk)) { | ||
231 | dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n"); | ||
232 | return PTR_ERR(phy->wkupclk); | ||
233 | } | ||
234 | clk_prepare(phy->wkupclk); | ||
235 | |||
236 | phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m"); | ||
237 | if (IS_ERR(phy->optclk)) { | ||
238 | dev_err(&pdev->dev, "unable to get usb_otg_ss_refclk960m\n"); | ||
239 | return PTR_ERR(phy->optclk); | ||
240 | } | ||
241 | clk_prepare(phy->optclk); | ||
242 | |||
243 | phy->sys_clk = devm_clk_get(phy->dev, "sys_clkin"); | ||
244 | if (IS_ERR(phy->sys_clk)) { | ||
245 | pr_err("%s: unable to get sys_clkin\n", __func__); | ||
246 | return -EINVAL; | ||
247 | } | ||
248 | |||
249 | control_node = of_parse_phandle(node, "ctrl-module", 0); | ||
250 | if (!control_node) { | ||
251 | dev_err(&pdev->dev, "Failed to get control device phandle\n"); | ||
252 | return -EINVAL; | ||
253 | } | ||
254 | control_pdev = of_find_device_by_node(control_node); | ||
255 | if (!control_pdev) { | ||
256 | dev_err(&pdev->dev, "Failed to get control device\n"); | ||
257 | return -EINVAL; | ||
258 | } | ||
259 | |||
260 | phy->control_dev = &control_pdev->dev; | ||
261 | |||
262 | omap_control_usb_phy_power(phy->control_dev, 0); | ||
263 | usb_add_phy_dev(&phy->phy); | ||
264 | |||
265 | platform_set_drvdata(pdev, phy); | ||
266 | |||
267 | pm_runtime_enable(phy->dev); | ||
268 | pm_runtime_get(&pdev->dev); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static int omap_usb3_remove(struct platform_device *pdev) | ||
274 | { | ||
275 | struct omap_usb *phy = platform_get_drvdata(pdev); | ||
276 | |||
277 | clk_unprepare(phy->wkupclk); | ||
278 | clk_unprepare(phy->optclk); | ||
279 | usb_remove_phy(&phy->phy); | ||
280 | if (!pm_runtime_suspended(&pdev->dev)) | ||
281 | pm_runtime_put(&pdev->dev); | ||
282 | pm_runtime_disable(&pdev->dev); | ||
283 | |||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | #ifdef CONFIG_PM_RUNTIME | ||
288 | |||
289 | static int omap_usb3_runtime_suspend(struct device *dev) | ||
290 | { | ||
291 | struct platform_device *pdev = to_platform_device(dev); | ||
292 | struct omap_usb *phy = platform_get_drvdata(pdev); | ||
293 | |||
294 | clk_disable(phy->wkupclk); | ||
295 | clk_disable(phy->optclk); | ||
296 | |||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static int omap_usb3_runtime_resume(struct device *dev) | ||
301 | { | ||
302 | u32 ret = 0; | ||
303 | struct platform_device *pdev = to_platform_device(dev); | ||
304 | struct omap_usb *phy = platform_get_drvdata(pdev); | ||
305 | |||
306 | ret = clk_enable(phy->optclk); | ||
307 | if (ret) { | ||
308 | dev_err(phy->dev, "Failed to enable optclk %d\n", ret); | ||
309 | goto err1; | ||
310 | } | ||
311 | |||
312 | ret = clk_enable(phy->wkupclk); | ||
313 | if (ret) { | ||
314 | dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret); | ||
315 | goto err2; | ||
316 | } | ||
317 | |||
318 | return 0; | ||
319 | |||
320 | err2: | ||
321 | clk_disable(phy->optclk); | ||
322 | |||
323 | err1: | ||
324 | return ret; | ||
325 | } | ||
326 | |||
327 | static const struct dev_pm_ops omap_usb3_pm_ops = { | ||
328 | SET_RUNTIME_PM_OPS(omap_usb3_runtime_suspend, omap_usb3_runtime_resume, | ||
329 | NULL) | ||
330 | }; | ||
331 | |||
332 | #define DEV_PM_OPS (&omap_usb3_pm_ops) | ||
333 | #else | ||
334 | #define DEV_PM_OPS NULL | ||
335 | #endif | ||
336 | |||
337 | #ifdef CONFIG_OF | ||
338 | static const struct of_device_id omap_usb3_id_table[] = { | ||
339 | { .compatible = "ti,omap-usb3" }, | ||
340 | {} | ||
341 | }; | ||
342 | MODULE_DEVICE_TABLE(of, omap_usb3_id_table); | ||
343 | #endif | ||
344 | |||
345 | static struct platform_driver omap_usb3_driver = { | ||
346 | .probe = omap_usb3_probe, | ||
347 | .remove = omap_usb3_remove, | ||
348 | .driver = { | ||
349 | .name = "omap-usb3", | ||
350 | .owner = THIS_MODULE, | ||
351 | .pm = DEV_PM_OPS, | ||
352 | .of_match_table = of_match_ptr(omap_usb3_id_table), | ||
353 | }, | ||
354 | }; | ||
355 | |||
356 | module_platform_driver(omap_usb3_driver); | ||
357 | |||
358 | MODULE_ALIAS("platform: omap_usb3"); | ||
359 | MODULE_AUTHOR("Texas Instruments Inc."); | ||
360 | MODULE_DESCRIPTION("OMAP USB3 phy driver"); | ||
361 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c index 214172b68d5d..04778cf80d60 100644 --- a/drivers/usb/phy/phy-twl6030-usb.c +++ b/drivers/usb/phy/phy-twl6030-usb.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <linux/io.h> | 27 | #include <linux/io.h> |
28 | #include <linux/usb/musb-omap.h> | 28 | #include <linux/usb/musb-omap.h> |
29 | #include <linux/usb/phy_companion.h> | 29 | #include <linux/usb/phy_companion.h> |
30 | #include <linux/usb/omap_usb.h> | 30 | #include <linux/phy/omap_usb.h> |
31 | #include <linux/i2c/twl.h> | 31 | #include <linux/i2c/twl.h> |
32 | #include <linux/regulator/consumer.h> | 32 | #include <linux/regulator/consumer.h> |
33 | #include <linux/err.h> | 33 | #include <linux/err.h> |
diff --git a/include/linux/usb/omap_control_usb.h b/include/linux/phy/omap_control_phy.h index 69ae383ee3cc..5450403c7546 100644 --- a/include/linux/usb/omap_control_usb.h +++ b/include/linux/phy/omap_control_phy.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * omap_control_usb.h - Header file for the USB part of control module. | 2 | * omap_control_phy.h - Header file for the PHY part of control module. |
3 | * | 3 | * |
4 | * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com | 4 | * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
@@ -16,10 +16,10 @@ | |||
16 | * | 16 | * |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #ifndef __OMAP_CONTROL_USB_H__ | 19 | #ifndef __OMAP_CONTROL_PHY_H__ |
20 | #define __OMAP_CONTROL_USB_H__ | 20 | #define __OMAP_CONTROL_PHY_H__ |
21 | 21 | ||
22 | enum omap_control_usb_type { | 22 | enum omap_control_phy_type { |
23 | OMAP_CTRL_TYPE_OTGHS = 1, /* Mailbox OTGHS_CONTROL */ | 23 | OMAP_CTRL_TYPE_OTGHS = 1, /* Mailbox OTGHS_CONTROL */ |
24 | OMAP_CTRL_TYPE_USB2, /* USB2_PHY, power down in CONTROL_DEV_CONF */ | 24 | OMAP_CTRL_TYPE_USB2, /* USB2_PHY, power down in CONTROL_DEV_CONF */ |
25 | OMAP_CTRL_TYPE_PIPE3, /* PIPE3 PHY, DPLL & seperate Rx/Tx power */ | 25 | OMAP_CTRL_TYPE_PIPE3, /* PIPE3 PHY, DPLL & seperate Rx/Tx power */ |
@@ -27,7 +27,7 @@ enum omap_control_usb_type { | |||
27 | OMAP_CTRL_TYPE_AM437USB2, /* USB2 PHY, power e.g. AM437x */ | 27 | OMAP_CTRL_TYPE_AM437USB2, /* USB2 PHY, power e.g. AM437x */ |
28 | }; | 28 | }; |
29 | 29 | ||
30 | struct omap_control_usb { | 30 | struct omap_control_phy { |
31 | struct device *dev; | 31 | struct device *dev; |
32 | 32 | ||
33 | u32 __iomem *otghs_control; | 33 | u32 __iomem *otghs_control; |
@@ -36,7 +36,7 @@ struct omap_control_usb { | |||
36 | 36 | ||
37 | struct clk *sys_clk; | 37 | struct clk *sys_clk; |
38 | 38 | ||
39 | enum omap_control_usb_type type; | 39 | enum omap_control_phy_type type; |
40 | }; | 40 | }; |
41 | 41 | ||
42 | enum omap_control_usb_mode { | 42 | enum omap_control_usb_mode { |
@@ -54,14 +54,14 @@ enum omap_control_usb_mode { | |||
54 | #define OMAP_CTRL_DEV_SESSEND BIT(3) | 54 | #define OMAP_CTRL_DEV_SESSEND BIT(3) |
55 | #define OMAP_CTRL_DEV_IDDIG BIT(4) | 55 | #define OMAP_CTRL_DEV_IDDIG BIT(4) |
56 | 56 | ||
57 | #define OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK 0x003FC000 | 57 | #define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK 0x003FC000 |
58 | #define OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT 0xE | 58 | #define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT 0xE |
59 | 59 | ||
60 | #define OMAP_CTRL_USB_PWRCTL_CLK_FREQ_MASK 0xFFC00000 | 60 | #define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK 0xFFC00000 |
61 | #define OMAP_CTRL_USB_PWRCTL_CLK_FREQ_SHIFT 0x16 | 61 | #define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT 0x16 |
62 | 62 | ||
63 | #define OMAP_CTRL_USB3_PHY_TX_RX_POWERON 0x3 | 63 | #define OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON 0x3 |
64 | #define OMAP_CTRL_USB3_PHY_TX_RX_POWEROFF 0x0 | 64 | #define OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF 0x0 |
65 | 65 | ||
66 | #define OMAP_CTRL_USB2_PHY_PD BIT(28) | 66 | #define OMAP_CTRL_USB2_PHY_PD BIT(28) |
67 | 67 | ||
@@ -70,13 +70,13 @@ enum omap_control_usb_mode { | |||
70 | #define AM437X_CTRL_USB2_OTGVDET_EN BIT(19) | 70 | #define AM437X_CTRL_USB2_OTGVDET_EN BIT(19) |
71 | #define AM437X_CTRL_USB2_OTGSESSEND_EN BIT(20) | 71 | #define AM437X_CTRL_USB2_OTGSESSEND_EN BIT(20) |
72 | 72 | ||
73 | #if IS_ENABLED(CONFIG_OMAP_CONTROL_USB) | 73 | #if IS_ENABLED(CONFIG_OMAP_CONTROL_PHY) |
74 | extern void omap_control_usb_phy_power(struct device *dev, int on); | 74 | void omap_control_phy_power(struct device *dev, int on); |
75 | extern void omap_control_usb_set_mode(struct device *dev, | 75 | void omap_control_usb_set_mode(struct device *dev, |
76 | enum omap_control_usb_mode mode); | 76 | enum omap_control_usb_mode mode); |
77 | #else | 77 | #else |
78 | 78 | ||
79 | static inline void omap_control_usb_phy_power(struct device *dev, int on) | 79 | static inline void omap_control_phy_power(struct device *dev, int on) |
80 | { | 80 | { |
81 | } | 81 | } |
82 | 82 | ||
@@ -86,4 +86,4 @@ static inline void omap_control_usb_set_mode(struct device *dev, | |||
86 | } | 86 | } |
87 | #endif | 87 | #endif |
88 | 88 | ||
89 | #endif /* __OMAP_CONTROL_USB_H__ */ | 89 | #endif /* __OMAP_CONTROL_PHY_H__ */ |
diff --git a/include/linux/usb/omap_usb.h b/include/linux/phy/omap_usb.h index 6ae29360e1d2..dc2c541a619b 100644 --- a/include/linux/usb/omap_usb.h +++ b/include/linux/phy/omap_usb.h | |||
@@ -34,14 +34,24 @@ struct omap_usb { | |||
34 | struct usb_phy phy; | 34 | struct usb_phy phy; |
35 | struct phy_companion *comparator; | 35 | struct phy_companion *comparator; |
36 | void __iomem *pll_ctrl_base; | 36 | void __iomem *pll_ctrl_base; |
37 | void __iomem *phy_base; | ||
37 | struct device *dev; | 38 | struct device *dev; |
38 | struct device *control_dev; | 39 | struct device *control_dev; |
39 | struct clk *wkupclk; | 40 | struct clk *wkupclk; |
40 | struct clk *sys_clk; | ||
41 | struct clk *optclk; | 41 | struct clk *optclk; |
42 | u8 is_suspended:1; | 42 | u8 flags; |
43 | }; | 43 | }; |
44 | 44 | ||
45 | struct usb_phy_data { | ||
46 | const char *label; | ||
47 | u8 flags; | ||
48 | }; | ||
49 | |||
50 | /* Driver Flags */ | ||
51 | #define OMAP_USB2_HAS_START_SRP (1 << 0) | ||
52 | #define OMAP_USB2_HAS_SET_VBUS (1 << 1) | ||
53 | #define OMAP_USB2_CALIBRATE_FALSE_DISCONNECT (1 << 2) | ||
54 | |||
45 | #define phy_to_omapusb(x) container_of((x), struct omap_usb, phy) | 55 | #define phy_to_omapusb(x) container_of((x), struct omap_usb, phy) |
46 | 56 | ||
47 | #if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE) | 57 | #if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE) |
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index 3f83459dbb20..e2f5ca96cddc 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h | |||
@@ -149,8 +149,11 @@ struct phy *phy_get(struct device *dev, const char *string); | |||
149 | struct phy *phy_optional_get(struct device *dev, const char *string); | 149 | struct phy *phy_optional_get(struct device *dev, const char *string); |
150 | struct phy *devm_phy_get(struct device *dev, const char *string); | 150 | struct phy *devm_phy_get(struct device *dev, const char *string); |
151 | struct phy *devm_phy_optional_get(struct device *dev, const char *string); | 151 | struct phy *devm_phy_optional_get(struct device *dev, const char *string); |
152 | struct phy *devm_of_phy_get(struct device *dev, struct device_node *np, | ||
153 | const char *con_id); | ||
152 | void phy_put(struct phy *phy); | 154 | void phy_put(struct phy *phy); |
153 | void devm_phy_put(struct device *dev, struct phy *phy); | 155 | void devm_phy_put(struct device *dev, struct phy *phy); |
156 | struct phy *of_phy_get(struct device_node *np, const char *con_id); | ||
154 | struct phy *of_phy_simple_xlate(struct device *dev, | 157 | struct phy *of_phy_simple_xlate(struct device *dev, |
155 | struct of_phandle_args *args); | 158 | struct of_phandle_args *args); |
156 | struct phy *phy_create(struct device *dev, const struct phy_ops *ops, | 159 | struct phy *phy_create(struct device *dev, const struct phy_ops *ops, |
@@ -251,6 +254,13 @@ static inline struct phy *devm_phy_optional_get(struct device *dev, | |||
251 | return ERR_PTR(-ENOSYS); | 254 | return ERR_PTR(-ENOSYS); |
252 | } | 255 | } |
253 | 256 | ||
257 | static inline struct phy *devm_of_phy_get(struct device *dev, | ||
258 | struct device_node *np, | ||
259 | const char *con_id) | ||
260 | { | ||
261 | return ERR_PTR(-ENOSYS); | ||
262 | } | ||
263 | |||
254 | static inline void phy_put(struct phy *phy) | 264 | static inline void phy_put(struct phy *phy) |
255 | { | 265 | { |
256 | } | 266 | } |
@@ -259,6 +269,11 @@ static inline void devm_phy_put(struct device *dev, struct phy *phy) | |||
259 | { | 269 | { |
260 | } | 270 | } |
261 | 271 | ||
272 | static inline struct phy *of_phy_get(struct device_node *np, const char *con_id) | ||
273 | { | ||
274 | return ERR_PTR(-ENOSYS); | ||
275 | } | ||
276 | |||
262 | static inline struct phy *of_phy_simple_xlate(struct device *dev, | 277 | static inline struct phy *of_phy_simple_xlate(struct device *dev, |
263 | struct of_phandle_args *args) | 278 | struct of_phandle_args *args) |
264 | { | 279 | { |