1*4882a593Smuzhiyun==================================== 2*4882a593SmuzhiyunSamsung USB 2.0 PHY adaptation layer 3*4882a593Smuzhiyun==================================== 4*4882a593Smuzhiyun 5*4882a593Smuzhiyun1. Description 6*4882a593Smuzhiyun-------------- 7*4882a593Smuzhiyun 8*4882a593SmuzhiyunThe architecture of the USB 2.0 PHY module in Samsung SoCs is similar 9*4882a593Smuzhiyunamong many SoCs. In spite of the similarities it proved difficult to 10*4882a593Smuzhiyuncreate a one driver that would fit all these PHY controllers. Often 11*4882a593Smuzhiyunthe differences were minor and were found in particular bits of the 12*4882a593Smuzhiyunregisters of the PHY. In some rare cases the order of register writes or 13*4882a593Smuzhiyunthe PHY powering up process had to be altered. This adaptation layer is 14*4882a593Smuzhiyuna compromise between having separate drivers and having a single driver 15*4882a593Smuzhiyunwith added support for many special cases. 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun2. Files description 18*4882a593Smuzhiyun-------------------- 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun- phy-samsung-usb2.c 21*4882a593Smuzhiyun This is the main file of the adaptation layer. This file contains 22*4882a593Smuzhiyun the probe function and provides two callbacks to the Generic PHY 23*4882a593Smuzhiyun Framework. This two callbacks are used to power on and power off the 24*4882a593Smuzhiyun phy. They carry out the common work that has to be done on all version 25*4882a593Smuzhiyun of the PHY module. Depending on which SoC was chosen they execute SoC 26*4882a593Smuzhiyun specific callbacks. The specific SoC version is selected by choosing 27*4882a593Smuzhiyun the appropriate compatible string. In addition, this file contains 28*4882a593Smuzhiyun struct of_device_id definitions for particular SoCs. 29*4882a593Smuzhiyun 30*4882a593Smuzhiyun- phy-samsung-usb2.h 31*4882a593Smuzhiyun This is the include file. It declares the structures used by this 32*4882a593Smuzhiyun driver. In addition it should contain extern declarations for 33*4882a593Smuzhiyun structures that describe particular SoCs. 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun3. Supporting SoCs 36*4882a593Smuzhiyun------------------ 37*4882a593Smuzhiyun 38*4882a593SmuzhiyunTo support a new SoC a new file should be added to the drivers/phy 39*4882a593Smuzhiyundirectory. Each SoC's configuration is stored in an instance of the 40*4882a593Smuzhiyunstruct samsung_usb2_phy_config:: 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun struct samsung_usb2_phy_config { 43*4882a593Smuzhiyun const struct samsung_usb2_common_phy *phys; 44*4882a593Smuzhiyun int (*rate_to_clk)(unsigned long, u32 *); 45*4882a593Smuzhiyun unsigned int num_phys; 46*4882a593Smuzhiyun bool has_mode_switch; 47*4882a593Smuzhiyun }; 48*4882a593Smuzhiyun 49*4882a593SmuzhiyunThe num_phys is the number of phys handled by the driver. `*phys` is an 50*4882a593Smuzhiyunarray that contains the configuration for each phy. The has_mode_switch 51*4882a593Smuzhiyunproperty is a boolean flag that determines whether the SoC has USB host 52*4882a593Smuzhiyunand device on a single pair of pins. If so, a special register has to 53*4882a593Smuzhiyunbe modified to change the internal routing of these pins between a USB 54*4882a593Smuzhiyundevice or host module. 55*4882a593Smuzhiyun 56*4882a593SmuzhiyunFor example the configuration for Exynos 4210 is following:: 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun const struct samsung_usb2_phy_config exynos4210_usb2_phy_config = { 59*4882a593Smuzhiyun .has_mode_switch = 0, 60*4882a593Smuzhiyun .num_phys = EXYNOS4210_NUM_PHYS, 61*4882a593Smuzhiyun .phys = exynos4210_phys, 62*4882a593Smuzhiyun .rate_to_clk = exynos4210_rate_to_clk, 63*4882a593Smuzhiyun } 64*4882a593Smuzhiyun 65*4882a593Smuzhiyun- `int (*rate_to_clk)(unsigned long, u32 *)` 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun The rate_to_clk callback is to convert the rate of the clock 68*4882a593Smuzhiyun used as the reference clock for the PHY module to the value 69*4882a593Smuzhiyun that should be written in the hardware register. 70*4882a593Smuzhiyun 71*4882a593SmuzhiyunThe exynos4210_phys configuration array is as follows:: 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun static const struct samsung_usb2_common_phy exynos4210_phys[] = { 74*4882a593Smuzhiyun { 75*4882a593Smuzhiyun .label = "device", 76*4882a593Smuzhiyun .id = EXYNOS4210_DEVICE, 77*4882a593Smuzhiyun .power_on = exynos4210_power_on, 78*4882a593Smuzhiyun .power_off = exynos4210_power_off, 79*4882a593Smuzhiyun }, 80*4882a593Smuzhiyun { 81*4882a593Smuzhiyun .label = "host", 82*4882a593Smuzhiyun .id = EXYNOS4210_HOST, 83*4882a593Smuzhiyun .power_on = exynos4210_power_on, 84*4882a593Smuzhiyun .power_off = exynos4210_power_off, 85*4882a593Smuzhiyun }, 86*4882a593Smuzhiyun { 87*4882a593Smuzhiyun .label = "hsic0", 88*4882a593Smuzhiyun .id = EXYNOS4210_HSIC0, 89*4882a593Smuzhiyun .power_on = exynos4210_power_on, 90*4882a593Smuzhiyun .power_off = exynos4210_power_off, 91*4882a593Smuzhiyun }, 92*4882a593Smuzhiyun { 93*4882a593Smuzhiyun .label = "hsic1", 94*4882a593Smuzhiyun .id = EXYNOS4210_HSIC1, 95*4882a593Smuzhiyun .power_on = exynos4210_power_on, 96*4882a593Smuzhiyun .power_off = exynos4210_power_off, 97*4882a593Smuzhiyun }, 98*4882a593Smuzhiyun {}, 99*4882a593Smuzhiyun }; 100*4882a593Smuzhiyun 101*4882a593Smuzhiyun- `int (*power_on)(struct samsung_usb2_phy_instance *);` 102*4882a593Smuzhiyun `int (*power_off)(struct samsung_usb2_phy_instance *);` 103*4882a593Smuzhiyun 104*4882a593Smuzhiyun These two callbacks are used to power on and power off the phy 105*4882a593Smuzhiyun by modifying appropriate registers. 106*4882a593Smuzhiyun 107*4882a593SmuzhiyunFinal change to the driver is adding appropriate compatible value to the 108*4882a593Smuzhiyunphy-samsung-usb2.c file. In case of Exynos 4210 the following lines were 109*4882a593Smuzhiyunadded to the struct of_device_id samsung_usb2_phy_of_match[] array:: 110*4882a593Smuzhiyun 111*4882a593Smuzhiyun #ifdef CONFIG_PHY_EXYNOS4210_USB2 112*4882a593Smuzhiyun { 113*4882a593Smuzhiyun .compatible = "samsung,exynos4210-usb2-phy", 114*4882a593Smuzhiyun .data = &exynos4210_usb2_phy_config, 115*4882a593Smuzhiyun }, 116*4882a593Smuzhiyun #endif 117*4882a593Smuzhiyun 118*4882a593SmuzhiyunTo add further flexibility to the driver the Kconfig file enables to 119*4882a593Smuzhiyuninclude support for selected SoCs in the compiled driver. The Kconfig 120*4882a593Smuzhiyunentry for Exynos 4210 is following:: 121*4882a593Smuzhiyun 122*4882a593Smuzhiyun config PHY_EXYNOS4210_USB2 123*4882a593Smuzhiyun bool "Support for Exynos 4210" 124*4882a593Smuzhiyun depends on PHY_SAMSUNG_USB2 125*4882a593Smuzhiyun depends on CPU_EXYNOS4210 126*4882a593Smuzhiyun help 127*4882a593Smuzhiyun Enable USB PHY support for Exynos 4210. This option requires that 128*4882a593Smuzhiyun Samsung USB 2.0 PHY driver is enabled and means that support for this 129*4882a593Smuzhiyun particular SoC is compiled in the driver. In case of Exynos 4210 four 130*4882a593Smuzhiyun phys are available - device, host, HSCI0 and HSCI1. 131*4882a593Smuzhiyun 132*4882a593SmuzhiyunThe newly created file that supports the new SoC has to be also added to the 133*4882a593SmuzhiyunMakefile. In case of Exynos 4210 the added line is following:: 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun obj-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o 136*4882a593Smuzhiyun 137*4882a593SmuzhiyunAfter completing these steps the support for the new SoC should be ready. 138