Commit | Line | Data |
---|---|---|
06fb0137 KD |
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. |