+++ /dev/null
-* APM X-Gene 15Gbps Multi-purpose PHY nodes
-
-PHY nodes are defined to describe on-chip 15Gbps Multi-purpose PHY. Each
-PHY (pair of lanes) has its own node.
-
-Required properties:
-- compatible : Shall be "apm,xgene-phy".
-- reg : PHY memory resource is the SDS PHY access resource.
-- #phy-cells : Shall be 1 as it expects one argument for setting
- the mode of the PHY. Possible values are 0 (SATA),
- 1 (SGMII), 2 (PCIe), 3 (USB), and 4 (XFI).
-
-Optional properties:
-- status : Shall be "ok" if enabled or "disabled" if disabled.
- Default is "ok".
-- clocks : Reference to the clock entry.
-- apm,tx-eye-tuning : Manual control to fine tune the capture of the serial
- bit lines from the automatic calibrated position.
- Two set of 3-tuple setting for each (up to 3)
- supported link speed on the host. Range from 0 to
- 127 in unit of one bit period. Default is 10.
-- apm,tx-eye-direction : Eye tuning manual control direction. 0 means sample
- data earlier than the nominal sampling point. 1 means
- sample data later than the nominal sampling point.
- Two set of 3-tuple setting for each (up to 3)
- supported link speed on the host. Default is 0.
-- apm,tx-boost-gain : Frequency boost AC (LSB 3-bit) and DC (2-bit)
- gain control. Two set of 3-tuple setting for each
- (up to 3) supported link speed on the host. Range is
- between 0 to 31 in unit of dB. Default is 3.
-- apm,tx-amplitude : Amplitude control. Two set of 3-tuple setting for
- each (up to 3) supported link speed on the host.
- Range is between 0 to 199500 in unit of uV.
- Default is 199500 uV.
-- apm,tx-pre-cursor1 : 1st pre-cursor emphasis taps control. Two set of
- 3-tuple setting for each (up to 3) supported link
- speed on the host. Range is 0 to 273000 in unit of
- uV. Default is 0.
-- apm,tx-pre-cursor2 : 2st pre-cursor emphasis taps control. Two set of
- 3-tuple setting for each (up to 3) supported link
- speed on the host. Range is 0 to 127400 in unit uV.
- Default is 0x0.
-- apm,tx-post-cursor : Post-cursor emphasis taps control. Two set of
- 3-tuple setting for Gen1, Gen2, and Gen3. Range is
- between 0 to 0x1f in unit of 18.2mV. Default is 0xf.
-- apm,tx-speed : Tx operating speed. One set of 3-tuple for each
- supported link speed on the host.
- 0 = 1-2Gbps
- 1 = 2-4Gbps (1st tuple default)
- 2 = 4-8Gbps
- 3 = 8-15Gbps (2nd tuple default)
- 4 = 2.5-4Gbps
- 5 = 4-5Gbps
- 6 = 5-6Gbps
- 7 = 6-16Gbps (3rd tuple default)
-
-NOTE: PHY override parameters are board specific setting.
-
-Example:
- phy1: phy@1f21a000 {
- compatible = "apm,xgene-phy";
- reg = <0x0 0x1f21a000 0x0 0x100>;
- #phy-cells = <1>;
- status = "disabled";
- };
-
- phy2: phy@1f22a000 {
- compatible = "apm,xgene-phy";
- reg = <0x0 0x1f22a000 0x0 0x100>;
- #phy-cells = <1>;
- status = "ok";
- };
-
- phy3: phy@1f23a000 {
- compatible = "apm,xgene-phy";
- reg = <0x0 0x1f23a000 0x0 0x100>;
- #phy-cells = <1>;
- status = "ok";
- };
+++ /dev/null
-BROADCOM KONA USB2 PHY
-
-Required properties:
- - compatible: brcm,kona-usb2-phy
- - reg: offset and length of the PHY registers
- - #phy-cells: must be 0
-Refer to phy/phy-bindings.txt for the generic PHY binding properties
-
-Example:
-
- usbphy: usb-phy@3f130000 {
- compatible = "brcm,kona-usb2-phy";
- reg = <0x3f130000 0x28>;
- #phy-cells = <0>;
- };
+++ /dev/null
-Berlin SATA PHY
----------------
-
-Required properties:
-- compatible: should be "marvell,berlin2q-sata-phy"
-- address-cells: should be 1
-- size-cells: should be 0
-- phy-cells: from the generic PHY bindings, must be 1
-- reg: address and length of the register
-- clocks: reference to the clock entry
-
-Sub-nodes:
-Each PHY should be represented as a sub-node.
-
-Sub-nodes required properties:
-- reg: the PHY number
-
-Example:
- sata_phy: phy@f7e900a0 {
- compatible = "marvell,berlin2q-sata-phy";
- reg = <0xf7e900a0 0x200>;
- clocks = <&chip CLKID_SATA>;
- #address-cells = <1>;
- #size-cells = <0>;
- #phy-cells = <1>;
-
- sata-phy@0 {
- reg = <0>;
- };
-
- sata-phy@1 {
- reg = <1>;
- };
- };
+++ /dev/null
-Hisilicon hix5hd2 SATA PHY
------------------------
-
-Required properties:
-- compatible: should be "hisilicon,hix5hd2-sata-phy"
-- reg: offset and length of the PHY registers
-- #phy-cells: must be 0
-Refer to phy/phy-bindings.txt for the generic PHY binding properties
-
-Optional Properties:
-- hisilicon,peripheral-syscon: phandle of syscon used to control peripheral.
-- hisilicon,power-reg: offset and bit number within peripheral-syscon,
- register of controlling sata power supply.
-
-Example:
- sata_phy: phy@f9900000 {
- compatible = "hisilicon,hix5hd2-sata-phy";
- reg = <0xf9900000 0x10000>;
- #phy-cells = <0>;
- hisilicon,peripheral-syscon = <&peripheral_ctrl>;
- hisilicon,power-reg = <0x8 10>;
- };
+++ /dev/null
-This document explains only the device tree data binding. For general
-information about PHY subsystem refer to Documentation/phy.txt
-
-PHY device node
-===============
-
-Required Properties:
-#phy-cells: Number of cells in a PHY specifier; The meaning of all those
- cells is defined by the binding for the phy node. The PHY
- provider can use the values in cells to find the appropriate
- PHY.
-
-Optional Properties:
-phy-supply: Phandle to a regulator that provides power to the PHY. This
- regulator will be managed during the PHY power on/off sequence.
-
-For example:
-
-phys: phy {
- compatible = "xxx";
- reg = <...>;
- .
- .
- #phy-cells = <1>;
- .
- .
-};
-
-That node describes an IP block (PHY provider) that implements 2 different PHYs.
-In order to differentiate between these 2 PHYs, an additional specifier should be
-given while trying to get a reference to it.
-
-PHY user node
-=============
-
-Required Properties:
-phys : the phandle for the PHY device (used by the PHY subsystem)
-phy-names : the names of the PHY corresponding to the PHYs present in the
- *phys* phandle
-
-Example 1:
-usb1: usb_otg_ss@xxx {
- compatible = "xxx";
- reg = <xxx>;
- .
- .
- phys = <&usb2_phy>, <&usb3_phy>;
- phy-names = "usb2phy", "usb3phy";
- .
- .
-};
-
-This node represents a controller that uses two PHYs, one for usb2 and one for
-usb3.
-
-Example 2:
-usb2: usb_otg_ss@xxx {
- compatible = "xxx";
- reg = <xxx>;
- .
- .
- phys = <&phys 1>;
- phy-names = "usbphy";
- .
- .
-};
-
-This node represents a controller that uses one of the PHYs of the PHY provider
-device defined previously. Note that the phy handle has an additional specifier
-"1" to differentiate between the two PHYs.
+++ /dev/null
-STMicroelectronics STi MIPHY365x PHY binding
-============================================
-
-This binding describes a miphy device that is used to control PHY hardware
-for SATA and PCIe.
-
-Required properties (controller (parent) node):
-- compatible : Should be "st,miphy365x-phy"
-- st,syscfg : Should be a phandle of the system configuration register group
- which contain the SATA, PCIe mode setting bits
-
-Required nodes : A sub-node is required for each channel the controller
- provides. Address range information including the usual
- 'reg' and 'reg-names' properties are used inside these
- nodes to describe the controller's topology. These nodes
- are translated by the driver's .xlate() function.
-
-Required properties (port (child) node):
-- #phy-cells : Should be 1 (See second example)
- Cell after port phandle is device type from:
- - MIPHY_TYPE_SATA
- - MIPHY_TYPE_PCI
-- reg : Address and length of register sets for each device in
- "reg-names"
-- reg-names : The names of the register addresses corresponding to the
- registers filled in "reg":
- - sata: For SATA devices
- - pcie: For PCIe devices
- - syscfg: To specify the syscfg based config register
-
-Optional properties (port (child) node):
-- st,sata-gen : Generation of locally attached SATA IP. Expected values
- are {1,2,3). If not supplied generation 1 hardware will
- be expected
-- st,pcie-tx-pol-inv : Bool property to invert the polarity PCIe Tx (Txn/Txp)
-- st,sata-tx-pol-inv : Bool property to invert the polarity SATA Tx (Txn/Txp)
-
-Example:
-
- miphy365x_phy: miphy365x@fe382000 {
- compatible = "st,miphy365x-phy";
- st,syscfg = <&syscfg_rear>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
-
- phy_port0: port@fe382000 {
- reg = <0xfe382000 0x100>, <0xfe394000 0x100>, <0x824 0x4>;
- reg-names = "sata", "pcie", "syscfg";
- #phy-cells = <1>;
- st,sata-gen = <3>;
- };
-
- phy_port1: port@fe38a000 {
- reg = <0xfe38a000 0x100>, <0xfe804000 0x100>, <0x828 0x4>;;
- reg-names = "sata", "pcie", "syscfg";
- #phy-cells = <1>;
- st,pcie-tx-pol-inv;
- };
- };
-
-Specifying phy control of devices
-=================================
-
-Device nodes should specify the configuration required in their "phys"
-property, containing a phandle to the phy port node and a device type.
-
-Example:
-
-#include <dt-bindings/phy/phy-miphy365x.h>
-
- sata0: sata@fe380000 {
- ...
- phys = <&phy_port0 MIPHY_TYPE_SATA>;
- ...
- };
+++ /dev/null
-ST STiH407 USB PHY controller
-
-This file documents the dt bindings for the usb picoPHY driver which is the PHY for both USB2 and USB3
-host controllers (when controlling usb2/1.1 devices) available on STiH407 SoC family from STMicroelectronics.
-
-Required properties:
-- compatible : should be "st,stih407-usb2-phy"
-- reg : contain the offset and length of the system configuration registers
- used as glue logic to control & parameter phy
-- reg-names : the names of the system configuration registers in "reg", should be "param" and "reg"
-- st,syscfg : sysconfig register to manage phy parameter at driver level
-- resets : list of phandle and reset specifier pairs. There should be two entries, one
- for the whole phy and one for the port
-- reset-names : list of reset signal names. Should be "global" and "port"
-See: Documentation/devicetree/bindings/reset/st,sti-powerdown.txt
-See: Documentation/devicetree/bindings/reset/reset.txt
-
-Example:
-
-usb2_picophy0: usbpicophy@f8 {
- compatible = "st,stih407-usb2-phy";
- reg = <0xf8 0x04>, /* syscfg 5062 */
- <0xf4 0x04>; /* syscfg 5061 */
- reg-names = "param", "ctrl";
- #phy-cells = <0>;
- st,syscfg = <&syscfg_core>;
- resets = <&softreset STIH407_PICOPHY_SOFTRESET>,
- <&picophyreset STIH407_PICOPHY0_RESET>;
- reset-names = "global", "port";
-};
+++ /dev/null
-STMicroelectronics STiH41x USB PHY binding
-------------------------------------------
-
-This file contains documentation for the usb phy found in STiH415/6 SoCs from
-STMicroelectronics.
-
-Required properties:
-- compatible : should be "st,stih416-usb-phy" or "st,stih415-usb-phy"
-- st,syscfg : should be a phandle of the syscfg node
-- clock-names : must contain "osc_phy"
-- clocks : must contain an entry for each name in clock-names.
-See: Documentation/devicetree/bindings/clock/clock-bindings.txt
-- #phy-cells : must be 0 for this phy
-See: Documentation/devicetree/bindings/phy/phy-bindings.txt
-
-Example:
-
-usb2_phy: usb2phy@0 {
- compatible = "st,stih416-usb-phy";
- #phy-cell = <0>;
- st,syscfg = <&syscfg_rear>;
- clocks = <&clk_sysin>;
- clock-names = "osc_phy";
-};
+++ /dev/null
-Qualcomm APQ8064 SATA PHY Controller
-------------------------------------
-
-SATA PHY nodes are defined to describe on-chip SATA Physical layer controllers.
-Each SATA PHY controller should have its own node.
-
-Required properties:
-- compatible: compatible list, contains "qcom,apq8064-sata-phy".
-- reg: offset and length of the SATA PHY register set;
-- #phy-cells: must be zero
-- clocks: a list of phandles and clock-specifier pairs, one for each entry in
- clock-names.
-- clock-names: must be "cfg" for phy config clock.
-
-Example:
- sata_phy: sata-phy@1b400000 {
- compatible = "qcom,apq8064-sata-phy";
- reg = <0x1b400000 0x200>;
-
- clocks = <&gcc SATA_PHY_CFG_CLK>;
- clock-names = "cfg";
-
- #phy-cells = <0>;
- };
+++ /dev/null
-Qualcomm DWC3 HS AND SS PHY CONTROLLER
---------------------------------------
-
-DWC3 PHY nodes are defined to describe on-chip Synopsis Physical layer
-controllers. Each DWC3 PHY controller should have its own node.
-
-Required properties:
-- compatible: should contain one of the following:
- - "qcom,dwc3-hs-usb-phy" for High Speed Synopsis PHY controller
- - "qcom,dwc3-ss-usb-phy" for Super Speed Synopsis PHY controller
-- reg: offset and length of the DWC3 PHY controller register set
-- #phy-cells: must be zero
-- clocks: a list of phandles and clock-specifier pairs, one for each entry in
- clock-names.
-- clock-names: Should contain "ref" for the PHY reference clock
-
-Optional clocks:
- "xo" External reference clock
-
-Example:
- phy@100f8800 {
- compatible = "qcom,dwc3-hs-usb-phy";
- reg = <0x100f8800 0x30>;
- clocks = <&gcc USB30_0_UTMI_CLK>;
- clock-names = "ref";
- #phy-cells = <0>;
-
- status = "ok";
- };
-
- phy@100f8830 {
- compatible = "qcom,dwc3-ss-usb-phy";
- reg = <0x100f8830 0x30>;
- clocks = <&gcc USB30_0_MASTER_CLK>;
- clock-names = "ref";
- #phy-cells = <0>;
-
- status = "ok";
- };
+++ /dev/null
-Qualcomm IPQ806x SATA PHY Controller
-------------------------------------
-
-SATA PHY nodes are defined to describe on-chip SATA Physical layer controllers.
-Each SATA PHY controller should have its own node.
-
-Required properties:
-- compatible: compatible list, contains "qcom,ipq806x-sata-phy"
-- reg: offset and length of the SATA PHY register set;
-- #phy-cells: must be zero
-- clocks: must be exactly one entry
-- clock-names: must be "cfg"
-
-Example:
- sata_phy: sata-phy@1b400000 {
- compatible = "qcom,ipq806x-sata-phy";
- reg = <0x1b400000 0x200>;
-
- clocks = <&gcc SATA_PHY_CFG_CLK>;
- clock-names = "cfg";
-
- #phy-cells = <0>;
- };
+++ /dev/null
-* Renesas R-Car generation 2 USB PHY
-
-This file provides information on what the device node for the R-Car generation
-2 USB PHY contains.
-
-Required properties:
-- compatible: "renesas,usb-phy-r8a7790" if the device is a part of R8A7790 SoC.
- "renesas,usb-phy-r8a7791" if the device is a part of R8A7791 SoC.
-- reg: offset and length of the register block.
-- #address-cells: number of address cells for the USB channel subnodes, must
- be <1>.
-- #size-cells: number of size cells for the USB channel subnodes, must be <0>.
-- clocks: clock phandle and specifier pair.
-- clock-names: string, clock input name, must be "usbhs".
-
-The USB PHY device tree node should have the subnodes corresponding to the USB
-channels. These subnodes must contain the following properties:
-- reg: the USB controller selector; see the table below for the values.
-- #phy-cells: see phy-bindings.txt in the same directory, must be <1>.
-
-The phandle's argument in the PHY specifier is the USB controller selector for
-the USB channel; see the selector meanings below:
-
-+-----------+---------------+---------------+
-|\ Selector | | |
-+ --------- + 0 | 1 |
-| Channel \| | |
-+-----------+---------------+---------------+
-| 0 | PCI EHCI/OHCI | HS-USB |
-| 2 | PCI EHCI/OHCI | xHCI |
-+-----------+---------------+---------------+
-
-Example (Lager board):
-
- usb-phy@e6590100 {
- compatible = "renesas,usb-phy-r8a7790";
- reg = <0 0xe6590100 0 0x100>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&mstp7_clks R8A7790_CLK_HSUSB>;
- clock-names = "usbhs";
-
- usb-channel@0 {
- reg = <0>;
- #phy-cells = <1>;
- };
- usb-channel@2 {
- reg = <2>;
- #phy-cells = <1>;
- };
- };
+++ /dev/null
-ROCKCHIP USB2 PHY
-
-Required properties:
- - compatible: rockchip,rk3288-usb-phy
- - rockchip,grf : phandle to the syscon managing the "general
- register files"
- - #phy-cells: must be 1
-Refer to phy/phy-bindings.txt for the generic PHY binding
-properties
-
-Example:
-
- usbphy: phy {
- #phy-cells = <1>;
- compatible = "rockchip,rk3288-usb-phy";
- rockchip,grf = <&grf>;
- };
+++ /dev/null
-Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY
--------------------------------------------------
-
-Required properties:
-- compatible : should be "samsung,s5pv210-mipi-video-phy";
-- reg : offset and length of the MIPI DPHY register set;
-- #phy-cells : from the generic phy bindings, must be 1;
-
-For "samsung,s5pv210-mipi-video-phy" compatible PHYs the second cell in
-the PHY specifier identifies the PHY and its meaning is as follows:
- 0 - MIPI CSIS 0,
- 1 - MIPI DSIM 0,
- 2 - MIPI CSIS 1,
- 3 - MIPI DSIM 1.
-
-Samsung EXYNOS SoC series Display Port PHY
--------------------------------------------------
-
-Required properties:
-- compatible : should be one of the following supported values:
- - "samsung,exynos5250-dp-video-phy"
- - "samsung,exynos5420-dp-video-phy"
-- samsung,pmu-syscon: phandle for PMU system controller interface, used to
- control pmu registers for power isolation.
-- #phy-cells : from the generic PHY bindings, must be 0;
-
-Samsung S5P/EXYNOS SoC series USB PHY
--------------------------------------------------
-
-Required properties:
-- compatible : should be one of the listed compatibles:
- - "samsung,exynos3250-usb2-phy"
- - "samsung,exynos4210-usb2-phy"
- - "samsung,exynos4x12-usb2-phy"
- - "samsung,exynos5250-usb2-phy"
- - "samsung,s5pv210-usb2-phy"
-- reg : a list of registers used by phy driver
- - first and obligatory is the location of phy modules registers
-- samsung,sysreg-phandle - handle to syscon used to control the system registers
-- samsung,pmureg-phandle - handle to syscon used to control PMU registers
-- #phy-cells : from the generic phy bindings, must be 1;
-- clocks and clock-names:
- - the "phy" clock is required by the phy module, used as a gate
- - the "ref" clock is used to get the rate of the clock provided to the
- PHY module
-
-The first phandle argument in the PHY specifier identifies the PHY, its
-meaning is compatible dependent. For the currently supported SoCs (Exynos 4210
-and Exynos 4212) it is as follows:
- 0 - USB device ("device"),
- 1 - USB host ("host"),
- 2 - HSIC0 ("hsic0"),
- 3 - HSIC1 ("hsic1"),
-Exynos3250 has only USB device phy available as phy 0.
-
-Exynos 4210 and Exynos 4212 use mode switching and require that mode switch
-register is supplied.
-
-Example:
-
-For Exynos 4412 (compatible with Exynos 4212):
-
-usbphy: phy@125b0000 {
- compatible = "samsung,exynos4x12-usb2-phy";
- reg = <0x125b0000 0x100>;
- clocks = <&clock 305>, <&clock 2>;
- clock-names = "phy", "ref";
- status = "okay";
- #phy-cells = <1>;
- samsung,sysreg-phandle = <&sys_reg>;
- samsung,pmureg-phandle = <&pmu_reg>;
-};
-
-Then the PHY can be used in other nodes such as:
-
-phy-consumer@12340000 {
- phys = <&usbphy 2>;
- phy-names = "phy";
-};
-
-Refer to DT bindings documentation of particular PHY consumer devices for more
-information about required PHYs and the way of specification.
-
-Samsung SATA PHY Controller
----------------------------
-
-SATA PHY nodes are defined to describe on-chip SATA Physical layer controllers.
-Each SATA PHY controller should have its own node.
-
-Required properties:
-- compatible : compatible list, contains "samsung,exynos5250-sata-phy"
-- reg : offset and length of the SATA PHY register set;
-- #phy-cells : must be zero
-- clocks : must be exactly one entry
-- clock-names : must be "sata_phyctrl"
-- samsung,exynos-sataphy-i2c-phandle : a phandle to the I2C device, no arguments
-- samsung,syscon-phandle : a phandle to the PMU system controller, no arguments
-
-Example:
- sata_phy: sata-phy@12170000 {
- compatible = "samsung,exynos5250-sata-phy";
- reg = <0x12170000 0x1ff>;
- clocks = <&clock 287>;
- clock-names = "sata_phyctrl";
- #phy-cells = <0>;
- samsung,exynos-sataphy-i2c-phandle = <&sata_phy_i2c>;
- samsung,syscon-phandle = <&pmu_syscon>;
- };
-
-Device-Tree bindings for sataphy i2c client driver
---------------------------------------------------
-
-Required properties:
-compatible: Should be "samsung,exynos-sataphy-i2c"
-- reg: I2C address of the sataphy i2c device.
-
-Example:
-
- sata_phy_i2c:sata-phy@38 {
- compatible = "samsung,exynos-sataphy-i2c";
- reg = <0x38>;
- };
-
-Samsung Exynos5 SoC series USB DRD PHY controller
---------------------------------------------------
-
-Required properties:
-- compatible : Should be set to one of the following supported values:
- - "samsung,exynos5250-usbdrd-phy" - for exynos5250 SoC,
- - "samsung,exynos5420-usbdrd-phy" - for exynos5420 SoC.
-- reg : Register offset and length of USB DRD PHY register set;
-- clocks: Clock IDs array as required by the controller
-- clock-names: names of clocks correseponding to IDs in the clock property;
- Required clocks:
- - phy: main PHY clock (same as USB DRD controller i.e. DWC3 IP clock),
- used for register access.
- - ref: PHY's reference clock (usually crystal clock), used for
- PHY operations, associated by phy name. It is used to
- determine bit values for clock settings register.
- For Exynos5420 this is given as 'sclk_usbphy30' in CMU.
-- samsung,pmu-syscon: phandle for PMU system controller interface, used to
- control pmu registers for power isolation.
-- #phy-cells : from the generic PHY bindings, must be 1;
-
-For "samsung,exynos5250-usbdrd-phy" and "samsung,exynos5420-usbdrd-phy"
-compatible PHYs, the second cell in the PHY specifier identifies the
-PHY id, which is interpreted as follows:
- 0 - UTMI+ type phy,
- 1 - PIPE3 type phy,
-
-Example:
- usbdrd_phy: usbphy@12100000 {
- compatible = "samsung,exynos5250-usbdrd-phy";
- reg = <0x12100000 0x100>;
- clocks = <&clock 286>, <&clock 1>;
- clock-names = "phy", "ref";
- samsung,pmu-syscon = <&pmu_system_controller>;
- #phy-cells = <1>;
- };
-
-- aliases: For SoCs like Exynos5420 having multiple USB 3.0 DRD PHY controllers,
- 'usbdrd_phy' nodes should have numbered alias in the aliases node,
- in the form of usbdrdphyN, N = 0, 1... (depending on number of
- controllers).
-Example:
- aliases {
- usbdrdphy0 = &usb3_phy0;
- usbdrdphy1 = &usb3_phy1;
- };
+++ /dev/null
-ST SPEAr miphy DT details
-=========================
-
-ST Microelectronics SPEAr miphy is a phy controller supporting PCIe and SATA.
-
-Required properties:
-- compatible : should be "st,spear1310-miphy" or "st,spear1340-miphy"
-- reg : offset and length of the PHY register set.
-- misc: phandle for the syscon node to access misc registers
-- #phy-cells : from the generic PHY bindings, must be 1.
- - cell[1]: 0 if phy used for SATA, 1 for PCIe.
-
-Optional properties:
-- phy-id: Instance id of the phy. Only required when there are multiple phys
- present on a implementation.
+++ /dev/null
-Allwinner sun4i USB PHY
------------------------
-
-Required properties:
-- compatible : should be one of
- * allwinner,sun4i-a10-usb-phy
- * allwinner,sun5i-a13-usb-phy
- * allwinner,sun6i-a31-usb-phy
- * allwinner,sun7i-a20-usb-phy
-- reg : a list of offset + length pairs
-- reg-names :
- * "phy_ctrl"
- * "pmu1"
- * "pmu2" for sun4i, sun6i or sun7i
-- #phy-cells : from the generic phy bindings, must be 1
-- clocks : phandle + clock specifier for the phy clocks
-- clock-names :
- * "usb_phy" for sun4i, sun5i or sun7i
- * "usb0_phy", "usb1_phy" and "usb2_phy" for sun6i
-- resets : a list of phandle + reset specifier pairs
-- reset-names :
- * "usb0_reset"
- * "usb1_reset"
- * "usb2_reset" for sun4i, sun6i or sun7i
-
-Example:
- usbphy: phy@0x01c13400 {
- #phy-cells = <1>;
- compatible = "allwinner,sun4i-a10-usb-phy";
- /* phy base regs, phy1 pmu reg, phy2 pmu reg */
- reg = <0x01c13400 0x10 0x01c14800 0x4 0x01c1c800 0x4>;
- reg-names = "phy_ctrl", "pmu1", "pmu2";
- clocks = <&usb_clk 8>;
- clock-names = "usb_phy";
- resets = <&usb_clk 1>, <&usb_clk 2>;
- reset-names = "usb1_reset", "usb2_reset";
- };
+++ /dev/null
-TI PHY: DT DOCUMENTATION FOR PHYs in TI PLATFORMs
-
-OMAP CONTROL PHY
-
-Required properties:
- - compatible: Should be one of
- "ti,control-phy-otghs" - if it has otghs_control mailbox register as on OMAP4.
- "ti,control-phy-usb2" - if it has Power down bit in control_dev_conf register
- e.g. USB2_PHY on OMAP5.
- "ti,control-phy-pipe3" - if it has DPLL and individual Rx & Tx power control
- e.g. USB3 PHY and SATA PHY on OMAP5.
- "ti,control-phy-pcie" - for pcie to support external clock for pcie and to
- set PCS delay value.
- e.g. PCIE PHY in DRA7x
- "ti,control-phy-usb2-dra7" - if it has power down register like USB2 PHY on
- DRA7 platform.
- "ti,control-phy-usb2-am437" - if it has power down register like USB2 PHY on
- AM437 platform.
- - reg : register ranges as listed in the reg-names property
- - reg-names: "otghs_control" for control-phy-otghs
- "power", "pcie_pcs" and "control_sma" for control-phy-pcie
- "power" for all other types
-
-omap_control_usb: omap-control-usb@4a002300 {
- compatible = "ti,control-phy-otghs";
- reg = <0x4a00233c 0x4>;
- reg-names = "otghs_control";
-};
-
-OMAP USB2 PHY
-
-Required properties:
- - compatible: Should be "ti,omap-usb2"
- - reg : Address and length of the register set for the device.
- - #phy-cells: determine the number of cells that should be given in the
- phandle while referencing this phy.
- - clocks: a list of phandles and clock-specifier pairs, one for each entry in
- clock-names.
- - clock-names: should include:
- * "wkupclk" - wakeup clock.
- * "refclk" - reference clock (optional).
-
-Optional properties:
- - ctrl-module : phandle of the control module used by PHY driver to power on
- the PHY.
-
-This is usually a subnode of ocp2scp to which it is connected.
-
-usb2phy@4a0ad080 {
- compatible = "ti,omap-usb2";
- reg = <0x4a0ad080 0x58>;
- ctrl-module = <&omap_control_usb>;
- #phy-cells = <0>;
- clocks = <&usb_phy_cm_clk32k>, <&usb_otg_ss_refclk960m>;
- clock-names = "wkupclk", "refclk";
-};
-
-TI PIPE3 PHY
-
-Required properties:
- - compatible: Should be "ti,phy-usb3", "ti,phy-pipe3-sata" or
- "ti,phy-pipe3-pcie. "ti,omap-usb3" is deprecated.
- - reg : Address and length of the register set for the device.
- - reg-names: The names of the register addresses corresponding to the registers
- filled in "reg".
- - #phy-cells: determine the number of cells that should be given in the
- phandle while referencing this phy.
- - clocks: a list of phandles and clock-specifier pairs, one for each entry in
- clock-names.
- - clock-names: should include:
- * "wkupclk" - wakeup clock.
- * "sysclk" - system clock.
- * "refclk" - reference clock.
- * "dpll_ref" - external dpll ref clk
- * "dpll_ref_m2" - external dpll ref clk
- * "phy-div" - divider for apll
- * "div-clk" - apll clock
-
-Optional properties:
- - ctrl-module : phandle of the control module used by PHY driver to power on
- the PHY.
- - id: If there are multiple instance of the same type, in order to
- differentiate between each instance "id" can be used (e.g., multi-lane PCIe
- PHY). If "id" is not provided, it is set to default value of '1'.
-
-This is usually a subnode of ocp2scp to which it is connected.
-
-usb3phy@4a084400 {
- compatible = "ti,phy-usb3";
- reg = <0x4a084400 0x80>,
- <0x4a084800 0x64>,
- <0x4a084c00 0x40>;
- reg-names = "phy_rx", "phy_tx", "pll_ctrl";
- ctrl-module = <&omap_control_usb>;
- #phy-cells = <0>;
- clocks = <&usb_phy_cm_clk32k>,
- <&sys_clkin>,
- <&usb_otg_ss_refclk960m>;
- clock-names = "wkupclk",
- "sysclk",
- "refclk";
-};
source "drivers/reset/Kconfig"
-source "drivers/phy/Kconfig"
-
source "drivers/gator/Kconfig"
source "drivers/headset_observe/Kconfig"
obj-y += irqchip/
obj-y += bus/
-obj-$(CONFIG_GENERIC_PHY) += phy/
-
# GPIO must come after pinctrl as gpios may need to mux pins etc
obj-y += pinctrl/
obj-y += gpio/
+++ /dev/null
-#
-# PHY
-#
-
-menu "PHY Subsystem"
-
-config GENERIC_PHY
- bool "PHY Core"
- help
- Generic PHY support.
-
- This framework is designed to provide a generic interface for PHY
- devices present in the kernel. This layer will have the generic
- API by which phy drivers can create PHY using the phy framework and
- phy users can obtain reference to the PHY. All the users of this
- framework should select this config.
-
-config PHY_BERLIN_SATA
- tristate "Marvell Berlin SATA PHY driver"
- depends on ARCH_BERLIN && HAS_IOMEM && OF
- select GENERIC_PHY
- help
- Enable this to support the SATA PHY on Marvell Berlin SoCs.
-
-config PHY_EXYNOS_MIPI_VIDEO
- tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver"
- depends on HAS_IOMEM
- depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
- select GENERIC_PHY
- default y if ARCH_S5PV210 || ARCH_EXYNOS
- help
- Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P
- and EXYNOS SoCs.
-
-config PHY_MVEBU_SATA
- def_bool y
- depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
- depends on OF
- select GENERIC_PHY
-
-config PHY_MIPHY365X
- tristate "STMicroelectronics MIPHY365X PHY driver for STiH41x series"
- depends on ARCH_STI
- depends on HAS_IOMEM
- depends on OF
- select GENERIC_PHY
- help
- Enable this to support the miphy transceiver (for SATA/PCIE)
- that is part of STMicroelectronics STiH41x SoC series.
-
-config PHY_RCAR_GEN2
- tristate "Renesas R-Car generation 2 USB PHY driver"
- depends on ARCH_SHMOBILE
- depends on GENERIC_PHY
- help
- Support for USB PHY found on Renesas R-Car generation 2 SoCs.
-
-config OMAP_CONTROL_PHY
- tristate "OMAP CONTROL PHY Driver"
- depends on ARCH_OMAP2PLUS || COMPILE_TEST
- help
- Enable this to add support for the PHY part present in the control
- module. This driver has API to power on the USB2 PHY and to write to
- the mailbox. The mailbox is present only in omap4 and the register to
- power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an
- additional register to power on USB3 PHY/SATA PHY/PCIE PHY
- (PIPE3 PHY).
-
-config OMAP_USB2
- tristate "OMAP USB2 PHY Driver"
- depends on ARCH_OMAP2PLUS
- depends on USB_PHY
- select GENERIC_PHY
- select OMAP_CONTROL_PHY
- depends on OMAP_OCP2SCP
- help
- Enable this to support the transceiver that is part of SOC. This
- driver takes care of all the PHY functionality apart from comparator.
- The USB OTG controller communicates with the comparator using this
- driver.
-
-config TI_PIPE3
- tristate "TI PIPE3 PHY Driver"
- depends on ARCH_OMAP2PLUS || COMPILE_TEST
- select GENERIC_PHY
- select OMAP_CONTROL_PHY
- depends on OMAP_OCP2SCP
- help
- Enable this to support the PIPE3 PHY that is part of TI SOCs. This
- driver takes care of all the PHY functionality apart from comparator.
- This driver interacts with the "OMAP Control PHY Driver" to power
- on/off the PHY.
-
-config TWL4030_USB
- tristate "TWL4030 USB Transceiver Driver"
- depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
- depends on USB_PHY
- select GENERIC_PHY
- help
- Enable this to support the USB OTG transceiver on TWL4030
- family chips (including the TWL5030 and TPS659x0 devices).
- This transceiver supports high and full speed devices plus,
- in host mode, low speed.
-
-config PHY_EXYNOS_DP_VIDEO
- tristate "EXYNOS SoC series Display Port PHY driver"
- depends on OF
- depends on ARCH_EXYNOS || COMPILE_TEST
- default ARCH_EXYNOS
- select GENERIC_PHY
- help
- Support for Display Port PHY found on Samsung EXYNOS SoCs.
-
-config BCM_KONA_USB2_PHY
- tristate "Broadcom Kona USB2 PHY Driver"
- depends on HAS_IOMEM
- select GENERIC_PHY
- help
- Enable this to support the Broadcom Kona USB 2.0 PHY.
-
-config PHY_EXYNOS5250_SATA
- tristate "Exynos5250 Sata SerDes/PHY driver"
- depends on SOC_EXYNOS5250
- depends on HAS_IOMEM
- depends on OF
- select GENERIC_PHY
- select I2C
- select I2C_S3C2410
- select MFD_SYSCON
- help
- Enable this to support SATA SerDes/Phy found on Samsung's
- Exynos5250 based SoCs.This SerDes/Phy supports SATA 1.5 Gb/s,
- SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host
- port to accept one SATA device.
-
-config PHY_HIX5HD2_SATA
- tristate "HIX5HD2 SATA PHY Driver"
- depends on ARCH_HIX5HD2 && OF && HAS_IOMEM
- select GENERIC_PHY
- select MFD_SYSCON
- help
- Support for SATA PHY on Hisilicon hix5hd2 Soc.
-
-config PHY_SUN4I_USB
- tristate "Allwinner sunxi SoC USB PHY driver"
- depends on ARCH_SUNXI && HAS_IOMEM && OF
- depends on RESET_CONTROLLER
- select GENERIC_PHY
- help
- Enable this to support the transceiver that is part of Allwinner
- sunxi SoCs.
-
- This driver controls the entire USB PHY block, both the USB OTG
- parts, as well as the 2 regular USB 2 host PHYs.
-
-config PHY_SAMSUNG_USB2
- tristate "Samsung USB 2.0 PHY driver"
- depends on HAS_IOMEM
- depends on USB_EHCI_EXYNOS || USB_OHCI_EXYNOS || USB_DWC2
- select GENERIC_PHY
- select MFD_SYSCON
- default ARCH_EXYNOS
- help
- Enable this to support the Samsung USB 2.0 PHY driver for Samsung
- SoCs. This driver provides the interface for USB 2.0 PHY. Support
- for particular PHYs will be enabled based on the SoC type in addition
- to this driver.
-
-config PHY_S5PV210_USB2
- bool "Support for S5PV210"
- depends on PHY_SAMSUNG_USB2
- depends on ARCH_S5PV210
- help
- Enable USB PHY support for S5PV210. This option requires that Samsung
- USB 2.0 PHY driver is enabled and means that support for this
- particular SoC is compiled in the driver. In case of S5PV210 two phys
- are available - device and host.
-
-config PHY_EXYNOS4210_USB2
- bool
- depends on PHY_SAMSUNG_USB2
- default CPU_EXYNOS4210
-
-config PHY_EXYNOS4X12_USB2
- bool
- depends on PHY_SAMSUNG_USB2
- default SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412
-
-config PHY_EXYNOS5250_USB2
- bool
- depends on PHY_SAMSUNG_USB2
- default SOC_EXYNOS5250 || SOC_EXYNOS5420
-
-config PHY_EXYNOS5_USBDRD
- tristate "Exynos5 SoC series USB DRD PHY driver"
- depends on ARCH_EXYNOS5 && OF
- depends on HAS_IOMEM
- depends on USB_DWC3_EXYNOS
- select GENERIC_PHY
- select MFD_SYSCON
- default y
- help
- Enable USB DRD PHY support for Exynos 5 SoC series.
- This driver provides PHY interface for USB 3.0 DRD controller
- present on Exynos5 SoC series.
-
-config PHY_QCOM_APQ8064_SATA
- tristate "Qualcomm APQ8064 SATA SerDes/PHY driver"
- depends on ARCH_QCOM
- depends on HAS_IOMEM
- depends on OF
- select GENERIC_PHY
-
-config PHY_QCOM_IPQ806X_SATA
- tristate "Qualcomm IPQ806x SATA SerDes/PHY driver"
- depends on ARCH_QCOM
- depends on HAS_IOMEM
- depends on OF
- select GENERIC_PHY
-
-config PHY_ST_SPEAR1310_MIPHY
- tristate "ST SPEAR1310-MIPHY driver"
- select GENERIC_PHY
- depends on MACH_SPEAR1310 || COMPILE_TEST
- help
- Support for ST SPEAr1310 MIPHY which can be used for PCIe and SATA.
-
-config PHY_ST_SPEAR1340_MIPHY
- tristate "ST SPEAR1340-MIPHY driver"
- select GENERIC_PHY
- depends on MACH_SPEAR1340 || COMPILE_TEST
- help
- Support for ST SPEAr1340 MIPHY which can be used for PCIe and SATA.
-
-config PHY_XGENE
- tristate "APM X-Gene 15Gbps PHY support"
- depends on HAS_IOMEM && OF && (ARM64 || COMPILE_TEST)
- select GENERIC_PHY
- help
- This option enables support for APM X-Gene SoC multi-purpose PHY.
-
-config PHY_STIH407_USB
- tristate "STMicroelectronics USB2 picoPHY driver for STiH407 family"
- depends on RESET_CONTROLLER
- depends on ARCH_STI || COMPILE_TEST
- select GENERIC_PHY
- help
- Enable this support to enable the picoPHY device used by USB2
- and USB3 controllers on STMicroelectronics STiH407 SoC families.
-
-config PHY_STIH41X_USB
- tristate "STMicroelectronics USB2 PHY driver for STiH41x series"
- depends on ARCH_STI
- select GENERIC_PHY
- help
- Enable this to support the USB transceiver that is part of
- STMicroelectronics STiH41x SoC series.
-
-endmenu
+++ /dev/null
-#
-# Makefile for the phy drivers.
-#
-
-obj-$(CONFIG_GENERIC_PHY) += phy-core.o
-obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o
-obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o
-obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
-obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
-obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o
-obj-$(CONFIG_PHY_MIPHY365X) += phy-miphy365x.o
-obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o
-obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o
-obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
-obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o
-obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
-obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o
-obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o
-obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o
-obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o
-phy-exynos-usb2-y += phy-samsung-usb2.o
-phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o
-phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o
-phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o
-phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o
-obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o
-obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o
-obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o
-obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o
-obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o
-obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
-obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o
-obj-$(CONFIG_PHY_STIH41X_USB) += phy-stih41x-usb.o
+++ /dev/null
-/*
- * phy-bcm-kona-usb2.c - Broadcom Kona USB2 Phy Driver
- *
- * Copyright (C) 2013 Linaro Limited
- * Matt Porter <mporter@linaro.org>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-
-#define OTGCTL (0)
-#define OTGCTL_OTGSTAT2 BIT(31)
-#define OTGCTL_OTGSTAT1 BIT(30)
-#define OTGCTL_PRST_N_SW BIT(11)
-#define OTGCTL_HRESET_N BIT(10)
-#define OTGCTL_UTMI_LINE_STATE1 BIT(9)
-#define OTGCTL_UTMI_LINE_STATE0 BIT(8)
-
-#define P1CTL (8)
-#define P1CTL_SOFT_RESET BIT(1)
-#define P1CTL_NON_DRIVING BIT(0)
-
-struct bcm_kona_usb {
- void __iomem *regs;
-};
-
-static void bcm_kona_usb_phy_power(struct bcm_kona_usb *phy, int on)
-{
- u32 val;
-
- val = readl(phy->regs + OTGCTL);
- if (on) {
- /* Configure and power PHY */
- val &= ~(OTGCTL_OTGSTAT2 | OTGCTL_OTGSTAT1 |
- OTGCTL_UTMI_LINE_STATE1 | OTGCTL_UTMI_LINE_STATE0);
- val |= OTGCTL_PRST_N_SW | OTGCTL_HRESET_N;
- } else {
- val &= ~(OTGCTL_PRST_N_SW | OTGCTL_HRESET_N);
- }
- writel(val, phy->regs + OTGCTL);
-}
-
-static int bcm_kona_usb_phy_init(struct phy *gphy)
-{
- struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
- u32 val;
-
- /* Soft reset PHY */
- val = readl(phy->regs + P1CTL);
- val &= ~P1CTL_NON_DRIVING;
- val |= P1CTL_SOFT_RESET;
- writel(val, phy->regs + P1CTL);
- writel(val & ~P1CTL_SOFT_RESET, phy->regs + P1CTL);
- /* Reset needs to be asserted for 2ms */
- mdelay(2);
- writel(val | P1CTL_SOFT_RESET, phy->regs + P1CTL);
-
- return 0;
-}
-
-static int bcm_kona_usb_phy_power_on(struct phy *gphy)
-{
- struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
-
- bcm_kona_usb_phy_power(phy, 1);
-
- return 0;
-}
-
-static int bcm_kona_usb_phy_power_off(struct phy *gphy)
-{
- struct bcm_kona_usb *phy = phy_get_drvdata(gphy);
-
- bcm_kona_usb_phy_power(phy, 0);
-
- return 0;
-}
-
-static struct phy_ops ops = {
- .init = bcm_kona_usb_phy_init,
- .power_on = bcm_kona_usb_phy_power_on,
- .power_off = bcm_kona_usb_phy_power_off,
- .owner = THIS_MODULE,
-};
-
-static int bcm_kona_usb2_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct bcm_kona_usb *phy;
- struct resource *res;
- struct phy *gphy;
- struct phy_provider *phy_provider;
-
- phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
- if (!phy)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- phy->regs = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(phy->regs))
- return PTR_ERR(phy->regs);
-
- platform_set_drvdata(pdev, phy);
-
- gphy = devm_phy_create(dev, NULL, &ops, NULL);
- if (IS_ERR(gphy))
- return PTR_ERR(gphy);
-
- /* The Kona PHY supports an 8-bit wide UTMI interface */
- phy_set_bus_width(gphy, 8);
-
- phy_set_drvdata(gphy, phy);
-
- phy_provider = devm_of_phy_provider_register(dev,
- of_phy_simple_xlate);
-
- return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static const struct of_device_id bcm_kona_usb2_dt_ids[] = {
- { .compatible = "brcm,kona-usb2-phy" },
- { /* sentinel */ }
-};
-
-MODULE_DEVICE_TABLE(of, bcm_kona_usb2_dt_ids);
-
-static struct platform_driver bcm_kona_usb2_driver = {
- .probe = bcm_kona_usb2_probe,
- .driver = {
- .name = "bcm-kona-usb2",
- .of_match_table = bcm_kona_usb2_dt_ids,
- },
-};
-
-module_platform_driver(bcm_kona_usb2_driver);
-
-MODULE_ALIAS("platform:bcm-kona-usb2");
-MODULE_AUTHOR("Matt Porter <mporter@linaro.org>");
-MODULE_DESCRIPTION("BCM Kona USB 2.0 PHY driver");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * Marvell Berlin SATA PHY driver
- *
- * Copyright (C) 2014 Marvell Technology Group Ltd.
- *
- * Antoine Ténart <antoine.tenart@free-electrons.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/clk.h>
-#include <linux/module.h>
-#include <linux/phy/phy.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-
-#define HOST_VSA_ADDR 0x0
-#define HOST_VSA_DATA 0x4
-#define PORT_SCR_CTL 0x2c
-#define PORT_VSR_ADDR 0x78
-#define PORT_VSR_DATA 0x7c
-
-#define CONTROL_REGISTER 0x0
-#define MBUS_SIZE_CONTROL 0x4
-
-#define POWER_DOWN_PHY0 BIT(6)
-#define POWER_DOWN_PHY1 BIT(14)
-#define MBUS_WRITE_REQUEST_SIZE_128 (BIT(2) << 16)
-#define MBUS_READ_REQUEST_SIZE_128 (BIT(2) << 19)
-
-#define PHY_BASE 0x200
-
-/* register 0x01 */
-#define REF_FREF_SEL_25 BIT(0)
-#define PHY_MODE_SATA (0x0 << 5)
-
-/* register 0x02 */
-#define USE_MAX_PLL_RATE BIT(12)
-
-/* register 0x23 */
-#define DATA_BIT_WIDTH_10 (0x0 << 10)
-#define DATA_BIT_WIDTH_20 (0x1 << 10)
-#define DATA_BIT_WIDTH_40 (0x2 << 10)
-
-/* register 0x25 */
-#define PHY_GEN_MAX_1_5 (0x0 << 10)
-#define PHY_GEN_MAX_3_0 (0x1 << 10)
-#define PHY_GEN_MAX_6_0 (0x2 << 10)
-
-struct phy_berlin_desc {
- struct phy *phy;
- u32 power_bit;
- unsigned index;
-};
-
-struct phy_berlin_priv {
- void __iomem *base;
- spinlock_t lock;
- struct clk *clk;
- struct phy_berlin_desc **phys;
- unsigned nphys;
-};
-
-static inline void phy_berlin_sata_reg_setbits(void __iomem *ctrl_reg, u32 reg,
- u32 mask, u32 val)
-{
- u32 regval;
-
- /* select register */
- writel(PHY_BASE + reg, ctrl_reg + PORT_VSR_ADDR);
-
- /* set bits */
- regval = readl(ctrl_reg + PORT_VSR_DATA);
- regval &= ~mask;
- regval |= val;
- writel(regval, ctrl_reg + PORT_VSR_DATA);
-}
-
-static int phy_berlin_sata_power_on(struct phy *phy)
-{
- struct phy_berlin_desc *desc = phy_get_drvdata(phy);
- struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
- void __iomem *ctrl_reg = priv->base + 0x60 + (desc->index * 0x80);
- int ret = 0;
- u32 regval;
-
- clk_prepare_enable(priv->clk);
-
- spin_lock(&priv->lock);
-
- /* Power on PHY */
- writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
- regval = readl(priv->base + HOST_VSA_DATA);
- regval &= ~desc->power_bit;
- writel(regval, priv->base + HOST_VSA_DATA);
-
- /* Configure MBus */
- writel(MBUS_SIZE_CONTROL, priv->base + HOST_VSA_ADDR);
- regval = readl(priv->base + HOST_VSA_DATA);
- regval |= MBUS_WRITE_REQUEST_SIZE_128 | MBUS_READ_REQUEST_SIZE_128;
- writel(regval, priv->base + HOST_VSA_DATA);
-
- /* set PHY mode and ref freq to 25 MHz */
- phy_berlin_sata_reg_setbits(ctrl_reg, 0x1, 0xff,
- REF_FREF_SEL_25 | PHY_MODE_SATA);
-
- /* set PHY up to 6 Gbps */
- phy_berlin_sata_reg_setbits(ctrl_reg, 0x25, 0xc00, PHY_GEN_MAX_6_0);
-
- /* set 40 bits width */
- phy_berlin_sata_reg_setbits(ctrl_reg, 0x23, 0xc00, DATA_BIT_WIDTH_40);
-
- /* use max pll rate */
- phy_berlin_sata_reg_setbits(ctrl_reg, 0x2, 0x0, USE_MAX_PLL_RATE);
-
- /* set Gen3 controller speed */
- regval = readl(ctrl_reg + PORT_SCR_CTL);
- regval &= ~GENMASK(7, 4);
- regval |= 0x30;
- writel(regval, ctrl_reg + PORT_SCR_CTL);
-
- spin_unlock(&priv->lock);
-
- clk_disable_unprepare(priv->clk);
-
- return ret;
-}
-
-static int phy_berlin_sata_power_off(struct phy *phy)
-{
- struct phy_berlin_desc *desc = phy_get_drvdata(phy);
- struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
- u32 regval;
-
- clk_prepare_enable(priv->clk);
-
- spin_lock(&priv->lock);
-
- /* Power down PHY */
- writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
- regval = readl(priv->base + HOST_VSA_DATA);
- regval |= desc->power_bit;
- writel(regval, priv->base + HOST_VSA_DATA);
-
- spin_unlock(&priv->lock);
-
- clk_disable_unprepare(priv->clk);
-
- return 0;
-}
-
-static struct phy *phy_berlin_sata_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
-{
- struct phy_berlin_priv *priv = dev_get_drvdata(dev);
- int i;
-
- if (WARN_ON(args->args[0] >= priv->nphys))
- return ERR_PTR(-ENODEV);
-
- for (i = 0; i < priv->nphys; i++) {
- if (priv->phys[i]->index == args->args[0])
- break;
- }
-
- if (i == priv->nphys)
- return ERR_PTR(-ENODEV);
-
- return priv->phys[i]->phy;
-}
-
-static struct phy_ops phy_berlin_sata_ops = {
- .power_on = phy_berlin_sata_power_on,
- .power_off = phy_berlin_sata_power_off,
- .owner = THIS_MODULE,
-};
-
-static u32 phy_berlin_power_down_bits[] = {
- POWER_DOWN_PHY0,
- POWER_DOWN_PHY1,
-};
-
-static int phy_berlin_sata_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct device_node *child;
- struct phy *phy;
- struct phy_provider *phy_provider;
- struct phy_berlin_priv *priv;
- struct resource *res;
- int i = 0;
- u32 phy_id;
-
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -EINVAL;
-
- priv->base = devm_ioremap(dev, res->start, resource_size(res));
- if (!priv->base)
- return -ENOMEM;
-
- priv->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(priv->clk))
- return PTR_ERR(priv->clk);
-
- priv->nphys = of_get_child_count(dev->of_node);
- if (priv->nphys == 0)
- return -ENODEV;
-
- priv->phys = devm_kzalloc(dev, priv->nphys * sizeof(*priv->phys),
- GFP_KERNEL);
- if (!priv->phys)
- return -ENOMEM;
-
- dev_set_drvdata(dev, priv);
- spin_lock_init(&priv->lock);
-
- for_each_available_child_of_node(dev->of_node, child) {
- struct phy_berlin_desc *phy_desc;
-
- if (of_property_read_u32(child, "reg", &phy_id)) {
- dev_err(dev, "missing reg property in node %s\n",
- child->name);
- return -EINVAL;
- }
-
- if (phy_id >= ARRAY_SIZE(phy_berlin_power_down_bits)) {
- dev_err(dev, "invalid reg in node %s\n", child->name);
- return -EINVAL;
- }
-
- phy_desc = devm_kzalloc(dev, sizeof(*phy_desc), GFP_KERNEL);
- if (!phy_desc)
- return -ENOMEM;
-
- phy = devm_phy_create(dev, NULL, &phy_berlin_sata_ops, NULL);
- if (IS_ERR(phy)) {
- dev_err(dev, "failed to create PHY %d\n", phy_id);
- return PTR_ERR(phy);
- }
-
- phy_desc->phy = phy;
- phy_desc->power_bit = phy_berlin_power_down_bits[phy_id];
- phy_desc->index = phy_id;
- phy_set_drvdata(phy, phy_desc);
-
- priv->phys[i++] = phy_desc;
-
- /* Make sure the PHY is off */
- phy_berlin_sata_power_off(phy);
- }
-
- phy_provider =
- devm_of_phy_provider_register(dev, phy_berlin_sata_phy_xlate);
- if (IS_ERR(phy_provider))
- return PTR_ERR(phy_provider);
-
- return 0;
-}
-
-static const struct of_device_id phy_berlin_sata_of_match[] = {
- { .compatible = "marvell,berlin2q-sata-phy" },
- { },
-};
-
-static struct platform_driver phy_berlin_sata_driver = {
- .probe = phy_berlin_sata_probe,
- .driver = {
- .name = "phy-berlin-sata",
- .of_match_table = phy_berlin_sata_of_match,
- },
-};
-module_platform_driver(phy_berlin_sata_driver);
-
-MODULE_DESCRIPTION("Marvell Berlin SATA PHY driver");
-MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * phy-core.c -- Generic Phy framework.
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
- *
- * Author: Kishon Vijay Abraham I <kishon@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/device.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/phy/phy.h>
-#include <linux/idr.h>
-#include <linux/pm_runtime.h>
-#include <linux/regulator/consumer.h>
-
-static struct class *phy_class;
-static DEFINE_MUTEX(phy_provider_mutex);
-static LIST_HEAD(phy_provider_list);
-static DEFINE_IDA(phy_ida);
-
-static void devm_phy_release(struct device *dev, void *res)
-{
- struct phy *phy = *(struct phy **)res;
-
- phy_put(phy);
-}
-
-static void devm_phy_provider_release(struct device *dev, void *res)
-{
- struct phy_provider *phy_provider = *(struct phy_provider **)res;
-
- of_phy_provider_unregister(phy_provider);
-}
-
-static void devm_phy_consume(struct device *dev, void *res)
-{
- struct phy *phy = *(struct phy **)res;
-
- phy_destroy(phy);
-}
-
-static int devm_phy_match(struct device *dev, void *res, void *match_data)
-{
- return res == match_data;
-}
-
-static struct phy *phy_lookup(struct device *device, const char *port)
-{
- unsigned int count;
- struct phy *phy;
- struct device *dev;
- struct phy_consumer *consumers;
- struct class_dev_iter iter;
-
- class_dev_iter_init(&iter, phy_class, NULL, NULL);
- while ((dev = class_dev_iter_next(&iter))) {
- phy = to_phy(dev);
-
- if (!phy->init_data)
- continue;
- count = phy->init_data->num_consumers;
- consumers = phy->init_data->consumers;
- while (count--) {
- if (!strcmp(consumers->dev_name, dev_name(device)) &&
- !strcmp(consumers->port, port)) {
- class_dev_iter_exit(&iter);
- return phy;
- }
- consumers++;
- }
- }
-
- class_dev_iter_exit(&iter);
- return ERR_PTR(-ENODEV);
-}
-
-static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
-{
- struct phy_provider *phy_provider;
- struct device_node *child;
-
- list_for_each_entry(phy_provider, &phy_provider_list, list) {
- if (phy_provider->dev->of_node == node)
- return phy_provider;
-
- for_each_child_of_node(phy_provider->dev->of_node, child)
- if (child == node)
- return phy_provider;
- }
-
- return ERR_PTR(-EPROBE_DEFER);
-}
-
-int phy_pm_runtime_get(struct phy *phy)
-{
- int ret;
-
- if (!pm_runtime_enabled(&phy->dev))
- return -ENOTSUPP;
-
- ret = pm_runtime_get(&phy->dev);
- if (ret < 0 && ret != -EINPROGRESS)
- pm_runtime_put_noidle(&phy->dev);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(phy_pm_runtime_get);
-
-int phy_pm_runtime_get_sync(struct phy *phy)
-{
- int ret;
-
- if (!pm_runtime_enabled(&phy->dev))
- return -ENOTSUPP;
-
- ret = pm_runtime_get_sync(&phy->dev);
- if (ret < 0)
- pm_runtime_put_sync(&phy->dev);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(phy_pm_runtime_get_sync);
-
-int phy_pm_runtime_put(struct phy *phy)
-{
- if (!pm_runtime_enabled(&phy->dev))
- return -ENOTSUPP;
-
- return pm_runtime_put(&phy->dev);
-}
-EXPORT_SYMBOL_GPL(phy_pm_runtime_put);
-
-int phy_pm_runtime_put_sync(struct phy *phy)
-{
- if (!pm_runtime_enabled(&phy->dev))
- return -ENOTSUPP;
-
- return pm_runtime_put_sync(&phy->dev);
-}
-EXPORT_SYMBOL_GPL(phy_pm_runtime_put_sync);
-
-void phy_pm_runtime_allow(struct phy *phy)
-{
- if (!pm_runtime_enabled(&phy->dev))
- return;
-
- pm_runtime_allow(&phy->dev);
-}
-EXPORT_SYMBOL_GPL(phy_pm_runtime_allow);
-
-void phy_pm_runtime_forbid(struct phy *phy)
-{
- if (!pm_runtime_enabled(&phy->dev))
- return;
-
- pm_runtime_forbid(&phy->dev);
-}
-EXPORT_SYMBOL_GPL(phy_pm_runtime_forbid);
-
-int phy_init(struct phy *phy)
-{
- int ret;
-
- if (!phy)
- return 0;
-
- ret = phy_pm_runtime_get_sync(phy);
- if (ret < 0 && ret != -ENOTSUPP)
- return ret;
-
- mutex_lock(&phy->mutex);
- if (phy->init_count == 0 && phy->ops->init) {
- ret = phy->ops->init(phy);
- if (ret < 0) {
- dev_err(&phy->dev, "phy init failed --> %d\n", ret);
- goto out;
- }
- } else {
- ret = 0; /* Override possible ret == -ENOTSUPP */
- }
- ++phy->init_count;
-
-out:
- mutex_unlock(&phy->mutex);
- phy_pm_runtime_put(phy);
- return ret;
-}
-EXPORT_SYMBOL_GPL(phy_init);
-
-int phy_exit(struct phy *phy)
-{
- int ret;
-
- if (!phy)
- return 0;
-
- ret = phy_pm_runtime_get_sync(phy);
- if (ret < 0 && ret != -ENOTSUPP)
- return ret;
-
- mutex_lock(&phy->mutex);
- if (phy->init_count == 1 && phy->ops->exit) {
- ret = phy->ops->exit(phy);
- if (ret < 0) {
- dev_err(&phy->dev, "phy exit failed --> %d\n", ret);
- goto out;
- }
- }
- --phy->init_count;
-
-out:
- mutex_unlock(&phy->mutex);
- phy_pm_runtime_put(phy);
- return ret;
-}
-EXPORT_SYMBOL_GPL(phy_exit);
-
-int phy_power_on(struct phy *phy)
-{
- int ret;
-
- if (!phy)
- return 0;
-
- if (phy->pwr) {
- ret = regulator_enable(phy->pwr);
- if (ret)
- return ret;
- }
-
- ret = phy_pm_runtime_get_sync(phy);
- if (ret < 0 && ret != -ENOTSUPP)
- return ret;
-
- mutex_lock(&phy->mutex);
- if (phy->power_count == 0 && phy->ops->power_on) {
- ret = phy->ops->power_on(phy);
- if (ret < 0) {
- dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
- goto out;
- }
- } else {
- ret = 0; /* Override possible ret == -ENOTSUPP */
- }
- ++phy->power_count;
- mutex_unlock(&phy->mutex);
- return 0;
-
-out:
- mutex_unlock(&phy->mutex);
- phy_pm_runtime_put_sync(phy);
- if (phy->pwr)
- regulator_disable(phy->pwr);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(phy_power_on);
-
-int phy_power_off(struct phy *phy)
-{
- int ret;
-
- if (!phy)
- return 0;
-
- mutex_lock(&phy->mutex);
- if (phy->power_count == 1 && phy->ops->power_off) {
- ret = phy->ops->power_off(phy);
- if (ret < 0) {
- dev_err(&phy->dev, "phy poweroff failed --> %d\n", ret);
- mutex_unlock(&phy->mutex);
- return ret;
- }
- }
- --phy->power_count;
- mutex_unlock(&phy->mutex);
- phy_pm_runtime_put(phy);
-
- if (phy->pwr)
- regulator_disable(phy->pwr);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(phy_power_off);
-
-/**
- * _of_phy_get() - lookup and obtain a reference to a phy by phandle
- * @np: device_node for which to get the phy
- * @index: the index of the phy
- *
- * Returns the phy associated with the given phandle value,
- * after getting a refcount to it or -ENODEV if there is no such phy or
- * -EPROBE_DEFER if there is a phandle to the phy, but the device is
- * not yet loaded. This function uses of_xlate call back function provided
- * while registering the phy_provider to find the phy instance.
- */
-static struct phy *_of_phy_get(struct device_node *np, int index)
-{
- int ret;
- struct phy_provider *phy_provider;
- struct phy *phy = NULL;
- struct of_phandle_args args;
-
- ret = of_parse_phandle_with_args(np, "phys", "#phy-cells",
- index, &args);
- if (ret)
- return ERR_PTR(-ENODEV);
-
- mutex_lock(&phy_provider_mutex);
- phy_provider = of_phy_provider_lookup(args.np);
- if (IS_ERR(phy_provider) || !try_module_get(phy_provider->owner)) {
- phy = ERR_PTR(-EPROBE_DEFER);
- goto err0;
- }
-
- phy = phy_provider->of_xlate(phy_provider->dev, &args);
- module_put(phy_provider->owner);
-
-err0:
- mutex_unlock(&phy_provider_mutex);
- of_node_put(args.np);
-
- return phy;
-}
-
-/**
- * of_phy_get() - lookup and obtain a reference to a phy using a device_node.
- * @np: device_node for which to get the phy
- * @con_id: name of the phy from device's point of view
- *
- * Returns the phy driver, after getting a refcount to it; or
- * -ENODEV if there is no such phy. The caller is responsible for
- * calling phy_put() to release that count.
- */
-struct phy *of_phy_get(struct device_node *np, const char *con_id)
-{
- struct phy *phy = NULL;
- int index = 0;
-
- if (con_id)
- index = of_property_match_string(np, "phy-names", con_id);
-
- phy = _of_phy_get(np, index);
- if (IS_ERR(phy))
- return phy;
-
- if (!try_module_get(phy->ops->owner))
- return ERR_PTR(-EPROBE_DEFER);
-
- get_device(&phy->dev);
-
- return phy;
-}
-EXPORT_SYMBOL_GPL(of_phy_get);
-
-/**
- * phy_put() - release the PHY
- * @phy: the phy returned by phy_get()
- *
- * Releases a refcount the caller received from phy_get().
- */
-void phy_put(struct phy *phy)
-{
- if (!phy || IS_ERR(phy))
- return;
-
- module_put(phy->ops->owner);
- put_device(&phy->dev);
-}
-EXPORT_SYMBOL_GPL(phy_put);
-
-/**
- * devm_phy_put() - release the PHY
- * @dev: device that wants to release this phy
- * @phy: the phy returned by devm_phy_get()
- *
- * destroys the devres associated with this phy and invokes phy_put
- * to release the phy.
- */
-void devm_phy_put(struct device *dev, struct phy *phy)
-{
- int r;
-
- if (!phy)
- return;
-
- r = devres_destroy(dev, devm_phy_release, devm_phy_match, phy);
- dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
-}
-EXPORT_SYMBOL_GPL(devm_phy_put);
-
-/**
- * of_phy_simple_xlate() - returns the phy instance from phy provider
- * @dev: the PHY provider device
- * @args: of_phandle_args (not used here)
- *
- * Intended to be used by phy provider for the common case where #phy-cells is
- * 0. For other cases where #phy-cells is greater than '0', the phy provider
- * should provide a custom of_xlate function that reads the *args* and returns
- * the appropriate phy.
- */
-struct phy *of_phy_simple_xlate(struct device *dev, struct of_phandle_args
- *args)
-{
- struct phy *phy;
- struct class_dev_iter iter;
- struct device_node *node = dev->of_node;
- struct device_node *child;
-
- class_dev_iter_init(&iter, phy_class, NULL, NULL);
- while ((dev = class_dev_iter_next(&iter))) {
- phy = to_phy(dev);
- if (node != phy->dev.of_node) {
- for_each_child_of_node(node, child) {
- if (child == phy->dev.of_node)
- goto phy_found;
- }
- continue;
- }
-
-phy_found:
- class_dev_iter_exit(&iter);
- return phy;
- }
-
- class_dev_iter_exit(&iter);
- return ERR_PTR(-ENODEV);
-}
-EXPORT_SYMBOL_GPL(of_phy_simple_xlate);
-
-/**
- * phy_get() - lookup and obtain a reference to a phy.
- * @dev: device that requests this phy
- * @string: the phy name as given in the dt data or the name of the controller
- * port for non-dt case
- *
- * Returns the phy driver, after getting a refcount to it; or
- * -ENODEV if there is no such phy. The caller is responsible for
- * calling phy_put() to release that count.
- */
-struct phy *phy_get(struct device *dev, const char *string)
-{
- int index = 0;
- struct phy *phy;
-
- if (string == NULL) {
- dev_WARN(dev, "missing string\n");
- return ERR_PTR(-EINVAL);
- }
-
- if (dev->of_node) {
- index = of_property_match_string(dev->of_node, "phy-names",
- string);
- phy = _of_phy_get(dev->of_node, index);
- } else {
- phy = phy_lookup(dev, string);
- }
- if (IS_ERR(phy))
- return phy;
-
- if (!try_module_get(phy->ops->owner))
- return ERR_PTR(-EPROBE_DEFER);
-
- get_device(&phy->dev);
-
- return phy;
-}
-EXPORT_SYMBOL_GPL(phy_get);
-
-/**
- * phy_optional_get() - lookup and obtain a reference to an optional phy.
- * @dev: device that requests this phy
- * @string: the phy name as given in the dt data or the name of the controller
- * port for non-dt case
- *
- * Returns the phy driver, after getting a refcount to it; or
- * NULL if there is no such phy. The caller is responsible for
- * calling phy_put() to release that count.
- */
-struct phy *phy_optional_get(struct device *dev, const char *string)
-{
- struct phy *phy = phy_get(dev, string);
-
- if (PTR_ERR(phy) == -ENODEV)
- phy = NULL;
-
- return phy;
-}
-EXPORT_SYMBOL_GPL(phy_optional_get);
-
-/**
- * devm_phy_get() - lookup and obtain a reference to a phy.
- * @dev: device that requests this phy
- * @string: the phy name as given in the dt data or phy device name
- * for non-dt case
- *
- * Gets the phy using phy_get(), and associates a device with it using
- * devres. On driver detach, release function is invoked on the devres data,
- * then, devres data is freed.
- */
-struct phy *devm_phy_get(struct device *dev, const char *string)
-{
- struct phy **ptr, *phy;
-
- ptr = devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL);
- if (!ptr)
- return ERR_PTR(-ENOMEM);
-
- phy = phy_get(dev, string);
- if (!IS_ERR(phy)) {
- *ptr = phy;
- devres_add(dev, ptr);
- } else {
- devres_free(ptr);
- }
-
- return phy;
-}
-EXPORT_SYMBOL_GPL(devm_phy_get);
-
-/**
- * devm_phy_optional_get() - lookup and obtain a reference to an optional phy.
- * @dev: device that requests this phy
- * @string: the phy name as given in the dt data or phy device name
- * for non-dt case
- *
- * Gets the phy using phy_get(), and associates a device with it using
- * devres. On driver detach, release function is invoked on the devres
- * data, then, devres data is freed. This differs to devm_phy_get() in
- * that if the phy does not exist, it is not considered an error and
- * -ENODEV will not be returned. Instead the NULL phy is returned,
- * which can be passed to all other phy consumer calls.
- */
-struct phy *devm_phy_optional_get(struct device *dev, const char *string)
-{
- struct phy *phy = devm_phy_get(dev, string);
-
- if (PTR_ERR(phy) == -ENODEV)
- phy = NULL;
-
- return phy;
-}
-EXPORT_SYMBOL_GPL(devm_phy_optional_get);
-
-/**
- * devm_of_phy_get() - lookup and obtain a reference to a phy.
- * @dev: device that requests this phy
- * @np: node containing the phy
- * @con_id: name of the phy from device's point of view
- *
- * Gets the phy using of_phy_get(), and associates a device with it using
- * devres. On driver detach, release function is invoked on the devres data,
- * then, devres data is freed.
- */
-struct phy *devm_of_phy_get(struct device *dev, struct device_node *np,
- const char *con_id)
-{
- struct phy **ptr, *phy;
-
- ptr = devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL);
- if (!ptr)
- return ERR_PTR(-ENOMEM);
-
- phy = of_phy_get(np, con_id);
- if (!IS_ERR(phy)) {
- *ptr = phy;
- devres_add(dev, ptr);
- } else {
- devres_free(ptr);
- }
-
- return phy;
-}
-EXPORT_SYMBOL_GPL(devm_of_phy_get);
-
-/**
- * phy_create() - create a new phy
- * @dev: device that is creating the new phy
- * @node: device node of the phy
- * @ops: function pointers for performing phy operations
- * @init_data: contains the list of PHY consumers or NULL
- *
- * Called to create a phy using phy framework.
- */
-struct phy *phy_create(struct device *dev, struct device_node *node,
- const struct phy_ops *ops,
- struct phy_init_data *init_data)
-{
- int ret;
- int id;
- struct phy *phy;
-
- if (WARN_ON(!dev))
- return ERR_PTR(-EINVAL);
-
- phy = kzalloc(sizeof(*phy), GFP_KERNEL);
- if (!phy)
- return ERR_PTR(-ENOMEM);
-
- id = ida_simple_get(&phy_ida, 0, 0, GFP_KERNEL);
- if (id < 0) {
- dev_err(dev, "unable to get id\n");
- ret = id;
- goto free_phy;
- }
-
- /* phy-supply */
- phy->pwr = regulator_get_optional(dev, "phy");
- if (IS_ERR(phy->pwr)) {
- if (PTR_ERR(phy->pwr) == -EPROBE_DEFER) {
- ret = -EPROBE_DEFER;
- goto free_ida;
- }
- phy->pwr = NULL;
- }
-
- device_initialize(&phy->dev);
- mutex_init(&phy->mutex);
-
- phy->dev.class = phy_class;
- phy->dev.parent = dev;
- phy->dev.of_node = node ?: dev->of_node;
- phy->id = id;
- phy->ops = ops;
- phy->init_data = init_data;
-
- ret = dev_set_name(&phy->dev, "phy-%s.%d", dev_name(dev), id);
- if (ret)
- goto put_dev;
-
- ret = device_add(&phy->dev);
- if (ret)
- goto put_dev;
-
- if (pm_runtime_enabled(dev)) {
- pm_runtime_enable(&phy->dev);
- pm_runtime_no_callbacks(&phy->dev);
- }
-
- return phy;
-
-put_dev:
- put_device(&phy->dev); /* calls phy_release() which frees resources */
- return ERR_PTR(ret);
-
-free_ida:
- ida_simple_remove(&phy_ida, phy->id);
-
-free_phy:
- kfree(phy);
- return ERR_PTR(ret);
-}
-EXPORT_SYMBOL_GPL(phy_create);
-
-/**
- * devm_phy_create() - create a new phy
- * @dev: device that is creating the new phy
- * @node: device node of the phy
- * @ops: function pointers for performing phy operations
- * @init_data: contains the list of PHY consumers or NULL
- *
- * Creates a new PHY device adding it to the PHY class.
- * While at that, it also associates the device with the phy using devres.
- * On driver detach, release function is invoked on the devres data,
- * then, devres data is freed.
- */
-struct phy *devm_phy_create(struct device *dev, struct device_node *node,
- const struct phy_ops *ops,
- struct phy_init_data *init_data)
-{
- struct phy **ptr, *phy;
-
- ptr = devres_alloc(devm_phy_consume, sizeof(*ptr), GFP_KERNEL);
- if (!ptr)
- return ERR_PTR(-ENOMEM);
-
- phy = phy_create(dev, node, ops, init_data);
- if (!IS_ERR(phy)) {
- *ptr = phy;
- devres_add(dev, ptr);
- } else {
- devres_free(ptr);
- }
-
- return phy;
-}
-EXPORT_SYMBOL_GPL(devm_phy_create);
-
-/**
- * phy_destroy() - destroy the phy
- * @phy: the phy to be destroyed
- *
- * Called to destroy the phy.
- */
-void phy_destroy(struct phy *phy)
-{
- pm_runtime_disable(&phy->dev);
- device_unregister(&phy->dev);
-}
-EXPORT_SYMBOL_GPL(phy_destroy);
-
-/**
- * devm_phy_destroy() - destroy the PHY
- * @dev: device that wants to release this phy
- * @phy: the phy returned by devm_phy_get()
- *
- * destroys the devres associated with this phy and invokes phy_destroy
- * to destroy the phy.
- */
-void devm_phy_destroy(struct device *dev, struct phy *phy)
-{
- int r;
-
- r = devres_destroy(dev, devm_phy_consume, devm_phy_match, phy);
- dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
-}
-EXPORT_SYMBOL_GPL(devm_phy_destroy);
-
-/**
- * __of_phy_provider_register() - create/register phy provider with the framework
- * @dev: struct device of the phy provider
- * @owner: the module owner containing of_xlate
- * @of_xlate: function pointer to obtain phy instance from phy provider
- *
- * Creates struct phy_provider from dev and of_xlate function pointer.
- * This is used in the case of dt boot for finding the phy instance from
- * phy provider.
- */
-struct phy_provider *__of_phy_provider_register(struct device *dev,
- struct module *owner, struct phy * (*of_xlate)(struct device *dev,
- struct of_phandle_args *args))
-{
- struct phy_provider *phy_provider;
-
- phy_provider = kzalloc(sizeof(*phy_provider), GFP_KERNEL);
- if (!phy_provider)
- return ERR_PTR(-ENOMEM);
-
- phy_provider->dev = dev;
- phy_provider->owner = owner;
- phy_provider->of_xlate = of_xlate;
-
- mutex_lock(&phy_provider_mutex);
- list_add_tail(&phy_provider->list, &phy_provider_list);
- mutex_unlock(&phy_provider_mutex);
-
- return phy_provider;
-}
-EXPORT_SYMBOL_GPL(__of_phy_provider_register);
-
-/**
- * __devm_of_phy_provider_register() - create/register phy provider with the
- * framework
- * @dev: struct device of the phy provider
- * @owner: the module owner containing of_xlate
- * @of_xlate: function pointer to obtain phy instance from phy provider
- *
- * Creates struct phy_provider from dev and of_xlate function pointer.
- * This is used in the case of dt boot for finding the phy instance from
- * phy provider. While at that, it also associates the device with the
- * phy provider using devres. On driver detach, release function is invoked
- * on the devres data, then, devres data is freed.
- */
-struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
- struct module *owner, struct phy * (*of_xlate)(struct device *dev,
- struct of_phandle_args *args))
-{
- struct phy_provider **ptr, *phy_provider;
-
- ptr = devres_alloc(devm_phy_provider_release, sizeof(*ptr), GFP_KERNEL);
- if (!ptr)
- return ERR_PTR(-ENOMEM);
-
- phy_provider = __of_phy_provider_register(dev, owner, of_xlate);
- if (!IS_ERR(phy_provider)) {
- *ptr = phy_provider;
- devres_add(dev, ptr);
- } else {
- devres_free(ptr);
- }
-
- return phy_provider;
-}
-EXPORT_SYMBOL_GPL(__devm_of_phy_provider_register);
-
-/**
- * of_phy_provider_unregister() - unregister phy provider from the framework
- * @phy_provider: phy provider returned by of_phy_provider_register()
- *
- * Removes the phy_provider created using of_phy_provider_register().
- */
-void of_phy_provider_unregister(struct phy_provider *phy_provider)
-{
- if (IS_ERR(phy_provider))
- return;
-
- mutex_lock(&phy_provider_mutex);
- list_del(&phy_provider->list);
- kfree(phy_provider);
- mutex_unlock(&phy_provider_mutex);
-}
-EXPORT_SYMBOL_GPL(of_phy_provider_unregister);
-
-/**
- * devm_of_phy_provider_unregister() - remove phy provider from the framework
- * @dev: struct device of the phy provider
- *
- * destroys the devres associated with this phy provider and invokes
- * of_phy_provider_unregister to unregister the phy provider.
- */
-void devm_of_phy_provider_unregister(struct device *dev,
- struct phy_provider *phy_provider) {
- int r;
-
- r = devres_destroy(dev, devm_phy_provider_release, devm_phy_match,
- phy_provider);
- dev_WARN_ONCE(dev, r, "couldn't find PHY provider device resource\n");
-}
-EXPORT_SYMBOL_GPL(devm_of_phy_provider_unregister);
-
-/**
- * phy_release() - release the phy
- * @dev: the dev member within phy
- *
- * When the last reference to the device is removed, it is called
- * from the embedded kobject as release method.
- */
-static void phy_release(struct device *dev)
-{
- struct phy *phy;
-
- phy = to_phy(dev);
- dev_vdbg(dev, "releasing '%s'\n", dev_name(dev));
- regulator_put(phy->pwr);
- ida_simple_remove(&phy_ida, phy->id);
- kfree(phy);
-}
-
-static int __init phy_core_init(void)
-{
- phy_class = class_create(THIS_MODULE, "phy");
- if (IS_ERR(phy_class)) {
- pr_err("failed to create phy class --> %ld\n",
- PTR_ERR(phy_class));
- return PTR_ERR(phy_class);
- }
-
- phy_class->dev_release = phy_release;
-
- return 0;
-}
-module_init(phy_core_init);
-
-static void __exit phy_core_exit(void)
-{
- class_destroy(phy_class);
-}
-module_exit(phy_core_exit);
-
-MODULE_DESCRIPTION("Generic PHY Framework");
-MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * Samsung EXYNOS SoC series Display Port PHY driver
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mfd/syscon.h>
-#include <linux/mfd/syscon/exynos5-pmu.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-
-struct exynos_dp_video_phy_drvdata {
- u32 phy_ctrl_offset;
-};
-
-struct exynos_dp_video_phy {
- struct regmap *regs;
- const struct exynos_dp_video_phy_drvdata *drvdata;
-};
-
-static void exynos_dp_video_phy_pwr_isol(struct exynos_dp_video_phy *state,
- unsigned int on)
-{
- unsigned int val;
-
- if (IS_ERR(state->regs))
- return;
-
- val = on ? 0 : EXYNOS5_PHY_ENABLE;
-
- regmap_update_bits(state->regs, state->drvdata->phy_ctrl_offset,
- EXYNOS5_PHY_ENABLE, val);
-}
-
-static int exynos_dp_video_phy_power_on(struct phy *phy)
-{
- struct exynos_dp_video_phy *state = phy_get_drvdata(phy);
-
- /* Disable power isolation on DP-PHY */
- exynos_dp_video_phy_pwr_isol(state, 0);
-
- return 0;
-}
-
-static int exynos_dp_video_phy_power_off(struct phy *phy)
-{
- struct exynos_dp_video_phy *state = phy_get_drvdata(phy);
-
- /* Enable power isolation on DP-PHY */
- exynos_dp_video_phy_pwr_isol(state, 1);
-
- return 0;
-}
-
-static struct phy_ops exynos_dp_video_phy_ops = {
- .power_on = exynos_dp_video_phy_power_on,
- .power_off = exynos_dp_video_phy_power_off,
- .owner = THIS_MODULE,
-};
-
-static const struct exynos_dp_video_phy_drvdata exynos5250_dp_video_phy = {
- .phy_ctrl_offset = EXYNOS5_DPTX_PHY_CONTROL,
-};
-
-static const struct exynos_dp_video_phy_drvdata exynos5420_dp_video_phy = {
- .phy_ctrl_offset = EXYNOS5420_DPTX_PHY_CONTROL,
-};
-
-static const struct of_device_id exynos_dp_video_phy_of_match[] = {
- {
- .compatible = "samsung,exynos5250-dp-video-phy",
- .data = &exynos5250_dp_video_phy,
- }, {
- .compatible = "samsung,exynos5420-dp-video-phy",
- .data = &exynos5420_dp_video_phy,
- },
- { },
-};
-MODULE_DEVICE_TABLE(of, exynos_dp_video_phy_of_match);
-
-static int exynos_dp_video_phy_probe(struct platform_device *pdev)
-{
- struct exynos_dp_video_phy *state;
- struct device *dev = &pdev->dev;
- const struct of_device_id *match;
- struct phy_provider *phy_provider;
- struct phy *phy;
-
- state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
- if (!state)
- return -ENOMEM;
-
- state->regs = syscon_regmap_lookup_by_phandle(dev->of_node,
- "samsung,pmu-syscon");
- if (IS_ERR(state->regs)) {
- dev_err(dev, "Failed to lookup PMU regmap\n");
- return PTR_ERR(state->regs);
- }
-
- match = of_match_node(exynos_dp_video_phy_of_match, dev->of_node);
- state->drvdata = match->data;
-
- phy = devm_phy_create(dev, NULL, &exynos_dp_video_phy_ops, NULL);
- if (IS_ERR(phy)) {
- dev_err(dev, "failed to create Display Port PHY\n");
- return PTR_ERR(phy);
- }
- phy_set_drvdata(phy, state);
-
- phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-
- return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static struct platform_driver exynos_dp_video_phy_driver = {
- .probe = exynos_dp_video_phy_probe,
- .driver = {
- .name = "exynos-dp-video-phy",
- .of_match_table = exynos_dp_video_phy_of_match,
- }
-};
-module_platform_driver(exynos_dp_video_phy_driver);
-
-MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
-MODULE_DESCRIPTION("Samsung EXYNOS SoC DP PHY driver");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY driver
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-
-/* MIPI_PHYn_CONTROL register offset: n = 0..1 */
-#define EXYNOS_MIPI_PHY_CONTROL(n) ((n) * 4)
-#define EXYNOS_MIPI_PHY_ENABLE (1 << 0)
-#define EXYNOS_MIPI_PHY_SRESETN (1 << 1)
-#define EXYNOS_MIPI_PHY_MRESETN (1 << 2)
-#define EXYNOS_MIPI_PHY_RESET_MASK (3 << 1)
-
-enum exynos_mipi_phy_id {
- EXYNOS_MIPI_PHY_ID_CSIS0,
- EXYNOS_MIPI_PHY_ID_DSIM0,
- EXYNOS_MIPI_PHY_ID_CSIS1,
- EXYNOS_MIPI_PHY_ID_DSIM1,
- EXYNOS_MIPI_PHYS_NUM
-};
-
-#define is_mipi_dsim_phy_id(id) \
- ((id) == EXYNOS_MIPI_PHY_ID_DSIM0 || (id) == EXYNOS_MIPI_PHY_ID_DSIM1)
-
-struct exynos_mipi_video_phy {
- spinlock_t slock;
- struct video_phy_desc {
- struct phy *phy;
- unsigned int index;
- } phys[EXYNOS_MIPI_PHYS_NUM];
- void __iomem *regs;
-};
-
-static int __set_phy_state(struct exynos_mipi_video_phy *state,
- enum exynos_mipi_phy_id id, unsigned int on)
-{
- void __iomem *addr;
- u32 reg, reset;
-
- addr = state->regs + EXYNOS_MIPI_PHY_CONTROL(id / 2);
-
- if (is_mipi_dsim_phy_id(id))
- reset = EXYNOS_MIPI_PHY_MRESETN;
- else
- reset = EXYNOS_MIPI_PHY_SRESETN;
-
- spin_lock(&state->slock);
- reg = readl(addr);
- if (on)
- reg |= reset;
- else
- reg &= ~reset;
- writel(reg, addr);
-
- /* Clear ENABLE bit only if MRESETN, SRESETN bits are not set. */
- if (on)
- reg |= EXYNOS_MIPI_PHY_ENABLE;
- else if (!(reg & EXYNOS_MIPI_PHY_RESET_MASK))
- reg &= ~EXYNOS_MIPI_PHY_ENABLE;
-
- writel(reg, addr);
- spin_unlock(&state->slock);
- return 0;
-}
-
-#define to_mipi_video_phy(desc) \
- container_of((desc), struct exynos_mipi_video_phy, phys[(desc)->index]);
-
-static int exynos_mipi_video_phy_power_on(struct phy *phy)
-{
- struct video_phy_desc *phy_desc = phy_get_drvdata(phy);
- struct exynos_mipi_video_phy *state = to_mipi_video_phy(phy_desc);
-
- return __set_phy_state(state, phy_desc->index, 1);
-}
-
-static int exynos_mipi_video_phy_power_off(struct phy *phy)
-{
- struct video_phy_desc *phy_desc = phy_get_drvdata(phy);
- struct exynos_mipi_video_phy *state = to_mipi_video_phy(phy_desc);
-
- return __set_phy_state(state, phy_desc->index, 0);
-}
-
-static struct phy *exynos_mipi_video_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
-{
- struct exynos_mipi_video_phy *state = dev_get_drvdata(dev);
-
- if (WARN_ON(args->args[0] >= EXYNOS_MIPI_PHYS_NUM))
- return ERR_PTR(-ENODEV);
-
- return state->phys[args->args[0]].phy;
-}
-
-static struct phy_ops exynos_mipi_video_phy_ops = {
- .power_on = exynos_mipi_video_phy_power_on,
- .power_off = exynos_mipi_video_phy_power_off,
- .owner = THIS_MODULE,
-};
-
-static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
-{
- struct exynos_mipi_video_phy *state;
- struct device *dev = &pdev->dev;
- struct resource *res;
- struct phy_provider *phy_provider;
- unsigned int i;
-
- state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
- if (!state)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- state->regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(state->regs))
- return PTR_ERR(state->regs);
-
- dev_set_drvdata(dev, state);
- spin_lock_init(&state->slock);
-
- for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) {
- struct phy *phy = devm_phy_create(dev, NULL,
- &exynos_mipi_video_phy_ops, NULL);
- if (IS_ERR(phy)) {
- dev_err(dev, "failed to create PHY %d\n", i);
- return PTR_ERR(phy);
- }
-
- state->phys[i].phy = phy;
- state->phys[i].index = i;
- phy_set_drvdata(phy, &state->phys[i]);
- }
-
- phy_provider = devm_of_phy_provider_register(dev,
- exynos_mipi_video_phy_xlate);
-
- return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static const struct of_device_id exynos_mipi_video_phy_of_match[] = {
- { .compatible = "samsung,s5pv210-mipi-video-phy" },
- { },
-};
-MODULE_DEVICE_TABLE(of, exynos_mipi_video_phy_of_match);
-
-static struct platform_driver exynos_mipi_video_phy_driver = {
- .probe = exynos_mipi_video_phy_probe,
- .driver = {
- .of_match_table = exynos_mipi_video_phy_of_match,
- .name = "exynos-mipi-video-phy",
- }
-};
-module_platform_driver(exynos_mipi_video_phy_driver);
-
-MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC MIPI CSI-2/DSI PHY driver");
-MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 4210 support
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Author: Kamil Debski <k.debski@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/phy/phy.h>
-#include <linux/regmap.h>
-#include "phy-samsung-usb2.h"
-
-/* Exynos USB PHY registers */
-
-/* PHY power control */
-#define EXYNOS_4210_UPHYPWR 0x0
-
-#define EXYNOS_4210_UPHYPWR_PHY0_SUSPEND BIT(0)
-#define EXYNOS_4210_UPHYPWR_PHY0_PWR BIT(3)
-#define EXYNOS_4210_UPHYPWR_PHY0_OTG_PWR BIT(4)
-#define EXYNOS_4210_UPHYPWR_PHY0_SLEEP BIT(5)
-#define EXYNOS_4210_UPHYPWR_PHY0 ( \
- EXYNOS_4210_UPHYPWR_PHY0_SUSPEND | \
- EXYNOS_4210_UPHYPWR_PHY0_PWR | \
- EXYNOS_4210_UPHYPWR_PHY0_OTG_PWR | \
- EXYNOS_4210_UPHYPWR_PHY0_SLEEP)
-
-#define EXYNOS_4210_UPHYPWR_PHY1_SUSPEND BIT(6)
-#define EXYNOS_4210_UPHYPWR_PHY1_PWR BIT(7)
-#define EXYNOS_4210_UPHYPWR_PHY1_SLEEP BIT(8)
-#define EXYNOS_4210_UPHYPWR_PHY1 ( \
- EXYNOS_4210_UPHYPWR_PHY1_SUSPEND | \
- EXYNOS_4210_UPHYPWR_PHY1_PWR | \
- EXYNOS_4210_UPHYPWR_PHY1_SLEEP)
-
-#define EXYNOS_4210_UPHYPWR_HSIC0_SUSPEND BIT(9)
-#define EXYNOS_4210_UPHYPWR_HSIC0_SLEEP BIT(10)
-#define EXYNOS_4210_UPHYPWR_HSIC0 ( \
- EXYNOS_4210_UPHYPWR_HSIC0_SUSPEND | \
- EXYNOS_4210_UPHYPWR_HSIC0_SLEEP)
-
-#define EXYNOS_4210_UPHYPWR_HSIC1_SUSPEND BIT(11)
-#define EXYNOS_4210_UPHYPWR_HSIC1_SLEEP BIT(12)
-#define EXYNOS_4210_UPHYPWR_HSIC1 ( \
- EXYNOS_4210_UPHYPWR_HSIC1_SUSPEND | \
- EXYNOS_4210_UPHYPWR_HSIC1_SLEEP)
-
-/* PHY clock control */
-#define EXYNOS_4210_UPHYCLK 0x4
-
-#define EXYNOS_4210_UPHYCLK_PHYFSEL_MASK (0x3 << 0)
-#define EXYNOS_4210_UPHYCLK_PHYFSEL_OFFSET 0
-#define EXYNOS_4210_UPHYCLK_PHYFSEL_48MHZ (0x0 << 0)
-#define EXYNOS_4210_UPHYCLK_PHYFSEL_24MHZ (0x3 << 0)
-#define EXYNOS_4210_UPHYCLK_PHYFSEL_12MHZ (0x2 << 0)
-
-#define EXYNOS_4210_UPHYCLK_PHY0_ID_PULLUP BIT(2)
-#define EXYNOS_4210_UPHYCLK_PHY0_COMMON_ON BIT(4)
-#define EXYNOS_4210_UPHYCLK_PHY1_COMMON_ON BIT(7)
-
-/* PHY reset control */
-#define EXYNOS_4210_UPHYRST 0x8
-
-#define EXYNOS_4210_URSTCON_PHY0 BIT(0)
-#define EXYNOS_4210_URSTCON_OTG_HLINK BIT(1)
-#define EXYNOS_4210_URSTCON_OTG_PHYLINK BIT(2)
-#define EXYNOS_4210_URSTCON_PHY1_ALL BIT(3)
-#define EXYNOS_4210_URSTCON_PHY1_P0 BIT(4)
-#define EXYNOS_4210_URSTCON_PHY1_P1P2 BIT(5)
-#define EXYNOS_4210_URSTCON_HOST_LINK_ALL BIT(6)
-#define EXYNOS_4210_URSTCON_HOST_LINK_P0 BIT(7)
-#define EXYNOS_4210_URSTCON_HOST_LINK_P1 BIT(8)
-#define EXYNOS_4210_URSTCON_HOST_LINK_P2 BIT(9)
-
-/* Isolation, configured in the power management unit */
-#define EXYNOS_4210_USB_ISOL_DEVICE_OFFSET 0x704
-#define EXYNOS_4210_USB_ISOL_DEVICE BIT(0)
-#define EXYNOS_4210_USB_ISOL_HOST_OFFSET 0x708
-#define EXYNOS_4210_USB_ISOL_HOST BIT(0)
-
-/* USBYPHY1 Floating prevention */
-#define EXYNOS_4210_UPHY1CON 0x34
-#define EXYNOS_4210_UPHY1CON_FLOAT_PREVENTION 0x1
-
-/* Mode switching SUB Device <-> Host */
-#define EXYNOS_4210_MODE_SWITCH_OFFSET 0x21c
-#define EXYNOS_4210_MODE_SWITCH_MASK 1
-#define EXYNOS_4210_MODE_SWITCH_DEVICE 0
-#define EXYNOS_4210_MODE_SWITCH_HOST 1
-
-enum exynos4210_phy_id {
- EXYNOS4210_DEVICE,
- EXYNOS4210_HOST,
- EXYNOS4210_HSIC0,
- EXYNOS4210_HSIC1,
- EXYNOS4210_NUM_PHYS,
-};
-
-/*
- * exynos4210_rate_to_clk() converts the supplied clock rate to the value that
- * can be written to the phy register.
- */
-static int exynos4210_rate_to_clk(unsigned long rate, u32 *reg)
-{
- switch (rate) {
- case 12 * MHZ:
- *reg = EXYNOS_4210_UPHYCLK_PHYFSEL_12MHZ;
- break;
- case 24 * MHZ:
- *reg = EXYNOS_4210_UPHYCLK_PHYFSEL_24MHZ;
- break;
- case 48 * MHZ:
- *reg = EXYNOS_4210_UPHYCLK_PHYFSEL_48MHZ;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void exynos4210_isol(struct samsung_usb2_phy_instance *inst, bool on)
-{
- struct samsung_usb2_phy_driver *drv = inst->drv;
- u32 offset;
- u32 mask;
-
- switch (inst->cfg->id) {
- case EXYNOS4210_DEVICE:
- offset = EXYNOS_4210_USB_ISOL_DEVICE_OFFSET;
- mask = EXYNOS_4210_USB_ISOL_DEVICE;
- break;
- case EXYNOS4210_HOST:
- offset = EXYNOS_4210_USB_ISOL_HOST_OFFSET;
- mask = EXYNOS_4210_USB_ISOL_HOST;
- break;
- default:
- return;
- };
-
- regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
-}
-
-static void exynos4210_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
-{
- struct samsung_usb2_phy_driver *drv = inst->drv;
- u32 rstbits = 0;
- u32 phypwr = 0;
- u32 rst;
- u32 pwr;
- u32 clk;
-
- switch (inst->cfg->id) {
- case EXYNOS4210_DEVICE:
- phypwr = EXYNOS_4210_UPHYPWR_PHY0;
- rstbits = EXYNOS_4210_URSTCON_PHY0;
- break;
- case EXYNOS4210_HOST:
- phypwr = EXYNOS_4210_UPHYPWR_PHY1;
- rstbits = EXYNOS_4210_URSTCON_PHY1_ALL |
- EXYNOS_4210_URSTCON_PHY1_P0 |
- EXYNOS_4210_URSTCON_PHY1_P1P2 |
- EXYNOS_4210_URSTCON_HOST_LINK_ALL |
- EXYNOS_4210_URSTCON_HOST_LINK_P0;
- writel(on, drv->reg_phy + EXYNOS_4210_UPHY1CON);
- break;
- case EXYNOS4210_HSIC0:
- phypwr = EXYNOS_4210_UPHYPWR_HSIC0;
- rstbits = EXYNOS_4210_URSTCON_PHY1_P1P2 |
- EXYNOS_4210_URSTCON_HOST_LINK_P1;
- break;
- case EXYNOS4210_HSIC1:
- phypwr = EXYNOS_4210_UPHYPWR_HSIC1;
- rstbits = EXYNOS_4210_URSTCON_PHY1_P1P2 |
- EXYNOS_4210_URSTCON_HOST_LINK_P2;
- break;
- };
-
- if (on) {
- clk = readl(drv->reg_phy + EXYNOS_4210_UPHYCLK);
- clk &= ~EXYNOS_4210_UPHYCLK_PHYFSEL_MASK;
- clk |= drv->ref_reg_val << EXYNOS_4210_UPHYCLK_PHYFSEL_OFFSET;
- writel(clk, drv->reg_phy + EXYNOS_4210_UPHYCLK);
-
- pwr = readl(drv->reg_phy + EXYNOS_4210_UPHYPWR);
- pwr &= ~phypwr;
- writel(pwr, drv->reg_phy + EXYNOS_4210_UPHYPWR);
-
- rst = readl(drv->reg_phy + EXYNOS_4210_UPHYRST);
- rst |= rstbits;
- writel(rst, drv->reg_phy + EXYNOS_4210_UPHYRST);
- udelay(10);
- rst &= ~rstbits;
- writel(rst, drv->reg_phy + EXYNOS_4210_UPHYRST);
- /* The following delay is necessary for the reset sequence to be
- * completed */
- udelay(80);
- } else {
- pwr = readl(drv->reg_phy + EXYNOS_4210_UPHYPWR);
- pwr |= phypwr;
- writel(pwr, drv->reg_phy + EXYNOS_4210_UPHYPWR);
- }
-}
-
-static int exynos4210_power_on(struct samsung_usb2_phy_instance *inst)
-{
- /* Order of initialisation is important - first power then isolation */
- exynos4210_phy_pwr(inst, 1);
- exynos4210_isol(inst, 0);
-
- return 0;
-}
-
-static int exynos4210_power_off(struct samsung_usb2_phy_instance *inst)
-{
- exynos4210_isol(inst, 1);
- exynos4210_phy_pwr(inst, 0);
-
- return 0;
-}
-
-
-static const struct samsung_usb2_common_phy exynos4210_phys[] = {
- {
- .label = "device",
- .id = EXYNOS4210_DEVICE,
- .power_on = exynos4210_power_on,
- .power_off = exynos4210_power_off,
- },
- {
- .label = "host",
- .id = EXYNOS4210_HOST,
- .power_on = exynos4210_power_on,
- .power_off = exynos4210_power_off,
- },
- {
- .label = "hsic0",
- .id = EXYNOS4210_HSIC0,
- .power_on = exynos4210_power_on,
- .power_off = exynos4210_power_off,
- },
- {
- .label = "hsic1",
- .id = EXYNOS4210_HSIC1,
- .power_on = exynos4210_power_on,
- .power_off = exynos4210_power_off,
- },
- {},
-};
-
-const struct samsung_usb2_phy_config exynos4210_usb2_phy_config = {
- .has_mode_switch = 0,
- .num_phys = EXYNOS4210_NUM_PHYS,
- .phys = exynos4210_phys,
- .rate_to_clk = exynos4210_rate_to_clk,
-};
+++ /dev/null
-/*
- * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 4x12 support
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Author: Kamil Debski <k.debski@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/phy/phy.h>
-#include <linux/regmap.h>
-#include "phy-samsung-usb2.h"
-
-/* Exynos USB PHY registers */
-
-/* PHY power control */
-#define EXYNOS_4x12_UPHYPWR 0x0
-
-#define EXYNOS_4x12_UPHYPWR_PHY0_SUSPEND BIT(0)
-#define EXYNOS_4x12_UPHYPWR_PHY0_PWR BIT(3)
-#define EXYNOS_4x12_UPHYPWR_PHY0_OTG_PWR BIT(4)
-#define EXYNOS_4x12_UPHYPWR_PHY0_SLEEP BIT(5)
-#define EXYNOS_4x12_UPHYPWR_PHY0 ( \
- EXYNOS_4x12_UPHYPWR_PHY0_SUSPEND | \
- EXYNOS_4x12_UPHYPWR_PHY0_PWR | \
- EXYNOS_4x12_UPHYPWR_PHY0_OTG_PWR | \
- EXYNOS_4x12_UPHYPWR_PHY0_SLEEP)
-
-#define EXYNOS_4x12_UPHYPWR_PHY1_SUSPEND BIT(6)
-#define EXYNOS_4x12_UPHYPWR_PHY1_PWR BIT(7)
-#define EXYNOS_4x12_UPHYPWR_PHY1_SLEEP BIT(8)
-#define EXYNOS_4x12_UPHYPWR_PHY1 ( \
- EXYNOS_4x12_UPHYPWR_PHY1_SUSPEND | \
- EXYNOS_4x12_UPHYPWR_PHY1_PWR | \
- EXYNOS_4x12_UPHYPWR_PHY1_SLEEP)
-
-#define EXYNOS_4x12_UPHYPWR_HSIC0_SUSPEND BIT(9)
-#define EXYNOS_4x12_UPHYPWR_HSIC0_PWR BIT(10)
-#define EXYNOS_4x12_UPHYPWR_HSIC0_SLEEP BIT(11)
-#define EXYNOS_4x12_UPHYPWR_HSIC0 ( \
- EXYNOS_4x12_UPHYPWR_HSIC0_SUSPEND | \
- EXYNOS_4x12_UPHYPWR_HSIC0_PWR | \
- EXYNOS_4x12_UPHYPWR_HSIC0_SLEEP)
-
-#define EXYNOS_4x12_UPHYPWR_HSIC1_SUSPEND BIT(12)
-#define EXYNOS_4x12_UPHYPWR_HSIC1_PWR BIT(13)
-#define EXYNOS_4x12_UPHYPWR_HSIC1_SLEEP BIT(14)
-#define EXYNOS_4x12_UPHYPWR_HSIC1 ( \
- EXYNOS_4x12_UPHYPWR_HSIC1_SUSPEND | \
- EXYNOS_4x12_UPHYPWR_HSIC1_PWR | \
- EXYNOS_4x12_UPHYPWR_HSIC1_SLEEP)
-
-/* PHY clock control */
-#define EXYNOS_4x12_UPHYCLK 0x4
-
-#define EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK (0x7 << 0)
-#define EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET 0
-#define EXYNOS_4x12_UPHYCLK_PHYFSEL_9MHZ6 (0x0 << 0)
-#define EXYNOS_4x12_UPHYCLK_PHYFSEL_10MHZ (0x1 << 0)
-#define EXYNOS_4x12_UPHYCLK_PHYFSEL_12MHZ (0x2 << 0)
-#define EXYNOS_4x12_UPHYCLK_PHYFSEL_19MHZ2 (0x3 << 0)
-#define EXYNOS_4x12_UPHYCLK_PHYFSEL_20MHZ (0x4 << 0)
-#define EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ (0x5 << 0)
-#define EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ (0x7 << 0)
-
-#define EXYNOS_3250_UPHYCLK_REFCLKSEL (0x2 << 8)
-
-#define EXYNOS_4x12_UPHYCLK_PHY0_ID_PULLUP BIT(3)
-#define EXYNOS_4x12_UPHYCLK_PHY0_COMMON_ON BIT(4)
-#define EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON BIT(7)
-
-#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_MASK (0x7f << 10)
-#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_OFFSET 10
-#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_12MHZ (0x24 << 10)
-#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_15MHZ (0x1c << 10)
-#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_16MHZ (0x1a << 10)
-#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_19MHZ2 (0x15 << 10)
-#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_20MHZ (0x14 << 10)
-
-/* PHY reset control */
-#define EXYNOS_4x12_UPHYRST 0x8
-
-#define EXYNOS_4x12_URSTCON_PHY0 BIT(0)
-#define EXYNOS_4x12_URSTCON_OTG_HLINK BIT(1)
-#define EXYNOS_4x12_URSTCON_OTG_PHYLINK BIT(2)
-#define EXYNOS_4x12_URSTCON_HOST_PHY BIT(3)
-/* The following bit defines are presented in the
- * order taken from the Exynos4412 reference manual.
- *
- * During experiments with the hardware and debugging
- * it was determined that the hardware behaves contrary
- * to the manual.
- *
- * The following bit values were chaned accordingly to the
- * results of real hardware experiments.
- */
-#define EXYNOS_4x12_URSTCON_PHY1 BIT(4)
-#define EXYNOS_4x12_URSTCON_HSIC0 BIT(6)
-#define EXYNOS_4x12_URSTCON_HSIC1 BIT(5)
-#define EXYNOS_4x12_URSTCON_HOST_LINK_ALL BIT(7)
-#define EXYNOS_4x12_URSTCON_HOST_LINK_P0 BIT(10)
-#define EXYNOS_4x12_URSTCON_HOST_LINK_P1 BIT(9)
-#define EXYNOS_4x12_URSTCON_HOST_LINK_P2 BIT(8)
-
-/* Isolation, configured in the power management unit */
-#define EXYNOS_4x12_USB_ISOL_OFFSET 0x704
-#define EXYNOS_4x12_USB_ISOL_OTG BIT(0)
-#define EXYNOS_4x12_USB_ISOL_HSIC0_OFFSET 0x708
-#define EXYNOS_4x12_USB_ISOL_HSIC0 BIT(0)
-#define EXYNOS_4x12_USB_ISOL_HSIC1_OFFSET 0x70c
-#define EXYNOS_4x12_USB_ISOL_HSIC1 BIT(0)
-
-/* Mode switching SUB Device <-> Host */
-#define EXYNOS_4x12_MODE_SWITCH_OFFSET 0x21c
-#define EXYNOS_4x12_MODE_SWITCH_MASK 1
-#define EXYNOS_4x12_MODE_SWITCH_DEVICE 0
-#define EXYNOS_4x12_MODE_SWITCH_HOST 1
-
-enum exynos4x12_phy_id {
- EXYNOS4x12_DEVICE,
- EXYNOS4x12_HOST,
- EXYNOS4x12_HSIC0,
- EXYNOS4x12_HSIC1,
- EXYNOS4x12_NUM_PHYS,
-};
-
-/*
- * exynos4x12_rate_to_clk() converts the supplied clock rate to the value that
- * can be written to the phy register.
- */
-static int exynos4x12_rate_to_clk(unsigned long rate, u32 *reg)
-{
- /* EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK */
-
- switch (rate) {
- case 9600 * KHZ:
- *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_9MHZ6;
- break;
- case 10 * MHZ:
- *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_10MHZ;
- break;
- case 12 * MHZ:
- *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_12MHZ;
- break;
- case 19200 * KHZ:
- *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_19MHZ2;
- break;
- case 20 * MHZ:
- *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_20MHZ;
- break;
- case 24 * MHZ:
- *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ;
- break;
- case 50 * MHZ:
- *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void exynos4x12_isol(struct samsung_usb2_phy_instance *inst, bool on)
-{
- struct samsung_usb2_phy_driver *drv = inst->drv;
- u32 offset;
- u32 mask;
-
- switch (inst->cfg->id) {
- case EXYNOS4x12_DEVICE:
- case EXYNOS4x12_HOST:
- offset = EXYNOS_4x12_USB_ISOL_OFFSET;
- mask = EXYNOS_4x12_USB_ISOL_OTG;
- break;
- case EXYNOS4x12_HSIC0:
- offset = EXYNOS_4x12_USB_ISOL_HSIC0_OFFSET;
- mask = EXYNOS_4x12_USB_ISOL_HSIC0;
- break;
- case EXYNOS4x12_HSIC1:
- offset = EXYNOS_4x12_USB_ISOL_HSIC1_OFFSET;
- mask = EXYNOS_4x12_USB_ISOL_HSIC1;
- break;
- default:
- return;
- };
-
- regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
-}
-
-static void exynos4x12_setup_clk(struct samsung_usb2_phy_instance *inst)
-{
- struct samsung_usb2_phy_driver *drv = inst->drv;
- u32 clk;
-
- clk = readl(drv->reg_phy + EXYNOS_4x12_UPHYCLK);
- clk &= ~EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK;
-
- if (drv->cfg->has_refclk_sel)
- clk = EXYNOS_3250_UPHYCLK_REFCLKSEL;
-
- clk |= drv->ref_reg_val << EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET;
- clk |= EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON;
- writel(clk, drv->reg_phy + EXYNOS_4x12_UPHYCLK);
-}
-
-static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
-{
- struct samsung_usb2_phy_driver *drv = inst->drv;
- u32 rstbits = 0;
- u32 phypwr = 0;
- u32 rst;
- u32 pwr;
-
- switch (inst->cfg->id) {
- case EXYNOS4x12_DEVICE:
- phypwr = EXYNOS_4x12_UPHYPWR_PHY0;
- rstbits = EXYNOS_4x12_URSTCON_PHY0;
- break;
- case EXYNOS4x12_HOST:
- phypwr = EXYNOS_4x12_UPHYPWR_PHY1;
- rstbits = EXYNOS_4x12_URSTCON_HOST_PHY |
- EXYNOS_4x12_URSTCON_PHY1 |
- EXYNOS_4x12_URSTCON_HOST_LINK_P0;
- break;
- case EXYNOS4x12_HSIC0:
- phypwr = EXYNOS_4x12_UPHYPWR_HSIC0;
- rstbits = EXYNOS_4x12_URSTCON_HSIC0 |
- EXYNOS_4x12_URSTCON_HOST_LINK_P1;
- break;
- case EXYNOS4x12_HSIC1:
- phypwr = EXYNOS_4x12_UPHYPWR_HSIC1;
- rstbits = EXYNOS_4x12_URSTCON_HSIC1 |
- EXYNOS_4x12_URSTCON_HOST_LINK_P1;
- break;
- };
-
- if (on) {
- pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
- pwr &= ~phypwr;
- writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
-
- rst = readl(drv->reg_phy + EXYNOS_4x12_UPHYRST);
- rst |= rstbits;
- writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST);
- udelay(10);
- rst &= ~rstbits;
- writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST);
- /* The following delay is necessary for the reset sequence to be
- * completed */
- udelay(80);
- } else {
- pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
- pwr |= phypwr;
- writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
- }
-}
-
-static void exynos4x12_power_on_int(struct samsung_usb2_phy_instance *inst)
-{
- if (inst->int_cnt++ > 0)
- return;
-
- exynos4x12_setup_clk(inst);
- exynos4x12_isol(inst, 0);
- exynos4x12_phy_pwr(inst, 1);
-}
-
-static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
-{
- struct samsung_usb2_phy_driver *drv = inst->drv;
-
- if (inst->ext_cnt++ > 0)
- return 0;
-
- if (inst->cfg->id == EXYNOS4x12_HOST) {
- regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
- EXYNOS_4x12_MODE_SWITCH_MASK,
- EXYNOS_4x12_MODE_SWITCH_HOST);
- exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
- }
-
- if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
- regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
- EXYNOS_4x12_MODE_SWITCH_MASK,
- EXYNOS_4x12_MODE_SWITCH_DEVICE);
-
- if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
- inst->cfg->id == EXYNOS4x12_HSIC1) {
- exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
- exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_HOST]);
- }
-
- exynos4x12_power_on_int(inst);
-
- return 0;
-}
-
-static void exynos4x12_power_off_int(struct samsung_usb2_phy_instance *inst)
-{
- if (inst->int_cnt-- > 1)
- return;
-
- exynos4x12_isol(inst, 1);
- exynos4x12_phy_pwr(inst, 0);
-}
-
-static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst)
-{
- struct samsung_usb2_phy_driver *drv = inst->drv;
-
- if (inst->ext_cnt-- > 1)
- return 0;
-
- if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
- regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
- EXYNOS_4x12_MODE_SWITCH_MASK,
- EXYNOS_4x12_MODE_SWITCH_HOST);
-
- if (inst->cfg->id == EXYNOS4x12_HOST)
- exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
-
- if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
- inst->cfg->id == EXYNOS4x12_HSIC1) {
- exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
- exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_HOST]);
- }
-
- exynos4x12_power_off_int(inst);
-
- return 0;
-}
-
-
-static const struct samsung_usb2_common_phy exynos4x12_phys[] = {
- {
- .label = "device",
- .id = EXYNOS4x12_DEVICE,
- .power_on = exynos4x12_power_on,
- .power_off = exynos4x12_power_off,
- },
- {
- .label = "host",
- .id = EXYNOS4x12_HOST,
- .power_on = exynos4x12_power_on,
- .power_off = exynos4x12_power_off,
- },
- {
- .label = "hsic0",
- .id = EXYNOS4x12_HSIC0,
- .power_on = exynos4x12_power_on,
- .power_off = exynos4x12_power_off,
- },
- {
- .label = "hsic1",
- .id = EXYNOS4x12_HSIC1,
- .power_on = exynos4x12_power_on,
- .power_off = exynos4x12_power_off,
- },
- {},
-};
-
-const struct samsung_usb2_phy_config exynos3250_usb2_phy_config = {
- .has_refclk_sel = 1,
- .num_phys = 1,
- .phys = exynos4x12_phys,
- .rate_to_clk = exynos4x12_rate_to_clk,
-};
-
-const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config = {
- .has_mode_switch = 1,
- .num_phys = EXYNOS4x12_NUM_PHYS,
- .phys = exynos4x12_phys,
- .rate_to_clk = exynos4x12_rate_to_clk,
-};
+++ /dev/null
-/*
- * Samsung EXYNOS5 SoC series USB DRD PHY driver
- *
- * Phy provider for USB 3.0 DRD controller on Exynos5 SoC series
- *
- * Copyright (C) 2014 Samsung Electronics Co., Ltd.
- * Author: Vivek Gautam <gautam.vivek@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-#include <linux/mfd/syscon.h>
-#include <linux/mfd/syscon/exynos5-pmu.h>
-#include <linux/regmap.h>
-#include <linux/regulator/consumer.h>
-
-/* Exynos USB PHY registers */
-#define EXYNOS5_FSEL_9MHZ6 0x0
-#define EXYNOS5_FSEL_10MHZ 0x1
-#define EXYNOS5_FSEL_12MHZ 0x2
-#define EXYNOS5_FSEL_19MHZ2 0x3
-#define EXYNOS5_FSEL_20MHZ 0x4
-#define EXYNOS5_FSEL_24MHZ 0x5
-#define EXYNOS5_FSEL_50MHZ 0x7
-
-/* EXYNOS5: USB 3.0 DRD PHY registers */
-#define EXYNOS5_DRD_LINKSYSTEM 0x04
-
-#define LINKSYSTEM_FLADJ_MASK (0x3f << 1)
-#define LINKSYSTEM_FLADJ(_x) ((_x) << 1)
-#define LINKSYSTEM_XHCI_VERSION_CONTROL BIT(27)
-
-#define EXYNOS5_DRD_PHYUTMI 0x08
-
-#define PHYUTMI_OTGDISABLE BIT(6)
-#define PHYUTMI_FORCESUSPEND BIT(1)
-#define PHYUTMI_FORCESLEEP BIT(0)
-
-#define EXYNOS5_DRD_PHYPIPE 0x0c
-
-#define EXYNOS5_DRD_PHYCLKRST 0x10
-
-#define PHYCLKRST_EN_UTMISUSPEND BIT(31)
-
-#define PHYCLKRST_SSC_REFCLKSEL_MASK (0xff << 23)
-#define PHYCLKRST_SSC_REFCLKSEL(_x) ((_x) << 23)
-
-#define PHYCLKRST_SSC_RANGE_MASK (0x03 << 21)
-#define PHYCLKRST_SSC_RANGE(_x) ((_x) << 21)
-
-#define PHYCLKRST_SSC_EN BIT(20)
-#define PHYCLKRST_REF_SSP_EN BIT(19)
-#define PHYCLKRST_REF_CLKDIV2 BIT(18)
-
-#define PHYCLKRST_MPLL_MULTIPLIER_MASK (0x7f << 11)
-#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF (0x19 << 11)
-#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF (0x32 << 11)
-#define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF (0x68 << 11)
-#define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF (0x7d << 11)
-#define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF (0x02 << 11)
-
-#define PHYCLKRST_FSEL_UTMI_MASK (0x7 << 5)
-#define PHYCLKRST_FSEL_PIPE_MASK (0x7 << 8)
-#define PHYCLKRST_FSEL(_x) ((_x) << 5)
-#define PHYCLKRST_FSEL_PAD_100MHZ (0x27 << 5)
-#define PHYCLKRST_FSEL_PAD_24MHZ (0x2a << 5)
-#define PHYCLKRST_FSEL_PAD_20MHZ (0x31 << 5)
-#define PHYCLKRST_FSEL_PAD_19_2MHZ (0x38 << 5)
-
-#define PHYCLKRST_RETENABLEN BIT(4)
-
-#define PHYCLKRST_REFCLKSEL_MASK (0x03 << 2)
-#define PHYCLKRST_REFCLKSEL_PAD_REFCLK (0x2 << 2)
-#define PHYCLKRST_REFCLKSEL_EXT_REFCLK (0x3 << 2)
-
-#define PHYCLKRST_PORTRESET BIT(1)
-#define PHYCLKRST_COMMONONN BIT(0)
-
-#define EXYNOS5_DRD_PHYREG0 0x14
-#define EXYNOS5_DRD_PHYREG1 0x18
-
-#define EXYNOS5_DRD_PHYPARAM0 0x1c
-
-#define PHYPARAM0_REF_USE_PAD BIT(31)
-#define PHYPARAM0_REF_LOSLEVEL_MASK (0x1f << 26)
-#define PHYPARAM0_REF_LOSLEVEL (0x9 << 26)
-
-#define EXYNOS5_DRD_PHYPARAM1 0x20
-
-#define PHYPARAM1_PCS_TXDEEMPH_MASK (0x1f << 0)
-#define PHYPARAM1_PCS_TXDEEMPH (0x1c)
-
-#define EXYNOS5_DRD_PHYTERM 0x24
-
-#define EXYNOS5_DRD_PHYTEST 0x28
-
-#define PHYTEST_POWERDOWN_SSP BIT(3)
-#define PHYTEST_POWERDOWN_HSP BIT(2)
-
-#define EXYNOS5_DRD_PHYADP 0x2c
-
-#define EXYNOS5_DRD_PHYUTMICLKSEL 0x30
-
-#define PHYUTMICLKSEL_UTMI_CLKSEL BIT(2)
-
-#define EXYNOS5_DRD_PHYRESUME 0x34
-#define EXYNOS5_DRD_LINKPORT 0x44
-
-#define KHZ 1000
-#define MHZ (KHZ * KHZ)
-
-enum exynos5_usbdrd_phy_id {
- EXYNOS5_DRDPHY_UTMI,
- EXYNOS5_DRDPHY_PIPE3,
- EXYNOS5_DRDPHYS_NUM,
-};
-
-struct phy_usb_instance;
-struct exynos5_usbdrd_phy;
-
-struct exynos5_usbdrd_phy_config {
- u32 id;
- void (*phy_isol)(struct phy_usb_instance *inst, u32 on);
- void (*phy_init)(struct exynos5_usbdrd_phy *phy_drd);
- unsigned int (*set_refclk)(struct phy_usb_instance *inst);
-};
-
-struct exynos5_usbdrd_phy_drvdata {
- const struct exynos5_usbdrd_phy_config *phy_cfg;
- u32 pmu_offset_usbdrd0_phy;
- u32 pmu_offset_usbdrd1_phy;
-};
-
-/**
- * struct exynos5_usbdrd_phy - driver data for USB 3.0 PHY
- * @dev: pointer to device instance of this platform device
- * @reg_phy: usb phy controller register memory base
- * @clk: phy clock for register access
- * @drv_data: pointer to SoC level driver data structure
- * @phys[]: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY
- * instances each with its 'phy' and 'phy_cfg'.
- * @extrefclk: frequency select settings when using 'separate
- * reference clocks' for SS and HS operations
- * @ref_clk: reference clock to PHY block from which PHY's
- * operational clocks are derived
- * @ref_rate: rate of above reference clock
- */
-struct exynos5_usbdrd_phy {
- struct device *dev;
- void __iomem *reg_phy;
- struct clk *clk;
- const struct exynos5_usbdrd_phy_drvdata *drv_data;
- struct phy_usb_instance {
- struct phy *phy;
- u32 index;
- struct regmap *reg_pmu;
- u32 pmu_offset;
- const struct exynos5_usbdrd_phy_config *phy_cfg;
- } phys[EXYNOS5_DRDPHYS_NUM];
- u32 extrefclk;
- struct clk *ref_clk;
- struct regulator *vbus;
-};
-
-static inline
-struct exynos5_usbdrd_phy *to_usbdrd_phy(struct phy_usb_instance *inst)
-{
- return container_of((inst), struct exynos5_usbdrd_phy,
- phys[(inst)->index]);
-}
-
-/*
- * exynos5_rate_to_clk() converts the supplied clock rate to the value that
- * can be written to the phy register.
- */
-static unsigned int exynos5_rate_to_clk(unsigned long rate, u32 *reg)
-{
- /* EXYNOS5_FSEL_MASK */
-
- switch (rate) {
- case 9600 * KHZ:
- *reg = EXYNOS5_FSEL_9MHZ6;
- break;
- case 10 * MHZ:
- *reg = EXYNOS5_FSEL_10MHZ;
- break;
- case 12 * MHZ:
- *reg = EXYNOS5_FSEL_12MHZ;
- break;
- case 19200 * KHZ:
- *reg = EXYNOS5_FSEL_19MHZ2;
- break;
- case 20 * MHZ:
- *reg = EXYNOS5_FSEL_20MHZ;
- break;
- case 24 * MHZ:
- *reg = EXYNOS5_FSEL_24MHZ;
- break;
- case 50 * MHZ:
- *reg = EXYNOS5_FSEL_50MHZ;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void exynos5_usbdrd_phy_isol(struct phy_usb_instance *inst,
- unsigned int on)
-{
- unsigned int val;
-
- if (!inst->reg_pmu)
- return;
-
- val = on ? 0 : EXYNOS5_PHY_ENABLE;
-
- regmap_update_bits(inst->reg_pmu, inst->pmu_offset,
- EXYNOS5_PHY_ENABLE, val);
-}
-
-/*
- * Sets the pipe3 phy's clk as EXTREFCLK (XXTI) which is internal clock
- * from clock core. Further sets multiplier values and spread spectrum
- * clock settings for SuperSpeed operations.
- */
-static unsigned int
-exynos5_usbdrd_pipe3_set_refclk(struct phy_usb_instance *inst)
-{
- static u32 reg;
- struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
-
- /* restore any previous reference clock settings */
- reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
-
- /* Use EXTREFCLK as ref clock */
- reg &= ~PHYCLKRST_REFCLKSEL_MASK;
- reg |= PHYCLKRST_REFCLKSEL_EXT_REFCLK;
-
- /* FSEL settings corresponding to reference clock */
- reg &= ~PHYCLKRST_FSEL_PIPE_MASK |
- PHYCLKRST_MPLL_MULTIPLIER_MASK |
- PHYCLKRST_SSC_REFCLKSEL_MASK;
- switch (phy_drd->extrefclk) {
- case EXYNOS5_FSEL_50MHZ:
- reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
- PHYCLKRST_SSC_REFCLKSEL(0x00));
- break;
- case EXYNOS5_FSEL_24MHZ:
- reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF |
- PHYCLKRST_SSC_REFCLKSEL(0x88));
- break;
- case EXYNOS5_FSEL_20MHZ:
- reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF |
- PHYCLKRST_SSC_REFCLKSEL(0x00));
- break;
- case EXYNOS5_FSEL_19MHZ2:
- reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF |
- PHYCLKRST_SSC_REFCLKSEL(0x88));
- break;
- default:
- dev_dbg(phy_drd->dev, "unsupported ref clk\n");
- break;
- }
-
- return reg;
-}
-
-/*
- * Sets the utmi phy's clk as EXTREFCLK (XXTI) which is internal clock
- * from clock core. Further sets the FSEL values for HighSpeed operations.
- */
-static unsigned int
-exynos5_usbdrd_utmi_set_refclk(struct phy_usb_instance *inst)
-{
- static u32 reg;
- struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
-
- /* restore any previous reference clock settings */
- reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
-
- reg &= ~PHYCLKRST_REFCLKSEL_MASK;
- reg |= PHYCLKRST_REFCLKSEL_EXT_REFCLK;
-
- reg &= ~PHYCLKRST_FSEL_UTMI_MASK |
- PHYCLKRST_MPLL_MULTIPLIER_MASK |
- PHYCLKRST_SSC_REFCLKSEL_MASK;
- reg |= PHYCLKRST_FSEL(phy_drd->extrefclk);
-
- return reg;
-}
-
-static void exynos5_usbdrd_pipe3_init(struct exynos5_usbdrd_phy *phy_drd)
-{
- u32 reg;
-
- reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
- /* Set Tx De-Emphasis level */
- reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
- reg |= PHYPARAM1_PCS_TXDEEMPH;
- writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
-
- reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
- reg &= ~PHYTEST_POWERDOWN_SSP;
- writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
-}
-
-static void exynos5_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
-{
- u32 reg;
-
- reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
- /* Set Loss-of-Signal Detector sensitivity */
- reg &= ~PHYPARAM0_REF_LOSLEVEL_MASK;
- reg |= PHYPARAM0_REF_LOSLEVEL;
- writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
-
- reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
- /* Set Tx De-Emphasis level */
- reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
- reg |= PHYPARAM1_PCS_TXDEEMPH;
- writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
-
- /* UTMI Power Control */
- writel(PHYUTMI_OTGDISABLE, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
-
- reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
- reg &= ~PHYTEST_POWERDOWN_HSP;
- writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
-}
-
-static int exynos5_usbdrd_phy_init(struct phy *phy)
-{
- int ret;
- u32 reg;
- struct phy_usb_instance *inst = phy_get_drvdata(phy);
- struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
-
- ret = clk_prepare_enable(phy_drd->clk);
- if (ret)
- return ret;
-
- /* Reset USB 3.0 PHY */
- writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
- writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYRESUME);
-
- /*
- * Setting the Frame length Adj value[6:1] to default 0x20
- * See xHCI 1.0 spec, 5.2.4
- */
- reg = LINKSYSTEM_XHCI_VERSION_CONTROL |
- LINKSYSTEM_FLADJ(0x20);
- writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_LINKSYSTEM);
-
- reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
- /* Select PHY CLK source */
- reg &= ~PHYPARAM0_REF_USE_PAD;
- writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
-
- /* This bit must be set for both HS and SS operations */
- reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);
- reg |= PHYUTMICLKSEL_UTMI_CLKSEL;
- writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);
-
- /* UTMI or PIPE3 specific init */
- inst->phy_cfg->phy_init(phy_drd);
-
- /* reference clock settings */
- reg = inst->phy_cfg->set_refclk(inst);
-
- /* Digital power supply in normal operating mode */
- reg |= PHYCLKRST_RETENABLEN |
- /* Enable ref clock for SS function */
- PHYCLKRST_REF_SSP_EN |
- /* Enable spread spectrum */
- PHYCLKRST_SSC_EN |
- /* Power down HS Bias and PLL blocks in suspend mode */
- PHYCLKRST_COMMONONN |
- /* Reset the port */
- PHYCLKRST_PORTRESET;
-
- writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
-
- udelay(10);
-
- reg &= ~PHYCLKRST_PORTRESET;
- writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
-
- clk_disable_unprepare(phy_drd->clk);
-
- return 0;
-}
-
-static int exynos5_usbdrd_phy_exit(struct phy *phy)
-{
- int ret;
- u32 reg;
- struct phy_usb_instance *inst = phy_get_drvdata(phy);
- struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
-
- ret = clk_prepare_enable(phy_drd->clk);
- if (ret)
- return ret;
-
- reg = PHYUTMI_OTGDISABLE |
- PHYUTMI_FORCESUSPEND |
- PHYUTMI_FORCESLEEP;
- writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
-
- /* Resetting the PHYCLKRST enable bits to reduce leakage current */
- reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
- reg &= ~(PHYCLKRST_REF_SSP_EN |
- PHYCLKRST_SSC_EN |
- PHYCLKRST_COMMONONN);
- writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
-
- /* Control PHYTEST to remove leakage current */
- reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
- reg |= PHYTEST_POWERDOWN_SSP |
- PHYTEST_POWERDOWN_HSP;
- writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
-
- clk_disable_unprepare(phy_drd->clk);
-
- return 0;
-}
-
-static int exynos5_usbdrd_phy_power_on(struct phy *phy)
-{
- int ret;
- struct phy_usb_instance *inst = phy_get_drvdata(phy);
- struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
-
- dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n");
-
- clk_prepare_enable(phy_drd->ref_clk);
-
- /* Enable VBUS supply */
- if (phy_drd->vbus) {
- ret = regulator_enable(phy_drd->vbus);
- if (ret) {
- dev_err(phy_drd->dev, "Failed to enable VBUS supply\n");
- goto fail_vbus;
- }
- }
-
- /* Power-on PHY*/
- inst->phy_cfg->phy_isol(inst, 0);
-
- return 0;
-
-fail_vbus:
- clk_disable_unprepare(phy_drd->ref_clk);
-
- return ret;
-}
-
-static int exynos5_usbdrd_phy_power_off(struct phy *phy)
-{
- struct phy_usb_instance *inst = phy_get_drvdata(phy);
- struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
-
- dev_dbg(phy_drd->dev, "Request to power_off usbdrd_phy phy\n");
-
- /* Power-off the PHY */
- inst->phy_cfg->phy_isol(inst, 1);
-
- /* Disable VBUS supply */
- if (phy_drd->vbus)
- regulator_disable(phy_drd->vbus);
-
- clk_disable_unprepare(phy_drd->ref_clk);
-
- return 0;
-}
-
-static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
-{
- struct exynos5_usbdrd_phy *phy_drd = dev_get_drvdata(dev);
-
- if (WARN_ON(args->args[0] > EXYNOS5_DRDPHYS_NUM))
- return ERR_PTR(-ENODEV);
-
- return phy_drd->phys[args->args[0]].phy;
-}
-
-static struct phy_ops exynos5_usbdrd_phy_ops = {
- .init = exynos5_usbdrd_phy_init,
- .exit = exynos5_usbdrd_phy_exit,
- .power_on = exynos5_usbdrd_phy_power_on,
- .power_off = exynos5_usbdrd_phy_power_off,
- .owner = THIS_MODULE,
-};
-
-static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
- {
- .id = EXYNOS5_DRDPHY_UTMI,
- .phy_isol = exynos5_usbdrd_phy_isol,
- .phy_init = exynos5_usbdrd_utmi_init,
- .set_refclk = exynos5_usbdrd_utmi_set_refclk,
- },
- {
- .id = EXYNOS5_DRDPHY_PIPE3,
- .phy_isol = exynos5_usbdrd_phy_isol,
- .phy_init = exynos5_usbdrd_pipe3_init,
- .set_refclk = exynos5_usbdrd_pipe3_set_refclk,
- },
-};
-
-static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
- .phy_cfg = phy_cfg_exynos5,
- .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
- .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL,
-};
-
-static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
- .phy_cfg = phy_cfg_exynos5,
- .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
-};
-
-static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
- {
- .compatible = "samsung,exynos5250-usbdrd-phy",
- .data = &exynos5250_usbdrd_phy
- }, {
- .compatible = "samsung,exynos5420-usbdrd-phy",
- .data = &exynos5420_usbdrd_phy
- },
- { },
-};
-MODULE_DEVICE_TABLE(of, exynos5_usbdrd_phy_of_match);
-
-static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct device_node *node = dev->of_node;
- struct exynos5_usbdrd_phy *phy_drd;
- struct phy_provider *phy_provider;
- struct resource *res;
- const struct of_device_id *match;
- const struct exynos5_usbdrd_phy_drvdata *drv_data;
- struct regmap *reg_pmu;
- u32 pmu_offset;
- unsigned long ref_rate;
- int i, ret;
- int channel;
-
- phy_drd = devm_kzalloc(dev, sizeof(*phy_drd), GFP_KERNEL);
- if (!phy_drd)
- return -ENOMEM;
-
- dev_set_drvdata(dev, phy_drd);
- phy_drd->dev = dev;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- phy_drd->reg_phy = devm_ioremap_resource(dev, res);
- if (IS_ERR(phy_drd->reg_phy))
- return PTR_ERR(phy_drd->reg_phy);
-
- match = of_match_node(exynos5_usbdrd_phy_of_match, pdev->dev.of_node);
-
- drv_data = match->data;
- phy_drd->drv_data = drv_data;
-
- phy_drd->clk = devm_clk_get(dev, "phy");
- if (IS_ERR(phy_drd->clk)) {
- dev_err(dev, "Failed to get clock of phy controller\n");
- return PTR_ERR(phy_drd->clk);
- }
-
- phy_drd->ref_clk = devm_clk_get(dev, "ref");
- if (IS_ERR(phy_drd->ref_clk)) {
- dev_err(dev, "Failed to get reference clock of usbdrd phy\n");
- return PTR_ERR(phy_drd->ref_clk);
- }
- ref_rate = clk_get_rate(phy_drd->ref_clk);
-
- ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);
- if (ret) {
- dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n",
- ref_rate);
- return ret;
- }
-
- reg_pmu = syscon_regmap_lookup_by_phandle(dev->of_node,
- "samsung,pmu-syscon");
- if (IS_ERR(reg_pmu)) {
- dev_err(dev, "Failed to lookup PMU regmap\n");
- return PTR_ERR(reg_pmu);
- }
-
- /*
- * Exynos5420 SoC has multiple channels for USB 3.0 PHY, with
- * each having separate power control registers.
- * 'channel' facilitates to set such registers.
- */
- channel = of_alias_get_id(node, "usbdrdphy");
- if (channel < 0)
- dev_dbg(dev, "Not a multi-controller usbdrd phy\n");
-
- switch (channel) {
- case 1:
- pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd1_phy;
- break;
- case 0:
- default:
- pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd0_phy;
- break;
- }
-
- /* Get Vbus regulator */
- phy_drd->vbus = devm_regulator_get(dev, "vbus");
- if (IS_ERR(phy_drd->vbus)) {
- ret = PTR_ERR(phy_drd->vbus);
- if (ret == -EPROBE_DEFER)
- return ret;
-
- dev_warn(dev, "Failed to get VBUS supply regulator\n");
- phy_drd->vbus = NULL;
- }
-
- dev_vdbg(dev, "Creating usbdrd_phy phy\n");
-
- for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {
- struct phy *phy = devm_phy_create(dev, NULL,
- &exynos5_usbdrd_phy_ops,
- NULL);
- if (IS_ERR(phy)) {
- dev_err(dev, "Failed to create usbdrd_phy phy\n");
- return PTR_ERR(phy);
- }
-
- phy_drd->phys[i].phy = phy;
- phy_drd->phys[i].index = i;
- phy_drd->phys[i].reg_pmu = reg_pmu;
- phy_drd->phys[i].pmu_offset = pmu_offset;
- phy_drd->phys[i].phy_cfg = &drv_data->phy_cfg[i];
- phy_set_drvdata(phy, &phy_drd->phys[i]);
- }
-
- phy_provider = devm_of_phy_provider_register(dev,
- exynos5_usbdrd_phy_xlate);
- if (IS_ERR(phy_provider)) {
- dev_err(phy_drd->dev, "Failed to register phy provider\n");
- return PTR_ERR(phy_provider);
- }
-
- return 0;
-}
-
-static struct platform_driver exynos5_usb3drd_phy = {
- .probe = exynos5_usbdrd_phy_probe,
- .driver = {
- .of_match_table = exynos5_usbdrd_phy_of_match,
- .name = "exynos5_usb3drd_phy",
- }
-};
-
-module_platform_driver(exynos5_usb3drd_phy);
-MODULE_DESCRIPTION("Samsung EXYNOS5 SoCs USB 3.0 DRD controller PHY driver");
-MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:exynos5_usb3drd_phy");
+++ /dev/null
-/*
- * Samsung SATA SerDes(PHY) driver
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Authors: Girish K S <ks.giri@samsung.com>
- * Yuvaraj Kumar C D <yuvaraj.cd@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-#include <linux/spinlock.h>
-#include <linux/mfd/syscon.h>
-
-#define SATAPHY_CONTROL_OFFSET 0x0724
-#define EXYNOS5_SATAPHY_PMU_ENABLE BIT(0)
-#define EXYNOS5_SATA_RESET 0x4
-#define RESET_GLOBAL_RST_N BIT(0)
-#define RESET_CMN_RST_N BIT(1)
-#define RESET_CMN_BLOCK_RST_N BIT(2)
-#define RESET_CMN_I2C_RST_N BIT(3)
-#define RESET_TX_RX_PIPE_RST_N BIT(4)
-#define RESET_TX_RX_BLOCK_RST_N BIT(5)
-#define RESET_TX_RX_I2C_RST_N (BIT(6) | BIT(7))
-#define LINK_RESET 0xf0000
-#define EXYNOS5_SATA_MODE0 0x10
-#define SATA_SPD_GEN3 BIT(1)
-#define EXYNOS5_SATA_CTRL0 0x14
-#define CTRL0_P0_PHY_CALIBRATED_SEL BIT(9)
-#define CTRL0_P0_PHY_CALIBRATED BIT(8)
-#define EXYNOS5_SATA_PHSATA_CTRLM 0xe0
-#define PHCTRLM_REF_RATE BIT(1)
-#define PHCTRLM_HIGH_SPEED BIT(0)
-#define EXYNOS5_SATA_PHSATA_STATM 0xf0
-#define PHSTATM_PLL_LOCKED BIT(0)
-
-#define PHY_PLL_TIMEOUT (usecs_to_jiffies(1000))
-
-struct exynos_sata_phy {
- struct phy *phy;
- struct clk *phyclk;
- void __iomem *regs;
- struct regmap *pmureg;
- struct i2c_client *client;
-};
-
-static int wait_for_reg_status(void __iomem *base, u32 reg, u32 checkbit,
- u32 status)
-{
- unsigned long timeout = jiffies + PHY_PLL_TIMEOUT;
-
- while (time_before(jiffies, timeout)) {
- if ((readl(base + reg) & checkbit) == status)
- return 0;
- }
-
- return -EFAULT;
-}
-
-static int exynos_sata_phy_power_on(struct phy *phy)
-{
- struct exynos_sata_phy *sata_phy = phy_get_drvdata(phy);
-
- return regmap_update_bits(sata_phy->pmureg, SATAPHY_CONTROL_OFFSET,
- EXYNOS5_SATAPHY_PMU_ENABLE, true);
-
-}
-
-static int exynos_sata_phy_power_off(struct phy *phy)
-{
- struct exynos_sata_phy *sata_phy = phy_get_drvdata(phy);
-
- return regmap_update_bits(sata_phy->pmureg, SATAPHY_CONTROL_OFFSET,
- EXYNOS5_SATAPHY_PMU_ENABLE, false);
-
-}
-
-static int exynos_sata_phy_init(struct phy *phy)
-{
- u32 val = 0;
- int ret = 0;
- u8 buf[] = { 0x3a, 0x0b };
- struct exynos_sata_phy *sata_phy = phy_get_drvdata(phy);
-
- ret = regmap_update_bits(sata_phy->pmureg, SATAPHY_CONTROL_OFFSET,
- EXYNOS5_SATAPHY_PMU_ENABLE, true);
- if (ret != 0)
- dev_err(&sata_phy->phy->dev, "phy init failed\n");
-
- writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
-
- val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
- val |= RESET_GLOBAL_RST_N | RESET_CMN_RST_N | RESET_CMN_BLOCK_RST_N
- | RESET_CMN_I2C_RST_N | RESET_TX_RX_PIPE_RST_N
- | RESET_TX_RX_BLOCK_RST_N | RESET_TX_RX_I2C_RST_N;
- writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
-
- val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
- val |= LINK_RESET;
- writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
-
- val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
- val |= RESET_CMN_RST_N;
- writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
-
- val = readl(sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);
- val &= ~PHCTRLM_REF_RATE;
- writel(val, sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);
-
- /* High speed enable for Gen3 */
- val = readl(sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);
- val |= PHCTRLM_HIGH_SPEED;
- writel(val, sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);
-
- val = readl(sata_phy->regs + EXYNOS5_SATA_CTRL0);
- val |= CTRL0_P0_PHY_CALIBRATED_SEL | CTRL0_P0_PHY_CALIBRATED;
- writel(val, sata_phy->regs + EXYNOS5_SATA_CTRL0);
-
- val = readl(sata_phy->regs + EXYNOS5_SATA_MODE0);
- val |= SATA_SPD_GEN3;
- writel(val, sata_phy->regs + EXYNOS5_SATA_MODE0);
-
- ret = i2c_master_send(sata_phy->client, buf, sizeof(buf));
- if (ret < 0)
- return ret;
-
- /* release cmu reset */
- val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
- val &= ~RESET_CMN_RST_N;
- writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
-
- val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
- val |= RESET_CMN_RST_N;
- writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
-
- ret = wait_for_reg_status(sata_phy->regs,
- EXYNOS5_SATA_PHSATA_STATM,
- PHSTATM_PLL_LOCKED, 1);
- if (ret < 0)
- dev_err(&sata_phy->phy->dev,
- "PHY PLL locking failed\n");
- return ret;
-}
-
-static struct phy_ops exynos_sata_phy_ops = {
- .init = exynos_sata_phy_init,
- .power_on = exynos_sata_phy_power_on,
- .power_off = exynos_sata_phy_power_off,
- .owner = THIS_MODULE,
-};
-
-static int exynos_sata_phy_probe(struct platform_device *pdev)
-{
- struct exynos_sata_phy *sata_phy;
- struct device *dev = &pdev->dev;
- struct resource *res;
- struct phy_provider *phy_provider;
- struct device_node *node;
- int ret = 0;
-
- sata_phy = devm_kzalloc(dev, sizeof(*sata_phy), GFP_KERNEL);
- if (!sata_phy)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- sata_phy->regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(sata_phy->regs))
- return PTR_ERR(sata_phy->regs);
-
- sata_phy->pmureg = syscon_regmap_lookup_by_phandle(dev->of_node,
- "samsung,syscon-phandle");
- if (IS_ERR(sata_phy->pmureg)) {
- dev_err(dev, "syscon regmap lookup failed.\n");
- return PTR_ERR(sata_phy->pmureg);
- }
-
- node = of_parse_phandle(dev->of_node,
- "samsung,exynos-sataphy-i2c-phandle", 0);
- if (!node)
- return -EINVAL;
-
- sata_phy->client = of_find_i2c_device_by_node(node);
- if (!sata_phy->client)
- return -EPROBE_DEFER;
-
- dev_set_drvdata(dev, sata_phy);
-
- sata_phy->phyclk = devm_clk_get(dev, "sata_phyctrl");
- if (IS_ERR(sata_phy->phyclk)) {
- dev_err(dev, "failed to get clk for PHY\n");
- return PTR_ERR(sata_phy->phyclk);
- }
-
- ret = clk_prepare_enable(sata_phy->phyclk);
- if (ret < 0) {
- dev_err(dev, "failed to enable source clk\n");
- return ret;
- }
-
- sata_phy->phy = devm_phy_create(dev, NULL, &exynos_sata_phy_ops, NULL);
- if (IS_ERR(sata_phy->phy)) {
- clk_disable_unprepare(sata_phy->phyclk);
- dev_err(dev, "failed to create PHY\n");
- return PTR_ERR(sata_phy->phy);
- }
-
- phy_set_drvdata(sata_phy->phy, sata_phy);
-
- phy_provider = devm_of_phy_provider_register(dev,
- of_phy_simple_xlate);
- if (IS_ERR(phy_provider)) {
- clk_disable_unprepare(sata_phy->phyclk);
- return PTR_ERR(phy_provider);
- }
-
- return 0;
-}
-
-static const struct of_device_id exynos_sata_phy_of_match[] = {
- { .compatible = "samsung,exynos5250-sata-phy" },
- { },
-};
-MODULE_DEVICE_TABLE(of, exynos_sata_phy_of_match);
-
-static struct platform_driver exynos_sata_phy_driver = {
- .probe = exynos_sata_phy_probe,
- .driver = {
- .of_match_table = exynos_sata_phy_of_match,
- .name = "samsung,sata-phy",
- }
-};
-module_platform_driver(exynos_sata_phy_driver);
-
-MODULE_DESCRIPTION("Samsung SerDes PHY driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Girish K S <ks.giri@samsung.com>");
-MODULE_AUTHOR("Yuvaraj C D <yuvaraj.cd@samsung.com>");
+++ /dev/null
-/*
- * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 5250 support
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Author: Kamil Debski <k.debski@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/phy/phy.h>
-#include <linux/regmap.h>
-#include "phy-samsung-usb2.h"
-
-/* Exynos USB PHY registers */
-#define EXYNOS_5250_REFCLKSEL_CRYSTAL 0x0
-#define EXYNOS_5250_REFCLKSEL_XO 0x1
-#define EXYNOS_5250_REFCLKSEL_CLKCORE 0x2
-
-#define EXYNOS_5250_FSEL_9MHZ6 0x0
-#define EXYNOS_5250_FSEL_10MHZ 0x1
-#define EXYNOS_5250_FSEL_12MHZ 0x2
-#define EXYNOS_5250_FSEL_19MHZ2 0x3
-#define EXYNOS_5250_FSEL_20MHZ 0x4
-#define EXYNOS_5250_FSEL_24MHZ 0x5
-#define EXYNOS_5250_FSEL_50MHZ 0x7
-
-/* Normal host */
-#define EXYNOS_5250_HOSTPHYCTRL0 0x0
-
-#define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL BIT(31)
-#define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT 19
-#define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_MASK \
- (0x3 << EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT)
-#define EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT 16
-#define EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK \
- (0x7 << EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT)
-#define EXYNOS_5250_HOSTPHYCTRL0_TESTBURNIN BIT(11)
-#define EXYNOS_5250_HOSTPHYCTRL0_RETENABLE BIT(10)
-#define EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N BIT(9)
-#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_MASK (0x3 << 7)
-#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_DUAL (0x0 << 7)
-#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ID0 (0x1 << 7)
-#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ANALOGTEST (0x2 << 7)
-#define EXYNOS_5250_HOSTPHYCTRL0_SIDDQ BIT(6)
-#define EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP BIT(5)
-#define EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND BIT(4)
-#define EXYNOS_5250_HOSTPHYCTRL0_WORDINTERFACE BIT(3)
-#define EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST BIT(2)
-#define EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST BIT(1)
-#define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST BIT(0)
-
-/* HSIC0 & HSIC1 */
-#define EXYNOS_5250_HSICPHYCTRL1 0x10
-#define EXYNOS_5250_HSICPHYCTRL2 0x20
-
-#define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_MASK (0x3 << 23)
-#define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT (0x2 << 23)
-#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_MASK (0x7f << 16)
-#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 (0x24 << 16)
-#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_15 (0x1c << 16)
-#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_16 (0x1a << 16)
-#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_19_2 (0x15 << 16)
-#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_20 (0x14 << 16)
-#define EXYNOS_5250_HSICPHYCTRLX_SIDDQ BIT(6)
-#define EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP BIT(5)
-#define EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND BIT(4)
-#define EXYNOS_5250_HSICPHYCTRLX_WORDINTERFACE BIT(3)
-#define EXYNOS_5250_HSICPHYCTRLX_UTMISWRST BIT(2)
-#define EXYNOS_5250_HSICPHYCTRLX_PHYSWRST BIT(0)
-
-/* EHCI control */
-#define EXYNOS_5250_HOSTEHCICTRL 0x30
-#define EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN BIT(29)
-#define EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 BIT(28)
-#define EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 BIT(27)
-#define EXYNOS_5250_HOSTEHCICTRL_ENAINCR16 BIT(26)
-#define EXYNOS_5250_HOSTEHCICTRL_AUTOPPDONOVRCUREN BIT(25)
-#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT 19
-#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK \
- (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT)
-#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT 13
-#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_MASK \
- (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT)
-#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL2_SHIFT 7
-#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK \
- (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT)
-#define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT 1
-#define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_MASK \
- (0x1 << EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT)
-#define EXYNOS_5250_HOSTEHCICTRL_SIMULATIONMODE BIT(0)
-
-/* OHCI control */
-#define EXYNOS_5250_HOSTOHCICTRL 0x34
-#define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT 1
-#define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_MASK \
- (0x3ff << EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT)
-#define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVALEN BIT(0)
-
-/* USBOTG */
-#define EXYNOS_5250_USBOTGSYS 0x38
-#define EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET BIT(14)
-#define EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG BIT(13)
-#define EXYNOS_5250_USBOTGSYS_PHY_SW_RST BIT(12)
-#define EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT 9
-#define EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK \
- (0x3 << EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT)
-#define EXYNOS_5250_USBOTGSYS_ID_PULLUP BIT(8)
-#define EXYNOS_5250_USBOTGSYS_COMMON_ON BIT(7)
-#define EXYNOS_5250_USBOTGSYS_FSEL_SHIFT 4
-#define EXYNOS_5250_USBOTGSYS_FSEL_MASK \
- (0x3 << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT)
-#define EXYNOS_5250_USBOTGSYS_FORCE_SLEEP BIT(3)
-#define EXYNOS_5250_USBOTGSYS_OTGDISABLE BIT(2)
-#define EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG BIT(1)
-#define EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND BIT(0)
-
-/* Isolation, configured in the power management unit */
-#define EXYNOS_5250_USB_ISOL_OTG_OFFSET 0x704
-#define EXYNOS_5250_USB_ISOL_OTG BIT(0)
-#define EXYNOS_5250_USB_ISOL_HOST_OFFSET 0x708
-#define EXYNOS_5250_USB_ISOL_HOST BIT(0)
-
-/* Mode swtich register */
-#define EXYNOS_5250_MODE_SWITCH_OFFSET 0x230
-#define EXYNOS_5250_MODE_SWITCH_MASK 1
-#define EXYNOS_5250_MODE_SWITCH_DEVICE 0
-#define EXYNOS_5250_MODE_SWITCH_HOST 1
-
-enum exynos4x12_phy_id {
- EXYNOS5250_DEVICE,
- EXYNOS5250_HOST,
- EXYNOS5250_HSIC0,
- EXYNOS5250_HSIC1,
- EXYNOS5250_NUM_PHYS,
-};
-
-/*
- * exynos5250_rate_to_clk() converts the supplied clock rate to the value that
- * can be written to the phy register.
- */
-static int exynos5250_rate_to_clk(unsigned long rate, u32 *reg)
-{
- /* EXYNOS_5250_FSEL_MASK */
-
- switch (rate) {
- case 9600 * KHZ:
- *reg = EXYNOS_5250_FSEL_9MHZ6;
- break;
- case 10 * MHZ:
- *reg = EXYNOS_5250_FSEL_10MHZ;
- break;
- case 12 * MHZ:
- *reg = EXYNOS_5250_FSEL_12MHZ;
- break;
- case 19200 * KHZ:
- *reg = EXYNOS_5250_FSEL_19MHZ2;
- break;
- case 20 * MHZ:
- *reg = EXYNOS_5250_FSEL_20MHZ;
- break;
- case 24 * MHZ:
- *reg = EXYNOS_5250_FSEL_24MHZ;
- break;
- case 50 * MHZ:
- *reg = EXYNOS_5250_FSEL_50MHZ;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void exynos5250_isol(struct samsung_usb2_phy_instance *inst, bool on)
-{
- struct samsung_usb2_phy_driver *drv = inst->drv;
- u32 offset;
- u32 mask;
-
- switch (inst->cfg->id) {
- case EXYNOS5250_DEVICE:
- offset = EXYNOS_5250_USB_ISOL_OTG_OFFSET;
- mask = EXYNOS_5250_USB_ISOL_OTG;
- break;
- case EXYNOS5250_HOST:
- offset = EXYNOS_5250_USB_ISOL_HOST_OFFSET;
- mask = EXYNOS_5250_USB_ISOL_HOST;
- break;
- default:
- return;
- };
-
- regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
-}
-
-static int exynos5250_power_on(struct samsung_usb2_phy_instance *inst)
-{
- struct samsung_usb2_phy_driver *drv = inst->drv;
- u32 ctrl0;
- u32 otg;
- u32 ehci;
- u32 ohci;
- u32 hsic;
-
- switch (inst->cfg->id) {
- case EXYNOS5250_DEVICE:
- regmap_update_bits(drv->reg_sys,
- EXYNOS_5250_MODE_SWITCH_OFFSET,
- EXYNOS_5250_MODE_SWITCH_MASK,
- EXYNOS_5250_MODE_SWITCH_DEVICE);
-
- /* OTG configuration */
- otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
- /* The clock */
- otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK;
- otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT;
- /* Reset */
- otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
- EXYNOS_5250_USBOTGSYS_FORCE_SLEEP |
- EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG);
- otg |= EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
- EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
- EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
- EXYNOS_5250_USBOTGSYS_OTGDISABLE;
- /* Ref clock */
- otg &= ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK;
- otg |= EXYNOS_5250_REFCLKSEL_CLKCORE <<
- EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT;
- writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
- udelay(100);
- otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
- EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
- EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
- EXYNOS_5250_USBOTGSYS_OTGDISABLE);
- writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
-
-
- break;
- case EXYNOS5250_HOST:
- case EXYNOS5250_HSIC0:
- case EXYNOS5250_HSIC1:
- /* Host registers configuration */
- ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
- /* The clock */
- ctrl0 &= ~EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK;
- ctrl0 |= drv->ref_reg_val <<
- EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT;
-
- /* Reset */
- ctrl0 &= ~(EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST |
- EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL |
- EXYNOS_5250_HOSTPHYCTRL0_SIDDQ |
- EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND |
- EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP);
- ctrl0 |= EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST |
- EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST |
- EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N;
- writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
- udelay(10);
- ctrl0 &= ~(EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST |
- EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST);
- writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
-
- /* OTG configuration */
- otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
- /* The clock */
- otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK;
- otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT;
- /* Reset */
- otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
- EXYNOS_5250_USBOTGSYS_FORCE_SLEEP |
- EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG);
- otg |= EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
- EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
- EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
- EXYNOS_5250_USBOTGSYS_OTGDISABLE;
- /* Ref clock */
- otg &= ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK;
- otg |= EXYNOS_5250_REFCLKSEL_CLKCORE <<
- EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT;
- writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
- udelay(10);
- otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
- EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
- EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET);
-
- /* HSIC phy configuration */
- hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 |
- EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT |
- EXYNOS_5250_HSICPHYCTRLX_PHYSWRST);
- writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
- writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
- udelay(10);
- hsic &= ~EXYNOS_5250_HSICPHYCTRLX_PHYSWRST;
- writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
- writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
- /* The following delay is necessary for the reset sequence to be
- * completed */
- udelay(80);
-
- /* Enable EHCI DMA burst */
- ehci = readl(drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL);
- ehci |= EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN |
- EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 |
- EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 |
- EXYNOS_5250_HOSTEHCICTRL_ENAINCR16;
- writel(ehci, drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL);
-
- /* OHCI settings */
- ohci = readl(drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL);
- /* Following code is based on the old driver */
- ohci |= 0x1 << 3;
- writel(ohci, drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL);
-
- break;
- }
- exynos5250_isol(inst, 0);
-
- return 0;
-}
-
-static int exynos5250_power_off(struct samsung_usb2_phy_instance *inst)
-{
- struct samsung_usb2_phy_driver *drv = inst->drv;
- u32 ctrl0;
- u32 otg;
- u32 hsic;
-
- exynos5250_isol(inst, 1);
-
- switch (inst->cfg->id) {
- case EXYNOS5250_DEVICE:
- otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
- otg |= (EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
- EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG |
- EXYNOS_5250_USBOTGSYS_FORCE_SLEEP);
- writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
- break;
- case EXYNOS5250_HOST:
- ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
- ctrl0 |= (EXYNOS_5250_HOSTPHYCTRL0_SIDDQ |
- EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND |
- EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP |
- EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST |
- EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL);
- writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
- break;
- case EXYNOS5250_HSIC0:
- case EXYNOS5250_HSIC1:
- hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 |
- EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT |
- EXYNOS_5250_HSICPHYCTRLX_SIDDQ |
- EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP |
- EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND
- );
- writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
- writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
- break;
- }
-
- return 0;
-}
-
-
-static const struct samsung_usb2_common_phy exynos5250_phys[] = {
- {
- .label = "device",
- .id = EXYNOS5250_DEVICE,
- .power_on = exynos5250_power_on,
- .power_off = exynos5250_power_off,
- },
- {
- .label = "host",
- .id = EXYNOS5250_HOST,
- .power_on = exynos5250_power_on,
- .power_off = exynos5250_power_off,
- },
- {
- .label = "hsic0",
- .id = EXYNOS5250_HSIC0,
- .power_on = exynos5250_power_on,
- .power_off = exynos5250_power_off,
- },
- {
- .label = "hsic1",
- .id = EXYNOS5250_HSIC1,
- .power_on = exynos5250_power_on,
- .power_off = exynos5250_power_off,
- },
- {},
-};
-
-const struct samsung_usb2_phy_config exynos5250_usb2_phy_config = {
- .has_mode_switch = 1,
- .num_phys = EXYNOS5250_NUM_PHYS,
- .phys = exynos5250_phys,
- .rate_to_clk = exynos5250_rate_to_clk,
-};
+++ /dev/null
-/*
- * Copyright (c) 2014 Linaro Ltd.
- * Copyright (c) 2014 Hisilicon Limited.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-
-#define SATA_PHY0_CTLL 0xa0
-#define MPLL_MULTIPLIER_SHIFT 1
-#define MPLL_MULTIPLIER_MASK 0xfe
-#define MPLL_MULTIPLIER_50M 0x3c
-#define MPLL_MULTIPLIER_100M 0x1e
-#define PHY_RESET BIT(0)
-#define REF_SSP_EN BIT(9)
-#define SSC_EN BIT(10)
-#define REF_USE_PAD BIT(23)
-
-#define SATA_PORT_PHYCTL 0x174
-#define SPEED_MODE_MASK 0x6f0000
-#define HALF_RATE_SHIFT 16
-#define PHY_CONFIG_SHIFT 18
-#define GEN2_EN_SHIFT 21
-#define SPEED_CTRL BIT(20)
-
-#define SATA_PORT_PHYCTL1 0x148
-#define AMPLITUDE_MASK 0x3ffffe
-#define AMPLITUDE_GEN3 0x68
-#define AMPLITUDE_GEN3_SHIFT 15
-#define AMPLITUDE_GEN2 0x56
-#define AMPLITUDE_GEN2_SHIFT 8
-#define AMPLITUDE_GEN1 0x56
-#define AMPLITUDE_GEN1_SHIFT 1
-
-#define SATA_PORT_PHYCTL2 0x14c
-#define PREEMPH_MASK 0x3ffff
-#define PREEMPH_GEN3 0x20
-#define PREEMPH_GEN3_SHIFT 12
-#define PREEMPH_GEN2 0x15
-#define PREEMPH_GEN2_SHIFT 6
-#define PREEMPH_GEN1 0x5
-#define PREEMPH_GEN1_SHIFT 0
-
-struct hix5hd2_priv {
- void __iomem *base;
- struct regmap *peri_ctrl;
-};
-
-enum phy_speed_mode {
- SPEED_MODE_GEN1 = 0,
- SPEED_MODE_GEN2 = 1,
- SPEED_MODE_GEN3 = 2,
-};
-
-static int hix5hd2_sata_phy_init(struct phy *phy)
-{
- struct hix5hd2_priv *priv = phy_get_drvdata(phy);
- u32 val, data[2];
- int ret;
-
- if (priv->peri_ctrl) {
- ret = of_property_read_u32_array(phy->dev.of_node,
- "hisilicon,power-reg",
- &data[0], 2);
- if (ret) {
- dev_err(&phy->dev, "Fail read hisilicon,power-reg\n");
- return ret;
- }
-
- regmap_update_bits(priv->peri_ctrl, data[0],
- BIT(data[1]), BIT(data[1]));
- }
-
- /* reset phy */
- val = readl_relaxed(priv->base + SATA_PHY0_CTLL);
- val &= ~(MPLL_MULTIPLIER_MASK | REF_USE_PAD);
- val |= MPLL_MULTIPLIER_50M << MPLL_MULTIPLIER_SHIFT |
- REF_SSP_EN | PHY_RESET;
- writel_relaxed(val, priv->base + SATA_PHY0_CTLL);
- msleep(20);
- val &= ~PHY_RESET;
- writel_relaxed(val, priv->base + SATA_PHY0_CTLL);
-
- val = readl_relaxed(priv->base + SATA_PORT_PHYCTL1);
- val &= ~AMPLITUDE_MASK;
- val |= AMPLITUDE_GEN3 << AMPLITUDE_GEN3_SHIFT |
- AMPLITUDE_GEN2 << AMPLITUDE_GEN2_SHIFT |
- AMPLITUDE_GEN1 << AMPLITUDE_GEN1_SHIFT;
- writel_relaxed(val, priv->base + SATA_PORT_PHYCTL1);
-
- val = readl_relaxed(priv->base + SATA_PORT_PHYCTL2);
- val &= ~PREEMPH_MASK;
- val |= PREEMPH_GEN3 << PREEMPH_GEN3_SHIFT |
- PREEMPH_GEN2 << PREEMPH_GEN2_SHIFT |
- PREEMPH_GEN1 << PREEMPH_GEN1_SHIFT;
- writel_relaxed(val, priv->base + SATA_PORT_PHYCTL2);
-
- /* ensure PHYCTRL setting takes effect */
- val = readl_relaxed(priv->base + SATA_PORT_PHYCTL);
- val &= ~SPEED_MODE_MASK;
- val |= SPEED_MODE_GEN1 << HALF_RATE_SHIFT |
- SPEED_MODE_GEN1 << PHY_CONFIG_SHIFT |
- SPEED_MODE_GEN1 << GEN2_EN_SHIFT | SPEED_CTRL;
- writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
-
- msleep(20);
- val &= ~SPEED_MODE_MASK;
- val |= SPEED_MODE_GEN3 << HALF_RATE_SHIFT |
- SPEED_MODE_GEN3 << PHY_CONFIG_SHIFT |
- SPEED_MODE_GEN3 << GEN2_EN_SHIFT | SPEED_CTRL;
- writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
-
- val &= ~(SPEED_MODE_MASK | SPEED_CTRL);
- val |= SPEED_MODE_GEN2 << HALF_RATE_SHIFT |
- SPEED_MODE_GEN2 << PHY_CONFIG_SHIFT |
- SPEED_MODE_GEN2 << GEN2_EN_SHIFT;
- writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
-
- return 0;
-}
-
-static struct phy_ops hix5hd2_sata_phy_ops = {
- .init = hix5hd2_sata_phy_init,
- .owner = THIS_MODULE,
-};
-
-static int hix5hd2_sata_phy_probe(struct platform_device *pdev)
-{
- struct phy_provider *phy_provider;
- struct device *dev = &pdev->dev;
- struct resource *res;
- struct phy *phy;
- struct hix5hd2_priv *priv;
-
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->base = devm_ioremap(dev, res->start, resource_size(res));
- if (!priv->base)
- return -ENOMEM;
-
- priv->peri_ctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
- "hisilicon,peripheral-syscon");
- if (IS_ERR(priv->peri_ctrl))
- priv->peri_ctrl = NULL;
-
- phy = devm_phy_create(dev, NULL, &hix5hd2_sata_phy_ops, NULL);
- if (IS_ERR(phy)) {
- dev_err(dev, "failed to create PHY\n");
- return PTR_ERR(phy);
- }
-
- phy_set_drvdata(phy, priv);
- phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
- if (IS_ERR(phy_provider))
- return PTR_ERR(phy_provider);
-
- return 0;
-}
-
-static const struct of_device_id hix5hd2_sata_phy_of_match[] = {
- {.compatible = "hisilicon,hix5hd2-sata-phy",},
- { },
-};
-MODULE_DEVICE_TABLE(of, hix5hd2_sata_phy_of_match);
-
-static struct platform_driver hix5hd2_sata_phy_driver = {
- .probe = hix5hd2_sata_phy_probe,
- .driver = {
- .name = "hix5hd2-sata-phy",
- .of_match_table = hix5hd2_sata_phy_of_match,
- }
-};
-module_platform_driver(hix5hd2_sata_phy_driver);
-
-MODULE_AUTHOR("Jiancheng Xue <xuejiancheng@huawei.com>");
-MODULE_DESCRIPTION("HISILICON HIX5HD2 SATA PHY driver");
-MODULE_ALIAS("platform:hix5hd2-sata-phy");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * Copyright (C) 2014 STMicroelectronics – All Rights Reserved
- *
- * STMicroelectronics PHY driver MiPHY365 (for SoC STiH416).
- *
- * Authors: Alexandre Torgue <alexandre.torgue@st.com>
- * Lee Jones <lee.jones@linaro.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2, as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/of_address.h>
-#include <linux/clk.h>
-#include <linux/phy/phy.h>
-#include <linux/delay.h>
-#include <linux/mfd/syscon.h>
-#include <linux/regmap.h>
-
-#include <dt-bindings/phy/phy-miphy365x.h>
-
-#define HFC_TIMEOUT 100
-
-#define SYSCFG_SELECT_SATA_MASK BIT(1)
-#define SYSCFG_SELECT_SATA_POS 1
-
-/* MiPHY365x register definitions */
-#define RESET_REG 0x00
-#define RST_PLL BIT(1)
-#define RST_PLL_CAL BIT(2)
-#define RST_RX BIT(4)
-#define RST_MACRO BIT(7)
-
-#define STATUS_REG 0x01
-#define IDLL_RDY BIT(0)
-#define PLL_RDY BIT(1)
-#define DES_BIT_LOCK BIT(2)
-#define DES_SYMBOL_LOCK BIT(3)
-
-#define CTRL_REG 0x02
-#define TERM_EN BIT(0)
-#define PCI_EN BIT(2)
-#define DES_BIT_LOCK_EN BIT(3)
-#define TX_POL BIT(5)
-
-#define INT_CTRL_REG 0x03
-
-#define BOUNDARY1_REG 0x10
-#define SPDSEL_SEL BIT(0)
-
-#define BOUNDARY3_REG 0x12
-#define TX_SPDSEL_GEN1_VAL 0
-#define TX_SPDSEL_GEN2_VAL 0x01
-#define TX_SPDSEL_GEN3_VAL 0x02
-#define RX_SPDSEL_GEN1_VAL 0
-#define RX_SPDSEL_GEN2_VAL (0x01 << 3)
-#define RX_SPDSEL_GEN3_VAL (0x02 << 3)
-
-#define PCIE_REG 0x16
-
-#define BUF_SEL_REG 0x20
-#define CONF_GEN_SEL_GEN3 0x02
-#define CONF_GEN_SEL_GEN2 0x01
-#define PD_VDDTFILTER BIT(4)
-
-#define TXBUF1_REG 0x21
-#define SWING_VAL 0x04
-#define SWING_VAL_GEN1 0x03
-#define PREEMPH_VAL (0x3 << 5)
-
-#define TXBUF2_REG 0x22
-#define TXSLEW_VAL 0x2
-#define TXSLEW_VAL_GEN1 0x4
-
-#define RXBUF_OFFSET_CTRL_REG 0x23
-
-#define RXBUF_REG 0x25
-#define SDTHRES_VAL 0x01
-#define EQ_ON3 (0x03 << 4)
-#define EQ_ON1 (0x01 << 4)
-
-#define COMP_CTRL1_REG 0x40
-#define START_COMSR BIT(0)
-#define START_COMZC BIT(1)
-#define COMSR_DONE BIT(2)
-#define COMZC_DONE BIT(3)
-#define COMP_AUTO_LOAD BIT(4)
-
-#define COMP_CTRL2_REG 0x41
-#define COMP_2MHZ_RAT_GEN1 0x1e
-#define COMP_2MHZ_RAT 0xf
-
-#define COMP_CTRL3_REG 0x42
-#define COMSR_COMP_REF 0x33
-
-#define COMP_IDLL_REG 0x47
-#define COMZC_IDLL 0x2a
-
-#define PLL_CTRL1_REG 0x50
-#define PLL_START_CAL BIT(0)
-#define BUF_EN BIT(2)
-#define SYNCHRO_TX BIT(3)
-#define SSC_EN BIT(6)
-#define CONFIG_PLL BIT(7)
-
-#define PLL_CTRL2_REG 0x51
-#define BYPASS_PLL_CAL BIT(1)
-
-#define PLL_RAT_REG 0x52
-
-#define PLL_SSC_STEP_MSB_REG 0x56
-#define PLL_SSC_STEP_MSB_VAL 0x03
-
-#define PLL_SSC_STEP_LSB_REG 0x57
-#define PLL_SSC_STEP_LSB_VAL 0x63
-
-#define PLL_SSC_PER_MSB_REG 0x58
-#define PLL_SSC_PER_MSB_VAL 0
-
-#define PLL_SSC_PER_LSB_REG 0x59
-#define PLL_SSC_PER_LSB_VAL 0xf1
-
-#define IDLL_TEST_REG 0x72
-#define START_CLK_HF BIT(6)
-
-#define DES_BITLOCK_REG 0x86
-#define BIT_LOCK_LEVEL 0x01
-#define BIT_LOCK_CNT_512 (0x03 << 5)
-
-struct miphy365x_phy {
- struct phy *phy;
- void __iomem *base;
- bool pcie_tx_pol_inv;
- bool sata_tx_pol_inv;
- u32 sata_gen;
- u64 ctrlreg;
- u8 type;
-};
-
-struct miphy365x_dev {
- struct device *dev;
- struct regmap *regmap;
- struct mutex miphy_mutex;
- struct miphy365x_phy **phys;
-};
-
-/*
- * These values are represented in Device tree. They are considered to be ABI
- * and although they can be extended any existing values must not change.
- */
-enum miphy_sata_gen {
- SATA_GEN1 = 1,
- SATA_GEN2,
- SATA_GEN3
-};
-
-static u8 rx_tx_spd[] = {
- 0, /* GEN0 doesn't exist. */
- TX_SPDSEL_GEN1_VAL | RX_SPDSEL_GEN1_VAL,
- TX_SPDSEL_GEN2_VAL | RX_SPDSEL_GEN2_VAL,
- TX_SPDSEL_GEN3_VAL | RX_SPDSEL_GEN3_VAL
-};
-
-/*
- * This function selects the system configuration,
- * either two SATA, one SATA and one PCIe, or two PCIe lanes.
- */
-static int miphy365x_set_path(struct miphy365x_phy *miphy_phy,
- struct miphy365x_dev *miphy_dev)
-{
- bool sata = (miphy_phy->type == MIPHY_TYPE_SATA);
-
- return regmap_update_bits(miphy_dev->regmap,
- (unsigned int)miphy_phy->ctrlreg,
- SYSCFG_SELECT_SATA_MASK,
- sata << SYSCFG_SELECT_SATA_POS);
-}
-
-static int miphy365x_init_pcie_port(struct miphy365x_phy *miphy_phy,
- struct miphy365x_dev *miphy_dev)
-{
- u8 val;
-
- if (miphy_phy->pcie_tx_pol_inv) {
- /* Invert Tx polarity and clear pci_txdetect_pol bit */
- val = TERM_EN | PCI_EN | DES_BIT_LOCK_EN | TX_POL;
- writeb_relaxed(val, miphy_phy->base + CTRL_REG);
- writeb_relaxed(0x00, miphy_phy->base + PCIE_REG);
- }
-
- return 0;
-}
-
-static inline int miphy365x_hfc_not_rdy(struct miphy365x_phy *miphy_phy,
- struct miphy365x_dev *miphy_dev)
-{
- unsigned long timeout = jiffies + msecs_to_jiffies(HFC_TIMEOUT);
- u8 mask = IDLL_RDY | PLL_RDY;
- u8 regval;
-
- do {
- regval = readb_relaxed(miphy_phy->base + STATUS_REG);
- if (!(regval & mask))
- return 0;
-
- usleep_range(2000, 2500);
- } while (time_before(jiffies, timeout));
-
- dev_err(miphy_dev->dev, "HFC ready timeout!\n");
- return -EBUSY;
-}
-
-static inline int miphy365x_rdy(struct miphy365x_phy *miphy_phy,
- struct miphy365x_dev *miphy_dev)
-{
- unsigned long timeout = jiffies + msecs_to_jiffies(HFC_TIMEOUT);
- u8 mask = IDLL_RDY | PLL_RDY;
- u8 regval;
-
- do {
- regval = readb_relaxed(miphy_phy->base + STATUS_REG);
- if ((regval & mask) == mask)
- return 0;
-
- usleep_range(2000, 2500);
- } while (time_before(jiffies, timeout));
-
- dev_err(miphy_dev->dev, "PHY not ready timeout!\n");
- return -EBUSY;
-}
-
-static inline void miphy365x_set_comp(struct miphy365x_phy *miphy_phy,
- struct miphy365x_dev *miphy_dev)
-{
- u8 val, mask;
-
- if (miphy_phy->sata_gen == SATA_GEN1)
- writeb_relaxed(COMP_2MHZ_RAT_GEN1,
- miphy_phy->base + COMP_CTRL2_REG);
- else
- writeb_relaxed(COMP_2MHZ_RAT,
- miphy_phy->base + COMP_CTRL2_REG);
-
- if (miphy_phy->sata_gen != SATA_GEN3) {
- writeb_relaxed(COMSR_COMP_REF,
- miphy_phy->base + COMP_CTRL3_REG);
- /*
- * Force VCO current to value defined by address 0x5A
- * and disable PCIe100Mref bit
- * Enable auto load compensation for pll_i_bias
- */
- writeb_relaxed(BYPASS_PLL_CAL, miphy_phy->base + PLL_CTRL2_REG);
- writeb_relaxed(COMZC_IDLL, miphy_phy->base + COMP_IDLL_REG);
- }
-
- /*
- * Force restart compensation and enable auto load
- * for Comzc_Tx, Comzc_Rx and Comsr on macro
- */
- val = START_COMSR | START_COMZC | COMP_AUTO_LOAD;
- writeb_relaxed(val, miphy_phy->base + COMP_CTRL1_REG);
-
- mask = COMSR_DONE | COMZC_DONE;
- while ((readb_relaxed(miphy_phy->base + COMP_CTRL1_REG) & mask) != mask)
- cpu_relax();
-}
-
-static inline void miphy365x_set_ssc(struct miphy365x_phy *miphy_phy,
- struct miphy365x_dev *miphy_dev)
-{
- u8 val;
-
- /*
- * SSC Settings. SSC will be enabled through Link
- * SSC Ampl. = 0.4%
- * SSC Freq = 31KHz
- */
- writeb_relaxed(PLL_SSC_STEP_MSB_VAL,
- miphy_phy->base + PLL_SSC_STEP_MSB_REG);
- writeb_relaxed(PLL_SSC_STEP_LSB_VAL,
- miphy_phy->base + PLL_SSC_STEP_LSB_REG);
- writeb_relaxed(PLL_SSC_PER_MSB_VAL,
- miphy_phy->base + PLL_SSC_PER_MSB_REG);
- writeb_relaxed(PLL_SSC_PER_LSB_VAL,
- miphy_phy->base + PLL_SSC_PER_LSB_REG);
-
- /* SSC Settings complete */
- if (miphy_phy->sata_gen == SATA_GEN1) {
- val = PLL_START_CAL | BUF_EN | SYNCHRO_TX | CONFIG_PLL;
- writeb_relaxed(val, miphy_phy->base + PLL_CTRL1_REG);
- } else {
- val = SSC_EN | PLL_START_CAL | BUF_EN | SYNCHRO_TX | CONFIG_PLL;
- writeb_relaxed(val, miphy_phy->base + PLL_CTRL1_REG);
- }
-}
-
-static int miphy365x_init_sata_port(struct miphy365x_phy *miphy_phy,
- struct miphy365x_dev *miphy_dev)
-{
- int ret;
- u8 val;
-
- /*
- * Force PHY macro reset, PLL calibration reset, PLL reset
- * and assert Deserializer Reset
- */
- val = RST_PLL | RST_PLL_CAL | RST_RX | RST_MACRO;
- writeb_relaxed(val, miphy_phy->base + RESET_REG);
-
- if (miphy_phy->sata_tx_pol_inv)
- writeb_relaxed(TX_POL, miphy_phy->base + CTRL_REG);
-
- /*
- * Force macro1 to use rx_lspd, tx_lspd
- * Force Rx_Clock on first I-DLL phase
- * Force Des in HP mode on macro, rx_lspd, tx_lspd for Gen2/3
- */
- writeb_relaxed(SPDSEL_SEL, miphy_phy->base + BOUNDARY1_REG);
- writeb_relaxed(START_CLK_HF, miphy_phy->base + IDLL_TEST_REG);
- val = rx_tx_spd[miphy_phy->sata_gen];
- writeb_relaxed(val, miphy_phy->base + BOUNDARY3_REG);
-
- /* Wait for HFC_READY = 0 */
- ret = miphy365x_hfc_not_rdy(miphy_phy, miphy_dev);
- if (ret)
- return ret;
-
- /* Compensation Recalibration */
- miphy365x_set_comp(miphy_phy, miphy_dev);
-
- switch (miphy_phy->sata_gen) {
- case SATA_GEN3:
- /*
- * TX Swing target 550-600mv peak to peak diff
- * Tx Slew target 90-110ps rising/falling time
- * Rx Eq ON3, Sigdet threshold SDTH1
- */
- val = PD_VDDTFILTER | CONF_GEN_SEL_GEN3;
- writeb_relaxed(val, miphy_phy->base + BUF_SEL_REG);
- val = SWING_VAL | PREEMPH_VAL;
- writeb_relaxed(val, miphy_phy->base + TXBUF1_REG);
- writeb_relaxed(TXSLEW_VAL, miphy_phy->base + TXBUF2_REG);
- writeb_relaxed(0x00, miphy_phy->base + RXBUF_OFFSET_CTRL_REG);
- val = SDTHRES_VAL | EQ_ON3;
- writeb_relaxed(val, miphy_phy->base + RXBUF_REG);
- break;
- case SATA_GEN2:
- /*
- * conf gen sel=0x1 to program Gen2 banked registers
- * VDDT filter ON
- * Tx Swing target 550-600mV peak-to-peak diff
- * Tx Slew target 90-110 ps rising/falling time
- * RX Equalization ON1, Sigdet threshold SDTH1
- */
- writeb_relaxed(CONF_GEN_SEL_GEN2,
- miphy_phy->base + BUF_SEL_REG);
- writeb_relaxed(SWING_VAL, miphy_phy->base + TXBUF1_REG);
- writeb_relaxed(TXSLEW_VAL, miphy_phy->base + TXBUF2_REG);
- val = SDTHRES_VAL | EQ_ON1;
- writeb_relaxed(val, miphy_phy->base + RXBUF_REG);
- break;
- case SATA_GEN1:
- /*
- * conf gen sel = 00b to program Gen1 banked registers
- * VDDT filter ON
- * Tx Swing target 500-550mV peak-to-peak diff
- * Tx Slew target120-140 ps rising/falling time
- */
- writeb_relaxed(PD_VDDTFILTER, miphy_phy->base + BUF_SEL_REG);
- writeb_relaxed(SWING_VAL_GEN1, miphy_phy->base + TXBUF1_REG);
- writeb_relaxed(TXSLEW_VAL_GEN1, miphy_phy->base + TXBUF2_REG);
- break;
- default:
- break;
- }
-
- /* Force Macro1 in partial mode & release pll cal reset */
- writeb_relaxed(RST_RX, miphy_phy->base + RESET_REG);
- usleep_range(100, 150);
-
- miphy365x_set_ssc(miphy_phy, miphy_dev);
-
- /* Wait for phy_ready */
- ret = miphy365x_rdy(miphy_phy, miphy_dev);
- if (ret)
- return ret;
-
- /*
- * Enable macro1 to use rx_lspd & tx_lspd
- * Release Rx_Clock on first I-DLL phase on macro1
- * Assert deserializer reset
- * des_bit_lock_en is set
- * bit lock detection strength
- * Deassert deserializer reset
- */
- writeb_relaxed(0x00, miphy_phy->base + BOUNDARY1_REG);
- writeb_relaxed(0x00, miphy_phy->base + IDLL_TEST_REG);
- writeb_relaxed(RST_RX, miphy_phy->base + RESET_REG);
- val = miphy_phy->sata_tx_pol_inv ?
- (TX_POL | DES_BIT_LOCK_EN) : DES_BIT_LOCK_EN;
- writeb_relaxed(val, miphy_phy->base + CTRL_REG);
-
- val = BIT_LOCK_CNT_512 | BIT_LOCK_LEVEL;
- writeb_relaxed(val, miphy_phy->base + DES_BITLOCK_REG);
- writeb_relaxed(0x00, miphy_phy->base + RESET_REG);
-
- return 0;
-}
-
-static int miphy365x_init(struct phy *phy)
-{
- struct miphy365x_phy *miphy_phy = phy_get_drvdata(phy);
- struct miphy365x_dev *miphy_dev = dev_get_drvdata(phy->dev.parent);
- int ret = 0;
-
- mutex_lock(&miphy_dev->miphy_mutex);
-
- ret = miphy365x_set_path(miphy_phy, miphy_dev);
- if (ret) {
- mutex_unlock(&miphy_dev->miphy_mutex);
- return ret;
- }
-
- /* Initialise Miphy for PCIe or SATA */
- if (miphy_phy->type == MIPHY_TYPE_PCIE)
- ret = miphy365x_init_pcie_port(miphy_phy, miphy_dev);
- else
- ret = miphy365x_init_sata_port(miphy_phy, miphy_dev);
-
- mutex_unlock(&miphy_dev->miphy_mutex);
-
- return ret;
-}
-
-int miphy365x_get_addr(struct device *dev, struct miphy365x_phy *miphy_phy,
- int index)
-{
- struct device_node *phynode = miphy_phy->phy->dev.of_node;
- const char *name;
- const __be32 *taddr;
- int type = miphy_phy->type;
- int ret;
-
- ret = of_property_read_string_index(phynode, "reg-names", index, &name);
- if (ret) {
- dev_err(dev, "no reg-names property not found\n");
- return ret;
- }
-
- if (!strncmp(name, "syscfg", 6)) {
- taddr = of_get_address(phynode, index, NULL, NULL);
- if (!taddr) {
- dev_err(dev, "failed to fetch syscfg address\n");
- return -EINVAL;
- }
-
- miphy_phy->ctrlreg = of_translate_address(phynode, taddr);
- if (miphy_phy->ctrlreg == OF_BAD_ADDR) {
- dev_err(dev, "failed to translate syscfg address\n");
- return -EINVAL;
- }
-
- return 0;
- }
-
- if (!((!strncmp(name, "sata", 4) && type == MIPHY_TYPE_SATA) ||
- (!strncmp(name, "pcie", 4) && type == MIPHY_TYPE_PCIE)))
- return 0;
-
- miphy_phy->base = of_iomap(phynode, index);
- if (!miphy_phy->base) {
- dev_err(dev, "Failed to map %s\n", phynode->full_name);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static struct phy *miphy365x_xlate(struct device *dev,
- struct of_phandle_args *args)
-{
- struct miphy365x_dev *miphy_dev = dev_get_drvdata(dev);
- struct miphy365x_phy *miphy_phy = NULL;
- struct device_node *phynode = args->np;
- int ret, index;
-
- if (!of_device_is_available(phynode)) {
- dev_warn(dev, "Requested PHY is disabled\n");
- return ERR_PTR(-ENODEV);
- }
-
- if (args->args_count != 1) {
- dev_err(dev, "Invalid number of cells in 'phy' property\n");
- return ERR_PTR(-EINVAL);
- }
-
- for (index = 0; index < of_get_child_count(dev->of_node); index++)
- if (phynode == miphy_dev->phys[index]->phy->dev.of_node) {
- miphy_phy = miphy_dev->phys[index];
- break;
- }
-
- if (!miphy_phy) {
- dev_err(dev, "Failed to find appropriate phy\n");
- return ERR_PTR(-EINVAL);
- }
-
- miphy_phy->type = args->args[0];
-
- if (!(miphy_phy->type == MIPHY_TYPE_SATA ||
- miphy_phy->type == MIPHY_TYPE_PCIE)) {
- dev_err(dev, "Unsupported device type: %d\n", miphy_phy->type);
- return ERR_PTR(-EINVAL);
- }
-
- /* Each port handles SATA and PCIE - third entry is always sysconf. */
- for (index = 0; index < 3; index++) {
- ret = miphy365x_get_addr(dev, miphy_phy, index);
- if (ret < 0)
- return ERR_PTR(ret);
- }
-
- return miphy_phy->phy;
-}
-
-static struct phy_ops miphy365x_ops = {
- .init = miphy365x_init,
- .owner = THIS_MODULE,
-};
-
-static int miphy365x_of_probe(struct device_node *phynode,
- struct miphy365x_phy *miphy_phy)
-{
- of_property_read_u32(phynode, "st,sata-gen", &miphy_phy->sata_gen);
- if (!miphy_phy->sata_gen)
- miphy_phy->sata_gen = SATA_GEN1;
-
- miphy_phy->pcie_tx_pol_inv =
- of_property_read_bool(phynode, "st,pcie-tx-pol-inv");
-
- miphy_phy->sata_tx_pol_inv =
- of_property_read_bool(phynode, "st,sata-tx-pol-inv");
-
- return 0;
-}
-
-static int miphy365x_probe(struct platform_device *pdev)
-{
- struct device_node *child, *np = pdev->dev.of_node;
- struct miphy365x_dev *miphy_dev;
- struct phy_provider *provider;
- struct phy *phy;
- int chancount, port = 0;
- int ret;
-
- miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL);
- if (!miphy_dev)
- return -ENOMEM;
-
- chancount = of_get_child_count(np);
- miphy_dev->phys = devm_kzalloc(&pdev->dev, sizeof(phy) * chancount,
- GFP_KERNEL);
- if (!miphy_dev->phys)
- return -ENOMEM;
-
- miphy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
- if (IS_ERR(miphy_dev->regmap)) {
- dev_err(miphy_dev->dev, "No syscfg phandle specified\n");
- return PTR_ERR(miphy_dev->regmap);
- }
-
- miphy_dev->dev = &pdev->dev;
-
- dev_set_drvdata(&pdev->dev, miphy_dev);
-
- mutex_init(&miphy_dev->miphy_mutex);
-
- for_each_child_of_node(np, child) {
- struct miphy365x_phy *miphy_phy;
-
- miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy),
- GFP_KERNEL);
- if (!miphy_phy)
- return -ENOMEM;
-
- miphy_dev->phys[port] = miphy_phy;
-
- phy = devm_phy_create(&pdev->dev, child, &miphy365x_ops, NULL);
- if (IS_ERR(phy)) {
- dev_err(&pdev->dev, "failed to create PHY\n");
- return PTR_ERR(phy);
- }
-
- miphy_dev->phys[port]->phy = phy;
-
- ret = miphy365x_of_probe(child, miphy_phy);
- if (ret)
- return ret;
-
- phy_set_drvdata(phy, miphy_dev->phys[port]);
- port++;
- }
-
- provider = devm_of_phy_provider_register(&pdev->dev, miphy365x_xlate);
- if (IS_ERR(provider))
- return PTR_ERR(provider);
-
- return 0;
-}
-
-static const struct of_device_id miphy365x_of_match[] = {
- { .compatible = "st,miphy365x-phy", },
- { },
-};
-MODULE_DEVICE_TABLE(of, miphy365x_of_match);
-
-static struct platform_driver miphy365x_driver = {
- .probe = miphy365x_probe,
- .driver = {
- .name = "miphy365x-phy",
- .of_match_table = miphy365x_of_match,
- }
-};
-module_platform_driver(miphy365x_driver);
-
-MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>");
-MODULE_DESCRIPTION("STMicroelectronics miphy365x driver");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * phy-mvebu-sata.c: SATA Phy driver for the Marvell mvebu SoCs.
- *
- * Copyright (C) 2013 Andrew Lunn <andrew@lunn.ch>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/phy/phy.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-
-struct priv {
- struct clk *clk;
- void __iomem *base;
-};
-
-#define SATA_PHY_MODE_2 0x0330
-#define MODE_2_FORCE_PU_TX BIT(0)
-#define MODE_2_FORCE_PU_RX BIT(1)
-#define MODE_2_PU_PLL BIT(2)
-#define MODE_2_PU_IVREF BIT(3)
-#define SATA_IF_CTRL 0x0050
-#define CTRL_PHY_SHUTDOWN BIT(9)
-
-static int phy_mvebu_sata_power_on(struct phy *phy)
-{
- struct priv *priv = phy_get_drvdata(phy);
- u32 reg;
-
- clk_prepare_enable(priv->clk);
-
- /* Enable PLL and IVREF */
- reg = readl(priv->base + SATA_PHY_MODE_2);
- reg |= (MODE_2_FORCE_PU_TX | MODE_2_FORCE_PU_RX |
- MODE_2_PU_PLL | MODE_2_PU_IVREF);
- writel(reg , priv->base + SATA_PHY_MODE_2);
-
- /* Enable PHY */
- reg = readl(priv->base + SATA_IF_CTRL);
- reg &= ~CTRL_PHY_SHUTDOWN;
- writel(reg, priv->base + SATA_IF_CTRL);
-
- clk_disable_unprepare(priv->clk);
-
- return 0;
-}
-
-static int phy_mvebu_sata_power_off(struct phy *phy)
-{
- struct priv *priv = phy_get_drvdata(phy);
- u32 reg;
-
- clk_prepare_enable(priv->clk);
-
- /* Disable PLL and IVREF */
- reg = readl(priv->base + SATA_PHY_MODE_2);
- reg &= ~(MODE_2_FORCE_PU_TX | MODE_2_FORCE_PU_RX |
- MODE_2_PU_PLL | MODE_2_PU_IVREF);
- writel(reg, priv->base + SATA_PHY_MODE_2);
-
- /* Disable PHY */
- reg = readl(priv->base + SATA_IF_CTRL);
- reg |= CTRL_PHY_SHUTDOWN;
- writel(reg, priv->base + SATA_IF_CTRL);
-
- clk_disable_unprepare(priv->clk);
-
- return 0;
-}
-
-static struct phy_ops phy_mvebu_sata_ops = {
- .power_on = phy_mvebu_sata_power_on,
- .power_off = phy_mvebu_sata_power_off,
- .owner = THIS_MODULE,
-};
-
-static int phy_mvebu_sata_probe(struct platform_device *pdev)
-{
- struct phy_provider *phy_provider;
- struct resource *res;
- struct priv *priv;
- struct phy *phy;
-
- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(priv->base))
- return PTR_ERR(priv->base);
-
- priv->clk = devm_clk_get(&pdev->dev, "sata");
- if (IS_ERR(priv->clk))
- return PTR_ERR(priv->clk);
-
- phy = devm_phy_create(&pdev->dev, NULL, &phy_mvebu_sata_ops, NULL);
- if (IS_ERR(phy))
- return PTR_ERR(phy);
-
- phy_set_drvdata(phy, priv);
-
- phy_provider = devm_of_phy_provider_register(&pdev->dev,
- of_phy_simple_xlate);
- if (IS_ERR(phy_provider))
- return PTR_ERR(phy_provider);
-
- /* The boot loader may of left it on. Turn it off. */
- phy_mvebu_sata_power_off(phy);
-
- return 0;
-}
-
-static const struct of_device_id phy_mvebu_sata_of_match[] = {
- { .compatible = "marvell,mvebu-sata-phy" },
- { },
-};
-MODULE_DEVICE_TABLE(of, phy_mvebu_sata_of_match);
-
-static struct platform_driver phy_mvebu_sata_driver = {
- .probe = phy_mvebu_sata_probe,
- .driver = {
- .name = "phy-mvebu-sata",
- .of_match_table = phy_mvebu_sata_of_match,
- }
-};
-module_platform_driver(phy_mvebu_sata_driver);
-
-MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
-MODULE_DESCRIPTION("Marvell MVEBU SATA PHY driver");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * omap-control-phy.c - The PHY part of control module.
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Author: Kishon Vijay Abraham I <kishon@ti.com>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/phy/omap_control_phy.h>
-
-/**
- * omap_control_pcie_pcs - set the PCS delay count
- * @dev: the control module device
- * @id: index of the pcie PHY (should be 1 or 2)
- * @delay: 8 bit delay value
- */
-void omap_control_pcie_pcs(struct device *dev, u8 id, u8 delay)
-{
- u32 val;
- struct omap_control_phy *control_phy;
-
- if (IS_ERR(dev) || !dev) {
- pr_err("%s: invalid device\n", __func__);
- return;
- }
-
- control_phy = dev_get_drvdata(dev);
- if (!control_phy) {
- dev_err(dev, "%s: invalid control phy device\n", __func__);
- return;
- }
-
- if (control_phy->type != OMAP_CTRL_TYPE_PCIE) {
- dev_err(dev, "%s: unsupported operation\n", __func__);
- return;
- }
-
- val = readl(control_phy->pcie_pcs);
- val &= ~(OMAP_CTRL_PCIE_PCS_MASK <<
- (id * OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT));
- val |= delay << (id * OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT);
- writel(val, control_phy->pcie_pcs);
-}
-EXPORT_SYMBOL_GPL(omap_control_pcie_pcs);
-
-/**
- * omap_control_phy_power - power on/off the phy using control module reg
- * @dev: the control module device
- * @on: 0 or 1, based on powering on or off the PHY
- */
-void omap_control_phy_power(struct device *dev, int on)
-{
- u32 val;
- unsigned long rate;
- struct omap_control_phy *control_phy;
-
- if (IS_ERR(dev) || !dev) {
- pr_err("%s: invalid device\n", __func__);
- return;
- }
-
- control_phy = dev_get_drvdata(dev);
- if (!control_phy) {
- dev_err(dev, "%s: invalid control phy device\n", __func__);
- return;
- }
-
- if (control_phy->type == OMAP_CTRL_TYPE_OTGHS)
- return;
-
- val = readl(control_phy->power);
-
- switch (control_phy->type) {
- case OMAP_CTRL_TYPE_USB2:
- if (on)
- val &= ~OMAP_CTRL_DEV_PHY_PD;
- else
- val |= OMAP_CTRL_DEV_PHY_PD;
- break;
-
- case OMAP_CTRL_TYPE_PCIE:
- case OMAP_CTRL_TYPE_PIPE3:
- rate = clk_get_rate(control_phy->sys_clk);
- rate = rate/1000000;
-
- if (on) {
- val &= ~(OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK |
- OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK);
- val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON <<
- OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
- val |= rate <<
- OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT;
- } else {
- val &= ~OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK;
- val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF <<
- OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
- }
- break;
-
- case OMAP_CTRL_TYPE_DRA7USB2:
- if (on)
- val &= ~OMAP_CTRL_USB2_PHY_PD;
- else
- val |= OMAP_CTRL_USB2_PHY_PD;
- break;
-
- case OMAP_CTRL_TYPE_AM437USB2:
- if (on) {
- val &= ~(AM437X_CTRL_USB2_PHY_PD |
- AM437X_CTRL_USB2_OTG_PD);
- val |= (AM437X_CTRL_USB2_OTGVDET_EN |
- AM437X_CTRL_USB2_OTGSESSEND_EN);
- } else {
- val &= ~(AM437X_CTRL_USB2_OTGVDET_EN |
- AM437X_CTRL_USB2_OTGSESSEND_EN);
- val |= (AM437X_CTRL_USB2_PHY_PD |
- AM437X_CTRL_USB2_OTG_PD);
- }
- break;
- default:
- dev_err(dev, "%s: type %d not recognized\n",
- __func__, control_phy->type);
- break;
- }
-
- writel(val, control_phy->power);
-}
-EXPORT_SYMBOL_GPL(omap_control_phy_power);
-
-/**
- * omap_control_usb_host_mode - set AVALID, VBUSVALID and ID pin in grounded
- * @ctrl_phy: struct omap_control_phy *
- *
- * Writes to the mailbox register to notify the usb core that a usb
- * device has been connected.
- */
-static void omap_control_usb_host_mode(struct omap_control_phy *ctrl_phy)
-{
- u32 val;
-
- val = readl(ctrl_phy->otghs_control);
- val &= ~(OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND);
- val |= OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID;
- writel(val, ctrl_phy->otghs_control);
-}
-
-/**
- * omap_control_usb_device_mode - set AVALID, VBUSVALID and ID pin in high
- * impedance
- * @ctrl_phy: struct omap_control_phy *
- *
- * Writes to the mailbox register to notify the usb core that it has been
- * connected to a usb host.
- */
-static void omap_control_usb_device_mode(struct omap_control_phy *ctrl_phy)
-{
- u32 val;
-
- val = readl(ctrl_phy->otghs_control);
- val &= ~OMAP_CTRL_DEV_SESSEND;
- val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_AVALID |
- OMAP_CTRL_DEV_VBUSVALID;
- writel(val, ctrl_phy->otghs_control);
-}
-
-/**
- * omap_control_usb_set_sessionend - Enable SESSIONEND and IDIG to high
- * impedance
- * @ctrl_phy: struct omap_control_phy *
- *
- * Writes to the mailbox register to notify the usb core it's now in
- * disconnected state.
- */
-static void omap_control_usb_set_sessionend(struct omap_control_phy *ctrl_phy)
-{
- u32 val;
-
- val = readl(ctrl_phy->otghs_control);
- val &= ~(OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID);
- val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND;
- writel(val, ctrl_phy->otghs_control);
-}
-
-/**
- * omap_control_usb_set_mode - Calls to functions to set USB in one of host mode
- * or device mode or to denote disconnected state
- * @dev: the control module device
- * @mode: The mode to which usb should be configured
- *
- * This is an API to write to the mailbox register to notify the usb core that
- * a usb device has been connected.
- */
-void omap_control_usb_set_mode(struct device *dev,
- enum omap_control_usb_mode mode)
-{
- struct omap_control_phy *ctrl_phy;
-
- if (IS_ERR(dev) || !dev)
- return;
-
- ctrl_phy = dev_get_drvdata(dev);
-
- if (!ctrl_phy) {
- dev_err(dev, "Invalid control phy device\n");
- return;
- }
-
- if (ctrl_phy->type != OMAP_CTRL_TYPE_OTGHS)
- return;
-
- switch (mode) {
- case USB_MODE_HOST:
- omap_control_usb_host_mode(ctrl_phy);
- break;
- case USB_MODE_DEVICE:
- omap_control_usb_device_mode(ctrl_phy);
- break;
- case USB_MODE_DISCONNECT:
- omap_control_usb_set_sessionend(ctrl_phy);
- break;
- default:
- dev_vdbg(dev, "invalid omap control usb mode\n");
- }
-}
-EXPORT_SYMBOL_GPL(omap_control_usb_set_mode);
-
-#ifdef CONFIG_OF
-
-static const enum omap_control_phy_type otghs_data = OMAP_CTRL_TYPE_OTGHS;
-static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2;
-static const enum omap_control_phy_type pipe3_data = OMAP_CTRL_TYPE_PIPE3;
-static const enum omap_control_phy_type pcie_data = OMAP_CTRL_TYPE_PCIE;
-static const enum omap_control_phy_type dra7usb2_data = OMAP_CTRL_TYPE_DRA7USB2;
-static const enum omap_control_phy_type am437usb2_data = OMAP_CTRL_TYPE_AM437USB2;
-
-static const struct of_device_id omap_control_phy_id_table[] = {
- {
- .compatible = "ti,control-phy-otghs",
- .data = &otghs_data,
- },
- {
- .compatible = "ti,control-phy-usb2",
- .data = &usb2_data,
- },
- {
- .compatible = "ti,control-phy-pipe3",
- .data = &pipe3_data,
- },
- {
- .compatible = "ti,control-phy-pcie",
- .data = &pcie_data,
- },
- {
- .compatible = "ti,control-phy-usb2-dra7",
- .data = &dra7usb2_data,
- },
- {
- .compatible = "ti,control-phy-usb2-am437",
- .data = &am437usb2_data,
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, omap_control_phy_id_table);
-#endif
-
-
-static int omap_control_phy_probe(struct platform_device *pdev)
-{
- struct resource *res;
- const struct of_device_id *of_id;
- struct omap_control_phy *control_phy;
-
- of_id = of_match_device(of_match_ptr(omap_control_phy_id_table),
- &pdev->dev);
- if (!of_id)
- return -EINVAL;
-
- control_phy = devm_kzalloc(&pdev->dev, sizeof(*control_phy),
- GFP_KERNEL);
- if (!control_phy)
- return -ENOMEM;
-
- control_phy->dev = &pdev->dev;
- control_phy->type = *(enum omap_control_phy_type *)of_id->data;
-
- if (control_phy->type == OMAP_CTRL_TYPE_OTGHS) {
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "otghs_control");
- control_phy->otghs_control = devm_ioremap_resource(
- &pdev->dev, res);
- if (IS_ERR(control_phy->otghs_control))
- return PTR_ERR(control_phy->otghs_control);
- } else {
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "power");
- control_phy->power = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(control_phy->power)) {
- dev_err(&pdev->dev, "Couldn't get power register\n");
- return PTR_ERR(control_phy->power);
- }
- }
-
- if (control_phy->type == OMAP_CTRL_TYPE_PIPE3 ||
- control_phy->type == OMAP_CTRL_TYPE_PCIE) {
- control_phy->sys_clk = devm_clk_get(control_phy->dev,
- "sys_clkin");
- if (IS_ERR(control_phy->sys_clk)) {
- pr_err("%s: unable to get sys_clkin\n", __func__);
- return -EINVAL;
- }
- }
-
- if (control_phy->type == OMAP_CTRL_TYPE_PCIE) {
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "pcie_pcs");
- control_phy->pcie_pcs = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(control_phy->pcie_pcs))
- return PTR_ERR(control_phy->pcie_pcs);
- }
-
- dev_set_drvdata(control_phy->dev, control_phy);
-
- return 0;
-}
-
-static struct platform_driver omap_control_phy_driver = {
- .probe = omap_control_phy_probe,
- .driver = {
- .name = "omap-control-phy",
- .of_match_table = of_match_ptr(omap_control_phy_id_table),
- },
-};
-
-static int __init omap_control_phy_init(void)
-{
- return platform_driver_register(&omap_control_phy_driver);
-}
-subsys_initcall(omap_control_phy_init);
-
-static void __exit omap_control_phy_exit(void)
-{
- platform_driver_unregister(&omap_control_phy_driver);
-}
-module_exit(omap_control_phy_exit);
-
-MODULE_ALIAS("platform: omap_control_phy");
-MODULE_AUTHOR("Texas Instruments Inc.");
-MODULE_DESCRIPTION("OMAP Control Module PHY Driver");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * omap-usb2.c - USB PHY, talking to musb controller in OMAP.
- *
- * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Author: Kishon Vijay Abraham I <kishon@ti.com>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/io.h>
-#include <linux/phy/omap_usb.h>
-#include <linux/usb/phy_companion.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/pm_runtime.h>
-#include <linux/delay.h>
-#include <linux/phy/omap_control_phy.h>
-#include <linux/phy/phy.h>
-#include <linux/of_platform.h>
-
-#define USB2PHY_DISCON_BYP_LATCH (1 << 31)
-#define USB2PHY_ANA_CONFIG1 0x4c
-
-/**
- * omap_usb2_set_comparator - links the comparator present in the sytem with
- * this phy
- * @comparator - the companion phy(comparator) for this phy
- *
- * The phy companion driver should call this API passing the phy_companion
- * filled with set_vbus and start_srp to be used by usb phy.
- *
- * For use by phy companion driver
- */
-int omap_usb2_set_comparator(struct phy_companion *comparator)
-{
- struct omap_usb *phy;
- struct usb_phy *x = usb_get_phy(USB_PHY_TYPE_USB2);
-
- if (IS_ERR(x))
- return -ENODEV;
-
- phy = phy_to_omapusb(x);
- phy->comparator = comparator;
- return 0;
-}
-EXPORT_SYMBOL_GPL(omap_usb2_set_comparator);
-
-static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled)
-{
- struct omap_usb *phy = phy_to_omapusb(otg->usb_phy);
-
- if (!phy->comparator)
- return -ENODEV;
-
- return phy->comparator->set_vbus(phy->comparator, enabled);
-}
-
-static int omap_usb_start_srp(struct usb_otg *otg)
-{
- struct omap_usb *phy = phy_to_omapusb(otg->usb_phy);
-
- if (!phy->comparator)
- return -ENODEV;
-
- return phy->comparator->start_srp(phy->comparator);
-}
-
-static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
- otg->host = host;
- if (!host)
- otg->state = OTG_STATE_UNDEFINED;
-
- return 0;
-}
-
-static int omap_usb_set_peripheral(struct usb_otg *otg,
- struct usb_gadget *gadget)
-{
- otg->gadget = gadget;
- if (!gadget)
- otg->state = OTG_STATE_UNDEFINED;
-
- return 0;
-}
-
-static int omap_usb_power_off(struct phy *x)
-{
- struct omap_usb *phy = phy_get_drvdata(x);
-
- omap_control_phy_power(phy->control_dev, 0);
-
- return 0;
-}
-
-static int omap_usb_power_on(struct phy *x)
-{
- struct omap_usb *phy = phy_get_drvdata(x);
-
- omap_control_phy_power(phy->control_dev, 1);
-
- return 0;
-}
-
-static int omap_usb_init(struct phy *x)
-{
- struct omap_usb *phy = phy_get_drvdata(x);
- u32 val;
-
- if (phy->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) {
- /*
- *
- * Reduce the sensitivity of internal PHY by enabling the
- * DISCON_BYP_LATCH of the USB2PHY_ANA_CONFIG1 register. This
- * resolves issues with certain devices which can otherwise
- * be prone to false disconnects.
- *
- */
- val = omap_usb_readl(phy->phy_base, USB2PHY_ANA_CONFIG1);
- val |= USB2PHY_DISCON_BYP_LATCH;
- omap_usb_writel(phy->phy_base, USB2PHY_ANA_CONFIG1, val);
- }
-
- return 0;
-}
-
-static struct phy_ops ops = {
- .init = omap_usb_init,
- .power_on = omap_usb_power_on,
- .power_off = omap_usb_power_off,
- .owner = THIS_MODULE,
-};
-
-#ifdef CONFIG_OF
-static const struct usb_phy_data omap_usb2_data = {
- .label = "omap_usb2",
- .flags = OMAP_USB2_HAS_START_SRP | OMAP_USB2_HAS_SET_VBUS,
-};
-
-static const struct usb_phy_data omap5_usb2_data = {
- .label = "omap5_usb2",
- .flags = 0,
-};
-
-static const struct usb_phy_data dra7x_usb2_data = {
- .label = "dra7x_usb2",
- .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
-};
-
-static const struct usb_phy_data am437x_usb2_data = {
- .label = "am437x_usb2",
- .flags = 0,
-};
-
-static const struct of_device_id omap_usb2_id_table[] = {
- {
- .compatible = "ti,omap-usb2",
- .data = &omap_usb2_data,
- },
- {
- .compatible = "ti,omap5-usb2",
- .data = &omap5_usb2_data,
- },
- {
- .compatible = "ti,dra7x-usb2",
- .data = &dra7x_usb2_data,
- },
- {
- .compatible = "ti,am437x-usb2",
- .data = &am437x_usb2_data,
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, omap_usb2_id_table);
-#endif
-
-static int omap_usb2_probe(struct platform_device *pdev)
-{
- struct omap_usb *phy;
- struct phy *generic_phy;
- struct resource *res;
- struct phy_provider *phy_provider;
- struct usb_otg *otg;
- struct device_node *node = pdev->dev.of_node;
- struct device_node *control_node;
- struct platform_device *control_pdev;
- const struct of_device_id *of_id;
- struct usb_phy_data *phy_data;
-
- of_id = of_match_device(of_match_ptr(omap_usb2_id_table), &pdev->dev);
-
- if (!of_id)
- return -EINVAL;
-
- phy_data = (struct usb_phy_data *)of_id->data;
-
- phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
- if (!phy)
- return -ENOMEM;
-
- otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
- if (!otg)
- return -ENOMEM;
-
- phy->dev = &pdev->dev;
-
- phy->phy.dev = phy->dev;
- phy->phy.label = phy_data->label;
- phy->phy.otg = otg;
- phy->phy.type = USB_PHY_TYPE_USB2;
-
- if (phy_data->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) {
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- phy->phy_base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(phy->phy_base))
- return PTR_ERR(phy->phy_base);
- phy->flags |= OMAP_USB2_CALIBRATE_FALSE_DISCONNECT;
- }
-
- control_node = of_parse_phandle(node, "ctrl-module", 0);
- if (!control_node) {
- dev_err(&pdev->dev, "Failed to get control device phandle\n");
- return -EINVAL;
- }
-
- control_pdev = of_find_device_by_node(control_node);
- if (!control_pdev) {
- dev_err(&pdev->dev, "Failed to get control device\n");
- return -EINVAL;
- }
-
- phy->control_dev = &control_pdev->dev;
- omap_control_phy_power(phy->control_dev, 0);
-
- otg->set_host = omap_usb_set_host;
- otg->set_peripheral = omap_usb_set_peripheral;
- if (phy_data->flags & OMAP_USB2_HAS_SET_VBUS)
- otg->set_vbus = omap_usb_set_vbus;
- if (phy_data->flags & OMAP_USB2_HAS_START_SRP)
- otg->start_srp = omap_usb_start_srp;
- otg->usb_phy = &phy->phy;
-
- platform_set_drvdata(pdev, phy);
- pm_runtime_enable(phy->dev);
-
- generic_phy = devm_phy_create(phy->dev, NULL, &ops, NULL);
- if (IS_ERR(generic_phy)) {
- pm_runtime_disable(phy->dev);
- return PTR_ERR(generic_phy);
- }
-
- phy_set_drvdata(generic_phy, phy);
-
- phy_provider = devm_of_phy_provider_register(phy->dev,
- of_phy_simple_xlate);
- if (IS_ERR(phy_provider)) {
- pm_runtime_disable(phy->dev);
- return PTR_ERR(phy_provider);
- }
-
- phy->wkupclk = devm_clk_get(phy->dev, "wkupclk");
- if (IS_ERR(phy->wkupclk)) {
- dev_warn(&pdev->dev, "unable to get wkupclk, trying old name\n");
- phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
- if (IS_ERR(phy->wkupclk)) {
- dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
- return PTR_ERR(phy->wkupclk);
- } else {
- dev_warn(&pdev->dev,
- "found usb_phy_cm_clk32k, please fix DTS\n");
- }
- }
- clk_prepare(phy->wkupclk);
-
- phy->optclk = devm_clk_get(phy->dev, "refclk");
- if (IS_ERR(phy->optclk)) {
- dev_dbg(&pdev->dev, "unable to get refclk, trying old name\n");
- phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");
- if (IS_ERR(phy->optclk)) {
- dev_dbg(&pdev->dev,
- "unable to get usb_otg_ss_refclk960m\n");
- } else {
- dev_warn(&pdev->dev,
- "found usb_otg_ss_refclk960m, please fix DTS\n");
- }
- } else {
- clk_prepare(phy->optclk);
- }
-
- usb_add_phy_dev(&phy->phy);
-
- return 0;
-}
-
-static int omap_usb2_remove(struct platform_device *pdev)
-{
- struct omap_usb *phy = platform_get_drvdata(pdev);
-
- clk_unprepare(phy->wkupclk);
- if (!IS_ERR(phy->optclk))
- clk_unprepare(phy->optclk);
- usb_remove_phy(&phy->phy);
- pm_runtime_disable(phy->dev);
-
- return 0;
-}
-
-#ifdef CONFIG_PM_RUNTIME
-
-static int omap_usb2_runtime_suspend(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct omap_usb *phy = platform_get_drvdata(pdev);
-
- clk_disable(phy->wkupclk);
- if (!IS_ERR(phy->optclk))
- clk_disable(phy->optclk);
-
- return 0;
-}
-
-static int omap_usb2_runtime_resume(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct omap_usb *phy = platform_get_drvdata(pdev);
- int ret;
-
- ret = clk_enable(phy->wkupclk);
- if (ret < 0) {
- dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
- goto err0;
- }
-
- if (!IS_ERR(phy->optclk)) {
- ret = clk_enable(phy->optclk);
- if (ret < 0) {
- dev_err(phy->dev, "Failed to enable optclk %d\n", ret);
- goto err1;
- }
- }
-
- return 0;
-
-err1:
- clk_disable(phy->wkupclk);
-
-err0:
- return ret;
-}
-
-static const struct dev_pm_ops omap_usb2_pm_ops = {
- SET_RUNTIME_PM_OPS(omap_usb2_runtime_suspend, omap_usb2_runtime_resume,
- NULL)
-};
-
-#define DEV_PM_OPS (&omap_usb2_pm_ops)
-#else
-#define DEV_PM_OPS NULL
-#endif
-
-static struct platform_driver omap_usb2_driver = {
- .probe = omap_usb2_probe,
- .remove = omap_usb2_remove,
- .driver = {
- .name = "omap-usb2",
- .pm = DEV_PM_OPS,
- .of_match_table = of_match_ptr(omap_usb2_id_table),
- },
-};
-
-module_platform_driver(omap_usb2_driver);
-
-MODULE_ALIAS("platform: omap_usb2");
-MODULE_AUTHOR("Texas Instruments Inc.");
-MODULE_DESCRIPTION("OMAP USB2 phy driver");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/time.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/phy/phy.h>
-
-/* PHY registers */
-#define UNIPHY_PLL_REFCLK_CFG 0x000
-#define UNIPHY_PLL_PWRGEN_CFG 0x014
-#define UNIPHY_PLL_GLB_CFG 0x020
-#define UNIPHY_PLL_SDM_CFG0 0x038
-#define UNIPHY_PLL_SDM_CFG1 0x03C
-#define UNIPHY_PLL_SDM_CFG2 0x040
-#define UNIPHY_PLL_SDM_CFG3 0x044
-#define UNIPHY_PLL_SDM_CFG4 0x048
-#define UNIPHY_PLL_SSC_CFG0 0x04C
-#define UNIPHY_PLL_SSC_CFG1 0x050
-#define UNIPHY_PLL_SSC_CFG2 0x054
-#define UNIPHY_PLL_SSC_CFG3 0x058
-#define UNIPHY_PLL_LKDET_CFG0 0x05C
-#define UNIPHY_PLL_LKDET_CFG1 0x060
-#define UNIPHY_PLL_LKDET_CFG2 0x064
-#define UNIPHY_PLL_CAL_CFG0 0x06C
-#define UNIPHY_PLL_CAL_CFG8 0x08C
-#define UNIPHY_PLL_CAL_CFG9 0x090
-#define UNIPHY_PLL_CAL_CFG10 0x094
-#define UNIPHY_PLL_CAL_CFG11 0x098
-#define UNIPHY_PLL_STATUS 0x0C0
-
-#define SATA_PHY_SER_CTRL 0x100
-#define SATA_PHY_TX_DRIV_CTRL0 0x104
-#define SATA_PHY_TX_DRIV_CTRL1 0x108
-#define SATA_PHY_TX_IMCAL0 0x11C
-#define SATA_PHY_TX_IMCAL2 0x124
-#define SATA_PHY_RX_IMCAL0 0x128
-#define SATA_PHY_EQUAL 0x13C
-#define SATA_PHY_OOB_TERM 0x144
-#define SATA_PHY_CDR_CTRL0 0x148
-#define SATA_PHY_CDR_CTRL1 0x14C
-#define SATA_PHY_CDR_CTRL2 0x150
-#define SATA_PHY_CDR_CTRL3 0x154
-#define SATA_PHY_PI_CTRL0 0x168
-#define SATA_PHY_POW_DWN_CTRL0 0x180
-#define SATA_PHY_POW_DWN_CTRL1 0x184
-#define SATA_PHY_TX_DATA_CTRL 0x188
-#define SATA_PHY_ALIGNP 0x1A4
-#define SATA_PHY_TX_IMCAL_STAT 0x1E4
-#define SATA_PHY_RX_IMCAL_STAT 0x1E8
-
-#define UNIPHY_PLL_LOCK BIT(0)
-#define SATA_PHY_TX_CAL BIT(0)
-#define SATA_PHY_RX_CAL BIT(0)
-
-/* default timeout set to 1 sec */
-#define TIMEOUT_MS 10000
-#define DELAY_INTERVAL_US 100
-
-struct qcom_apq8064_sata_phy {
- void __iomem *mmio;
- struct clk *cfg_clk;
- struct device *dev;
-};
-
-/* Helper function to do poll and timeout */
-static int read_poll_timeout(void __iomem *addr, u32 mask)
-{
- unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS);
-
- do {
- if (readl_relaxed(addr) & mask)
- return 0;
-
- usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50);
- } while (!time_after(jiffies, timeout));
-
- return (readl_relaxed(addr) & mask) ? 0 : -ETIMEDOUT;
-}
-
-static int qcom_apq8064_sata_phy_init(struct phy *generic_phy)
-{
- struct qcom_apq8064_sata_phy *phy = phy_get_drvdata(generic_phy);
- void __iomem *base = phy->mmio;
- int ret = 0;
-
- /* SATA phy initialization */
- writel_relaxed(0x01, base + SATA_PHY_SER_CTRL);
- writel_relaxed(0xB1, base + SATA_PHY_POW_DWN_CTRL0);
- /* Make sure the power down happens before power up */
- mb();
- usleep_range(10, 60);
-
- writel_relaxed(0x01, base + SATA_PHY_POW_DWN_CTRL0);
- writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1);
- writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0);
- writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0);
- writel_relaxed(0x02, base + SATA_PHY_TX_IMCAL2);
-
- /* Write UNIPHYPLL registers to configure PLL */
- writel_relaxed(0x04, base + UNIPHY_PLL_REFCLK_CFG);
- writel_relaxed(0x00, base + UNIPHY_PLL_PWRGEN_CFG);
-
- writel_relaxed(0x0A, base + UNIPHY_PLL_CAL_CFG0);
- writel_relaxed(0xF3, base + UNIPHY_PLL_CAL_CFG8);
- writel_relaxed(0x01, base + UNIPHY_PLL_CAL_CFG9);
- writel_relaxed(0xED, base + UNIPHY_PLL_CAL_CFG10);
- writel_relaxed(0x02, base + UNIPHY_PLL_CAL_CFG11);
-
- writel_relaxed(0x36, base + UNIPHY_PLL_SDM_CFG0);
- writel_relaxed(0x0D, base + UNIPHY_PLL_SDM_CFG1);
- writel_relaxed(0xA3, base + UNIPHY_PLL_SDM_CFG2);
- writel_relaxed(0xF0, base + UNIPHY_PLL_SDM_CFG3);
- writel_relaxed(0x00, base + UNIPHY_PLL_SDM_CFG4);
-
- writel_relaxed(0x19, base + UNIPHY_PLL_SSC_CFG0);
- writel_relaxed(0xE1, base + UNIPHY_PLL_SSC_CFG1);
- writel_relaxed(0x00, base + UNIPHY_PLL_SSC_CFG2);
- writel_relaxed(0x11, base + UNIPHY_PLL_SSC_CFG3);
-
- writel_relaxed(0x04, base + UNIPHY_PLL_LKDET_CFG0);
- writel_relaxed(0xFF, base + UNIPHY_PLL_LKDET_CFG1);
-
- writel_relaxed(0x02, base + UNIPHY_PLL_GLB_CFG);
- /* make sure global config LDO power down happens before power up */
- mb();
-
- writel_relaxed(0x03, base + UNIPHY_PLL_GLB_CFG);
- writel_relaxed(0x05, base + UNIPHY_PLL_LKDET_CFG2);
-
- /* PLL Lock wait */
- ret = read_poll_timeout(base + UNIPHY_PLL_STATUS, UNIPHY_PLL_LOCK);
- if (ret) {
- dev_err(phy->dev, "poll timeout UNIPHY_PLL_STATUS\n");
- return ret;
- }
-
- /* TX Calibration */
- ret = read_poll_timeout(base + SATA_PHY_TX_IMCAL_STAT, SATA_PHY_TX_CAL);
- if (ret) {
- dev_err(phy->dev, "poll timeout SATA_PHY_TX_IMCAL_STAT\n");
- return ret;
- }
-
- /* RX Calibration */
- ret = read_poll_timeout(base + SATA_PHY_RX_IMCAL_STAT, SATA_PHY_RX_CAL);
- if (ret) {
- dev_err(phy->dev, "poll timeout SATA_PHY_RX_IMCAL_STAT\n");
- return ret;
- }
-
- /* SATA phy calibrated succesfully, power up to functional mode */
- writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1);
- writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0);
- writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0);
-
- writel_relaxed(0x00, base + SATA_PHY_POW_DWN_CTRL1);
- writel_relaxed(0x59, base + SATA_PHY_CDR_CTRL0);
- writel_relaxed(0x04, base + SATA_PHY_CDR_CTRL1);
- writel_relaxed(0x00, base + SATA_PHY_CDR_CTRL2);
- writel_relaxed(0x00, base + SATA_PHY_PI_CTRL0);
- writel_relaxed(0x00, base + SATA_PHY_CDR_CTRL3);
- writel_relaxed(0x01, base + SATA_PHY_POW_DWN_CTRL0);
-
- writel_relaxed(0x11, base + SATA_PHY_TX_DATA_CTRL);
- writel_relaxed(0x43, base + SATA_PHY_ALIGNP);
- writel_relaxed(0x04, base + SATA_PHY_OOB_TERM);
-
- writel_relaxed(0x01, base + SATA_PHY_EQUAL);
- writel_relaxed(0x09, base + SATA_PHY_TX_DRIV_CTRL0);
- writel_relaxed(0x09, base + SATA_PHY_TX_DRIV_CTRL1);
-
- return 0;
-}
-
-static int qcom_apq8064_sata_phy_exit(struct phy *generic_phy)
-{
- struct qcom_apq8064_sata_phy *phy = phy_get_drvdata(generic_phy);
- void __iomem *base = phy->mmio;
-
- /* Power down PHY */
- writel_relaxed(0xF8, base + SATA_PHY_POW_DWN_CTRL0);
- writel_relaxed(0xFE, base + SATA_PHY_POW_DWN_CTRL1);
-
- /* Power down PLL block */
- writel_relaxed(0x00, base + UNIPHY_PLL_GLB_CFG);
-
- return 0;
-}
-
-static struct phy_ops qcom_apq8064_sata_phy_ops = {
- .init = qcom_apq8064_sata_phy_init,
- .exit = qcom_apq8064_sata_phy_exit,
- .owner = THIS_MODULE,
-};
-
-static int qcom_apq8064_sata_phy_probe(struct platform_device *pdev)
-{
- struct qcom_apq8064_sata_phy *phy;
- struct device *dev = &pdev->dev;
- struct resource *res;
- struct phy_provider *phy_provider;
- struct phy *generic_phy;
- int ret;
-
- phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
- if (!phy)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- phy->mmio = devm_ioremap_resource(dev, res);
- if (IS_ERR(phy->mmio))
- return PTR_ERR(phy->mmio);
-
- generic_phy = devm_phy_create(dev, NULL, &qcom_apq8064_sata_phy_ops,
- NULL);
- if (IS_ERR(generic_phy)) {
- dev_err(dev, "%s: failed to create phy\n", __func__);
- return PTR_ERR(generic_phy);
- }
-
- phy->dev = dev;
- phy_set_drvdata(generic_phy, phy);
- platform_set_drvdata(pdev, phy);
-
- phy->cfg_clk = devm_clk_get(dev, "cfg");
- if (IS_ERR(phy->cfg_clk)) {
- dev_err(dev, "Failed to get sata cfg clock\n");
- return PTR_ERR(phy->cfg_clk);
- }
-
- ret = clk_prepare_enable(phy->cfg_clk);
- if (ret)
- return ret;
-
- phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
- if (IS_ERR(phy_provider)) {
- clk_disable_unprepare(phy->cfg_clk);
- dev_err(dev, "%s: failed to register phy\n", __func__);
- return PTR_ERR(phy_provider);
- }
-
- return 0;
-}
-
-static int qcom_apq8064_sata_phy_remove(struct platform_device *pdev)
-{
- struct qcom_apq8064_sata_phy *phy = platform_get_drvdata(pdev);
-
- clk_disable_unprepare(phy->cfg_clk);
-
- return 0;
-}
-
-static const struct of_device_id qcom_apq8064_sata_phy_of_match[] = {
- { .compatible = "qcom,apq8064-sata-phy" },
- { },
-};
-MODULE_DEVICE_TABLE(of, qcom_apq8064_sata_phy_of_match);
-
-static struct platform_driver qcom_apq8064_sata_phy_driver = {
- .probe = qcom_apq8064_sata_phy_probe,
- .remove = qcom_apq8064_sata_phy_remove,
- .driver = {
- .name = "qcom-apq8064-sata-phy",
- .of_match_table = qcom_apq8064_sata_phy_of_match,
- }
-};
-module_platform_driver(qcom_apq8064_sata_phy_driver);
-
-MODULE_DESCRIPTION("QCOM apq8064 SATA PHY driver");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/time.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/phy/phy.h>
-
-struct qcom_ipq806x_sata_phy {
- void __iomem *mmio;
- struct clk *cfg_clk;
- struct device *dev;
-};
-
-#define __set(v, a, b) (((v) << (b)) & GENMASK(a, b))
-
-#define SATA_PHY_P0_PARAM0 0x200
-#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3(x) __set(x, 17, 12)
-#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3_MASK GENMASK(17, 12)
-#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2(x) __set(x, 11, 6)
-#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2_MASK GENMASK(11, 6)
-#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1(x) __set(x, 5, 0)
-#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1_MASK GENMASK(5, 0)
-
-#define SATA_PHY_P0_PARAM1 0x204
-#define SATA_PHY_P0_PARAM1_RESERVED_BITS31_21(x) __set(x, 31, 21)
-#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3(x) __set(x, 20, 14)
-#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3_MASK GENMASK(20, 14)
-#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2(x) __set(x, 13, 7)
-#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2_MASK GENMASK(13, 7)
-#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1(x) __set(x, 6, 0)
-#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1_MASK GENMASK(6, 0)
-
-#define SATA_PHY_P0_PARAM2 0x208
-#define SATA_PHY_P0_PARAM2_RX_EQ(x) __set(x, 20, 18)
-#define SATA_PHY_P0_PARAM2_RX_EQ_MASK GENMASK(20, 18)
-
-#define SATA_PHY_P0_PARAM3 0x20C
-#define SATA_PHY_SSC_EN 0x8
-#define SATA_PHY_P0_PARAM4 0x210
-#define SATA_PHY_REF_SSP_EN 0x2
-#define SATA_PHY_RESET 0x1
-
-static int qcom_ipq806x_sata_phy_init(struct phy *generic_phy)
-{
- struct qcom_ipq806x_sata_phy *phy = phy_get_drvdata(generic_phy);
- u32 reg;
-
- /* Setting SSC_EN to 1 */
- reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM3);
- reg = reg | SATA_PHY_SSC_EN;
- writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM3);
-
- reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM0) &
- ~(SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3_MASK |
- SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2_MASK |
- SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1_MASK);
- reg |= SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3(0xf);
- writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM0);
-
- reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM1) &
- ~(SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3_MASK |
- SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2_MASK |
- SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1_MASK);
- reg |= SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3(0x55) |
- SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2(0x55) |
- SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1(0x55);
- writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM1);
-
- reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM2) &
- ~SATA_PHY_P0_PARAM2_RX_EQ_MASK;
- reg |= SATA_PHY_P0_PARAM2_RX_EQ(0x3);
- writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM2);
-
- /* Setting PHY_RESET to 1 */
- reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
- reg = reg | SATA_PHY_RESET;
- writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
-
- /* Setting REF_SSP_EN to 1 */
- reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
- reg = reg | SATA_PHY_REF_SSP_EN | SATA_PHY_RESET;
- writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
-
- /* make sure all changes complete before we let the PHY out of reset */
- mb();
-
- /* sleep for max. 50us more to combine processor wakeups */
- usleep_range(20, 20 + 50);
-
- /* Clearing PHY_RESET to 0 */
- reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
- reg = reg & ~SATA_PHY_RESET;
- writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
-
- return 0;
-}
-
-static int qcom_ipq806x_sata_phy_exit(struct phy *generic_phy)
-{
- struct qcom_ipq806x_sata_phy *phy = phy_get_drvdata(generic_phy);
- u32 reg;
-
- /* Setting PHY_RESET to 1 */
- reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
- reg = reg | SATA_PHY_RESET;
- writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
-
- return 0;
-}
-
-static struct phy_ops qcom_ipq806x_sata_phy_ops = {
- .init = qcom_ipq806x_sata_phy_init,
- .exit = qcom_ipq806x_sata_phy_exit,
- .owner = THIS_MODULE,
-};
-
-static int qcom_ipq806x_sata_phy_probe(struct platform_device *pdev)
-{
- struct qcom_ipq806x_sata_phy *phy;
- struct device *dev = &pdev->dev;
- struct resource *res;
- struct phy_provider *phy_provider;
- struct phy *generic_phy;
- int ret;
-
- phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
- if (!phy)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- phy->mmio = devm_ioremap_resource(dev, res);
- if (IS_ERR(phy->mmio))
- return PTR_ERR(phy->mmio);
-
- generic_phy = devm_phy_create(dev, NULL, &qcom_ipq806x_sata_phy_ops,
- NULL);
- if (IS_ERR(generic_phy)) {
- dev_err(dev, "%s: failed to create phy\n", __func__);
- return PTR_ERR(generic_phy);
- }
-
- phy->dev = dev;
- phy_set_drvdata(generic_phy, phy);
- platform_set_drvdata(pdev, phy);
-
- phy->cfg_clk = devm_clk_get(dev, "cfg");
- if (IS_ERR(phy->cfg_clk)) {
- dev_err(dev, "Failed to get sata cfg clock\n");
- return PTR_ERR(phy->cfg_clk);
- }
-
- ret = clk_prepare_enable(phy->cfg_clk);
- if (ret)
- return ret;
-
- phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
- if (IS_ERR(phy_provider)) {
- clk_disable_unprepare(phy->cfg_clk);
- dev_err(dev, "%s: failed to register phy\n", __func__);
- return PTR_ERR(phy_provider);
- }
-
- return 0;
-}
-
-static int qcom_ipq806x_sata_phy_remove(struct platform_device *pdev)
-{
- struct qcom_ipq806x_sata_phy *phy = platform_get_drvdata(pdev);
-
- clk_disable_unprepare(phy->cfg_clk);
-
- return 0;
-}
-
-static const struct of_device_id qcom_ipq806x_sata_phy_of_match[] = {
- { .compatible = "qcom,ipq806x-sata-phy" },
- { },
-};
-MODULE_DEVICE_TABLE(of, qcom_ipq806x_sata_phy_of_match);
-
-static struct platform_driver qcom_ipq806x_sata_phy_driver = {
- .probe = qcom_ipq806x_sata_phy_probe,
- .remove = qcom_ipq806x_sata_phy_remove,
- .driver = {
- .name = "qcom-ipq806x-sata-phy",
- .of_match_table = qcom_ipq806x_sata_phy_of_match,
- }
-};
-module_platform_driver(qcom_ipq806x_sata_phy_driver);
-
-MODULE_DESCRIPTION("QCOM IPQ806x SATA PHY driver");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * Renesas R-Car Gen2 PHY driver
- *
- * Copyright (C) 2014 Renesas Solutions Corp.
- * Copyright (C) 2014 Cogent Embedded, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-
-#include <asm/cmpxchg.h>
-
-#define USBHS_LPSTS 0x02
-#define USBHS_UGCTRL 0x80
-#define USBHS_UGCTRL2 0x84
-#define USBHS_UGSTS 0x88 /* The manuals have 0x90 */
-
-/* Low Power Status register (LPSTS) */
-#define USBHS_LPSTS_SUSPM 0x4000
-
-/* USB General control register (UGCTRL) */
-#define USBHS_UGCTRL_CONNECT 0x00000004
-#define USBHS_UGCTRL_PLLRESET 0x00000001
-
-/* USB General control register 2 (UGCTRL2) */
-#define USBHS_UGCTRL2_USB2SEL 0x80000000
-#define USBHS_UGCTRL2_USB2SEL_PCI 0x00000000
-#define USBHS_UGCTRL2_USB2SEL_USB30 0x80000000
-#define USBHS_UGCTRL2_USB0SEL 0x00000030
-#define USBHS_UGCTRL2_USB0SEL_PCI 0x00000010
-#define USBHS_UGCTRL2_USB0SEL_HS_USB 0x00000030
-
-/* USB General status register (UGSTS) */
-#define USBHS_UGSTS_LOCK 0x00000300 /* The manuals have 0x3 */
-
-#define PHYS_PER_CHANNEL 2
-
-struct rcar_gen2_phy {
- struct phy *phy;
- struct rcar_gen2_channel *channel;
- int number;
- u32 select_value;
-};
-
-struct rcar_gen2_channel {
- struct device_node *of_node;
- struct rcar_gen2_phy_driver *drv;
- struct rcar_gen2_phy phys[PHYS_PER_CHANNEL];
- int selected_phy;
- u32 select_mask;
-};
-
-struct rcar_gen2_phy_driver {
- void __iomem *base;
- struct clk *clk;
- spinlock_t lock;
- int num_channels;
- struct rcar_gen2_channel *channels;
-};
-
-static int rcar_gen2_phy_init(struct phy *p)
-{
- struct rcar_gen2_phy *phy = phy_get_drvdata(p);
- struct rcar_gen2_channel *channel = phy->channel;
- struct rcar_gen2_phy_driver *drv = channel->drv;
- unsigned long flags;
- u32 ugctrl2;
-
- /*
- * Try to acquire exclusive access to PHY. The first driver calling
- * phy_init() on a given channel wins, and all attempts to use another
- * PHY on this channel will fail until phy_exit() is called by the first
- * driver. Achieving this with cmpxcgh() should be SMP-safe.
- */
- if (cmpxchg(&channel->selected_phy, -1, phy->number) != -1)
- return -EBUSY;
-
- clk_prepare_enable(drv->clk);
-
- spin_lock_irqsave(&drv->lock, flags);
- ugctrl2 = readl(drv->base + USBHS_UGCTRL2);
- ugctrl2 &= ~channel->select_mask;
- ugctrl2 |= phy->select_value;
- writel(ugctrl2, drv->base + USBHS_UGCTRL2);
- spin_unlock_irqrestore(&drv->lock, flags);
- return 0;
-}
-
-static int rcar_gen2_phy_exit(struct phy *p)
-{
- struct rcar_gen2_phy *phy = phy_get_drvdata(p);
- struct rcar_gen2_channel *channel = phy->channel;
-
- clk_disable_unprepare(channel->drv->clk);
-
- channel->selected_phy = -1;
-
- return 0;
-}
-
-static int rcar_gen2_phy_power_on(struct phy *p)
-{
- struct rcar_gen2_phy *phy = phy_get_drvdata(p);
- struct rcar_gen2_phy_driver *drv = phy->channel->drv;
- void __iomem *base = drv->base;
- unsigned long flags;
- u32 value;
- int err = 0, i;
-
- /* Skip if it's not USBHS */
- if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB)
- return 0;
-
- spin_lock_irqsave(&drv->lock, flags);
-
- /* Power on USBHS PHY */
- value = readl(base + USBHS_UGCTRL);
- value &= ~USBHS_UGCTRL_PLLRESET;
- writel(value, base + USBHS_UGCTRL);
-
- value = readw(base + USBHS_LPSTS);
- value |= USBHS_LPSTS_SUSPM;
- writew(value, base + USBHS_LPSTS);
-
- for (i = 0; i < 20; i++) {
- value = readl(base + USBHS_UGSTS);
- if ((value & USBHS_UGSTS_LOCK) == USBHS_UGSTS_LOCK) {
- value = readl(base + USBHS_UGCTRL);
- value |= USBHS_UGCTRL_CONNECT;
- writel(value, base + USBHS_UGCTRL);
- goto out;
- }
- udelay(1);
- }
-
- /* Timed out waiting for the PLL lock */
- err = -ETIMEDOUT;
-
-out:
- spin_unlock_irqrestore(&drv->lock, flags);
-
- return err;
-}
-
-static int rcar_gen2_phy_power_off(struct phy *p)
-{
- struct rcar_gen2_phy *phy = phy_get_drvdata(p);
- struct rcar_gen2_phy_driver *drv = phy->channel->drv;
- void __iomem *base = drv->base;
- unsigned long flags;
- u32 value;
-
- /* Skip if it's not USBHS */
- if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB)
- return 0;
-
- spin_lock_irqsave(&drv->lock, flags);
-
- /* Power off USBHS PHY */
- value = readl(base + USBHS_UGCTRL);
- value &= ~USBHS_UGCTRL_CONNECT;
- writel(value, base + USBHS_UGCTRL);
-
- value = readw(base + USBHS_LPSTS);
- value &= ~USBHS_LPSTS_SUSPM;
- writew(value, base + USBHS_LPSTS);
-
- value = readl(base + USBHS_UGCTRL);
- value |= USBHS_UGCTRL_PLLRESET;
- writel(value, base + USBHS_UGCTRL);
-
- spin_unlock_irqrestore(&drv->lock, flags);
-
- return 0;
-}
-
-static struct phy_ops rcar_gen2_phy_ops = {
- .init = rcar_gen2_phy_init,
- .exit = rcar_gen2_phy_exit,
- .power_on = rcar_gen2_phy_power_on,
- .power_off = rcar_gen2_phy_power_off,
- .owner = THIS_MODULE,
-};
-
-static const struct of_device_id rcar_gen2_phy_match_table[] = {
- { .compatible = "renesas,usb-phy-r8a7790" },
- { .compatible = "renesas,usb-phy-r8a7791" },
- { }
-};
-MODULE_DEVICE_TABLE(of, rcar_gen2_phy_match_table);
-
-static struct phy *rcar_gen2_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
-{
- struct rcar_gen2_phy_driver *drv;
- struct device_node *np = args->np;
- int i;
-
- if (!of_device_is_available(np)) {
- dev_warn(dev, "Requested PHY is disabled\n");
- return ERR_PTR(-ENODEV);
- }
-
- drv = dev_get_drvdata(dev);
- if (!drv)
- return ERR_PTR(-EINVAL);
-
- for (i = 0; i < drv->num_channels; i++) {
- if (np == drv->channels[i].of_node)
- break;
- }
-
- if (i >= drv->num_channels || args->args[0] >= 2)
- return ERR_PTR(-ENODEV);
-
- return drv->channels[i].phys[args->args[0]].phy;
-}
-
-static const u32 select_mask[] = {
- [0] = USBHS_UGCTRL2_USB0SEL,
- [2] = USBHS_UGCTRL2_USB2SEL,
-};
-
-static const u32 select_value[][PHYS_PER_CHANNEL] = {
- [0] = { USBHS_UGCTRL2_USB0SEL_PCI, USBHS_UGCTRL2_USB0SEL_HS_USB },
- [2] = { USBHS_UGCTRL2_USB2SEL_PCI, USBHS_UGCTRL2_USB2SEL_USB30 },
-};
-
-static int rcar_gen2_phy_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct rcar_gen2_phy_driver *drv;
- struct phy_provider *provider;
- struct device_node *np;
- struct resource *res;
- void __iomem *base;
- struct clk *clk;
- int i = 0;
-
- if (!dev->of_node) {
- dev_err(dev,
- "This driver is required to be instantiated from device tree\n");
- return -EINVAL;
- }
-
- clk = devm_clk_get(dev, "usbhs");
- if (IS_ERR(clk)) {
- dev_err(dev, "Can't get USBHS clock\n");
- return PTR_ERR(clk);
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(dev, res);
- if (IS_ERR(base))
- return PTR_ERR(base);
-
- drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
- if (!drv)
- return -ENOMEM;
-
- spin_lock_init(&drv->lock);
-
- drv->clk = clk;
- drv->base = base;
-
- drv->num_channels = of_get_child_count(dev->of_node);
- drv->channels = devm_kcalloc(dev, drv->num_channels,
- sizeof(struct rcar_gen2_channel),
- GFP_KERNEL);
- if (!drv->channels)
- return -ENOMEM;
-
- for_each_child_of_node(dev->of_node, np) {
- struct rcar_gen2_channel *channel = drv->channels + i;
- u32 channel_num;
- int error, n;
-
- channel->of_node = np;
- channel->drv = drv;
- channel->selected_phy = -1;
-
- error = of_property_read_u32(np, "reg", &channel_num);
- if (error || channel_num > 2) {
- dev_err(dev, "Invalid \"reg\" property\n");
- return error;
- }
- channel->select_mask = select_mask[channel_num];
-
- for (n = 0; n < PHYS_PER_CHANNEL; n++) {
- struct rcar_gen2_phy *phy = &channel->phys[n];
-
- phy->channel = channel;
- phy->number = n;
- phy->select_value = select_value[channel_num][n];
-
- phy->phy = devm_phy_create(dev, NULL,
- &rcar_gen2_phy_ops, NULL);
- if (IS_ERR(phy->phy)) {
- dev_err(dev, "Failed to create PHY\n");
- return PTR_ERR(phy->phy);
- }
- phy_set_drvdata(phy->phy, phy);
- }
-
- i++;
- }
-
- provider = devm_of_phy_provider_register(dev, rcar_gen2_phy_xlate);
- if (IS_ERR(provider)) {
- dev_err(dev, "Failed to register PHY provider\n");
- return PTR_ERR(provider);
- }
-
- dev_set_drvdata(dev, drv);
-
- return 0;
-}
-
-static struct platform_driver rcar_gen2_phy_driver = {
- .driver = {
- .name = "phy_rcar_gen2",
- .of_match_table = rcar_gen2_phy_match_table,
- },
- .probe = rcar_gen2_phy_probe,
-};
-
-module_platform_driver(rcar_gen2_phy_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Renesas R-Car Gen2 PHY");
-MODULE_AUTHOR("Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>");
+++ /dev/null
-/*
- * Rockchip usb PHY driver
- *
- * Copyright (C) 2014 Roy Li <lyz@rock-chips.com>
- * Copyright (C) 2014 ROCKCHIP, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-#include <linux/reset.h>
-#include <linux/regmap.h>
-#include <linux/mfd/syscon.h>
-
-#define ROCKCHIP_RK3288_UOC(n) (0x320 + n * 0x14)
-
-#define SIDDQ_MSK (1 << (13 + 16))
-#define SIDDQ_ON (1 << 13)
-#define SIDDQ_OFF (0 << 13)
-
-enum rk3288_phy_id {
- RK3288_OTG,
- RK3288_HOST0,
- RK3288_HOST1,
- RK3288_NUM_PHYS,
-};
-
-struct rockchip_usb_phy {
- struct regmap *reg_base;
- unsigned int reg_offset;
- struct clk *clk;
- struct phy *phy;
-};
-
-static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
- bool siddq)
-{
- return regmap_write(phy->reg_base, phy->reg_offset,
- SIDDQ_MSK | (siddq ? SIDDQ_ON : SIDDQ_OFF));
-}
-
-static int rockchip_usb_phy_power_off(struct phy *_phy)
-{
- struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
- int ret = 0;
-
- /* Power down usb phy analog blocks by set siddq 1*/
- ret = rockchip_usb_phy_power(phy, 1);
- if (ret)
- return ret;
-
- clk_disable_unprepare(phy->clk);
- if (ret)
- return ret;
-
- return 0;
-}
-
-static int rockchip_usb_phy_power_on(struct phy *_phy)
-{
- struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
- int ret = 0;
-
- ret = clk_prepare_enable(phy->clk);
- if (ret)
- return ret;
-
- /* Power up usb phy analog blocks by set siddq 0*/
- ret = rockchip_usb_phy_power(phy, 0);
- if (ret)
- return ret;
-
- return 0;
-}
-
-static struct phy *rockchip_usb_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
-{
- struct rockchip_usb_phy *phy_array = dev_get_drvdata(dev);
-
- if (WARN_ON(args->args[0] == 0 || args->args[0] >= RK3288_NUM_PHYS))
- return ERR_PTR(-ENODEV);
-
- return (phy_array + args->args[0])->phy;
-}
-
-static struct phy_ops ops = {
- .power_on = rockchip_usb_phy_power_on,
- .power_off = rockchip_usb_phy_power_off,
- .owner = THIS_MODULE,
-};
-
-static int rockchip_usb_phy_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct rockchip_usb_phy *rk_phy;
- struct rockchip_usb_phy *phy_array;
- struct phy_provider *phy_provider;
- struct regmap *grf;
- char clk_name[16];
- int i;
-
- grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
- if (IS_ERR(grf)) {
- dev_err(&pdev->dev, "Missing rockchip,grf property\n");
- return PTR_ERR(grf);
- }
-
- phy_array = devm_kzalloc(dev, RK3288_NUM_PHYS * sizeof(*rk_phy),
- GFP_KERNEL);
- if (!phy_array)
- return -ENOMEM;
-
- for (i = 0; i < RK3288_NUM_PHYS; i++) {
- rk_phy = &phy_array[i];
-
- rk_phy->reg_base = grf;
-
- rk_phy->reg_offset = ROCKCHIP_RK3288_UOC(i);
-
- snprintf(clk_name, sizeof(clk_name), "usbphy%d", i);
- rk_phy->clk = devm_clk_get(dev, clk_name);
- if (IS_ERR(rk_phy->clk)) {
- dev_warn(dev, "failed to get clock %s\n", clk_name);
- rk_phy->clk = NULL;
- }
-
- rk_phy->phy = devm_phy_create(dev, NULL, &ops, NULL);
- if (IS_ERR(rk_phy->phy)) {
- dev_err(dev, "failed to create PHY %d\n", i);
- return PTR_ERR(rk_phy->phy);
- }
- phy_set_drvdata(rk_phy->phy, rk_phy);
- }
-
- platform_set_drvdata(pdev, phy_array);
-
- phy_provider = devm_of_phy_provider_register(dev,
- rockchip_usb_phy_xlate);
- return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
- { .compatible = "rockchip,rk3288-usb-phy" },
- {}
-};
-
-MODULE_DEVICE_TABLE(of, rockchip_usb_phy_dt_ids);
-
-static struct platform_driver rockchip_usb_driver = {
- .probe = rockchip_usb_phy_probe,
- .driver = {
- .name = "rockchip-usb-phy",
- .owner = THIS_MODULE,
- .of_match_table = rockchip_usb_phy_dt_ids,
- },
-};
-
-module_platform_driver(rockchip_usb_driver);
-
-MODULE_AUTHOR("Roy Li <lyz@rock-chips.com>");
-MODULE_DESCRIPTION("Rockchip USB 2.0 PHY driver");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * Samsung SoC USB 1.1/2.0 PHY driver - S5PV210 support
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Authors: Kamil Debski <k.debski@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/phy/phy.h>
-#include "phy-samsung-usb2.h"
-
-/* Exynos USB PHY registers */
-
-/* PHY power control */
-#define S5PV210_UPHYPWR 0x0
-
-#define S5PV210_UPHYPWR_PHY0_SUSPEND BIT(0)
-#define S5PV210_UPHYPWR_PHY0_PWR BIT(3)
-#define S5PV210_UPHYPWR_PHY0_OTG_PWR BIT(4)
-#define S5PV210_UPHYPWR_PHY0 ( \
- S5PV210_UPHYPWR_PHY0_SUSPEND | \
- S5PV210_UPHYPWR_PHY0_PWR | \
- S5PV210_UPHYPWR_PHY0_OTG_PWR)
-
-#define S5PV210_UPHYPWR_PHY1_SUSPEND BIT(6)
-#define S5PV210_UPHYPWR_PHY1_PWR BIT(7)
-#define S5PV210_UPHYPWR_PHY1 ( \
- S5PV210_UPHYPWR_PHY1_SUSPEND | \
- S5PV210_UPHYPWR_PHY1_PWR)
-
-/* PHY clock control */
-#define S5PV210_UPHYCLK 0x4
-
-#define S5PV210_UPHYCLK_PHYFSEL_MASK (0x3 << 0)
-#define S5PV210_UPHYCLK_PHYFSEL_48MHZ (0x0 << 0)
-#define S5PV210_UPHYCLK_PHYFSEL_24MHZ (0x3 << 0)
-#define S5PV210_UPHYCLK_PHYFSEL_12MHZ (0x2 << 0)
-
-#define S5PV210_UPHYCLK_PHY0_ID_PULLUP BIT(2)
-#define S5PV210_UPHYCLK_PHY0_COMMON_ON BIT(4)
-#define S5PV210_UPHYCLK_PHY1_COMMON_ON BIT(7)
-
-/* PHY reset control */
-#define S5PV210_UPHYRST 0x8
-
-#define S5PV210_URSTCON_PHY0 BIT(0)
-#define S5PV210_URSTCON_OTG_HLINK BIT(1)
-#define S5PV210_URSTCON_OTG_PHYLINK BIT(2)
-#define S5PV210_URSTCON_PHY1_ALL BIT(3)
-#define S5PV210_URSTCON_HOST_LINK_ALL BIT(4)
-
-/* Isolation, configured in the power management unit */
-#define S5PV210_USB_ISOL_OFFSET 0x680c
-#define S5PV210_USB_ISOL_DEVICE BIT(0)
-#define S5PV210_USB_ISOL_HOST BIT(1)
-
-
-enum s5pv210_phy_id {
- S5PV210_DEVICE,
- S5PV210_HOST,
- S5PV210_NUM_PHYS,
-};
-
-/*
- * s5pv210_rate_to_clk() converts the supplied clock rate to the value that
- * can be written to the phy register.
- */
-static int s5pv210_rate_to_clk(unsigned long rate, u32 *reg)
-{
- switch (rate) {
- case 12 * MHZ:
- *reg = S5PV210_UPHYCLK_PHYFSEL_12MHZ;
- break;
- case 24 * MHZ:
- *reg = S5PV210_UPHYCLK_PHYFSEL_24MHZ;
- break;
- case 48 * MHZ:
- *reg = S5PV210_UPHYCLK_PHYFSEL_48MHZ;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void s5pv210_isol(struct samsung_usb2_phy_instance *inst, bool on)
-{
- struct samsung_usb2_phy_driver *drv = inst->drv;
- u32 mask;
-
- switch (inst->cfg->id) {
- case S5PV210_DEVICE:
- mask = S5PV210_USB_ISOL_DEVICE;
- break;
- case S5PV210_HOST:
- mask = S5PV210_USB_ISOL_HOST;
- break;
- default:
- return;
- };
-
- regmap_update_bits(drv->reg_pmu, S5PV210_USB_ISOL_OFFSET,
- mask, on ? 0 : mask);
-}
-
-static void s5pv210_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
-{
- struct samsung_usb2_phy_driver *drv = inst->drv;
- u32 rstbits = 0;
- u32 phypwr = 0;
- u32 rst;
- u32 pwr;
-
- switch (inst->cfg->id) {
- case S5PV210_DEVICE:
- phypwr = S5PV210_UPHYPWR_PHY0;
- rstbits = S5PV210_URSTCON_PHY0;
- break;
- case S5PV210_HOST:
- phypwr = S5PV210_UPHYPWR_PHY1;
- rstbits = S5PV210_URSTCON_PHY1_ALL |
- S5PV210_URSTCON_HOST_LINK_ALL;
- break;
- };
-
- if (on) {
- writel(drv->ref_reg_val, drv->reg_phy + S5PV210_UPHYCLK);
-
- pwr = readl(drv->reg_phy + S5PV210_UPHYPWR);
- pwr &= ~phypwr;
- writel(pwr, drv->reg_phy + S5PV210_UPHYPWR);
-
- rst = readl(drv->reg_phy + S5PV210_UPHYRST);
- rst |= rstbits;
- writel(rst, drv->reg_phy + S5PV210_UPHYRST);
- udelay(10);
- rst &= ~rstbits;
- writel(rst, drv->reg_phy + S5PV210_UPHYRST);
- } else {
- pwr = readl(drv->reg_phy + S5PV210_UPHYPWR);
- pwr |= phypwr;
- writel(pwr, drv->reg_phy + S5PV210_UPHYPWR);
- }
-}
-
-static int s5pv210_power_on(struct samsung_usb2_phy_instance *inst)
-{
- s5pv210_isol(inst, 0);
- s5pv210_phy_pwr(inst, 1);
-
- return 0;
-}
-
-static int s5pv210_power_off(struct samsung_usb2_phy_instance *inst)
-{
- s5pv210_phy_pwr(inst, 0);
- s5pv210_isol(inst, 1);
-
- return 0;
-}
-
-static const struct samsung_usb2_common_phy s5pv210_phys[S5PV210_NUM_PHYS] = {
- [S5PV210_DEVICE] = {
- .label = "device",
- .id = S5PV210_DEVICE,
- .power_on = s5pv210_power_on,
- .power_off = s5pv210_power_off,
- },
- [S5PV210_HOST] = {
- .label = "host",
- .id = S5PV210_HOST,
- .power_on = s5pv210_power_on,
- .power_off = s5pv210_power_off,
- },
-};
-
-const struct samsung_usb2_phy_config s5pv210_usb2_phy_config = {
- .num_phys = ARRAY_SIZE(s5pv210_phys),
- .phys = s5pv210_phys,
- .rate_to_clk = s5pv210_rate_to_clk,
-};
+++ /dev/null
-/*
- * Samsung SoC USB 1.1/2.0 PHY driver
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Author: Kamil Debski <k.debski@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/clk.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include "phy-samsung-usb2.h"
-
-static int samsung_usb2_phy_power_on(struct phy *phy)
-{
- struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
- struct samsung_usb2_phy_driver *drv = inst->drv;
- int ret;
-
- dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
- inst->cfg->label);
- ret = clk_prepare_enable(drv->clk);
- if (ret)
- goto err_main_clk;
- ret = clk_prepare_enable(drv->ref_clk);
- if (ret)
- goto err_instance_clk;
- if (inst->cfg->power_on) {
- spin_lock(&drv->lock);
- ret = inst->cfg->power_on(inst);
- spin_unlock(&drv->lock);
- }
-
- return 0;
-
-err_instance_clk:
- clk_disable_unprepare(drv->clk);
-err_main_clk:
- return ret;
-}
-
-static int samsung_usb2_phy_power_off(struct phy *phy)
-{
- struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
- struct samsung_usb2_phy_driver *drv = inst->drv;
- int ret = 0;
-
- dev_dbg(drv->dev, "Request to power_off \"%s\" usb phy\n",
- inst->cfg->label);
- if (inst->cfg->power_off) {
- spin_lock(&drv->lock);
- ret = inst->cfg->power_off(inst);
- spin_unlock(&drv->lock);
- }
- clk_disable_unprepare(drv->ref_clk);
- clk_disable_unprepare(drv->clk);
- return ret;
-}
-
-static struct phy_ops samsung_usb2_phy_ops = {
- .power_on = samsung_usb2_phy_power_on,
- .power_off = samsung_usb2_phy_power_off,
- .owner = THIS_MODULE,
-};
-
-static struct phy *samsung_usb2_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
-{
- struct samsung_usb2_phy_driver *drv;
-
- drv = dev_get_drvdata(dev);
- if (!drv)
- return ERR_PTR(-EINVAL);
-
- if (WARN_ON(args->args[0] >= drv->cfg->num_phys))
- return ERR_PTR(-ENODEV);
-
- return drv->instances[args->args[0]].phy;
-}
-
-static const struct of_device_id samsung_usb2_phy_of_match[] = {
-#ifdef CONFIG_PHY_EXYNOS4X12_USB2
- {
- .compatible = "samsung,exynos3250-usb2-phy",
- .data = &exynos3250_usb2_phy_config,
- },
-#endif
-#ifdef CONFIG_PHY_EXYNOS4210_USB2
- {
- .compatible = "samsung,exynos4210-usb2-phy",
- .data = &exynos4210_usb2_phy_config,
- },
-#endif
-#ifdef CONFIG_PHY_EXYNOS4X12_USB2
- {
- .compatible = "samsung,exynos4x12-usb2-phy",
- .data = &exynos4x12_usb2_phy_config,
- },
-#endif
-#ifdef CONFIG_PHY_EXYNOS5250_USB2
- {
- .compatible = "samsung,exynos5250-usb2-phy",
- .data = &exynos5250_usb2_phy_config,
- },
-#endif
-#ifdef CONFIG_PHY_S5PV210_USB2
- {
- .compatible = "samsung,s5pv210-usb2-phy",
- .data = &s5pv210_usb2_phy_config,
- },
-#endif
- { },
-};
-MODULE_DEVICE_TABLE(of, samsung_usb2_phy_of_match);
-
-static int samsung_usb2_phy_probe(struct platform_device *pdev)
-{
- const struct of_device_id *match;
- const struct samsung_usb2_phy_config *cfg;
- struct device *dev = &pdev->dev;
- struct phy_provider *phy_provider;
- struct resource *mem;
- struct samsung_usb2_phy_driver *drv;
- int i, ret;
-
- if (!pdev->dev.of_node) {
- dev_err(dev, "This driver is required to be instantiated from device tree\n");
- return -EINVAL;
- }
-
- match = of_match_node(samsung_usb2_phy_of_match, pdev->dev.of_node);
- if (!match) {
- dev_err(dev, "of_match_node() failed\n");
- return -EINVAL;
- }
- cfg = match->data;
-
- drv = devm_kzalloc(dev, sizeof(struct samsung_usb2_phy_driver) +
- cfg->num_phys * sizeof(struct samsung_usb2_phy_instance),
- GFP_KERNEL);
- if (!drv)
- return -ENOMEM;
-
- dev_set_drvdata(dev, drv);
- spin_lock_init(&drv->lock);
-
- drv->cfg = cfg;
- drv->dev = dev;
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- drv->reg_phy = devm_ioremap_resource(dev, mem);
- if (IS_ERR(drv->reg_phy)) {
- dev_err(dev, "Failed to map register memory (phy)\n");
- return PTR_ERR(drv->reg_phy);
- }
-
- drv->reg_pmu = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
- "samsung,pmureg-phandle");
- if (IS_ERR(drv->reg_pmu)) {
- dev_err(dev, "Failed to map PMU registers (via syscon)\n");
- return PTR_ERR(drv->reg_pmu);
- }
-
- if (drv->cfg->has_mode_switch) {
- drv->reg_sys = syscon_regmap_lookup_by_phandle(
- pdev->dev.of_node, "samsung,sysreg-phandle");
- if (IS_ERR(drv->reg_sys)) {
- dev_err(dev, "Failed to map system registers (via syscon)\n");
- return PTR_ERR(drv->reg_sys);
- }
- }
-
- drv->clk = devm_clk_get(dev, "phy");
- if (IS_ERR(drv->clk)) {
- dev_err(dev, "Failed to get clock of phy controller\n");
- return PTR_ERR(drv->clk);
- }
-
- drv->ref_clk = devm_clk_get(dev, "ref");
- if (IS_ERR(drv->ref_clk)) {
- dev_err(dev, "Failed to get reference clock for the phy controller\n");
- return PTR_ERR(drv->ref_clk);
- }
-
- drv->ref_rate = clk_get_rate(drv->ref_clk);
- if (drv->cfg->rate_to_clk) {
- ret = drv->cfg->rate_to_clk(drv->ref_rate, &drv->ref_reg_val);
- if (ret)
- return ret;
- }
-
- for (i = 0; i < drv->cfg->num_phys; i++) {
- char *label = drv->cfg->phys[i].label;
- struct samsung_usb2_phy_instance *p = &drv->instances[i];
-
- dev_dbg(dev, "Creating phy \"%s\"\n", label);
- p->phy = devm_phy_create(dev, NULL, &samsung_usb2_phy_ops,
- NULL);
- if (IS_ERR(p->phy)) {
- dev_err(drv->dev, "Failed to create usb2_phy \"%s\"\n",
- label);
- return PTR_ERR(p->phy);
- }
-
- p->cfg = &drv->cfg->phys[i];
- p->drv = drv;
- phy_set_bus_width(p->phy, 8);
- phy_set_drvdata(p->phy, p);
- }
-
- phy_provider = devm_of_phy_provider_register(dev,
- samsung_usb2_phy_xlate);
- if (IS_ERR(phy_provider)) {
- dev_err(drv->dev, "Failed to register phy provider\n");
- return PTR_ERR(phy_provider);
- }
-
- return 0;
-}
-
-static struct platform_driver samsung_usb2_phy_driver = {
- .probe = samsung_usb2_phy_probe,
- .driver = {
- .of_match_table = samsung_usb2_phy_of_match,
- .name = "samsung-usb2-phy",
- }
-};
-
-module_platform_driver(samsung_usb2_phy_driver);
-MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC USB PHY driver");
-MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:samsung-usb2-phy");
+++ /dev/null
-/*
- * Samsung SoC USB 1.1/2.0 PHY driver
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Author: Kamil Debski <k.debski@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _PHY_EXYNOS_USB2_H
-#define _PHY_EXYNOS_USB2_H
-
-#include <linux/clk.h>
-#include <linux/phy/phy.h>
-#include <linux/device.h>
-#include <linux/regmap.h>
-#include <linux/spinlock.h>
-
-#define KHZ 1000
-#define MHZ (KHZ * KHZ)
-
-struct samsung_usb2_phy_driver;
-struct samsung_usb2_phy_instance;
-struct samsung_usb2_phy_config;
-
-struct samsung_usb2_phy_instance {
- const struct samsung_usb2_common_phy *cfg;
- struct phy *phy;
- struct samsung_usb2_phy_driver *drv;
- int int_cnt;
- int ext_cnt;
-};
-
-struct samsung_usb2_phy_driver {
- const struct samsung_usb2_phy_config *cfg;
- struct clk *clk;
- struct clk *ref_clk;
- unsigned long ref_rate;
- u32 ref_reg_val;
- struct device *dev;
- void __iomem *reg_phy;
- struct regmap *reg_pmu;
- struct regmap *reg_sys;
- spinlock_t lock;
- struct samsung_usb2_phy_instance instances[0];
-};
-
-struct samsung_usb2_common_phy {
- int (*power_on)(struct samsung_usb2_phy_instance *);
- int (*power_off)(struct samsung_usb2_phy_instance *);
- unsigned int id;
- char *label;
-};
-
-
-struct samsung_usb2_phy_config {
- const struct samsung_usb2_common_phy *phys;
- int (*rate_to_clk)(unsigned long, u32 *);
- unsigned int num_phys;
- bool has_mode_switch;
- bool has_refclk_sel;
-};
-
-extern const struct samsung_usb2_phy_config exynos3250_usb2_phy_config;
-extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config;
-extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config;
-extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config;
-extern const struct samsung_usb2_phy_config s5pv210_usb2_phy_config;
-#endif
+++ /dev/null
-/*
- * ST SPEAr1310-miphy driver
- *
- * Copyright (C) 2014 ST Microelectronics
- * Pratyush Anand <pratyush.anand@st.com>
- * Mohit Kumar <mohit.kumar@st.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/kernel.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/phy/phy.h>
-#include <linux/regmap.h>
-
-/* SPEAr1310 Registers */
-#define SPEAR1310_PCIE_SATA_CFG 0x3A4
- #define SPEAR1310_PCIE_SATA2_SEL_PCIE (0 << 31)
- #define SPEAR1310_PCIE_SATA1_SEL_PCIE (0 << 30)
- #define SPEAR1310_PCIE_SATA0_SEL_PCIE (0 << 29)
- #define SPEAR1310_PCIE_SATA2_SEL_SATA BIT(31)
- #define SPEAR1310_PCIE_SATA1_SEL_SATA BIT(30)
- #define SPEAR1310_PCIE_SATA0_SEL_SATA BIT(29)
- #define SPEAR1310_SATA2_CFG_TX_CLK_EN BIT(27)
- #define SPEAR1310_SATA2_CFG_RX_CLK_EN BIT(26)
- #define SPEAR1310_SATA2_CFG_POWERUP_RESET BIT(25)
- #define SPEAR1310_SATA2_CFG_PM_CLK_EN BIT(24)
- #define SPEAR1310_SATA1_CFG_TX_CLK_EN BIT(23)
- #define SPEAR1310_SATA1_CFG_RX_CLK_EN BIT(22)
- #define SPEAR1310_SATA1_CFG_POWERUP_RESET BIT(21)
- #define SPEAR1310_SATA1_CFG_PM_CLK_EN BIT(20)
- #define SPEAR1310_SATA0_CFG_TX_CLK_EN BIT(19)
- #define SPEAR1310_SATA0_CFG_RX_CLK_EN BIT(18)
- #define SPEAR1310_SATA0_CFG_POWERUP_RESET BIT(17)
- #define SPEAR1310_SATA0_CFG_PM_CLK_EN BIT(16)
- #define SPEAR1310_PCIE2_CFG_DEVICE_PRESENT BIT(11)
- #define SPEAR1310_PCIE2_CFG_POWERUP_RESET BIT(10)
- #define SPEAR1310_PCIE2_CFG_CORE_CLK_EN BIT(9)
- #define SPEAR1310_PCIE2_CFG_AUX_CLK_EN BIT(8)
- #define SPEAR1310_PCIE1_CFG_DEVICE_PRESENT BIT(7)
- #define SPEAR1310_PCIE1_CFG_POWERUP_RESET BIT(6)
- #define SPEAR1310_PCIE1_CFG_CORE_CLK_EN BIT(5)
- #define SPEAR1310_PCIE1_CFG_AUX_CLK_EN BIT(4)
- #define SPEAR1310_PCIE0_CFG_DEVICE_PRESENT BIT(3)
- #define SPEAR1310_PCIE0_CFG_POWERUP_RESET BIT(2)
- #define SPEAR1310_PCIE0_CFG_CORE_CLK_EN BIT(1)
- #define SPEAR1310_PCIE0_CFG_AUX_CLK_EN BIT(0)
-
- #define SPEAR1310_PCIE_CFG_MASK(x) ((0xF << (x * 4)) | BIT((x + 29)))
- #define SPEAR1310_SATA_CFG_MASK(x) ((0xF << (x * 4 + 16)) | \
- BIT((x + 29)))
- #define SPEAR1310_PCIE_CFG_VAL(x) \
- (SPEAR1310_PCIE_SATA##x##_SEL_PCIE | \
- SPEAR1310_PCIE##x##_CFG_AUX_CLK_EN | \
- SPEAR1310_PCIE##x##_CFG_CORE_CLK_EN | \
- SPEAR1310_PCIE##x##_CFG_POWERUP_RESET | \
- SPEAR1310_PCIE##x##_CFG_DEVICE_PRESENT)
- #define SPEAR1310_SATA_CFG_VAL(x) \
- (SPEAR1310_PCIE_SATA##x##_SEL_SATA | \
- SPEAR1310_SATA##x##_CFG_PM_CLK_EN | \
- SPEAR1310_SATA##x##_CFG_POWERUP_RESET | \
- SPEAR1310_SATA##x##_CFG_RX_CLK_EN | \
- SPEAR1310_SATA##x##_CFG_TX_CLK_EN)
-
-#define SPEAR1310_PCIE_MIPHY_CFG_1 0x3A8
- #define SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT BIT(31)
- #define SPEAR1310_MIPHY_DUAL_CLK_REF_DIV2 BIT(28)
- #define SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(x) (x << 16)
- #define SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT BIT(15)
- #define SPEAR1310_MIPHY_SINGLE_CLK_REF_DIV2 BIT(12)
- #define SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(x) (x << 0)
- #define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA_MASK (0xFFFF)
- #define SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK (0xFFFF << 16)
- #define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA \
- (SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT | \
- SPEAR1310_MIPHY_DUAL_CLK_REF_DIV2 | \
- SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(60) | \
- SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT | \
- SPEAR1310_MIPHY_SINGLE_CLK_REF_DIV2 | \
- SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(60))
- #define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
- (SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(120))
- #define SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE \
- (SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT | \
- SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(25) | \
- SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT | \
- SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(25))
-
-#define SPEAR1310_PCIE_MIPHY_CFG_2 0x3AC
-
-enum spear1310_miphy_mode {
- SATA,
- PCIE,
-};
-
-struct spear1310_miphy_priv {
- /* instance id of this phy */
- u32 id;
- /* phy mode: 0 for SATA 1 for PCIe */
- enum spear1310_miphy_mode mode;
- /* regmap for any soc specific misc registers */
- struct regmap *misc;
- /* phy struct pointer */
- struct phy *phy;
-};
-
-static int spear1310_miphy_pcie_init(struct spear1310_miphy_priv *priv)
-{
- u32 val;
-
- regmap_update_bits(priv->misc, SPEAR1310_PCIE_MIPHY_CFG_1,
- SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK,
- SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE);
-
- switch (priv->id) {
- case 0:
- val = SPEAR1310_PCIE_CFG_VAL(0);
- break;
- case 1:
- val = SPEAR1310_PCIE_CFG_VAL(1);
- break;
- case 2:
- val = SPEAR1310_PCIE_CFG_VAL(2);
- break;
- default:
- return -EINVAL;
- }
-
- regmap_update_bits(priv->misc, SPEAR1310_PCIE_SATA_CFG,
- SPEAR1310_PCIE_CFG_MASK(priv->id), val);
-
- return 0;
-}
-
-static int spear1310_miphy_pcie_exit(struct spear1310_miphy_priv *priv)
-{
- regmap_update_bits(priv->misc, SPEAR1310_PCIE_SATA_CFG,
- SPEAR1310_PCIE_CFG_MASK(priv->id), 0);
-
- regmap_update_bits(priv->misc, SPEAR1310_PCIE_MIPHY_CFG_1,
- SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK, 0);
-
- return 0;
-}
-
-static int spear1310_miphy_init(struct phy *phy)
-{
- struct spear1310_miphy_priv *priv = phy_get_drvdata(phy);
- int ret = 0;
-
- if (priv->mode == PCIE)
- ret = spear1310_miphy_pcie_init(priv);
-
- return ret;
-}
-
-static int spear1310_miphy_exit(struct phy *phy)
-{
- struct spear1310_miphy_priv *priv = phy_get_drvdata(phy);
- int ret = 0;
-
- if (priv->mode == PCIE)
- ret = spear1310_miphy_pcie_exit(priv);
-
- return ret;
-}
-
-static const struct of_device_id spear1310_miphy_of_match[] = {
- { .compatible = "st,spear1310-miphy" },
- { },
-};
-MODULE_DEVICE_TABLE(of, spear1310_miphy_of_match);
-
-static struct phy_ops spear1310_miphy_ops = {
- .init = spear1310_miphy_init,
- .exit = spear1310_miphy_exit,
- .owner = THIS_MODULE,
-};
-
-static struct phy *spear1310_miphy_xlate(struct device *dev,
- struct of_phandle_args *args)
-{
- struct spear1310_miphy_priv *priv = dev_get_drvdata(dev);
-
- if (args->args_count < 1) {
- dev_err(dev, "DT did not pass correct no of args\n");
- return NULL;
- }
-
- priv->mode = args->args[0];
-
- if (priv->mode != SATA && priv->mode != PCIE) {
- dev_err(dev, "DT did not pass correct phy mode\n");
- return NULL;
- }
-
- return priv->phy;
-}
-
-static int spear1310_miphy_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct spear1310_miphy_priv *priv;
- struct phy_provider *phy_provider;
-
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- priv->misc =
- syscon_regmap_lookup_by_phandle(dev->of_node, "misc");
- if (IS_ERR(priv->misc)) {
- dev_err(dev, "failed to find misc regmap\n");
- return PTR_ERR(priv->misc);
- }
-
- if (of_property_read_u32(dev->of_node, "phy-id", &priv->id)) {
- dev_err(dev, "failed to find phy id\n");
- return -EINVAL;
- }
-
- priv->phy = devm_phy_create(dev, NULL, &spear1310_miphy_ops, NULL);
- if (IS_ERR(priv->phy)) {
- dev_err(dev, "failed to create SATA PCIe PHY\n");
- return PTR_ERR(priv->phy);
- }
-
- dev_set_drvdata(dev, priv);
- phy_set_drvdata(priv->phy, priv);
-
- phy_provider =
- devm_of_phy_provider_register(dev, spear1310_miphy_xlate);
- if (IS_ERR(phy_provider)) {
- dev_err(dev, "failed to register phy provider\n");
- return PTR_ERR(phy_provider);
- }
-
- return 0;
-}
-
-static struct platform_driver spear1310_miphy_driver = {
- .probe = spear1310_miphy_probe,
- .driver = {
- .name = "spear1310-miphy",
- .of_match_table = of_match_ptr(spear1310_miphy_of_match),
- },
-};
-
-module_platform_driver(spear1310_miphy_driver);
-
-MODULE_DESCRIPTION("ST SPEAR1310-MIPHY driver");
-MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * ST spear1340-miphy driver
- *
- * Copyright (C) 2014 ST Microelectronics
- * Pratyush Anand <pratyush.anand@st.com>
- * Mohit Kumar <mohit.kumar@st.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/kernel.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/phy/phy.h>
-#include <linux/regmap.h>
-
-/* SPEAr1340 Registers */
-/* Power Management Registers */
-#define SPEAR1340_PCM_CFG 0x100
- #define SPEAR1340_PCM_CFG_SATA_POWER_EN BIT(11)
-#define SPEAR1340_PCM_WKUP_CFG 0x104
-#define SPEAR1340_SWITCH_CTR 0x108
-
-#define SPEAR1340_PERIP1_SW_RST 0x318
- #define SPEAR1340_PERIP1_SW_RSATA BIT(12)
-#define SPEAR1340_PERIP2_SW_RST 0x31C
-#define SPEAR1340_PERIP3_SW_RST 0x320
-
-/* PCIE - SATA configuration registers */
-#define SPEAR1340_PCIE_SATA_CFG 0x424
- /* PCIE CFG MASks */
- #define SPEAR1340_PCIE_CFG_DEVICE_PRESENT BIT(11)
- #define SPEAR1340_PCIE_CFG_POWERUP_RESET BIT(10)
- #define SPEAR1340_PCIE_CFG_CORE_CLK_EN BIT(9)
- #define SPEAR1340_PCIE_CFG_AUX_CLK_EN BIT(8)
- #define SPEAR1340_SATA_CFG_TX_CLK_EN BIT(4)
- #define SPEAR1340_SATA_CFG_RX_CLK_EN BIT(3)
- #define SPEAR1340_SATA_CFG_POWERUP_RESET BIT(2)
- #define SPEAR1340_SATA_CFG_PM_CLK_EN BIT(1)
- #define SPEAR1340_PCIE_SATA_SEL_PCIE (0)
- #define SPEAR1340_PCIE_SATA_SEL_SATA (1)
- #define SPEAR1340_PCIE_SATA_CFG_MASK 0xF1F
- #define SPEAR1340_PCIE_CFG_VAL (SPEAR1340_PCIE_SATA_SEL_PCIE | \
- SPEAR1340_PCIE_CFG_AUX_CLK_EN | \
- SPEAR1340_PCIE_CFG_CORE_CLK_EN | \
- SPEAR1340_PCIE_CFG_POWERUP_RESET | \
- SPEAR1340_PCIE_CFG_DEVICE_PRESENT)
- #define SPEAR1340_SATA_CFG_VAL (SPEAR1340_PCIE_SATA_SEL_SATA | \
- SPEAR1340_SATA_CFG_PM_CLK_EN | \
- SPEAR1340_SATA_CFG_POWERUP_RESET | \
- SPEAR1340_SATA_CFG_RX_CLK_EN | \
- SPEAR1340_SATA_CFG_TX_CLK_EN)
-
-#define SPEAR1340_PCIE_MIPHY_CFG 0x428
- #define SPEAR1340_MIPHY_OSC_BYPASS_EXT BIT(31)
- #define SPEAR1340_MIPHY_CLK_REF_DIV2 BIT(27)
- #define SPEAR1340_MIPHY_CLK_REF_DIV4 (2 << 27)
- #define SPEAR1340_MIPHY_CLK_REF_DIV8 (3 << 27)
- #define SPEAR1340_MIPHY_PLL_RATIO_TOP(x) (x << 0)
- #define SPEAR1340_PCIE_MIPHY_CFG_MASK 0xF80000FF
- #define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA \
- (SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
- SPEAR1340_MIPHY_CLK_REF_DIV2 | \
- SPEAR1340_MIPHY_PLL_RATIO_TOP(60))
- #define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
- (SPEAR1340_MIPHY_PLL_RATIO_TOP(120))
- #define SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE \
- (SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
- SPEAR1340_MIPHY_PLL_RATIO_TOP(25))
-
-enum spear1340_miphy_mode {
- SATA,
- PCIE,
-};
-
-struct spear1340_miphy_priv {
- /* phy mode: 0 for SATA 1 for PCIe */
- enum spear1340_miphy_mode mode;
- /* regmap for any soc specific misc registers */
- struct regmap *misc;
- /* phy struct pointer */
- struct phy *phy;
-};
-
-static int spear1340_miphy_sata_init(struct spear1340_miphy_priv *priv)
-{
- regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
- SPEAR1340_PCIE_SATA_CFG_MASK,
- SPEAR1340_SATA_CFG_VAL);
- regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
- SPEAR1340_PCIE_MIPHY_CFG_MASK,
- SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK);
- /* Switch on sata power domain */
- regmap_update_bits(priv->misc, SPEAR1340_PCM_CFG,
- SPEAR1340_PCM_CFG_SATA_POWER_EN,
- SPEAR1340_PCM_CFG_SATA_POWER_EN);
- /* Wait for SATA power domain on */
- msleep(20);
-
- /* Disable PCIE SATA Controller reset */
- regmap_update_bits(priv->misc, SPEAR1340_PERIP1_SW_RST,
- SPEAR1340_PERIP1_SW_RSATA, 0);
- /* Wait for SATA reset de-assert completion */
- msleep(20);
-
- return 0;
-}
-
-static int spear1340_miphy_sata_exit(struct spear1340_miphy_priv *priv)
-{
- regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
- SPEAR1340_PCIE_SATA_CFG_MASK, 0);
- regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
- SPEAR1340_PCIE_MIPHY_CFG_MASK, 0);
-
- /* Enable PCIE SATA Controller reset */
- regmap_update_bits(priv->misc, SPEAR1340_PERIP1_SW_RST,
- SPEAR1340_PERIP1_SW_RSATA,
- SPEAR1340_PERIP1_SW_RSATA);
- /* Wait for SATA power domain off */
- msleep(20);
- /* Switch off sata power domain */
- regmap_update_bits(priv->misc, SPEAR1340_PCM_CFG,
- SPEAR1340_PCM_CFG_SATA_POWER_EN, 0);
- /* Wait for SATA reset assert completion */
- msleep(20);
-
- return 0;
-}
-
-static int spear1340_miphy_pcie_init(struct spear1340_miphy_priv *priv)
-{
- regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
- SPEAR1340_PCIE_MIPHY_CFG_MASK,
- SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE);
- regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
- SPEAR1340_PCIE_SATA_CFG_MASK,
- SPEAR1340_PCIE_CFG_VAL);
-
- return 0;
-}
-
-static int spear1340_miphy_pcie_exit(struct spear1340_miphy_priv *priv)
-{
- regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
- SPEAR1340_PCIE_MIPHY_CFG_MASK, 0);
- regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
- SPEAR1340_PCIE_SATA_CFG_MASK, 0);
-
- return 0;
-}
-
-static int spear1340_miphy_init(struct phy *phy)
-{
- struct spear1340_miphy_priv *priv = phy_get_drvdata(phy);
- int ret = 0;
-
- if (priv->mode == SATA)
- ret = spear1340_miphy_sata_init(priv);
- else if (priv->mode == PCIE)
- ret = spear1340_miphy_pcie_init(priv);
-
- return ret;
-}
-
-static int spear1340_miphy_exit(struct phy *phy)
-{
- struct spear1340_miphy_priv *priv = phy_get_drvdata(phy);
- int ret = 0;
-
- if (priv->mode == SATA)
- ret = spear1340_miphy_sata_exit(priv);
- else if (priv->mode == PCIE)
- ret = spear1340_miphy_pcie_exit(priv);
-
- return ret;
-}
-
-static const struct of_device_id spear1340_miphy_of_match[] = {
- { .compatible = "st,spear1340-miphy" },
- { },
-};
-MODULE_DEVICE_TABLE(of, spear1340_miphy_of_match);
-
-static struct phy_ops spear1340_miphy_ops = {
- .init = spear1340_miphy_init,
- .exit = spear1340_miphy_exit,
- .owner = THIS_MODULE,
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int spear1340_miphy_suspend(struct device *dev)
-{
- struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
- int ret = 0;
-
- if (priv->mode == SATA)
- ret = spear1340_miphy_sata_exit(priv);
-
- return ret;
-}
-
-static int spear1340_miphy_resume(struct device *dev)
-{
- struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
- int ret = 0;
-
- if (priv->mode == SATA)
- ret = spear1340_miphy_sata_init(priv);
-
- return ret;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(spear1340_miphy_pm_ops, spear1340_miphy_suspend,
- spear1340_miphy_resume);
-
-static struct phy *spear1340_miphy_xlate(struct device *dev,
- struct of_phandle_args *args)
-{
- struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
-
- if (args->args_count < 1) {
- dev_err(dev, "DT did not pass correct no of args\n");
- return NULL;
- }
-
- priv->mode = args->args[0];
-
- if (priv->mode != SATA && priv->mode != PCIE) {
- dev_err(dev, "DT did not pass correct phy mode\n");
- return NULL;
- }
-
- return priv->phy;
-}
-
-static int spear1340_miphy_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct spear1340_miphy_priv *priv;
- struct phy_provider *phy_provider;
-
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- priv->misc =
- syscon_regmap_lookup_by_phandle(dev->of_node, "misc");
- if (IS_ERR(priv->misc)) {
- dev_err(dev, "failed to find misc regmap\n");
- return PTR_ERR(priv->misc);
- }
-
- priv->phy = devm_phy_create(dev, NULL, &spear1340_miphy_ops, NULL);
- if (IS_ERR(priv->phy)) {
- dev_err(dev, "failed to create SATA PCIe PHY\n");
- return PTR_ERR(priv->phy);
- }
-
- dev_set_drvdata(dev, priv);
- phy_set_drvdata(priv->phy, priv);
-
- phy_provider =
- devm_of_phy_provider_register(dev, spear1340_miphy_xlate);
- if (IS_ERR(phy_provider)) {
- dev_err(dev, "failed to register phy provider\n");
- return PTR_ERR(phy_provider);
- }
-
- return 0;
-}
-
-static struct platform_driver spear1340_miphy_driver = {
- .probe = spear1340_miphy_probe,
- .driver = {
- .name = "spear1340-miphy",
- .pm = &spear1340_miphy_pm_ops,
- .of_match_table = of_match_ptr(spear1340_miphy_of_match),
- },
-};
-
-module_platform_driver(spear1340_miphy_driver);
-
-MODULE_DESCRIPTION("ST SPEAR1340-MIPHY driver");
-MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * Copyright (C) 2014 STMicroelectronics
- *
- * STMicroelectronics Generic PHY driver for STiH407 USB2.
- *
- * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2, as
- * published by the Free Software Foundation.
- *
- */
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/clk.h>
-#include <linux/regmap.h>
-#include <linux/reset.h>
-#include <linux/mfd/syscon.h>
-#include <linux/phy/phy.h>
-
-/* Default PHY_SEL and REFCLKSEL configuration */
-#define STIH407_USB_PICOPHY_CTRL_PORT_CONF 0x6
-#define STIH407_USB_PICOPHY_CTRL_PORT_MASK 0x1f
-
-/* ports parameters overriding */
-#define STIH407_USB_PICOPHY_PARAM_DEF 0x39a4dc
-#define STIH407_USB_PICOPHY_PARAM_MASK 0xffffffff
-
-struct stih407_usb2_picophy {
- struct phy *phy;
- struct regmap *regmap;
- struct device *dev;
- struct reset_control *rstc;
- struct reset_control *rstport;
- int ctrl;
- int param;
-};
-
-static int stih407_usb2_pico_ctrl(struct stih407_usb2_picophy *phy_dev)
-{
- reset_control_deassert(phy_dev->rstc);
-
- return regmap_update_bits(phy_dev->regmap, phy_dev->ctrl,
- STIH407_USB_PICOPHY_CTRL_PORT_MASK,
- STIH407_USB_PICOPHY_CTRL_PORT_CONF);
-}
-
-static int stih407_usb2_init_port(struct phy *phy)
-{
- int ret;
- struct stih407_usb2_picophy *phy_dev = phy_get_drvdata(phy);
-
- stih407_usb2_pico_ctrl(phy_dev);
-
- ret = regmap_update_bits(phy_dev->regmap,
- phy_dev->param,
- STIH407_USB_PICOPHY_PARAM_MASK,
- STIH407_USB_PICOPHY_PARAM_DEF);
- if (ret)
- return ret;
-
- return reset_control_deassert(phy_dev->rstport);
-}
-
-static int stih407_usb2_exit_port(struct phy *phy)
-{
- struct stih407_usb2_picophy *phy_dev = phy_get_drvdata(phy);
-
- /*
- * Only port reset is asserted, phy global reset is kept untouched
- * as other ports may still be active. When all ports are in reset
- * state, assumption is made that power will be cut off on the phy, in
- * case of suspend for instance. Theoretically, asserting individual
- * reset (like here) or global reset should be equivalent.
- */
- return reset_control_assert(phy_dev->rstport);
-}
-
-static const struct phy_ops stih407_usb2_picophy_data = {
- .init = stih407_usb2_init_port,
- .exit = stih407_usb2_exit_port,
- .owner = THIS_MODULE,
-};
-
-static int stih407_usb2_picophy_probe(struct platform_device *pdev)
-{
- struct stih407_usb2_picophy *phy_dev;
- struct device *dev = &pdev->dev;
- struct device_node *np = dev->of_node;
- struct phy_provider *phy_provider;
- struct phy *phy;
- struct resource *res;
-
- phy_dev = devm_kzalloc(dev, sizeof(*phy_dev), GFP_KERNEL);
- if (!phy_dev)
- return -ENOMEM;
-
- phy_dev->dev = dev;
- dev_set_drvdata(dev, phy_dev);
-
- phy_dev->rstc = devm_reset_control_get(dev, "global");
- if (IS_ERR(phy_dev->rstc)) {
- dev_err(dev, "failed to ctrl picoPHY reset\n");
- return PTR_ERR(phy_dev->rstc);
- }
-
- phy_dev->rstport = devm_reset_control_get(dev, "port");
- if (IS_ERR(phy_dev->rstport)) {
- dev_err(dev, "failed to ctrl picoPHY reset\n");
- return PTR_ERR(phy_dev->rstport);
- }
-
- /* Reset port by default: only deassert it in phy init */
- reset_control_assert(phy_dev->rstport);
-
- phy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
- if (IS_ERR(phy_dev->regmap)) {
- dev_err(dev, "No syscfg phandle specified\n");
- return PTR_ERR(phy_dev->regmap);
- }
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl");
- if (!res) {
- dev_err(dev, "No ctrl reg found\n");
- return -ENXIO;
- }
- phy_dev->ctrl = res->start;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "param");
- if (!res) {
- dev_err(dev, "No param reg found\n");
- return -ENXIO;
- }
- phy_dev->param = res->start;
-
- phy = devm_phy_create(dev, NULL, &stih407_usb2_picophy_data, NULL);
- if (IS_ERR(phy)) {
- dev_err(dev, "failed to create Display Port PHY\n");
- return PTR_ERR(phy);
- }
-
- phy_dev->phy = phy;
- phy_set_drvdata(phy, phy_dev);
-
- phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
- if (IS_ERR(phy_provider))
- return PTR_ERR(phy_provider);
-
- dev_info(dev, "STiH407 USB Generic picoPHY driver probed!");
-
- return 0;
-}
-
-static const struct of_device_id stih407_usb2_picophy_of_match[] = {
- { .compatible = "st,stih407-usb2-phy" },
- { /*sentinel */ },
-};
-
-MODULE_DEVICE_TABLE(of, stih407_usb2_picophy_of_match);
-
-static struct platform_driver stih407_usb2_picophy_driver = {
- .probe = stih407_usb2_picophy_probe,
- .driver = {
- .name = "stih407-usb-genphy",
- .of_match_table = stih407_usb2_picophy_of_match,
- }
-};
-
-module_platform_driver(stih407_usb2_picophy_driver);
-
-MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
-MODULE_DESCRIPTION("STMicroelectronics Generic picoPHY driver for STiH407");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * Copyright (C) 2014 STMicroelectronics
- *
- * STMicroelectronics PHY driver for STiH41x USB.
- *
- * Author: Maxime Coquelin <maxime.coquelin@st.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2, as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/clk.h>
-#include <linux/phy/phy.h>
-#include <linux/regmap.h>
-#include <linux/mfd/syscon.h>
-
-#define SYSCFG332 0x80
-#define SYSCFG2520 0x820
-
-/**
- * struct stih41x_usb_cfg - SoC specific PHY register mapping
- * @syscfg: Offset in syscfg registers bank
- * @cfg_mask: Bits mask for PHY configuration
- * @cfg: Static configuration value for PHY
- * @oscok: Notify the PHY oscillator clock is ready
- * Setting this bit enable the PHY
- */
-struct stih41x_usb_cfg {
- u32 syscfg;
- u32 cfg_mask;
- u32 cfg;
- u32 oscok;
-};
-
-/**
- * struct stih41x_usb_phy - Private data for the PHY
- * @dev: device for this controller
- * @regmap: Syscfg registers bank in which PHY is configured
- * @cfg: SoC specific PHY register mapping
- * @clk: Oscillator used by the PHY
- */
-struct stih41x_usb_phy {
- struct device *dev;
- struct regmap *regmap;
- const struct stih41x_usb_cfg *cfg;
- struct clk *clk;
-};
-
-static struct stih41x_usb_cfg stih415_usb_phy_cfg = {
- .syscfg = SYSCFG332,
- .cfg_mask = 0x3f,
- .cfg = 0x38,
- .oscok = BIT(6),
-};
-
-static struct stih41x_usb_cfg stih416_usb_phy_cfg = {
- .syscfg = SYSCFG2520,
- .cfg_mask = 0x33f,
- .cfg = 0x238,
- .oscok = BIT(6),
-};
-
-static int stih41x_usb_phy_init(struct phy *phy)
-{
- struct stih41x_usb_phy *phy_dev = phy_get_drvdata(phy);
-
- return regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg,
- phy_dev->cfg->cfg_mask, phy_dev->cfg->cfg);
-}
-
-static int stih41x_usb_phy_power_on(struct phy *phy)
-{
- struct stih41x_usb_phy *phy_dev = phy_get_drvdata(phy);
- int ret;
-
- ret = clk_prepare_enable(phy_dev->clk);
- if (ret) {
- dev_err(phy_dev->dev, "Failed to enable osc_phy clock\n");
- return ret;
- }
-
- return regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg,
- phy_dev->cfg->oscok, phy_dev->cfg->oscok);
-}
-
-static int stih41x_usb_phy_power_off(struct phy *phy)
-{
- struct stih41x_usb_phy *phy_dev = phy_get_drvdata(phy);
- int ret;
-
- ret = regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg,
- phy_dev->cfg->oscok, 0);
- if (ret) {
- dev_err(phy_dev->dev, "Failed to clear oscok bit\n");
- return ret;
- }
-
- clk_disable_unprepare(phy_dev->clk);
-
- return 0;
-}
-
-static struct phy_ops stih41x_usb_phy_ops = {
- .init = stih41x_usb_phy_init,
- .power_on = stih41x_usb_phy_power_on,
- .power_off = stih41x_usb_phy_power_off,
- .owner = THIS_MODULE,
-};
-
-static const struct of_device_id stih41x_usb_phy_of_match[];
-
-static int stih41x_usb_phy_probe(struct platform_device *pdev)
-{
- struct device_node *np = pdev->dev.of_node;
- const struct of_device_id *match;
- struct stih41x_usb_phy *phy_dev;
- struct device *dev = &pdev->dev;
- struct phy_provider *phy_provider;
- struct phy *phy;
-
- phy_dev = devm_kzalloc(dev, sizeof(*phy_dev), GFP_KERNEL);
- if (!phy_dev)
- return -ENOMEM;
-
- match = of_match_device(stih41x_usb_phy_of_match, &pdev->dev);
- if (!match)
- return -ENODEV;
-
- phy_dev->cfg = match->data;
-
- phy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
- if (IS_ERR(phy_dev->regmap)) {
- dev_err(dev, "No syscfg phandle specified\n");
- return PTR_ERR(phy_dev->regmap);
- }
-
- phy_dev->clk = devm_clk_get(dev, "osc_phy");
- if (IS_ERR(phy_dev->clk)) {
- dev_err(dev, "osc_phy clk not found\n");
- return PTR_ERR(phy_dev->clk);
- }
-
- phy = devm_phy_create(dev, NULL, &stih41x_usb_phy_ops, NULL);
-
- if (IS_ERR(phy)) {
- dev_err(dev, "failed to create phy\n");
- return PTR_ERR(phy);
- }
-
- phy_dev->dev = dev;
-
- phy_set_drvdata(phy, phy_dev);
-
- phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
- if (IS_ERR(phy_provider))
- return PTR_ERR(phy_provider);
-
- return 0;
-}
-
-static const struct of_device_id stih41x_usb_phy_of_match[] = {
- { .compatible = "st,stih415-usb-phy", .data = &stih415_usb_phy_cfg },
- { .compatible = "st,stih416-usb-phy", .data = &stih416_usb_phy_cfg },
- { /* sentinel */ },
-};
-MODULE_DEVICE_TABLE(of, stih41x_usb_phy_of_match);
-
-static struct platform_driver stih41x_usb_phy_driver = {
- .probe = stih41x_usb_phy_probe,
- .driver = {
- .name = "stih41x-usb-phy",
- .of_match_table = stih41x_usb_phy_of_match,
- }
-};
-module_platform_driver(stih41x_usb_phy_driver);
-
-MODULE_AUTHOR("Maxime Coquelin <maxime.coquelin@st.com>");
-MODULE_DESCRIPTION("STMicroelectronics USB PHY driver for STiH41x series");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * Allwinner sun4i USB phy driver
- *
- * Copyright (C) 2014 Hans de Goede <hdegoede@redhat.com>
- *
- * Based on code from
- * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
- *
- * Modelled after: Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY driver
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-#include <linux/reset.h>
-
-#define REG_ISCR 0x00
-#define REG_PHYCTL 0x04
-#define REG_PHYBIST 0x08
-#define REG_PHYTUNE 0x0c
-
-#define PHYCTL_DATA BIT(7)
-
-#define SUNXI_AHB_ICHR8_EN BIT(10)
-#define SUNXI_AHB_INCR4_BURST_EN BIT(9)
-#define SUNXI_AHB_INCRX_ALIGN_EN BIT(8)
-#define SUNXI_ULPI_BYPASS_EN BIT(0)
-
-/* Common Control Bits for Both PHYs */
-#define PHY_PLL_BW 0x03
-#define PHY_RES45_CAL_EN 0x0c
-
-/* Private Control Bits for Each PHY */
-#define PHY_TX_AMPLITUDE_TUNE 0x20
-#define PHY_TX_SLEWRATE_TUNE 0x22
-#define PHY_VBUSVALID_TH_SEL 0x25
-#define PHY_PULLUP_RES_SEL 0x27
-#define PHY_OTG_FUNC_EN 0x28
-#define PHY_VBUS_DET_EN 0x29
-#define PHY_DISCON_TH_SEL 0x2a
-
-#define MAX_PHYS 3
-
-struct sun4i_usb_phy_data {
- void __iomem *base;
- struct mutex mutex;
- int num_phys;
- u32 disc_thresh;
- struct sun4i_usb_phy {
- struct phy *phy;
- void __iomem *pmu;
- struct regulator *vbus;
- struct reset_control *reset;
- struct clk *clk;
- int index;
- } phys[MAX_PHYS];
-};
-
-#define to_sun4i_usb_phy_data(phy) \
- container_of((phy), struct sun4i_usb_phy_data, phys[(phy)->index])
-
-static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
- int len)
-{
- struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy);
- u32 temp, usbc_bit = BIT(phy->index * 2);
- int i;
-
- mutex_lock(&phy_data->mutex);
-
- for (i = 0; i < len; i++) {
- temp = readl(phy_data->base + REG_PHYCTL);
-
- /* clear the address portion */
- temp &= ~(0xff << 8);
-
- /* set the address */
- temp |= ((addr + i) << 8);
- writel(temp, phy_data->base + REG_PHYCTL);
-
- /* set the data bit and clear usbc bit*/
- temp = readb(phy_data->base + REG_PHYCTL);
- if (data & 0x1)
- temp |= PHYCTL_DATA;
- else
- temp &= ~PHYCTL_DATA;
- temp &= ~usbc_bit;
- writeb(temp, phy_data->base + REG_PHYCTL);
-
- /* pulse usbc_bit */
- temp = readb(phy_data->base + REG_PHYCTL);
- temp |= usbc_bit;
- writeb(temp, phy_data->base + REG_PHYCTL);
-
- temp = readb(phy_data->base + REG_PHYCTL);
- temp &= ~usbc_bit;
- writeb(temp, phy_data->base + REG_PHYCTL);
-
- data >>= 1;
- }
- mutex_unlock(&phy_data->mutex);
-}
-
-static void sun4i_usb_phy_passby(struct sun4i_usb_phy *phy, int enable)
-{
- u32 bits, reg_value;
-
- if (!phy->pmu)
- return;
-
- bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN |
- SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_EN;
-
- reg_value = readl(phy->pmu);
-
- if (enable)
- reg_value |= bits;
- else
- reg_value &= ~bits;
-
- writel(reg_value, phy->pmu);
-}
-
-static int sun4i_usb_phy_init(struct phy *_phy)
-{
- struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
- struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
- int ret;
-
- ret = clk_prepare_enable(phy->clk);
- if (ret)
- return ret;
-
- ret = reset_control_deassert(phy->reset);
- if (ret) {
- clk_disable_unprepare(phy->clk);
- return ret;
- }
-
- /* Adjust PHY's magnitude and rate */
- sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5);
-
- /* Disconnect threshold adjustment */
- sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, data->disc_thresh, 2);
-
- sun4i_usb_phy_passby(phy, 1);
-
- return 0;
-}
-
-static int sun4i_usb_phy_exit(struct phy *_phy)
-{
- struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
-
- sun4i_usb_phy_passby(phy, 0);
- reset_control_assert(phy->reset);
- clk_disable_unprepare(phy->clk);
-
- return 0;
-}
-
-static int sun4i_usb_phy_power_on(struct phy *_phy)
-{
- struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
- int ret = 0;
-
- if (phy->vbus)
- ret = regulator_enable(phy->vbus);
-
- return ret;
-}
-
-static int sun4i_usb_phy_power_off(struct phy *_phy)
-{
- struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
-
- if (phy->vbus)
- regulator_disable(phy->vbus);
-
- return 0;
-}
-
-static struct phy_ops sun4i_usb_phy_ops = {
- .init = sun4i_usb_phy_init,
- .exit = sun4i_usb_phy_exit,
- .power_on = sun4i_usb_phy_power_on,
- .power_off = sun4i_usb_phy_power_off,
- .owner = THIS_MODULE,
-};
-
-static struct phy *sun4i_usb_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
-{
- struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
-
- if (WARN_ON(args->args[0] == 0 || args->args[0] >= data->num_phys))
- return ERR_PTR(-ENODEV);
-
- return data->phys[args->args[0]].phy;
-}
-
-static int sun4i_usb_phy_probe(struct platform_device *pdev)
-{
- struct sun4i_usb_phy_data *data;
- struct device *dev = &pdev->dev;
- struct device_node *np = dev->of_node;
- struct phy_provider *phy_provider;
- bool dedicated_clocks;
- struct resource *res;
- int i;
-
- data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- mutex_init(&data->mutex);
-
- if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy"))
- data->num_phys = 2;
- else
- data->num_phys = 3;
-
- if (of_device_is_compatible(np, "allwinner,sun4i-a10-usb-phy"))
- data->disc_thresh = 3;
- else
- data->disc_thresh = 2;
-
- if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy"))
- dedicated_clocks = true;
- else
- dedicated_clocks = false;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
- data->base = devm_ioremap_resource(dev, res);
- if (IS_ERR(data->base))
- return PTR_ERR(data->base);
-
- /* Skip 0, 0 is the phy for otg which is not yet supported. */
- for (i = 1; i < data->num_phys; i++) {
- struct sun4i_usb_phy *phy = data->phys + i;
- char name[16];
-
- snprintf(name, sizeof(name), "usb%d_vbus", i);
- phy->vbus = devm_regulator_get_optional(dev, name);
- if (IS_ERR(phy->vbus)) {
- if (PTR_ERR(phy->vbus) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
- phy->vbus = NULL;
- }
-
- if (dedicated_clocks)
- snprintf(name, sizeof(name), "usb%d_phy", i);
- else
- strlcpy(name, "usb_phy", sizeof(name));
-
- phy->clk = devm_clk_get(dev, name);
- if (IS_ERR(phy->clk)) {
- dev_err(dev, "failed to get clock %s\n", name);
- return PTR_ERR(phy->clk);
- }
-
- snprintf(name, sizeof(name), "usb%d_reset", i);
- phy->reset = devm_reset_control_get(dev, name);
- if (IS_ERR(phy->reset)) {
- dev_err(dev, "failed to get reset %s\n", name);
- return PTR_ERR(phy->reset);
- }
-
- if (i) { /* No pmu for usbc0 */
- snprintf(name, sizeof(name), "pmu%d", i);
- res = platform_get_resource_byname(pdev,
- IORESOURCE_MEM, name);
- phy->pmu = devm_ioremap_resource(dev, res);
- if (IS_ERR(phy->pmu))
- return PTR_ERR(phy->pmu);
- }
-
- phy->phy = devm_phy_create(dev, NULL, &sun4i_usb_phy_ops, NULL);
- if (IS_ERR(phy->phy)) {
- dev_err(dev, "failed to create PHY %d\n", i);
- return PTR_ERR(phy->phy);
- }
-
- phy->index = i;
- phy_set_drvdata(phy->phy, &data->phys[i]);
- }
-
- dev_set_drvdata(dev, data);
- phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate);
-
- return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static const struct of_device_id sun4i_usb_phy_of_match[] = {
- { .compatible = "allwinner,sun4i-a10-usb-phy" },
- { .compatible = "allwinner,sun5i-a13-usb-phy" },
- { .compatible = "allwinner,sun6i-a31-usb-phy" },
- { .compatible = "allwinner,sun7i-a20-usb-phy" },
- { },
-};
-MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
-
-static struct platform_driver sun4i_usb_phy_driver = {
- .probe = sun4i_usb_phy_probe,
- .driver = {
- .of_match_table = sun4i_usb_phy_of_match,
- .name = "sun4i-usb-phy",
- }
-};
-module_platform_driver(sun4i_usb_phy_driver);
-
-MODULE_DESCRIPTION("Allwinner sun4i USB phy driver");
-MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * phy-ti-pipe3 - PIPE3 PHY driver.
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Author: Kishon Vijay Abraham I <kishon@ti.com>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/phy/phy.h>
-#include <linux/of.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/pm_runtime.h>
-#include <linux/delay.h>
-#include <linux/phy/omap_control_phy.h>
-#include <linux/of_platform.h>
-
-#define PLL_STATUS 0x00000004
-#define PLL_GO 0x00000008
-#define PLL_CONFIGURATION1 0x0000000C
-#define PLL_CONFIGURATION2 0x00000010
-#define PLL_CONFIGURATION3 0x00000014
-#define PLL_CONFIGURATION4 0x00000020
-
-#define PLL_REGM_MASK 0x001FFE00
-#define PLL_REGM_SHIFT 0x9
-#define PLL_REGM_F_MASK 0x0003FFFF
-#define PLL_REGM_F_SHIFT 0x0
-#define PLL_REGN_MASK 0x000001FE
-#define PLL_REGN_SHIFT 0x1
-#define PLL_SELFREQDCO_MASK 0x0000000E
-#define PLL_SELFREQDCO_SHIFT 0x1
-#define PLL_SD_MASK 0x0003FC00
-#define PLL_SD_SHIFT 10
-#define SET_PLL_GO 0x1
-#define PLL_LDOPWDN BIT(15)
-#define PLL_TICOPWDN BIT(16)
-#define PLL_LOCK 0x2
-#define PLL_IDLE 0x1
-
-/*
- * This is an Empirical value that works, need to confirm the actual
- * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status
- * to be correctly reflected in the PIPE3PHY_PLL_STATUS register.
- */
-#define PLL_IDLE_TIME 100 /* in milliseconds */
-#define PLL_LOCK_TIME 100 /* in milliseconds */
-
-struct pipe3_dpll_params {
- u16 m;
- u8 n;
- u8 freq:3;
- u8 sd;
- u32 mf;
-};
-
-struct pipe3_dpll_map {
- unsigned long rate;
- struct pipe3_dpll_params params;
-};
-
-struct ti_pipe3 {
- void __iomem *pll_ctrl_base;
- struct device *dev;
- struct device *control_dev;
- struct clk *wkupclk;
- struct clk *sys_clk;
- struct clk *refclk;
- struct clk *div_clk;
- struct pipe3_dpll_map *dpll_map;
- u8 id;
-};
-
-static struct pipe3_dpll_map dpll_map_usb[] = {
- {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */
- {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */
- {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */
- {20000000, {1000, 7, 4, 10, 0} }, /* 20 MHz */
- {26000000, {1250, 12, 4, 20, 0} }, /* 26 MHz */
- {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */
- { }, /* Terminator */
-};
-
-static struct pipe3_dpll_map dpll_map_sata[] = {
- {12000000, {1000, 7, 4, 6, 0} }, /* 12 MHz */
- {16800000, {714, 7, 4, 6, 0} }, /* 16.8 MHz */
- {19200000, {625, 7, 4, 6, 0} }, /* 19.2 MHz */
- {20000000, {600, 7, 4, 6, 0} }, /* 20 MHz */
- {26000000, {461, 7, 4, 6, 0} }, /* 26 MHz */
- {38400000, {312, 7, 4, 6, 0} }, /* 38.4 MHz */
- { }, /* Terminator */
-};
-
-static inline u32 ti_pipe3_readl(void __iomem *addr, unsigned offset)
-{
- return __raw_readl(addr + offset);
-}
-
-static inline void ti_pipe3_writel(void __iomem *addr, unsigned offset,
- u32 data)
-{
- __raw_writel(data, addr + offset);
-}
-
-static struct pipe3_dpll_params *ti_pipe3_get_dpll_params(struct ti_pipe3 *phy)
-{
- unsigned long rate;
- struct pipe3_dpll_map *dpll_map = phy->dpll_map;
-
- rate = clk_get_rate(phy->sys_clk);
-
- for (; dpll_map->rate; dpll_map++) {
- if (rate == dpll_map->rate)
- return &dpll_map->params;
- }
-
- dev_err(phy->dev, "No DPLL configuration for %lu Hz SYS CLK\n", rate);
-
- return NULL;
-}
-
-static int ti_pipe3_power_off(struct phy *x)
-{
- struct ti_pipe3 *phy = phy_get_drvdata(x);
-
- omap_control_phy_power(phy->control_dev, 0);
-
- return 0;
-}
-
-static int ti_pipe3_power_on(struct phy *x)
-{
- struct ti_pipe3 *phy = phy_get_drvdata(x);
-
- omap_control_phy_power(phy->control_dev, 1);
-
- return 0;
-}
-
-static int ti_pipe3_dpll_wait_lock(struct ti_pipe3 *phy)
-{
- u32 val;
- unsigned long timeout;
-
- timeout = jiffies + msecs_to_jiffies(PLL_LOCK_TIME);
- do {
- cpu_relax();
- val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
- if (val & PLL_LOCK)
- break;
- } while (!time_after(jiffies, timeout));
-
- if (!(val & PLL_LOCK)) {
- dev_err(phy->dev, "DPLL failed to lock\n");
- return -EBUSY;
- }
-
- return 0;
-}
-
-static int ti_pipe3_dpll_program(struct ti_pipe3 *phy)
-{
- u32 val;
- struct pipe3_dpll_params *dpll_params;
-
- dpll_params = ti_pipe3_get_dpll_params(phy);
- if (!dpll_params)
- return -EINVAL;
-
- val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
- val &= ~PLL_REGN_MASK;
- val |= dpll_params->n << PLL_REGN_SHIFT;
- ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
-
- val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
- val &= ~PLL_SELFREQDCO_MASK;
- val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
- ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
-
- val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
- val &= ~PLL_REGM_MASK;
- val |= dpll_params->m << PLL_REGM_SHIFT;
- ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
-
- val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
- val &= ~PLL_REGM_F_MASK;
- val |= dpll_params->mf << PLL_REGM_F_SHIFT;
- ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
-
- val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
- val &= ~PLL_SD_MASK;
- val |= dpll_params->sd << PLL_SD_SHIFT;
- ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
-
- ti_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
-
- return ti_pipe3_dpll_wait_lock(phy);
-}
-
-static int ti_pipe3_init(struct phy *x)
-{
- struct ti_pipe3 *phy = phy_get_drvdata(x);
- u32 val;
- int ret = 0;
-
- if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) {
- omap_control_pcie_pcs(phy->control_dev, phy->id, 0xF1);
- return 0;
- }
-
- /* Bring it out of IDLE if it is IDLE */
- val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
- if (val & PLL_IDLE) {
- val &= ~PLL_IDLE;
- ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
- ret = ti_pipe3_dpll_wait_lock(phy);
- }
-
- /* Program the DPLL only if not locked */
- val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
- if (!(val & PLL_LOCK))
- if (ti_pipe3_dpll_program(phy))
- return -EINVAL;
-
- return ret;
-}
-
-static int ti_pipe3_exit(struct phy *x)
-{
- struct ti_pipe3 *phy = phy_get_drvdata(x);
- u32 val;
- unsigned long timeout;
-
- /* SATA DPLL can't be powered down due to Errata i783 and PCIe
- * does not have internal DPLL
- */
- if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") ||
- of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie"))
- return 0;
-
- /* Put DPLL in IDLE mode */
- val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
- val |= PLL_IDLE;
- ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
-
- /* wait for LDO and Oscillator to power down */
- timeout = jiffies + msecs_to_jiffies(PLL_IDLE_TIME);
- do {
- cpu_relax();
- val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
- if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN))
- break;
- } while (!time_after(jiffies, timeout));
-
- if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) {
- dev_err(phy->dev, "Failed to power down: PLL_STATUS 0x%x\n",
- val);
- return -EBUSY;
- }
-
- return 0;
-}
-static struct phy_ops ops = {
- .init = ti_pipe3_init,
- .exit = ti_pipe3_exit,
- .power_on = ti_pipe3_power_on,
- .power_off = ti_pipe3_power_off,
- .owner = THIS_MODULE,
-};
-
-#ifdef CONFIG_OF
-static const struct of_device_id ti_pipe3_id_table[];
-#endif
-
-static int ti_pipe3_probe(struct platform_device *pdev)
-{
- struct ti_pipe3 *phy;
- struct phy *generic_phy;
- struct phy_provider *phy_provider;
- struct resource *res;
- struct device_node *node = pdev->dev.of_node;
- struct device_node *control_node;
- struct platform_device *control_pdev;
- const struct of_device_id *match;
- struct clk *clk;
-
- phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
- if (!phy)
- return -ENOMEM;
-
- phy->dev = &pdev->dev;
-
- if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
- match = of_match_device(of_match_ptr(ti_pipe3_id_table),
- &pdev->dev);
- if (!match)
- return -EINVAL;
-
- phy->dpll_map = (struct pipe3_dpll_map *)match->data;
- if (!phy->dpll_map) {
- dev_err(&pdev->dev, "no DPLL data\n");
- return -EINVAL;
- }
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "pll_ctrl");
- phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(phy->pll_ctrl_base))
- return PTR_ERR(phy->pll_ctrl_base);
-
- phy->sys_clk = devm_clk_get(phy->dev, "sysclk");
- if (IS_ERR(phy->sys_clk)) {
- dev_err(&pdev->dev, "unable to get sysclk\n");
- return -EINVAL;
- }
- }
-
- if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
- phy->wkupclk = devm_clk_get(phy->dev, "wkupclk");
- if (IS_ERR(phy->wkupclk)) {
- dev_err(&pdev->dev, "unable to get wkupclk\n");
- return PTR_ERR(phy->wkupclk);
- }
-
- phy->refclk = devm_clk_get(phy->dev, "refclk");
- if (IS_ERR(phy->refclk)) {
- dev_err(&pdev->dev, "unable to get refclk\n");
- return PTR_ERR(phy->refclk);
- }
- } else {
- phy->wkupclk = ERR_PTR(-ENODEV);
- phy->refclk = ERR_PTR(-ENODEV);
- }
-
- if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
- if (of_property_read_u8(node, "id", &phy->id) < 0)
- phy->id = 1;
-
- clk = devm_clk_get(phy->dev, "dpll_ref");
- if (IS_ERR(clk)) {
- dev_err(&pdev->dev, "unable to get dpll ref clk\n");
- return PTR_ERR(clk);
- }
- clk_set_rate(clk, 1500000000);
-
- clk = devm_clk_get(phy->dev, "dpll_ref_m2");
- if (IS_ERR(clk)) {
- dev_err(&pdev->dev, "unable to get dpll ref m2 clk\n");
- return PTR_ERR(clk);
- }
- clk_set_rate(clk, 100000000);
-
- clk = devm_clk_get(phy->dev, "phy-div");
- if (IS_ERR(clk)) {
- dev_err(&pdev->dev, "unable to get phy-div clk\n");
- return PTR_ERR(clk);
- }
- clk_set_rate(clk, 100000000);
-
- phy->div_clk = devm_clk_get(phy->dev, "div-clk");
- if (IS_ERR(phy->div_clk)) {
- dev_err(&pdev->dev, "unable to get div-clk\n");
- return PTR_ERR(phy->div_clk);
- }
- } else {
- phy->div_clk = ERR_PTR(-ENODEV);
- }
-
- control_node = of_parse_phandle(node, "ctrl-module", 0);
- if (!control_node) {
- dev_err(&pdev->dev, "Failed to get control device phandle\n");
- return -EINVAL;
- }
-
- control_pdev = of_find_device_by_node(control_node);
- if (!control_pdev) {
- dev_err(&pdev->dev, "Failed to get control device\n");
- return -EINVAL;
- }
-
- phy->control_dev = &control_pdev->dev;
-
- omap_control_phy_power(phy->control_dev, 0);
-
- platform_set_drvdata(pdev, phy);
- pm_runtime_enable(phy->dev);
-
- generic_phy = devm_phy_create(phy->dev, NULL, &ops, NULL);
- if (IS_ERR(generic_phy))
- return PTR_ERR(generic_phy);
-
- phy_set_drvdata(generic_phy, phy);
- phy_provider = devm_of_phy_provider_register(phy->dev,
- of_phy_simple_xlate);
- if (IS_ERR(phy_provider))
- return PTR_ERR(phy_provider);
-
- pm_runtime_get(&pdev->dev);
-
- return 0;
-}
-
-static int ti_pipe3_remove(struct platform_device *pdev)
-{
- if (!pm_runtime_suspended(&pdev->dev))
- pm_runtime_put(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
-
- return 0;
-}
-
-#ifdef CONFIG_PM_RUNTIME
-
-static int ti_pipe3_runtime_suspend(struct device *dev)
-{
- struct ti_pipe3 *phy = dev_get_drvdata(dev);
-
- if (!IS_ERR(phy->wkupclk))
- clk_disable_unprepare(phy->wkupclk);
- if (!IS_ERR(phy->refclk))
- clk_disable_unprepare(phy->refclk);
- if (!IS_ERR(phy->div_clk))
- clk_disable_unprepare(phy->div_clk);
-
- return 0;
-}
-
-static int ti_pipe3_runtime_resume(struct device *dev)
-{
- u32 ret = 0;
- struct ti_pipe3 *phy = dev_get_drvdata(dev);
-
- if (!IS_ERR(phy->refclk)) {
- ret = clk_prepare_enable(phy->refclk);
- if (ret) {
- dev_err(phy->dev, "Failed to enable refclk %d\n", ret);
- goto err1;
- }
- }
-
- if (!IS_ERR(phy->wkupclk)) {
- ret = clk_prepare_enable(phy->wkupclk);
- if (ret) {
- dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
- goto err2;
- }
- }
-
- if (!IS_ERR(phy->div_clk)) {
- ret = clk_prepare_enable(phy->div_clk);
- if (ret) {
- dev_err(phy->dev, "Failed to enable div_clk %d\n", ret);
- goto err3;
- }
- }
- return 0;
-
-err3:
- if (!IS_ERR(phy->wkupclk))
- clk_disable_unprepare(phy->wkupclk);
-
-err2:
- if (!IS_ERR(phy->refclk))
- clk_disable_unprepare(phy->refclk);
-
-err1:
- return ret;
-}
-
-static const struct dev_pm_ops ti_pipe3_pm_ops = {
- SET_RUNTIME_PM_OPS(ti_pipe3_runtime_suspend,
- ti_pipe3_runtime_resume, NULL)
-};
-
-#define DEV_PM_OPS (&ti_pipe3_pm_ops)
-#else
-#define DEV_PM_OPS NULL
-#endif
-
-#ifdef CONFIG_OF
-static const struct of_device_id ti_pipe3_id_table[] = {
- {
- .compatible = "ti,phy-usb3",
- .data = dpll_map_usb,
- },
- {
- .compatible = "ti,omap-usb3",
- .data = dpll_map_usb,
- },
- {
- .compatible = "ti,phy-pipe3-sata",
- .data = dpll_map_sata,
- },
- {
- .compatible = "ti,phy-pipe3-pcie",
- },
- {}
-};
-MODULE_DEVICE_TABLE(of, ti_pipe3_id_table);
-#endif
-
-static struct platform_driver ti_pipe3_driver = {
- .probe = ti_pipe3_probe,
- .remove = ti_pipe3_remove,
- .driver = {
- .name = "ti-pipe3",
- .pm = DEV_PM_OPS,
- .of_match_table = of_match_ptr(ti_pipe3_id_table),
- },
-};
-
-module_platform_driver(ti_pipe3_driver);
-
-MODULE_ALIAS("platform: ti_pipe3");
-MODULE_AUTHOR("Texas Instruments Inc.");
-MODULE_DESCRIPTION("TI PIPE3 phy driver");
-MODULE_LICENSE("GPL v2");
+++ /dev/null
-/*
- * twl4030_usb - TWL4030 USB transceiver, talking to OMAP OTG controller
- *
- * Copyright (C) 2004-2007 Texas Instruments
- * Copyright (C) 2008 Nokia Corporation
- * Contact: Felipe Balbi <felipe.balbi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Current status:
- * - HS USB ULPI mode works.
- * - 3-pin mode support may be added in future.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/workqueue.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/usb/otg.h>
-#include <linux/phy/phy.h>
-#include <linux/pm_runtime.h>
-#include <linux/usb/musb-omap.h>
-#include <linux/usb/ulpi.h>
-#include <linux/i2c/twl.h>
-#include <linux/regulator/consumer.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-
-/* Register defines */
-
-#define MCPC_CTRL 0x30
-#define MCPC_CTRL_RTSOL (1 << 7)
-#define MCPC_CTRL_EXTSWR (1 << 6)
-#define MCPC_CTRL_EXTSWC (1 << 5)
-#define MCPC_CTRL_VOICESW (1 << 4)
-#define MCPC_CTRL_OUT64K (1 << 3)
-#define MCPC_CTRL_RTSCTSSW (1 << 2)
-#define MCPC_CTRL_HS_UART (1 << 0)
-
-#define MCPC_IO_CTRL 0x33
-#define MCPC_IO_CTRL_MICBIASEN (1 << 5)
-#define MCPC_IO_CTRL_CTS_NPU (1 << 4)
-#define MCPC_IO_CTRL_RXD_PU (1 << 3)
-#define MCPC_IO_CTRL_TXDTYP (1 << 2)
-#define MCPC_IO_CTRL_CTSTYP (1 << 1)
-#define MCPC_IO_CTRL_RTSTYP (1 << 0)
-
-#define MCPC_CTRL2 0x36
-#define MCPC_CTRL2_MCPC_CK_EN (1 << 0)
-
-#define OTHER_FUNC_CTRL 0x80
-#define OTHER_FUNC_CTRL_BDIS_ACON_EN (1 << 4)
-#define OTHER_FUNC_CTRL_FIVEWIRE_MODE (1 << 2)
-
-#define OTHER_IFC_CTRL 0x83
-#define OTHER_IFC_CTRL_OE_INT_EN (1 << 6)
-#define OTHER_IFC_CTRL_CEA2011_MODE (1 << 5)
-#define OTHER_IFC_CTRL_FSLSSERIALMODE_4PIN (1 << 4)
-#define OTHER_IFC_CTRL_HIZ_ULPI_60MHZ_OUT (1 << 3)
-#define OTHER_IFC_CTRL_HIZ_ULPI (1 << 2)
-#define OTHER_IFC_CTRL_ALT_INT_REROUTE (1 << 0)
-
-#define OTHER_INT_EN_RISE 0x86
-#define OTHER_INT_EN_FALL 0x89
-#define OTHER_INT_STS 0x8C
-#define OTHER_INT_LATCH 0x8D
-#define OTHER_INT_VB_SESS_VLD (1 << 7)
-#define OTHER_INT_DM_HI (1 << 6) /* not valid for "latch" reg */
-#define OTHER_INT_DP_HI (1 << 5) /* not valid for "latch" reg */
-#define OTHER_INT_BDIS_ACON (1 << 3) /* not valid for "fall" regs */
-#define OTHER_INT_MANU (1 << 1)
-#define OTHER_INT_ABNORMAL_STRESS (1 << 0)
-
-#define ID_STATUS 0x96
-#define ID_RES_FLOAT (1 << 4)
-#define ID_RES_440K (1 << 3)
-#define ID_RES_200K (1 << 2)
-#define ID_RES_102K (1 << 1)
-#define ID_RES_GND (1 << 0)
-
-#define POWER_CTRL 0xAC
-#define POWER_CTRL_OTG_ENAB (1 << 5)
-
-#define OTHER_IFC_CTRL2 0xAF
-#define OTHER_IFC_CTRL2_ULPI_STP_LOW (1 << 4)
-#define OTHER_IFC_CTRL2_ULPI_TXEN_POL (1 << 3)
-#define OTHER_IFC_CTRL2_ULPI_4PIN_2430 (1 << 2)
-#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_MASK (3 << 0) /* bits 0 and 1 */
-#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT1N (0 << 0)
-#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT2N (1 << 0)
-
-#define REG_CTRL_EN 0xB2
-#define REG_CTRL_ERROR 0xB5
-#define ULPI_I2C_CONFLICT_INTEN (1 << 0)
-
-#define OTHER_FUNC_CTRL2 0xB8
-#define OTHER_FUNC_CTRL2_VBAT_TIMER_EN (1 << 0)
-
-/* following registers do not have separate _clr and _set registers */
-#define VBUS_DEBOUNCE 0xC0
-#define ID_DEBOUNCE 0xC1
-#define VBAT_TIMER 0xD3
-#define PHY_PWR_CTRL 0xFD
-#define PHY_PWR_PHYPWD (1 << 0)
-#define PHY_CLK_CTRL 0xFE
-#define PHY_CLK_CTRL_CLOCKGATING_EN (1 << 2)
-#define PHY_CLK_CTRL_CLK32K_EN (1 << 1)
-#define REQ_PHY_DPLL_CLK (1 << 0)
-#define PHY_CLK_CTRL_STS 0xFF
-#define PHY_DPLL_CLK (1 << 0)
-
-/* In module TWL_MODULE_PM_MASTER */
-#define STS_HW_CONDITIONS 0x0F
-
-/* In module TWL_MODULE_PM_RECEIVER */
-#define VUSB_DEDICATED1 0x7D
-#define VUSB_DEDICATED2 0x7E
-#define VUSB1V5_DEV_GRP 0x71
-#define VUSB1V5_TYPE 0x72
-#define VUSB1V5_REMAP 0x73
-#define VUSB1V8_DEV_GRP 0x74
-#define VUSB1V8_TYPE 0x75
-#define VUSB1V8_REMAP 0x76
-#define VUSB3V1_DEV_GRP 0x77
-#define VUSB3V1_TYPE 0x78
-#define VUSB3V1_REMAP 0x79
-
-/* In module TWL4030_MODULE_INTBR */
-#define PMBR1 0x0D
-#define GPIO_USB_4PIN_ULPI_2430C (3 << 0)
-
-struct twl4030_usb {
- struct usb_phy phy;
- struct device *dev;
-
- /* TWL4030 internal USB regulator supplies */
- struct regulator *usb1v5;
- struct regulator *usb1v8;
- struct regulator *usb3v1;
-
- /* for vbus reporting with irqs disabled */
- struct mutex lock;
-
- /* pin configuration */
- enum twl4030_usb_mode usb_mode;
-
- int irq;
- enum omap_musb_vbus_id_status linkstat;
- bool vbus_supplied;
-
- struct delayed_work id_workaround_work;
-};
-
-/* internal define on top of container_of */
-#define phy_to_twl(x) container_of((x), struct twl4030_usb, phy)
-
-/*-------------------------------------------------------------------------*/
-
-static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl,
- u8 module, u8 data, u8 address)
-{
- u8 check;
-
- if ((twl_i2c_write_u8(module, data, address) >= 0) &&
- (twl_i2c_read_u8(module, &check, address) >= 0) &&
- (check == data))
- return 0;
- dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n",
- 1, module, address, check, data);
-
- /* Failed once: Try again */
- if ((twl_i2c_write_u8(module, data, address) >= 0) &&
- (twl_i2c_read_u8(module, &check, address) >= 0) &&
- (check == data))
- return 0;
- dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n",
- 2, module, address, check, data);
-
- /* Failed again: Return error */
- return -EBUSY;
-}
-
-#define twl4030_usb_write_verify(twl, address, data) \
- twl4030_i2c_write_u8_verify(twl, TWL_MODULE_USB, (data), (address))
-
-static inline int twl4030_usb_write(struct twl4030_usb *twl,
- u8 address, u8 data)
-{
- int ret = 0;
-
- ret = twl_i2c_write_u8(TWL_MODULE_USB, data, address);
- if (ret < 0)
- dev_dbg(twl->dev,
- "TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
- return ret;
-}
-
-static inline int twl4030_readb(struct twl4030_usb *twl, u8 module, u8 address)
-{
- u8 data;
- int ret = 0;
-
- ret = twl_i2c_read_u8(module, &data, address);
- if (ret >= 0)
- ret = data;
- else
- dev_dbg(twl->dev,
- "TWL4030:readb[0x%x,0x%x] Error %d\n",
- module, address, ret);
-
- return ret;
-}
-
-static inline int twl4030_usb_read(struct twl4030_usb *twl, u8 address)
-{
- return twl4030_readb(twl, TWL_MODULE_USB, address);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static inline int
-twl4030_usb_set_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
-{
- return twl4030_usb_write(twl, ULPI_SET(reg), bits);
-}
-
-static inline int
-twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
-{
- return twl4030_usb_write(twl, ULPI_CLR(reg), bits);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static bool twl4030_is_driving_vbus(struct twl4030_usb *twl)
-{
- int ret;
-
- ret = twl4030_usb_read(twl, PHY_CLK_CTRL_STS);
- if (ret < 0 || !(ret & PHY_DPLL_CLK))
- /*
- * if clocks are off, registers are not updated,
- * but we can assume we don't drive VBUS in this case
- */
- return false;
-
- ret = twl4030_usb_read(twl, ULPI_OTG_CTRL);
- if (ret < 0)
- return false;
-
- return (ret & (ULPI_OTG_DRVVBUS | ULPI_OTG_CHRGVBUS)) ? true : false;
-}
-
-static enum omap_musb_vbus_id_status
- twl4030_usb_linkstat(struct twl4030_usb *twl)
-{
- int status;
- enum omap_musb_vbus_id_status linkstat = OMAP_MUSB_UNKNOWN;
-
- twl->vbus_supplied = false;
-
- /*
- * For ID/VBUS sensing, see manual section 15.4.8 ...
- * except when using only battery backup power, two
- * comparators produce VBUS_PRES and ID_PRES signals,
- * which don't match docs elsewhere. But ... BIT(7)
- * and BIT(2) of STS_HW_CONDITIONS, respectively, do
- * seem to match up. If either is true the USB_PRES
- * signal is active, the OTG module is activated, and
- * its interrupt may be raised (may wake the system).
- */
- status = twl4030_readb(twl, TWL_MODULE_PM_MASTER, STS_HW_CONDITIONS);
- if (status < 0)
- dev_err(twl->dev, "USB link status err %d\n", status);
- else if (status & (BIT(7) | BIT(2))) {
- if (status & BIT(7)) {
- if (twl4030_is_driving_vbus(twl))
- status &= ~BIT(7);
- else
- twl->vbus_supplied = true;
- }
-
- if (status & BIT(2))
- linkstat = OMAP_MUSB_ID_GROUND;
- else if (status & BIT(7))
- linkstat = OMAP_MUSB_VBUS_VALID;
- else
- linkstat = OMAP_MUSB_VBUS_OFF;
- } else {
- if (twl->linkstat != OMAP_MUSB_UNKNOWN)
- linkstat = OMAP_MUSB_VBUS_OFF;
- }
-
- dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
- status, status, linkstat);
-
- /* REVISIT this assumes host and peripheral controllers
- * are registered, and that both are active...
- */
-
- return linkstat;
-}
-
-static void twl4030_usb_set_mode(struct twl4030_usb *twl, int mode)
-{
- twl->usb_mode = mode;
-
- switch (mode) {
- case T2_USB_MODE_ULPI:
- twl4030_usb_clear_bits(twl, ULPI_IFC_CTRL,
- ULPI_IFC_CTRL_CARKITMODE);
- twl4030_usb_set_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
- twl4030_usb_clear_bits(twl, ULPI_FUNC_CTRL,
- ULPI_FUNC_CTRL_XCVRSEL_MASK |
- ULPI_FUNC_CTRL_OPMODE_MASK);
- break;
- case -1:
- /* FIXME: power on defaults */
- break;
- default:
- dev_err(twl->dev, "unsupported T2 transceiver mode %d\n",
- mode);
- break;
- }
-}
-
-static void twl4030_i2c_access(struct twl4030_usb *twl, int on)
-{
- unsigned long timeout;
- int val = twl4030_usb_read(twl, PHY_CLK_CTRL);
-
- if (val >= 0) {
- if (on) {
- /* enable DPLL to access PHY registers over I2C */
- val |= REQ_PHY_DPLL_CLK;
- WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL,
- (u8)val) < 0);
-
- timeout = jiffies + HZ;
- while (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) &
- PHY_DPLL_CLK)
- && time_before(jiffies, timeout))
- udelay(10);
- if (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) &
- PHY_DPLL_CLK))
- dev_err(twl->dev, "Timeout setting T2 HSUSB "
- "PHY DPLL clock\n");
- } else {
- /* let ULPI control the DPLL clock */
- val &= ~REQ_PHY_DPLL_CLK;
- WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL,
- (u8)val) < 0);
- }
- }
-}
-
-static void __twl4030_phy_power(struct twl4030_usb *twl, int on)
-{
- u8 pwr = twl4030_usb_read(twl, PHY_PWR_CTRL);
-
- if (on)
- pwr &= ~PHY_PWR_PHYPWD;
- else
- pwr |= PHY_PWR_PHYPWD;
-
- WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
-}
-
-static int twl4030_usb_runtime_suspend(struct device *dev)
-{
- struct twl4030_usb *twl = dev_get_drvdata(dev);
-
- dev_dbg(twl->dev, "%s\n", __func__);
- if (pm_runtime_suspended(dev))
- return 0;
-
- __twl4030_phy_power(twl, 0);
- regulator_disable(twl->usb1v5);
- regulator_disable(twl->usb1v8);
- regulator_disable(twl->usb3v1);
-
- return 0;
-}
-
-static int twl4030_usb_runtime_resume(struct device *dev)
-{
- struct twl4030_usb *twl = dev_get_drvdata(dev);
- int res;
-
- dev_dbg(twl->dev, "%s\n", __func__);
- if (pm_runtime_active(dev))
- return 0;
-
- res = regulator_enable(twl->usb3v1);
- if (res)
- dev_err(twl->dev, "Failed to enable usb3v1\n");
-
- res = regulator_enable(twl->usb1v8);
- if (res)
- dev_err(twl->dev, "Failed to enable usb1v8\n");
-
- /*
- * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP
- * in twl4030) resets the VUSB_DEDICATED2 register. This reset
- * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to
- * SLEEP. We work around this by clearing the bit after usv3v1
- * is re-activated. This ensures that VUSB3V1 is really active.
- */
- twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);
-
- res = regulator_enable(twl->usb1v5);
- if (res)
- dev_err(twl->dev, "Failed to enable usb1v5\n");
-
- __twl4030_phy_power(twl, 1);
- twl4030_usb_write(twl, PHY_CLK_CTRL,
- twl4030_usb_read(twl, PHY_CLK_CTRL) |
- (PHY_CLK_CTRL_CLOCKGATING_EN |
- PHY_CLK_CTRL_CLK32K_EN));
-
- return 0;
-}
-
-static int twl4030_phy_power_off(struct phy *phy)
-{
- struct twl4030_usb *twl = phy_get_drvdata(phy);
-
- dev_dbg(twl->dev, "%s\n", __func__);
- pm_runtime_mark_last_busy(twl->dev);
- pm_runtime_put_autosuspend(twl->dev);
-
- return 0;
-}
-
-static int twl4030_phy_power_on(struct phy *phy)
-{
- struct twl4030_usb *twl = phy_get_drvdata(phy);
-
- dev_dbg(twl->dev, "%s\n", __func__);
- pm_runtime_get_sync(twl->dev);
- twl4030_i2c_access(twl, 1);
- twl4030_usb_set_mode(twl, twl->usb_mode);
- if (twl->usb_mode == T2_USB_MODE_ULPI)
- twl4030_i2c_access(twl, 0);
- schedule_delayed_work(&twl->id_workaround_work, 0);
-
- return 0;
-}
-
-static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
-{
- /* Enable writing to power configuration registers */
- twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
- TWL4030_PM_MASTER_PROTECT_KEY);
-
- twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
- TWL4030_PM_MASTER_PROTECT_KEY);
-
- /* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/
- /*twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/
-
- /* input to VUSB3V1 LDO is from VBAT, not VBUS */
- twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);
-
- /* Initialize 3.1V regulator */
- twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
-
- twl->usb3v1 = devm_regulator_get(twl->dev, "usb3v1");
- if (IS_ERR(twl->usb3v1))
- return -ENODEV;
-
- twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);
-
- /* Initialize 1.5V regulator */
- twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);
-
- twl->usb1v5 = devm_regulator_get(twl->dev, "usb1v5");
- if (IS_ERR(twl->usb1v5))
- return -ENODEV;
-
- twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);
-
- /* Initialize 1.8V regulator */
- twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP);
-
- twl->usb1v8 = devm_regulator_get(twl->dev, "usb1v8");
- if (IS_ERR(twl->usb1v8))
- return -ENODEV;
-
- twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);
-
- /* disable access to power configuration registers */
- twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
- TWL4030_PM_MASTER_PROTECT_KEY);
-
- return 0;
-}
-
-static ssize_t twl4030_usb_vbus_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct twl4030_usb *twl = dev_get_drvdata(dev);
- int ret = -EINVAL;
-
- mutex_lock(&twl->lock);
- ret = sprintf(buf, "%s\n",
- twl->vbus_supplied ? "on" : "off");
- mutex_unlock(&twl->lock);
-
- return ret;
-}
-static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL);
-
-static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
-{
- struct twl4030_usb *twl = _twl;
- enum omap_musb_vbus_id_status status;
- bool status_changed = false;
-
- status = twl4030_usb_linkstat(twl);
-
- mutex_lock(&twl->lock);
- if (status >= 0 && status != twl->linkstat) {
- twl->linkstat = status;
- status_changed = true;
- }
- mutex_unlock(&twl->lock);
-
- if (status_changed) {
- /* FIXME add a set_power() method so that B-devices can
- * configure the charger appropriately. It's not always
- * correct to consume VBUS power, and how much current to
- * consume is a function of the USB configuration chosen
- * by the host.
- *
- * REVISIT usb_gadget_vbus_connect(...) as needed, ditto
- * its disconnect() sibling, when changing to/from the
- * USB_LINK_VBUS state. musb_hdrc won't care until it
- * starts to handle softconnect right.
- */
- if ((status == OMAP_MUSB_VBUS_VALID) ||
- (status == OMAP_MUSB_ID_GROUND)) {
- if (pm_runtime_suspended(twl->dev))
- pm_runtime_get_sync(twl->dev);
- } else {
- if (pm_runtime_active(twl->dev)) {
- pm_runtime_mark_last_busy(twl->dev);
- pm_runtime_put_autosuspend(twl->dev);
- }
- }
- omap_musb_mailbox(status);
- }
-
- /* don't schedule during sleep - irq works right then */
- if (status == OMAP_MUSB_ID_GROUND && pm_runtime_active(twl->dev)) {
- cancel_delayed_work(&twl->id_workaround_work);
- schedule_delayed_work(&twl->id_workaround_work, HZ);
- }
-
- if (irq)
- sysfs_notify(&twl->dev->kobj, NULL, "vbus");
-
- return IRQ_HANDLED;
-}
-
-static void twl4030_id_workaround_work(struct work_struct *work)
-{
- struct twl4030_usb *twl = container_of(work, struct twl4030_usb,
- id_workaround_work.work);
-
- twl4030_usb_irq(0, twl);
-}
-
-static int twl4030_phy_init(struct phy *phy)
-{
- struct twl4030_usb *twl = phy_get_drvdata(phy);
-
- pm_runtime_get_sync(twl->dev);
- schedule_delayed_work(&twl->id_workaround_work, 0);
- pm_runtime_mark_last_busy(twl->dev);
- pm_runtime_put_autosuspend(twl->dev);
-
- return 0;
-}
-
-static int twl4030_set_peripheral(struct usb_otg *otg,
- struct usb_gadget *gadget)
-{
- if (!otg)
- return -ENODEV;
-
- otg->gadget = gadget;
- if (!gadget)
- otg->state = OTG_STATE_UNDEFINED;
-
- return 0;
-}
-
-static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
- if (!otg)
- return -ENODEV;
-
- otg->host = host;
- if (!host)
- otg->state = OTG_STATE_UNDEFINED;
-
- return 0;
-}
-
-static const struct phy_ops ops = {
- .init = twl4030_phy_init,
- .power_on = twl4030_phy_power_on,
- .power_off = twl4030_phy_power_off,
- .owner = THIS_MODULE,
-};
-
-static const struct dev_pm_ops twl4030_usb_pm_ops = {
- SET_RUNTIME_PM_OPS(twl4030_usb_runtime_suspend,
- twl4030_usb_runtime_resume, NULL)
-};
-
-static int twl4030_usb_probe(struct platform_device *pdev)
-{
- struct twl4030_usb_data *pdata = dev_get_platdata(&pdev->dev);
- struct twl4030_usb *twl;
- struct phy *phy;
- int status, err;
- struct usb_otg *otg;
- struct device_node *np = pdev->dev.of_node;
- struct phy_provider *phy_provider;
- struct phy_init_data *init_data = NULL;
-
- twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL);
- if (!twl)
- return -ENOMEM;
-
- if (np)
- of_property_read_u32(np, "usb_mode",
- (enum twl4030_usb_mode *)&twl->usb_mode);
- else if (pdata) {
- twl->usb_mode = pdata->usb_mode;
- init_data = pdata->init_data;
- } else {
- dev_err(&pdev->dev, "twl4030 initialized without pdata\n");
- return -EINVAL;
- }
-
- otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
- if (!otg)
- return -ENOMEM;
-
- twl->dev = &pdev->dev;
- twl->irq = platform_get_irq(pdev, 0);
- twl->vbus_supplied = false;
- twl->linkstat = -EINVAL;
- twl->linkstat = OMAP_MUSB_UNKNOWN;
-
- twl->phy.dev = twl->dev;
- twl->phy.label = "twl4030";
- twl->phy.otg = otg;
- twl->phy.type = USB_PHY_TYPE_USB2;
-
- otg->usb_phy = &twl->phy;
- otg->set_host = twl4030_set_host;
- otg->set_peripheral = twl4030_set_peripheral;
-
- phy = devm_phy_create(twl->dev, NULL, &ops, init_data);
- if (IS_ERR(phy)) {
- dev_dbg(&pdev->dev, "Failed to create PHY\n");
- return PTR_ERR(phy);
- }
-
- phy_set_drvdata(phy, twl);
-
- phy_provider = devm_of_phy_provider_register(twl->dev,
- of_phy_simple_xlate);
- if (IS_ERR(phy_provider))
- return PTR_ERR(phy_provider);
-
- /* init mutex for workqueue */
- mutex_init(&twl->lock);
-
- INIT_DELAYED_WORK(&twl->id_workaround_work, twl4030_id_workaround_work);
-
- err = twl4030_usb_ldo_init(twl);
- if (err) {
- dev_err(&pdev->dev, "ldo init failed\n");
- return err;
- }
- usb_add_phy_dev(&twl->phy);
-
- platform_set_drvdata(pdev, twl);
- if (device_create_file(&pdev->dev, &dev_attr_vbus))
- dev_warn(&pdev->dev, "could not create sysfs file\n");
-
- ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
-
- pm_runtime_use_autosuspend(&pdev->dev);
- pm_runtime_set_autosuspend_delay(&pdev->dev, 2000);
- pm_runtime_enable(&pdev->dev);
- pm_runtime_get_sync(&pdev->dev);
-
- /* Our job is to use irqs and status from the power module
- * to keep the transceiver disabled when nothing's connected.
- *
- * FIXME we actually shouldn't start enabling it until the
- * USB controller drivers have said they're ready, by calling
- * set_host() and/or set_peripheral() ... OTG_capable boards
- * need both handles, otherwise just one suffices.
- */
- status = devm_request_threaded_irq(twl->dev, twl->irq, NULL,
- twl4030_usb_irq, IRQF_TRIGGER_FALLING |
- IRQF_TRIGGER_RISING | IRQF_ONESHOT, "twl4030_usb", twl);
- if (status < 0) {
- dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n",
- twl->irq, status);
- return status;
- }
-
- pm_runtime_mark_last_busy(&pdev->dev);
- pm_runtime_put_autosuspend(twl->dev);
-
- dev_info(&pdev->dev, "Initialized TWL4030 USB module\n");
- return 0;
-}
-
-static int twl4030_usb_remove(struct platform_device *pdev)
-{
- struct twl4030_usb *twl = platform_get_drvdata(pdev);
- int val;
-
- pm_runtime_get_sync(twl->dev);
- cancel_delayed_work(&twl->id_workaround_work);
- device_remove_file(twl->dev, &dev_attr_vbus);
-
- /* set transceiver mode to power on defaults */
- twl4030_usb_set_mode(twl, -1);
-
- /* autogate 60MHz ULPI clock,
- * clear dpll clock request for i2c access,
- * disable 32KHz
- */
- val = twl4030_usb_read(twl, PHY_CLK_CTRL);
- if (val >= 0) {
- val |= PHY_CLK_CTRL_CLOCKGATING_EN;
- val &= ~(PHY_CLK_CTRL_CLK32K_EN | REQ_PHY_DPLL_CLK);
- twl4030_usb_write(twl, PHY_CLK_CTRL, (u8)val);
- }
-
- /* disable complete OTG block */
- twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
- pm_runtime_mark_last_busy(twl->dev);
- pm_runtime_put(twl->dev);
-
- return 0;
-}
-
-#ifdef CONFIG_OF
-static const struct of_device_id twl4030_usb_id_table[] = {
- { .compatible = "ti,twl4030-usb" },
- {}
-};
-MODULE_DEVICE_TABLE(of, twl4030_usb_id_table);
-#endif
-
-static struct platform_driver twl4030_usb_driver = {
- .probe = twl4030_usb_probe,
- .remove = twl4030_usb_remove,
- .driver = {
- .name = "twl4030_usb",
- .pm = &twl4030_usb_pm_ops,
- .of_match_table = of_match_ptr(twl4030_usb_id_table),
- },
-};
-
-static int __init twl4030_usb_init(void)
-{
- return platform_driver_register(&twl4030_usb_driver);
-}
-subsys_initcall(twl4030_usb_init);
-
-static void __exit twl4030_usb_exit(void)
-{
- platform_driver_unregister(&twl4030_usb_driver);
-}
-module_exit(twl4030_usb_exit);
-
-MODULE_ALIAS("platform:twl4030_usb");
-MODULE_AUTHOR("Texas Instruments, Inc, Nokia Corporation");
-MODULE_DESCRIPTION("TWL4030 USB transceiver driver");
-MODULE_LICENSE("GPL");
+++ /dev/null
-/*
- * AppliedMicro X-Gene Multi-purpose PHY driver
- *
- * Copyright (c) 2014, Applied Micro Circuits Corporation
- * Author: Loc Ho <lho@apm.com>
- * Tuan Phan <tphan@apm.com>
- * Suman Tripathi <stripathi@apm.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * The APM X-Gene PHY consists of two PLL clock macro's (CMU) and lanes.
- * The first PLL clock macro is used for internal reference clock. The second
- * PLL clock macro is used to generate the clock for the PHY. This driver
- * configures the first PLL CMU, the second PLL CMU, and programs the PHY to
- * operate according to the mode of operation. The first PLL CMU is only
- * required if internal clock is enabled.
- *
- * Logical Layer Out Of HW module units:
- *
- * -----------------
- * | Internal | |------|
- * | Ref PLL CMU |----| | ------------- ---------
- * ------------ ---- | MUX |-----|PHY PLL CMU|----| Serdes|
- * | | | | ---------
- * External Clock ------| | -------------
- * |------|
- *
- * The Ref PLL CMU CSR (Configuration System Registers) is accessed
- * indirectly from the SDS offset at 0x2000. It is only required for
- * internal reference clock.
- * The PHY PLL CMU CSR is accessed indirectly from the SDS offset at 0x0000.
- * The Serdes CSR is accessed indirectly from the SDS offset at 0x0400.
- *
- * The Ref PLL CMU can be located within the same PHY IP or outside the PHY IP
- * due to shared Ref PLL CMU. For PHY with Ref PLL CMU shared with another IP,
- * it is located outside the PHY IP. This is the case for the PHY located
- * at 0x1f23a000 (SATA Port 4/5). For such PHY, another resource is required
- * to located the SDS/Ref PLL CMU module and its clock for that IP enabled.
- *
- * Currently, this driver only supports Gen3 SATA mode with external clock.
- */
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/phy/phy.h>
-#include <linux/clk.h>
-
-/* Max 2 lanes per a PHY unit */
-#define MAX_LANE 2
-
-/* Register offset inside the PHY */
-#define SERDES_PLL_INDIRECT_OFFSET 0x0000
-#define SERDES_PLL_REF_INDIRECT_OFFSET 0x2000
-#define SERDES_INDIRECT_OFFSET 0x0400
-#define SERDES_LANE_STRIDE 0x0200
-
-/* Some default Serdes parameters */
-#define DEFAULT_SATA_TXBOOST_GAIN { 0x1e, 0x1e, 0x1e }
-#define DEFAULT_SATA_TXEYEDIRECTION { 0x0, 0x0, 0x0 }
-#define DEFAULT_SATA_TXEYETUNING { 0xa, 0xa, 0xa }
-#define DEFAULT_SATA_SPD_SEL { 0x1, 0x3, 0x7 }
-#define DEFAULT_SATA_TXAMP { 0x8, 0x8, 0x8 }
-#define DEFAULT_SATA_TXCN1 { 0x2, 0x2, 0x2 }
-#define DEFAULT_SATA_TXCN2 { 0x0, 0x0, 0x0 }
-#define DEFAULT_SATA_TXCP1 { 0xa, 0xa, 0xa }
-
-#define SATA_SPD_SEL_GEN3 0x7
-#define SATA_SPD_SEL_GEN2 0x3
-#define SATA_SPD_SEL_GEN1 0x1
-
-#define SSC_DISABLE 0
-#define SSC_ENABLE 1
-
-#define FBDIV_VAL_50M 0x77
-#define REFDIV_VAL_50M 0x1
-#define FBDIV_VAL_100M 0x3B
-#define REFDIV_VAL_100M 0x0
-
-/* SATA Clock/Reset CSR */
-#define SATACLKENREG 0x00000000
-#define SATA0_CORE_CLKEN 0x00000002
-#define SATA1_CORE_CLKEN 0x00000004
-#define SATASRESETREG 0x00000004
-#define SATA_MEM_RESET_MASK 0x00000020
-#define SATA_MEM_RESET_RD(src) (((src) & 0x00000020) >> 5)
-#define SATA_SDS_RESET_MASK 0x00000004
-#define SATA_CSR_RESET_MASK 0x00000001
-#define SATA_CORE_RESET_MASK 0x00000002
-#define SATA_PMCLK_RESET_MASK 0x00000010
-#define SATA_PCLK_RESET_MASK 0x00000008
-
-/* SDS CSR used for PHY Indirect access */
-#define SATA_ENET_SDS_PCS_CTL0 0x00000000
-#define REGSPEC_CFG_I_TX_WORDMODE0_SET(dst, src) \
- (((dst) & ~0x00070000) | (((u32) (src) << 16) & 0x00070000))
-#define REGSPEC_CFG_I_RX_WORDMODE0_SET(dst, src) \
- (((dst) & ~0x00e00000) | (((u32) (src) << 21) & 0x00e00000))
-#define SATA_ENET_SDS_CTL0 0x0000000c
-#define REGSPEC_CFG_I_CUSTOMER_PIN_MODE0_SET(dst, src) \
- (((dst) & ~0x00007fff) | (((u32) (src)) & 0x00007fff))
-#define SATA_ENET_SDS_CTL1 0x00000010
-#define CFG_I_SPD_SEL_CDR_OVR1_SET(dst, src) \
- (((dst) & ~0x0000000f) | (((u32) (src)) & 0x0000000f))
-#define SATA_ENET_SDS_RST_CTL 0x00000024
-#define SATA_ENET_SDS_IND_CMD_REG 0x0000003c
-#define CFG_IND_WR_CMD_MASK 0x00000001
-#define CFG_IND_RD_CMD_MASK 0x00000002
-#define CFG_IND_CMD_DONE_MASK 0x00000004
-#define CFG_IND_ADDR_SET(dst, src) \
- (((dst) & ~0x003ffff0) | (((u32) (src) << 4) & 0x003ffff0))
-#define SATA_ENET_SDS_IND_RDATA_REG 0x00000040
-#define SATA_ENET_SDS_IND_WDATA_REG 0x00000044
-#define SATA_ENET_CLK_MACRO_REG 0x0000004c
-#define I_RESET_B_SET(dst, src) \
- (((dst) & ~0x00000001) | (((u32) (src)) & 0x00000001))
-#define I_PLL_FBDIV_SET(dst, src) \
- (((dst) & ~0x001ff000) | (((u32) (src) << 12) & 0x001ff000))
-#define I_CUSTOMEROV_SET(dst, src) \
- (((dst) & ~0x00000f80) | (((u32) (src) << 7) & 0x00000f80))
-#define O_PLL_LOCK_RD(src) (((src) & 0x40000000) >> 30)
-#define O_PLL_READY_RD(src) (((src) & 0x80000000) >> 31)
-
-/* PLL Clock Macro Unit (CMU) CSR accessing from SDS indirectly */
-#define CMU_REG0 0x00000
-#define CMU_REG0_PLL_REF_SEL_MASK 0x00002000
-#define CMU_REG0_PLL_REF_SEL_SET(dst, src) \
- (((dst) & ~0x00002000) | (((u32) (src) << 13) & 0x00002000))
-#define CMU_REG0_PDOWN_MASK 0x00004000
-#define CMU_REG0_CAL_COUNT_RESOL_SET(dst, src) \
- (((dst) & ~0x000000e0) | (((u32) (src) << 5) & 0x000000e0))
-#define CMU_REG1 0x00002
-#define CMU_REG1_PLL_CP_SET(dst, src) \
- (((dst) & ~0x00003c00) | (((u32) (src) << 10) & 0x00003c00))
-#define CMU_REG1_PLL_MANUALCAL_SET(dst, src) \
- (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
-#define CMU_REG1_PLL_CP_SEL_SET(dst, src) \
- (((dst) & ~0x000003e0) | (((u32) (src) << 5) & 0x000003e0))
-#define CMU_REG1_REFCLK_CMOS_SEL_MASK 0x00000001
-#define CMU_REG1_REFCLK_CMOS_SEL_SET(dst, src) \
- (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001))
-#define CMU_REG2 0x00004
-#define CMU_REG2_PLL_REFDIV_SET(dst, src) \
- (((dst) & ~0x0000c000) | (((u32) (src) << 14) & 0x0000c000))
-#define CMU_REG2_PLL_LFRES_SET(dst, src) \
- (((dst) & ~0x0000001e) | (((u32) (src) << 1) & 0x0000001e))
-#define CMU_REG2_PLL_FBDIV_SET(dst, src) \
- (((dst) & ~0x00003fe0) | (((u32) (src) << 5) & 0x00003fe0))
-#define CMU_REG3 0x00006
-#define CMU_REG3_VCOVARSEL_SET(dst, src) \
- (((dst) & ~0x0000000f) | (((u32) (src) << 0) & 0x0000000f))
-#define CMU_REG3_VCO_MOMSEL_INIT_SET(dst, src) \
- (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0))
-#define CMU_REG3_VCO_MANMOMSEL_SET(dst, src) \
- (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00))
-#define CMU_REG4 0x00008
-#define CMU_REG5 0x0000a
-#define CMU_REG5_PLL_LFSMCAP_SET(dst, src) \
- (((dst) & ~0x0000c000) | (((u32) (src) << 14) & 0x0000c000))
-#define CMU_REG5_PLL_LOCK_RESOLUTION_SET(dst, src) \
- (((dst) & ~0x0000000e) | (((u32) (src) << 1) & 0x0000000e))
-#define CMU_REG5_PLL_LFCAP_SET(dst, src) \
- (((dst) & ~0x00003000) | (((u32) (src) << 12) & 0x00003000))
-#define CMU_REG5_PLL_RESETB_MASK 0x00000001
-#define CMU_REG6 0x0000c
-#define CMU_REG6_PLL_VREGTRIM_SET(dst, src) \
- (((dst) & ~0x00000600) | (((u32) (src) << 9) & 0x00000600))
-#define CMU_REG6_MAN_PVT_CAL_SET(dst, src) \
- (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004))
-#define CMU_REG7 0x0000e
-#define CMU_REG7_PLL_CALIB_DONE_RD(src) ((0x00004000 & (u32) (src)) >> 14)
-#define CMU_REG7_VCO_CAL_FAIL_RD(src) ((0x00000c00 & (u32) (src)) >> 10)
-#define CMU_REG8 0x00010
-#define CMU_REG9 0x00012
-#define CMU_REG9_WORD_LEN_8BIT 0x000
-#define CMU_REG9_WORD_LEN_10BIT 0x001
-#define CMU_REG9_WORD_LEN_16BIT 0x002
-#define CMU_REG9_WORD_LEN_20BIT 0x003
-#define CMU_REG9_WORD_LEN_32BIT 0x004
-#define CMU_REG9_WORD_LEN_40BIT 0x005
-#define CMU_REG9_WORD_LEN_64BIT 0x006
-#define CMU_REG9_WORD_LEN_66BIT 0x007
-#define CMU_REG9_TX_WORD_MODE_CH1_SET(dst, src) \
- (((dst) & ~0x00000380) | (((u32) (src) << 7) & 0x00000380))
-#define CMU_REG9_TX_WORD_MODE_CH0_SET(dst, src) \
- (((dst) & ~0x00000070) | (((u32) (src) << 4) & 0x00000070))
-#define CMU_REG9_PLL_POST_DIVBY2_SET(dst, src) \
- (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
-#define CMU_REG9_VBG_BYPASSB_SET(dst, src) \
- (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004))
-#define CMU_REG9_IGEN_BYPASS_SET(dst, src) \
- (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002))
-#define CMU_REG10 0x00014
-#define CMU_REG10_VREG_REFSEL_SET(dst, src) \
- (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001))
-#define CMU_REG11 0x00016
-#define CMU_REG12 0x00018
-#define CMU_REG12_STATE_DELAY9_SET(dst, src) \
- (((dst) & ~0x000000f0) | (((u32) (src) << 4) & 0x000000f0))
-#define CMU_REG13 0x0001a
-#define CMU_REG14 0x0001c
-#define CMU_REG15 0x0001e
-#define CMU_REG16 0x00020
-#define CMU_REG16_PVT_DN_MAN_ENA_MASK 0x00000001
-#define CMU_REG16_PVT_UP_MAN_ENA_MASK 0x00000002
-#define CMU_REG16_VCOCAL_WAIT_BTW_CODE_SET(dst, src) \
- (((dst) & ~0x0000001c) | (((u32) (src) << 2) & 0x0000001c))
-#define CMU_REG16_CALIBRATION_DONE_OVERRIDE_SET(dst, src) \
- (((dst) & ~0x00000040) | (((u32) (src) << 6) & 0x00000040))
-#define CMU_REG16_BYPASS_PLL_LOCK_SET(dst, src) \
- (((dst) & ~0x00000020) | (((u32) (src) << 5) & 0x00000020))
-#define CMU_REG17 0x00022
-#define CMU_REG17_PVT_CODE_R2A_SET(dst, src) \
- (((dst) & ~0x00007f00) | (((u32) (src) << 8) & 0x00007f00))
-#define CMU_REG17_RESERVED_7_SET(dst, src) \
- (((dst) & ~0x000000e0) | (((u32) (src) << 5) & 0x000000e0))
-#define CMU_REG17_PVT_TERM_MAN_ENA_MASK 0x00008000
-#define CMU_REG18 0x00024
-#define CMU_REG19 0x00026
-#define CMU_REG20 0x00028
-#define CMU_REG21 0x0002a
-#define CMU_REG22 0x0002c
-#define CMU_REG23 0x0002e
-#define CMU_REG24 0x00030
-#define CMU_REG25 0x00032
-#define CMU_REG26 0x00034
-#define CMU_REG26_FORCE_PLL_LOCK_SET(dst, src) \
- (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001))
-#define CMU_REG27 0x00036
-#define CMU_REG28 0x00038
-#define CMU_REG29 0x0003a
-#define CMU_REG30 0x0003c
-#define CMU_REG30_LOCK_COUNT_SET(dst, src) \
- (((dst) & ~0x00000006) | (((u32) (src) << 1) & 0x00000006))
-#define CMU_REG30_PCIE_MODE_SET(dst, src) \
- (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
-#define CMU_REG31 0x0003e
-#define CMU_REG32 0x00040
-#define CMU_REG32_FORCE_VCOCAL_START_MASK 0x00004000
-#define CMU_REG32_PVT_CAL_WAIT_SEL_SET(dst, src) \
- (((dst) & ~0x00000006) | (((u32) (src) << 1) & 0x00000006))
-#define CMU_REG32_IREF_ADJ_SET(dst, src) \
- (((dst) & ~0x00000180) | (((u32) (src) << 7) & 0x00000180))
-#define CMU_REG33 0x00042
-#define CMU_REG34 0x00044
-#define CMU_REG34_VCO_CAL_VTH_LO_MAX_SET(dst, src) \
- (((dst) & ~0x0000000f) | (((u32) (src) << 0) & 0x0000000f))
-#define CMU_REG34_VCO_CAL_VTH_HI_MAX_SET(dst, src) \
- (((dst) & ~0x00000f00) | (((u32) (src) << 8) & 0x00000f00))
-#define CMU_REG34_VCO_CAL_VTH_LO_MIN_SET(dst, src) \
- (((dst) & ~0x000000f0) | (((u32) (src) << 4) & 0x000000f0))
-#define CMU_REG34_VCO_CAL_VTH_HI_MIN_SET(dst, src) \
- (((dst) & ~0x0000f000) | (((u32) (src) << 12) & 0x0000f000))
-#define CMU_REG35 0x00046
-#define CMU_REG35_PLL_SSC_MOD_SET(dst, src) \
- (((dst) & ~0x0000fe00) | (((u32) (src) << 9) & 0x0000fe00))
-#define CMU_REG36 0x00048
-#define CMU_REG36_PLL_SSC_EN_SET(dst, src) \
- (((dst) & ~0x00000010) | (((u32) (src) << 4) & 0x00000010))
-#define CMU_REG36_PLL_SSC_VSTEP_SET(dst, src) \
- (((dst) & ~0x0000ffc0) | (((u32) (src) << 6) & 0x0000ffc0))
-#define CMU_REG36_PLL_SSC_DSMSEL_SET(dst, src) \
- (((dst) & ~0x00000020) | (((u32) (src) << 5) & 0x00000020))
-#define CMU_REG37 0x0004a
-#define CMU_REG38 0x0004c
-#define CMU_REG39 0x0004e
-
-/* PHY lane CSR accessing from SDS indirectly */
-#define RXTX_REG0 0x000
-#define RXTX_REG0_CTLE_EQ_HR_SET(dst, src) \
- (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800))
-#define RXTX_REG0_CTLE_EQ_QR_SET(dst, src) \
- (((dst) & ~0x000007c0) | (((u32) (src) << 6) & 0x000007c0))
-#define RXTX_REG0_CTLE_EQ_FR_SET(dst, src) \
- (((dst) & ~0x0000003e) | (((u32) (src) << 1) & 0x0000003e))
-#define RXTX_REG1 0x002
-#define RXTX_REG1_RXACVCM_SET(dst, src) \
- (((dst) & ~0x0000f000) | (((u32) (src) << 12) & 0x0000f000))
-#define RXTX_REG1_CTLE_EQ_SET(dst, src) \
- (((dst) & ~0x00000f80) | (((u32) (src) << 7) & 0x00000f80))
-#define RXTX_REG1_RXVREG1_SET(dst, src) \
- (((dst) & ~0x00000060) | (((u32) (src) << 5) & 0x00000060))
-#define RXTX_REG1_RXIREF_ADJ_SET(dst, src) \
- (((dst) & ~0x00000006) | (((u32) (src) << 1) & 0x00000006))
-#define RXTX_REG2 0x004
-#define RXTX_REG2_VTT_ENA_SET(dst, src) \
- (((dst) & ~0x00000100) | (((u32) (src) << 8) & 0x00000100))
-#define RXTX_REG2_TX_FIFO_ENA_SET(dst, src) \
- (((dst) & ~0x00000020) | (((u32) (src) << 5) & 0x00000020))
-#define RXTX_REG2_VTT_SEL_SET(dst, src) \
- (((dst) & ~0x000000c0) | (((u32) (src) << 6) & 0x000000c0))
-#define RXTX_REG4 0x008
-#define RXTX_REG4_TX_LOOPBACK_BUF_EN_MASK 0x00000040
-#define RXTX_REG4_TX_DATA_RATE_SET(dst, src) \
- (((dst) & ~0x0000c000) | (((u32) (src) << 14) & 0x0000c000))
-#define RXTX_REG4_TX_WORD_MODE_SET(dst, src) \
- (((dst) & ~0x00003800) | (((u32) (src) << 11) & 0x00003800))
-#define RXTX_REG5 0x00a
-#define RXTX_REG5_TX_CN1_SET(dst, src) \
- (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800))
-#define RXTX_REG5_TX_CP1_SET(dst, src) \
- (((dst) & ~0x000007e0) | (((u32) (src) << 5) & 0x000007e0))
-#define RXTX_REG5_TX_CN2_SET(dst, src) \
- (((dst) & ~0x0000001f) | (((u32) (src) << 0) & 0x0000001f))
-#define RXTX_REG6 0x00c
-#define RXTX_REG6_TXAMP_CNTL_SET(dst, src) \
- (((dst) & ~0x00000780) | (((u32) (src) << 7) & 0x00000780))
-#define RXTX_REG6_TXAMP_ENA_SET(dst, src) \
- (((dst) & ~0x00000040) | (((u32) (src) << 6) & 0x00000040))
-#define RXTX_REG6_RX_BIST_ERRCNT_RD_SET(dst, src) \
- (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001))
-#define RXTX_REG6_TX_IDLE_SET(dst, src) \
- (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
-#define RXTX_REG6_RX_BIST_RESYNC_SET(dst, src) \
- (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002))
-#define RXTX_REG7 0x00e
-#define RXTX_REG7_RESETB_RXD_MASK 0x00000100
-#define RXTX_REG7_RESETB_RXA_MASK 0x00000080
-#define RXTX_REG7_BIST_ENA_RX_SET(dst, src) \
- (((dst) & ~0x00000040) | (((u32) (src) << 6) & 0x00000040))
-#define RXTX_REG7_RX_WORD_MODE_SET(dst, src) \
- (((dst) & ~0x00003800) | (((u32) (src) << 11) & 0x00003800))
-#define RXTX_REG8 0x010
-#define RXTX_REG8_CDR_LOOP_ENA_SET(dst, src) \
- (((dst) & ~0x00004000) | (((u32) (src) << 14) & 0x00004000))
-#define RXTX_REG8_CDR_BYPASS_RXLOS_SET(dst, src) \
- (((dst) & ~0x00000800) | (((u32) (src) << 11) & 0x00000800))
-#define RXTX_REG8_SSC_ENABLE_SET(dst, src) \
- (((dst) & ~0x00000200) | (((u32) (src) << 9) & 0x00000200))
-#define RXTX_REG8_SD_VREF_SET(dst, src) \
- (((dst) & ~0x000000f0) | (((u32) (src) << 4) & 0x000000f0))
-#define RXTX_REG8_SD_DISABLE_SET(dst, src) \
- (((dst) & ~0x00000100) | (((u32) (src) << 8) & 0x00000100))
-#define RXTX_REG7 0x00e
-#define RXTX_REG7_RESETB_RXD_SET(dst, src) \
- (((dst) & ~0x00000100) | (((u32) (src) << 8) & 0x00000100))
-#define RXTX_REG7_RESETB_RXA_SET(dst, src) \
- (((dst) & ~0x00000080) | (((u32) (src) << 7) & 0x00000080))
-#define RXTX_REG7_LOOP_BACK_ENA_CTLE_MASK 0x00004000
-#define RXTX_REG7_LOOP_BACK_ENA_CTLE_SET(dst, src) \
- (((dst) & ~0x00004000) | (((u32) (src) << 14) & 0x00004000))
-#define RXTX_REG11 0x016
-#define RXTX_REG11_PHASE_ADJUST_LIMIT_SET(dst, src) \
- (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800))
-#define RXTX_REG12 0x018
-#define RXTX_REG12_LATCH_OFF_ENA_SET(dst, src) \
- (((dst) & ~0x00002000) | (((u32) (src) << 13) & 0x00002000))
-#define RXTX_REG12_SUMOS_ENABLE_SET(dst, src) \
- (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004))
-#define RXTX_REG12_RX_DET_TERM_ENABLE_MASK 0x00000002
-#define RXTX_REG12_RX_DET_TERM_ENABLE_SET(dst, src) \
- (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002))
-#define RXTX_REG13 0x01a
-#define RXTX_REG14 0x01c
-#define RXTX_REG14_CLTE_LATCAL_MAN_PROG_SET(dst, src) \
- (((dst) & ~0x0000003f) | (((u32) (src) << 0) & 0x0000003f))
-#define RXTX_REG14_CTLE_LATCAL_MAN_ENA_SET(dst, src) \
- (((dst) & ~0x00000040) | (((u32) (src) << 6) & 0x00000040))
-#define RXTX_REG26 0x034
-#define RXTX_REG26_PERIOD_ERROR_LATCH_SET(dst, src) \
- (((dst) & ~0x00003800) | (((u32) (src) << 11) & 0x00003800))
-#define RXTX_REG26_BLWC_ENA_SET(dst, src) \
- (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
-#define RXTX_REG21 0x02a
-#define RXTX_REG21_DO_LATCH_CALOUT_RD(src) ((0x0000fc00 & (u32) (src)) >> 10)
-#define RXTX_REG21_XO_LATCH_CALOUT_RD(src) ((0x000003f0 & (u32) (src)) >> 4)
-#define RXTX_REG21_LATCH_CAL_FAIL_ODD_RD(src) ((0x0000000f & (u32)(src)))
-#define RXTX_REG22 0x02c
-#define RXTX_REG22_SO_LATCH_CALOUT_RD(src) ((0x000003f0 & (u32) (src)) >> 4)
-#define RXTX_REG22_EO_LATCH_CALOUT_RD(src) ((0x0000fc00 & (u32) (src)) >> 10)
-#define RXTX_REG22_LATCH_CAL_FAIL_EVEN_RD(src) ((0x0000000f & (u32)(src)))
-#define RXTX_REG23 0x02e
-#define RXTX_REG23_DE_LATCH_CALOUT_RD(src) ((0x0000fc00 & (u32) (src)) >> 10)
-#define RXTX_REG23_XE_LATCH_CALOUT_RD(src) ((0x000003f0 & (u32) (src)) >> 4)
-#define RXTX_REG24 0x030
-#define RXTX_REG24_EE_LATCH_CALOUT_RD(src) ((0x0000fc00 & (u32) (src)) >> 10)
-#define RXTX_REG24_SE_LATCH_CALOUT_RD(src) ((0x000003f0 & (u32) (src)) >> 4)
-#define RXTX_REG27 0x036
-#define RXTX_REG28 0x038
-#define RXTX_REG31 0x03e
-#define RXTX_REG38 0x04c
-#define RXTX_REG38_CUSTOMER_PINMODE_INV_SET(dst, src) \
- (((dst) & 0x0000fffe) | (((u32) (src) << 1) & 0x0000fffe))
-#define RXTX_REG39 0x04e
-#define RXTX_REG40 0x050
-#define RXTX_REG41 0x052
-#define RXTX_REG42 0x054
-#define RXTX_REG43 0x056
-#define RXTX_REG44 0x058
-#define RXTX_REG45 0x05a
-#define RXTX_REG46 0x05c
-#define RXTX_REG47 0x05e
-#define RXTX_REG48 0x060
-#define RXTX_REG49 0x062
-#define RXTX_REG50 0x064
-#define RXTX_REG51 0x066
-#define RXTX_REG52 0x068
-#define RXTX_REG53 0x06a
-#define RXTX_REG54 0x06c
-#define RXTX_REG55 0x06e
-#define RXTX_REG61 0x07a
-#define RXTX_REG61_ISCAN_INBERT_SET(dst, src) \
- (((dst) & ~0x00000010) | (((u32) (src) << 4) & 0x00000010))
-#define RXTX_REG61_LOADFREQ_SHIFT_SET(dst, src) \
- (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
-#define RXTX_REG61_EYE_COUNT_WIDTH_SEL_SET(dst, src) \
- (((dst) & ~0x000000c0) | (((u32) (src) << 6) & 0x000000c0))
-#define RXTX_REG61_SPD_SEL_CDR_SET(dst, src) \
- (((dst) & ~0x00003c00) | (((u32) (src) << 10) & 0x00003c00))
-#define RXTX_REG62 0x07c
-#define RXTX_REG62_PERIOD_H1_QLATCH_SET(dst, src) \
- (((dst) & ~0x00003800) | (((u32) (src) << 11) & 0x00003800))
-#define RXTX_REG81 0x0a2
-#define RXTX_REG89_MU_TH7_SET(dst, src) \
- (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800))
-#define RXTX_REG89_MU_TH8_SET(dst, src) \
- (((dst) & ~0x000007c0) | (((u32) (src) << 6) & 0x000007c0))
-#define RXTX_REG89_MU_TH9_SET(dst, src) \
- (((dst) & ~0x0000003e) | (((u32) (src) << 1) & 0x0000003e))
-#define RXTX_REG96 0x0c0
-#define RXTX_REG96_MU_FREQ1_SET(dst, src) \
- (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800))
-#define RXTX_REG96_MU_FREQ2_SET(dst, src) \
- (((dst) & ~0x000007c0) | (((u32) (src) << 6) & 0x000007c0))
-#define RXTX_REG96_MU_FREQ3_SET(dst, src) \
- (((dst) & ~0x0000003e) | (((u32) (src) << 1) & 0x0000003e))
-#define RXTX_REG99 0x0c6
-#define RXTX_REG99_MU_PHASE1_SET(dst, src) \
- (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800))
-#define RXTX_REG99_MU_PHASE2_SET(dst, src) \
- (((dst) & ~0x000007c0) | (((u32) (src) << 6) & 0x000007c0))
-#define RXTX_REG99_MU_PHASE3_SET(dst, src) \
- (((dst) & ~0x0000003e) | (((u32) (src) << 1) & 0x0000003e))
-#define RXTX_REG102 0x0cc
-#define RXTX_REG102_FREQLOOP_LIMIT_SET(dst, src) \
- (((dst) & ~0x00000060) | (((u32) (src) << 5) & 0x00000060))
-#define RXTX_REG114 0x0e4
-#define RXTX_REG121 0x0f2
-#define RXTX_REG121_SUMOS_CAL_CODE_RD(src) ((0x0000003e & (u32)(src)) >> 0x1)
-#define RXTX_REG125 0x0fa
-#define RXTX_REG125_PQ_REG_SET(dst, src) \
- (((dst) & ~0x0000fe00) | (((u32) (src) << 9) & 0x0000fe00))
-#define RXTX_REG125_SIGN_PQ_SET(dst, src) \
- (((dst) & ~0x00000100) | (((u32) (src) << 8) & 0x00000100))
-#define RXTX_REG125_SIGN_PQ_2C_SET(dst, src) \
- (((dst) & ~0x00000080) | (((u32) (src) << 7) & 0x00000080))
-#define RXTX_REG125_PHZ_MANUALCODE_SET(dst, src) \
- (((dst) & ~0x0000007c) | (((u32) (src) << 2) & 0x0000007c))
-#define RXTX_REG125_PHZ_MANUAL_SET(dst, src) \
- (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002))
-#define RXTX_REG127 0x0fe
-#define RXTX_REG127_FORCE_SUM_CAL_START_MASK 0x00000002
-#define RXTX_REG127_FORCE_LAT_CAL_START_MASK 0x00000004
-#define RXTX_REG127_FORCE_SUM_CAL_START_SET(dst, src) \
- (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002))
-#define RXTX_REG127_FORCE_LAT_CAL_START_SET(dst, src) \
- (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004))
-#define RXTX_REG127_LATCH_MAN_CAL_ENA_SET(dst, src) \
- (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
-#define RXTX_REG127_DO_LATCH_MANCAL_SET(dst, src) \
- (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00))
-#define RXTX_REG127_XO_LATCH_MANCAL_SET(dst, src) \
- (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0))
-#define RXTX_REG128 0x100
-#define RXTX_REG128_LATCH_CAL_WAIT_SEL_SET(dst, src) \
- (((dst) & ~0x0000000c) | (((u32) (src) << 2) & 0x0000000c))
-#define RXTX_REG128_EO_LATCH_MANCAL_SET(dst, src) \
- (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00))
-#define RXTX_REG128_SO_LATCH_MANCAL_SET(dst, src) \
- (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0))
-#define RXTX_REG129 0x102
-#define RXTX_REG129_DE_LATCH_MANCAL_SET(dst, src) \
- (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00))
-#define RXTX_REG129_XE_LATCH_MANCAL_SET(dst, src) \
- (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0))
-#define RXTX_REG130 0x104
-#define RXTX_REG130_EE_LATCH_MANCAL_SET(dst, src) \
- (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00))
-#define RXTX_REG130_SE_LATCH_MANCAL_SET(dst, src) \
- (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0))
-#define RXTX_REG145 0x122
-#define RXTX_REG145_TX_IDLE_SATA_SET(dst, src) \
- (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001))
-#define RXTX_REG145_RXES_ENA_SET(dst, src) \
- (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002))
-#define RXTX_REG145_RXDFE_CONFIG_SET(dst, src) \
- (((dst) & ~0x0000c000) | (((u32) (src) << 14) & 0x0000c000))
-#define RXTX_REG145_RXVWES_LATENA_SET(dst, src) \
- (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004))
-#define RXTX_REG147 0x126
-#define RXTX_REG148 0x128
-
-/* Clock macro type */
-enum cmu_type_t {
- REF_CMU = 0, /* Clock macro is the internal reference clock */
- PHY_CMU = 1, /* Clock macro is the PLL for the Serdes */
-};
-
-enum mux_type_t {
- MUX_SELECT_ATA = 0, /* Switch the MUX to ATA */
- MUX_SELECT_SGMMII = 0, /* Switch the MUX to SGMII */
-};
-
-enum clk_type_t {
- CLK_EXT_DIFF = 0, /* External differential */
- CLK_INT_DIFF = 1, /* Internal differential */
- CLK_INT_SING = 2, /* Internal single ended */
-};
-
-enum phy_mode {
- MODE_SATA = 0, /* List them for simple reference */
- MODE_SGMII = 1,
- MODE_PCIE = 2,
- MODE_USB = 3,
- MODE_XFI = 4,
- MODE_MAX
-};
-
-struct xgene_sata_override_param {
- u32 speed[MAX_LANE]; /* Index for override parameter per lane */
- u32 txspeed[3]; /* Tx speed */
- u32 txboostgain[MAX_LANE*3]; /* Tx freq boost and gain control */
- u32 txeyetuning[MAX_LANE*3]; /* Tx eye tuning */
- u32 txeyedirection[MAX_LANE*3]; /* Tx eye tuning direction */
- u32 txamplitude[MAX_LANE*3]; /* Tx amplitude control */
- u32 txprecursor_cn1[MAX_LANE*3]; /* Tx emphasis taps 1st pre-cursor */
- u32 txprecursor_cn2[MAX_LANE*3]; /* Tx emphasis taps 2nd pre-cursor */
- u32 txpostcursor_cp1[MAX_LANE*3]; /* Tx emphasis taps post-cursor */
-};
-
-struct xgene_phy_ctx {
- struct device *dev;
- struct phy *phy;
- enum phy_mode mode; /* Mode of operation */
- enum clk_type_t clk_type; /* Input clock selection */
- void __iomem *sds_base; /* PHY CSR base addr */
- struct clk *clk; /* Optional clock */
-
- /* Override Serdes parameters */
- struct xgene_sata_override_param sata_param;
-};
-
-/*
- * For chip earlier than A3 version, enable this flag.
- * To enable, pass boot argument phy_xgene.preA3Chip=1
- */
-static int preA3Chip;
-MODULE_PARM_DESC(preA3Chip, "Enable pre-A3 chip support (1=enable 0=disable)");
-module_param_named(preA3Chip, preA3Chip, int, 0444);
-
-static void sds_wr(void __iomem *csr_base, u32 indirect_cmd_reg,
- u32 indirect_data_reg, u32 addr, u32 data)
-{
- unsigned long deadline = jiffies + HZ;
- u32 val;
- u32 cmd;
-
- cmd = CFG_IND_WR_CMD_MASK | CFG_IND_CMD_DONE_MASK;
- cmd = CFG_IND_ADDR_SET(cmd, addr);
- writel(data, csr_base + indirect_data_reg);
- readl(csr_base + indirect_data_reg); /* Force a barrier */
- writel(cmd, csr_base + indirect_cmd_reg);
- readl(csr_base + indirect_cmd_reg); /* Force a barrier */
- do {
- val = readl(csr_base + indirect_cmd_reg);
- } while (!(val & CFG_IND_CMD_DONE_MASK) &&
- time_before(jiffies, deadline));
- if (!(val & CFG_IND_CMD_DONE_MASK))
- pr_err("SDS WR timeout at 0x%p offset 0x%08X value 0x%08X\n",
- csr_base + indirect_cmd_reg, addr, data);
-}
-
-static void sds_rd(void __iomem *csr_base, u32 indirect_cmd_reg,
- u32 indirect_data_reg, u32 addr, u32 *data)
-{
- unsigned long deadline = jiffies + HZ;
- u32 val;
- u32 cmd;
-
- cmd = CFG_IND_RD_CMD_MASK | CFG_IND_CMD_DONE_MASK;
- cmd = CFG_IND_ADDR_SET(cmd, addr);
- writel(cmd, csr_base + indirect_cmd_reg);
- readl(csr_base + indirect_cmd_reg); /* Force a barrier */
- do {
- val = readl(csr_base + indirect_cmd_reg);
- } while (!(val & CFG_IND_CMD_DONE_MASK) &&
- time_before(jiffies, deadline));
- *data = readl(csr_base + indirect_data_reg);
- if (!(val & CFG_IND_CMD_DONE_MASK))
- pr_err("SDS WR timeout at 0x%p offset 0x%08X value 0x%08X\n",
- csr_base + indirect_cmd_reg, addr, *data);
-}
-
-static void cmu_wr(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type,
- u32 reg, u32 data)
-{
- void __iomem *sds_base = ctx->sds_base;
- u32 val;
-
- if (cmu_type == REF_CMU)
- reg += SERDES_PLL_REF_INDIRECT_OFFSET;
- else
- reg += SERDES_PLL_INDIRECT_OFFSET;
- sds_wr(sds_base, SATA_ENET_SDS_IND_CMD_REG,
- SATA_ENET_SDS_IND_WDATA_REG, reg, data);
- sds_rd(sds_base, SATA_ENET_SDS_IND_CMD_REG,
- SATA_ENET_SDS_IND_RDATA_REG, reg, &val);
- pr_debug("CMU WR addr 0x%X value 0x%08X <-> 0x%08X\n", reg, data, val);
-}
-
-static void cmu_rd(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type,
- u32 reg, u32 *data)
-{
- void __iomem *sds_base = ctx->sds_base;
-
- if (cmu_type == REF_CMU)
- reg += SERDES_PLL_REF_INDIRECT_OFFSET;
- else
- reg += SERDES_PLL_INDIRECT_OFFSET;
- sds_rd(sds_base, SATA_ENET_SDS_IND_CMD_REG,
- SATA_ENET_SDS_IND_RDATA_REG, reg, data);
- pr_debug("CMU RD addr 0x%X value 0x%08X\n", reg, *data);
-}
-
-static void cmu_toggle1to0(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type,
- u32 reg, u32 bits)
-{
- u32 val;
-
- cmu_rd(ctx, cmu_type, reg, &val);
- val |= bits;
- cmu_wr(ctx, cmu_type, reg, val);
- cmu_rd(ctx, cmu_type, reg, &val);
- val &= ~bits;
- cmu_wr(ctx, cmu_type, reg, val);
-}
-
-static void cmu_clrbits(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type,
- u32 reg, u32 bits)
-{
- u32 val;
-
- cmu_rd(ctx, cmu_type, reg, &val);
- val &= ~bits;
- cmu_wr(ctx, cmu_type, reg, val);
-}
-
-static void cmu_setbits(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type,
- u32 reg, u32 bits)
-{
- u32 val;
-
- cmu_rd(ctx, cmu_type, reg, &val);
- val |= bits;
- cmu_wr(ctx, cmu_type, reg, val);
-}
-
-static void serdes_wr(struct xgene_phy_ctx *ctx, int lane, u32 reg, u32 data)
-{
- void __iomem *sds_base = ctx->sds_base;
- u32 val;
-
- reg += SERDES_INDIRECT_OFFSET;
- reg += lane * SERDES_LANE_STRIDE;
- sds_wr(sds_base, SATA_ENET_SDS_IND_CMD_REG,
- SATA_ENET_SDS_IND_WDATA_REG, reg, data);
- sds_rd(sds_base, SATA_ENET_SDS_IND_CMD_REG,
- SATA_ENET_SDS_IND_RDATA_REG, reg, &val);
- pr_debug("SERDES WR addr 0x%X value 0x%08X <-> 0x%08X\n", reg, data,
- val);
-}
-
-static void serdes_rd(struct xgene_phy_ctx *ctx, int lane, u32 reg, u32 *data)
-{
- void __iomem *sds_base = ctx->sds_base;
-
- reg += SERDES_INDIRECT_OFFSET;
- reg += lane * SERDES_LANE_STRIDE;
- sds_rd(sds_base, SATA_ENET_SDS_IND_CMD_REG,
- SATA_ENET_SDS_IND_RDATA_REG, reg, data);
- pr_debug("SERDES RD addr 0x%X value 0x%08X\n", reg, *data);
-}
-
-static void serdes_clrbits(struct xgene_phy_ctx *ctx, int lane, u32 reg,
- u32 bits)
-{
- u32 val;
-
- serdes_rd(ctx, lane, reg, &val);
- val &= ~bits;
- serdes_wr(ctx, lane, reg, val);
-}
-
-static void serdes_setbits(struct xgene_phy_ctx *ctx, int lane, u32 reg,
- u32 bits)
-{
- u32 val;
-
- serdes_rd(ctx, lane, reg, &val);
- val |= bits;
- serdes_wr(ctx, lane, reg, val);
-}
-
-static void xgene_phy_cfg_cmu_clk_type(struct xgene_phy_ctx *ctx,
- enum cmu_type_t cmu_type,
- enum clk_type_t clk_type)
-{
- u32 val;
-
- /* Set the reset sequence delay for TX ready assertion */
- cmu_rd(ctx, cmu_type, CMU_REG12, &val);
- val = CMU_REG12_STATE_DELAY9_SET(val, 0x1);
- cmu_wr(ctx, cmu_type, CMU_REG12, val);
- /* Set the programmable stage delays between various enable stages */
- cmu_wr(ctx, cmu_type, CMU_REG13, 0x0222);
- cmu_wr(ctx, cmu_type, CMU_REG14, 0x2225);
-
- /* Configure clock type */
- if (clk_type == CLK_EXT_DIFF) {
- /* Select external clock mux */
- cmu_rd(ctx, cmu_type, CMU_REG0, &val);
- val = CMU_REG0_PLL_REF_SEL_SET(val, 0x0);
- cmu_wr(ctx, cmu_type, CMU_REG0, val);
- /* Select CMOS as reference clock */
- cmu_rd(ctx, cmu_type, CMU_REG1, &val);
- val = CMU_REG1_REFCLK_CMOS_SEL_SET(val, 0x0);
- cmu_wr(ctx, cmu_type, CMU_REG1, val);
- dev_dbg(ctx->dev, "Set external reference clock\n");
- } else if (clk_type == CLK_INT_DIFF) {
- /* Select internal clock mux */
- cmu_rd(ctx, cmu_type, CMU_REG0, &val);
- val = CMU_REG0_PLL_REF_SEL_SET(val, 0x1);
- cmu_wr(ctx, cmu_type, CMU_REG0, val);
- /* Select CMOS as reference clock */
- cmu_rd(ctx, cmu_type, CMU_REG1, &val);
- val = CMU_REG1_REFCLK_CMOS_SEL_SET(val, 0x1);
- cmu_wr(ctx, cmu_type, CMU_REG1, val);
- dev_dbg(ctx->dev, "Set internal reference clock\n");
- } else if (clk_type == CLK_INT_SING) {
- /*
- * NOTE: This clock type is NOT support for controller
- * whose internal clock shared in the PCIe controller
- *
- * Select internal clock mux
- */
- cmu_rd(ctx, cmu_type, CMU_REG1, &val);
- val = CMU_REG1_REFCLK_CMOS_SEL_SET(val, 0x1);
- cmu_wr(ctx, cmu_type, CMU_REG1, val);
- /* Select CML as reference clock */
- cmu_rd(ctx, cmu_type, CMU_REG1, &val);
- val = CMU_REG1_REFCLK_CMOS_SEL_SET(val, 0x0);
- cmu_wr(ctx, cmu_type, CMU_REG1, val);
- dev_dbg(ctx->dev,
- "Set internal single ended reference clock\n");
- }
-}
-
-static void xgene_phy_sata_cfg_cmu_core(struct xgene_phy_ctx *ctx,
- enum cmu_type_t cmu_type,
- enum clk_type_t clk_type)
-{
- u32 val;
- int ref_100MHz;
-
- if (cmu_type == REF_CMU) {
- /* Set VCO calibration voltage threshold */
- cmu_rd(ctx, cmu_type, CMU_REG34, &val);
- val = CMU_REG34_VCO_CAL_VTH_LO_MAX_SET(val, 0x7);
- val = CMU_REG34_VCO_CAL_VTH_HI_MAX_SET(val, 0xc);
- val = CMU_REG34_VCO_CAL_VTH_LO_MIN_SET(val, 0x3);
- val = CMU_REG34_VCO_CAL_VTH_HI_MIN_SET(val, 0x8);
- cmu_wr(ctx, cmu_type, CMU_REG34, val);
- }
-
- /* Set the VCO calibration counter */
- cmu_rd(ctx, cmu_type, CMU_REG0, &val);
- if (cmu_type == REF_CMU || preA3Chip)
- val = CMU_REG0_CAL_COUNT_RESOL_SET(val, 0x4);
- else
- val = CMU_REG0_CAL_COUNT_RESOL_SET(val, 0x7);
- cmu_wr(ctx, cmu_type, CMU_REG0, val);
-
- /* Configure PLL for calibration */
- cmu_rd(ctx, cmu_type, CMU_REG1, &val);
- val = CMU_REG1_PLL_CP_SET(val, 0x1);
- if (cmu_type == REF_CMU || preA3Chip)
- val = CMU_REG1_PLL_CP_SEL_SET(val, 0x5);
- else
- val = CMU_REG1_PLL_CP_SEL_SET(val, 0x3);
- if (cmu_type == REF_CMU)
- val = CMU_REG1_PLL_MANUALCAL_SET(val, 0x0);
- else
- val = CMU_REG1_PLL_MANUALCAL_SET(val, 0x1);
- cmu_wr(ctx, cmu_type, CMU_REG1, val);
-
- if (cmu_type != REF_CMU)
- cmu_clrbits(ctx, cmu_type, CMU_REG5, CMU_REG5_PLL_RESETB_MASK);
-
- /* Configure the PLL for either 100MHz or 50MHz */
- cmu_rd(ctx, cmu_type, CMU_REG2, &val);
- if (cmu_type == REF_CMU) {
- val = CMU_REG2_PLL_LFRES_SET(val, 0xa);
- ref_100MHz = 1;
- } else {
- val = CMU_REG2_PLL_LFRES_SET(val, 0x3);
- if (clk_type == CLK_EXT_DIFF)
- ref_100MHz = 0;
- else
- ref_100MHz = 1;
- }
- if (ref_100MHz) {
- val = CMU_REG2_PLL_FBDIV_SET(val, FBDIV_VAL_100M);
- val = CMU_REG2_PLL_REFDIV_SET(val, REFDIV_VAL_100M);
- } else {
- val = CMU_REG2_PLL_FBDIV_SET(val, FBDIV_VAL_50M);
- val = CMU_REG2_PLL_REFDIV_SET(val, REFDIV_VAL_50M);
- }
- cmu_wr(ctx, cmu_type, CMU_REG2, val);
-
- /* Configure the VCO */
- cmu_rd(ctx, cmu_type, CMU_REG3, &val);
- if (cmu_type == REF_CMU) {
- val = CMU_REG3_VCOVARSEL_SET(val, 0x3);
- val = CMU_REG3_VCO_MOMSEL_INIT_SET(val, 0x10);
- } else {
- val = CMU_REG3_VCOVARSEL_SET(val, 0xF);
- if (preA3Chip)
- val = CMU_REG3_VCO_MOMSEL_INIT_SET(val, 0x15);
- else
- val = CMU_REG3_VCO_MOMSEL_INIT_SET(val, 0x1a);
- val = CMU_REG3_VCO_MANMOMSEL_SET(val, 0x15);
- }
- cmu_wr(ctx, cmu_type, CMU_REG3, val);
-
- /* Disable force PLL lock */
- cmu_rd(ctx, cmu_type, CMU_REG26, &val);
- val = CMU_REG26_FORCE_PLL_LOCK_SET(val, 0x0);
- cmu_wr(ctx, cmu_type, CMU_REG26, val);
-
- /* Setup PLL loop filter */
- cmu_rd(ctx, cmu_type, CMU_REG5, &val);
- val = CMU_REG5_PLL_LFSMCAP_SET(val, 0x3);
- val = CMU_REG5_PLL_LFCAP_SET(val, 0x3);
- if (cmu_type == REF_CMU || !preA3Chip)
- val = CMU_REG5_PLL_LOCK_RESOLUTION_SET(val, 0x7);
- else
- val = CMU_REG5_PLL_LOCK_RESOLUTION_SET(val, 0x4);
- cmu_wr(ctx, cmu_type, CMU_REG5, val);
-
- /* Enable or disable manual calibration */
- cmu_rd(ctx, cmu_type, CMU_REG6, &val);
- val = CMU_REG6_PLL_VREGTRIM_SET(val, preA3Chip ? 0x0 : 0x2);
- val = CMU_REG6_MAN_PVT_CAL_SET(val, preA3Chip ? 0x1 : 0x0);
- cmu_wr(ctx, cmu_type, CMU_REG6, val);
-
- /* Configure lane for 20-bits */
- if (cmu_type == PHY_CMU) {
- cmu_rd(ctx, cmu_type, CMU_REG9, &val);
- val = CMU_REG9_TX_WORD_MODE_CH1_SET(val,
- CMU_REG9_WORD_LEN_20BIT);
- val = CMU_REG9_TX_WORD_MODE_CH0_SET(val,
- CMU_REG9_WORD_LEN_20BIT);
- val = CMU_REG9_PLL_POST_DIVBY2_SET(val, 0x1);
- if (!preA3Chip) {
- val = CMU_REG9_VBG_BYPASSB_SET(val, 0x0);
- val = CMU_REG9_IGEN_BYPASS_SET(val , 0x0);
- }
- cmu_wr(ctx, cmu_type, CMU_REG9, val);
-
- if (!preA3Chip) {
- cmu_rd(ctx, cmu_type, CMU_REG10, &val);
- val = CMU_REG10_VREG_REFSEL_SET(val, 0x1);
- cmu_wr(ctx, cmu_type, CMU_REG10, val);
- }
- }
-
- cmu_rd(ctx, cmu_type, CMU_REG16, &val);
- val = CMU_REG16_CALIBRATION_DONE_OVERRIDE_SET(val, 0x1);
- val = CMU_REG16_BYPASS_PLL_LOCK_SET(val, 0x1);
- if (cmu_type == REF_CMU || preA3Chip)
- val = CMU_REG16_VCOCAL_WAIT_BTW_CODE_SET(val, 0x4);
- else
- val = CMU_REG16_VCOCAL_WAIT_BTW_CODE_SET(val, 0x7);
- cmu_wr(ctx, cmu_type, CMU_REG16, val);
-
- /* Configure for SATA */
- cmu_rd(ctx, cmu_type, CMU_REG30, &val);
- val = CMU_REG30_PCIE_MODE_SET(val, 0x0);
- val = CMU_REG30_LOCK_COUNT_SET(val, 0x3);
- cmu_wr(ctx, cmu_type, CMU_REG30, val);
-
- /* Disable state machine bypass */
- cmu_wr(ctx, cmu_type, CMU_REG31, 0xF);
-
- cmu_rd(ctx, cmu_type, CMU_REG32, &val);
- val = CMU_REG32_PVT_CAL_WAIT_SEL_SET(val, 0x3);
- if (cmu_type == REF_CMU || preA3Chip)
- val = CMU_REG32_IREF_ADJ_SET(val, 0x3);
- else
- val = CMU_REG32_IREF_ADJ_SET(val, 0x1);
- cmu_wr(ctx, cmu_type, CMU_REG32, val);
-
- /* Set VCO calibration threshold */
- if (cmu_type != REF_CMU && preA3Chip)
- cmu_wr(ctx, cmu_type, CMU_REG34, 0x8d27);
- else
- cmu_wr(ctx, cmu_type, CMU_REG34, 0x873c);
-
- /* Set CTLE Override and override waiting from state machine */
- cmu_wr(ctx, cmu_type, CMU_REG37, 0xF00F);
-}
-
-static void xgene_phy_ssc_enable(struct xgene_phy_ctx *ctx,
- enum cmu_type_t cmu_type)
-{
- u32 val;
-
- /* Set SSC modulation value */
- cmu_rd(ctx, cmu_type, CMU_REG35, &val);
- val = CMU_REG35_PLL_SSC_MOD_SET(val, 98);
- cmu_wr(ctx, cmu_type, CMU_REG35, val);
-
- /* Enable SSC, set vertical step and DSM value */
- cmu_rd(ctx, cmu_type, CMU_REG36, &val);
- val = CMU_REG36_PLL_SSC_VSTEP_SET(val, 30);
- val = CMU_REG36_PLL_SSC_EN_SET(val, 1);
- val = CMU_REG36_PLL_SSC_DSMSEL_SET(val, 1);
- cmu_wr(ctx, cmu_type, CMU_REG36, val);
-
- /* Reset the PLL */
- cmu_clrbits(ctx, cmu_type, CMU_REG5, CMU_REG5_PLL_RESETB_MASK);
- cmu_setbits(ctx, cmu_type, CMU_REG5, CMU_REG5_PLL_RESETB_MASK);
-
- /* Force VCO calibration to restart */
- cmu_toggle1to0(ctx, cmu_type, CMU_REG32,
- CMU_REG32_FORCE_VCOCAL_START_MASK);
-}
-
-static void xgene_phy_sata_cfg_lanes(struct xgene_phy_ctx *ctx)
-{
- u32 val;
- u32 reg;
- int i;
- int lane;
-
- for (lane = 0; lane < MAX_LANE; lane++) {
- serdes_wr(ctx, lane, RXTX_REG147, 0x6);
-
- /* Set boost control for quarter, half, and full rate */
- serdes_rd(ctx, lane, RXTX_REG0, &val);
- val = RXTX_REG0_CTLE_EQ_HR_SET(val, 0x10);
- val = RXTX_REG0_CTLE_EQ_QR_SET(val, 0x10);
- val = RXTX_REG0_CTLE_EQ_FR_SET(val, 0x10);
- serdes_wr(ctx, lane, RXTX_REG0, val);
-
- /* Set boost control value */
- serdes_rd(ctx, lane, RXTX_REG1, &val);
- val = RXTX_REG1_RXACVCM_SET(val, 0x7);
- val = RXTX_REG1_CTLE_EQ_SET(val,
- ctx->sata_param.txboostgain[lane * 3 +
- ctx->sata_param.speed[lane]]);
- serdes_wr(ctx, lane, RXTX_REG1, val);
-
- /* Latch VTT value based on the termination to ground and
- enable TX FIFO */
- serdes_rd(ctx, lane, RXTX_REG2, &val);
- val = RXTX_REG2_VTT_ENA_SET(val, 0x1);
- val = RXTX_REG2_VTT_SEL_SET(val, 0x1);
- val = RXTX_REG2_TX_FIFO_ENA_SET(val, 0x1);
- serdes_wr(ctx, lane, RXTX_REG2, val);
-
- /* Configure Tx for 20-bits */
- serdes_rd(ctx, lane, RXTX_REG4, &val);
- val = RXTX_REG4_TX_WORD_MODE_SET(val, CMU_REG9_WORD_LEN_20BIT);
- serdes_wr(ctx, lane, RXTX_REG4, val);
-
- if (!preA3Chip) {
- serdes_rd(ctx, lane, RXTX_REG1, &val);
- val = RXTX_REG1_RXVREG1_SET(val, 0x2);
- val = RXTX_REG1_RXIREF_ADJ_SET(val, 0x2);
- serdes_wr(ctx, lane, RXTX_REG1, val);
- }
-
- /* Set pre-emphasis first 1 and 2, and post-emphasis values */
- serdes_rd(ctx, lane, RXTX_REG5, &val);
- val = RXTX_REG5_TX_CN1_SET(val,
- ctx->sata_param.txprecursor_cn1[lane * 3 +
- ctx->sata_param.speed[lane]]);
- val = RXTX_REG5_TX_CP1_SET(val,
- ctx->sata_param.txpostcursor_cp1[lane * 3 +
- ctx->sata_param.speed[lane]]);
- val = RXTX_REG5_TX_CN2_SET(val,
- ctx->sata_param.txprecursor_cn2[lane * 3 +
- ctx->sata_param.speed[lane]]);
- serdes_wr(ctx, lane, RXTX_REG5, val);
-
- /* Set TX amplitude value */
- serdes_rd(ctx, lane, RXTX_REG6, &val);
- val = RXTX_REG6_TXAMP_CNTL_SET(val,
- ctx->sata_param.txamplitude[lane * 3 +
- ctx->sata_param.speed[lane]]);
- val = RXTX_REG6_TXAMP_ENA_SET(val, 0x1);
- val = RXTX_REG6_TX_IDLE_SET(val, 0x0);
- val = RXTX_REG6_RX_BIST_RESYNC_SET(val, 0x0);
- val = RXTX_REG6_RX_BIST_ERRCNT_RD_SET(val, 0x0);
- serdes_wr(ctx, lane, RXTX_REG6, val);
-
- /* Configure Rx for 20-bits */
- serdes_rd(ctx, lane, RXTX_REG7, &val);
- val = RXTX_REG7_BIST_ENA_RX_SET(val, 0x0);
- val = RXTX_REG7_RX_WORD_MODE_SET(val, CMU_REG9_WORD_LEN_20BIT);
- serdes_wr(ctx, lane, RXTX_REG7, val);
-
- /* Set CDR and LOS values and enable Rx SSC */
- serdes_rd(ctx, lane, RXTX_REG8, &val);
- val = RXTX_REG8_CDR_LOOP_ENA_SET(val, 0x1);
- val = RXTX_REG8_CDR_BYPASS_RXLOS_SET(val, 0x0);
- val = RXTX_REG8_SSC_ENABLE_SET(val, 0x1);
- val = RXTX_REG8_SD_DISABLE_SET(val, 0x0);
- val = RXTX_REG8_SD_VREF_SET(val, 0x4);
- serdes_wr(ctx, lane, RXTX_REG8, val);
-
- /* Set phase adjust upper/lower limits */
- serdes_rd(ctx, lane, RXTX_REG11, &val);
- val = RXTX_REG11_PHASE_ADJUST_LIMIT_SET(val, 0x0);
- serdes_wr(ctx, lane, RXTX_REG11, val);
-
- /* Enable Latch Off; disable SUMOS and Tx termination */
- serdes_rd(ctx, lane, RXTX_REG12, &val);
- val = RXTX_REG12_LATCH_OFF_ENA_SET(val, 0x1);
- val = RXTX_REG12_SUMOS_ENABLE_SET(val, 0x0);
- val = RXTX_REG12_RX_DET_TERM_ENABLE_SET(val, 0x0);
- serdes_wr(ctx, lane, RXTX_REG12, val);
-
- /* Set period error latch to 512T and enable BWL */
- serdes_rd(ctx, lane, RXTX_REG26, &val);
- val = RXTX_REG26_PERIOD_ERROR_LATCH_SET(val, 0x0);
- val = RXTX_REG26_BLWC_ENA_SET(val, 0x1);
- serdes_wr(ctx, lane, RXTX_REG26, val);
-
- serdes_wr(ctx, lane, RXTX_REG28, 0x0);
-
- /* Set DFE loop preset value */
- serdes_wr(ctx, lane, RXTX_REG31, 0x0);
-
- /* Set Eye Monitor counter width to 12-bit */
- serdes_rd(ctx, lane, RXTX_REG61, &val);
- val = RXTX_REG61_ISCAN_INBERT_SET(val, 0x1);
- val = RXTX_REG61_LOADFREQ_SHIFT_SET(val, 0x0);
- val = RXTX_REG61_EYE_COUNT_WIDTH_SEL_SET(val, 0x0);
- serdes_wr(ctx, lane, RXTX_REG61, val);
-
- serdes_rd(ctx, lane, RXTX_REG62, &val);
- val = RXTX_REG62_PERIOD_H1_QLATCH_SET(val, 0x0);
- serdes_wr(ctx, lane, RXTX_REG62, val);
-
- /* Set BW select tap X for DFE loop */
- for (i = 0; i < 9; i++) {
- reg = RXTX_REG81 + i * 2;
- serdes_rd(ctx, lane, reg, &val);
- val = RXTX_REG89_MU_TH7_SET(val, 0xe);
- val = RXTX_REG89_MU_TH8_SET(val, 0xe);
- val = RXTX_REG89_MU_TH9_SET(val, 0xe);
- serdes_wr(ctx, lane, reg, val);
- }
-
- /* Set BW select tap X for frequency adjust loop */
- for (i = 0; i < 3; i++) {
- reg = RXTX_REG96 + i * 2;
- serdes_rd(ctx, lane, reg, &val);
- val = RXTX_REG96_MU_FREQ1_SET(val, 0x10);
- val = RXTX_REG96_MU_FREQ2_SET(val, 0x10);
- val = RXTX_REG96_MU_FREQ3_SET(val, 0x10);
- serdes_wr(ctx, lane, reg, val);
- }
-
- /* Set BW select tap X for phase adjust loop */
- for (i = 0; i < 3; i++) {
- reg = RXTX_REG99 + i * 2;
- serdes_rd(ctx, lane, reg, &val);
- val = RXTX_REG99_MU_PHASE1_SET(val, 0x7);
- val = RXTX_REG99_MU_PHASE2_SET(val, 0x7);
- val = RXTX_REG99_MU_PHASE3_SET(val, 0x7);
- serdes_wr(ctx, lane, reg, val);
- }
-
- serdes_rd(ctx, lane, RXTX_REG102, &val);
- val = RXTX_REG102_FREQLOOP_LIMIT_SET(val, 0x0);
- serdes_wr(ctx, lane, RXTX_REG102, val);
-
- serdes_wr(ctx, lane, RXTX_REG114, 0xffe0);
-
- serdes_rd(ctx, lane, RXTX_REG125, &val);
- val = RXTX_REG125_SIGN_PQ_SET(val,
- ctx->sata_param.txeyedirection[lane * 3 +
- ctx->sata_param.speed[lane]]);
- val = RXTX_REG125_PQ_REG_SET(val,
- ctx->sata_param.txeyetuning[lane * 3 +
- ctx->sata_param.speed[lane]]);
- val = RXTX_REG125_PHZ_MANUAL_SET(val, 0x1);
- serdes_wr(ctx, lane, RXTX_REG125, val);
-
- serdes_rd(ctx, lane, RXTX_REG127, &val);
- val = RXTX_REG127_LATCH_MAN_CAL_ENA_SET(val, 0x0);
- serdes_wr(ctx, lane, RXTX_REG127, val);
-
- serdes_rd(ctx, lane, RXTX_REG128, &val);
- val = RXTX_REG128_LATCH_CAL_WAIT_SEL_SET(val, 0x3);
- serdes_wr(ctx, lane, RXTX_REG128, val);
-
- serdes_rd(ctx, lane, RXTX_REG145, &val);
- val = RXTX_REG145_RXDFE_CONFIG_SET(val, 0x3);
- val = RXTX_REG145_TX_IDLE_SATA_SET(val, 0x0);
- if (preA3Chip) {
- val = RXTX_REG145_RXES_ENA_SET(val, 0x1);
- val = RXTX_REG145_RXVWES_LATENA_SET(val, 0x1);
- } else {
- val = RXTX_REG145_RXES_ENA_SET(val, 0x0);
- val = RXTX_REG145_RXVWES_LATENA_SET(val, 0x0);
- }
- serdes_wr(ctx, lane, RXTX_REG145, val);
-
- /*
- * Set Rx LOS filter clock rate, sample rate, and threshold
- * windows
- */
- for (i = 0; i < 4; i++) {
- reg = RXTX_REG148 + i * 2;
- serdes_wr(ctx, lane, reg, 0xFFFF);
- }
- }
-}
-
-static int xgene_phy_cal_rdy_chk(struct xgene_phy_ctx *ctx,
- enum cmu_type_t cmu_type,
- enum clk_type_t clk_type)
-{
- void __iomem *csr_serdes = ctx->sds_base;
- int loop;
- u32 val;
-
- /* Release PHY main reset */
- writel(0xdf, csr_serdes + SATA_ENET_SDS_RST_CTL);
- readl(csr_serdes + SATA_ENET_SDS_RST_CTL); /* Force a barrier */
-
- if (cmu_type != REF_CMU) {
- cmu_setbits(ctx, cmu_type, CMU_REG5, CMU_REG5_PLL_RESETB_MASK);
- /*
- * As per PHY design spec, the PLL reset requires a minimum
- * of 800us.
- */
- usleep_range(800, 1000);
-
- cmu_rd(ctx, cmu_type, CMU_REG1, &val);
- val = CMU_REG1_PLL_MANUALCAL_SET(val, 0x0);
- cmu_wr(ctx, cmu_type, CMU_REG1, val);
- /*
- * As per PHY design spec, the PLL auto calibration requires
- * a minimum of 800us.
- */
- usleep_range(800, 1000);
-
- cmu_toggle1to0(ctx, cmu_type, CMU_REG32,
- CMU_REG32_FORCE_VCOCAL_START_MASK);
- /*
- * As per PHY design spec, the PLL requires a minimum of
- * 800us to settle.
- */
- usleep_range(800, 1000);
- }
-
- if (!preA3Chip)
- goto skip_manual_cal;
-
- /*
- * Configure the termination resister calibration
- * The serial receive pins, RXP/RXN, have TERMination resistor
- * that is required to be calibrated.
- */
- cmu_rd(ctx, cmu_type, CMU_REG17, &val);
- val = CMU_REG17_PVT_CODE_R2A_SET(val, 0x12);
- val = CMU_REG17_RESERVED_7_SET(val, 0x0);
- cmu_wr(ctx, cmu_type, CMU_REG17, val);
- cmu_toggle1to0(ctx, cmu_type, CMU_REG17,
- CMU_REG17_PVT_TERM_MAN_ENA_MASK);
- /*
- * The serial transmit pins, TXP/TXN, have Pull-UP and Pull-DOWN
- * resistors that are required to the calibrated.
- * Configure the pull DOWN calibration
- */
- cmu_rd(ctx, cmu_type, CMU_REG17, &val);
- val = CMU_REG17_PVT_CODE_R2A_SET(val, 0x29);
- val = CMU_REG17_RESERVED_7_SET(val, 0x0);
- cmu_wr(ctx, cmu_type, CMU_REG17, val);
- cmu_toggle1to0(ctx, cmu_type, CMU_REG16,
- CMU_REG16_PVT_DN_MAN_ENA_MASK);
- /* Configure the pull UP calibration */
- cmu_rd(ctx, cmu_type, CMU_REG17, &val);
- val = CMU_REG17_PVT_CODE_R2A_SET(val, 0x28);
- val = CMU_REG17_RESERVED_7_SET(val, 0x0);
- cmu_wr(ctx, cmu_type, CMU_REG17, val);
- cmu_toggle1to0(ctx, cmu_type, CMU_REG16,
- CMU_REG16_PVT_UP_MAN_ENA_MASK);
-
-skip_manual_cal:
- /* Poll the PLL calibration completion status for at least 1 ms */
- loop = 100;
- do {
- cmu_rd(ctx, cmu_type, CMU_REG7, &val);
- if (CMU_REG7_PLL_CALIB_DONE_RD(val))
- break;
- /*
- * As per PHY design spec, PLL calibration status requires
- * a minimum of 10us to be updated.
- */
- usleep_range(10, 100);
- } while (--loop > 0);
-
- cmu_rd(ctx, cmu_type, CMU_REG7, &val);
- dev_dbg(ctx->dev, "PLL calibration %s\n",
- CMU_REG7_PLL_CALIB_DONE_RD(val) ? "done" : "failed");
- if (CMU_REG7_VCO_CAL_FAIL_RD(val)) {
- dev_err(ctx->dev,
- "PLL calibration failed due to VCO failure\n");
- return -1;
- }
- dev_dbg(ctx->dev, "PLL calibration successful\n");
-
- cmu_rd(ctx, cmu_type, CMU_REG15, &val);
- dev_dbg(ctx->dev, "PHY Tx is %sready\n", val & 0x300 ? "" : "not ");
- return 0;
-}
-
-static void xgene_phy_pdwn_force_vco(struct xgene_phy_ctx *ctx,
- enum cmu_type_t cmu_type,
- enum clk_type_t clk_type)
-{
- u32 val;
-
- dev_dbg(ctx->dev, "Reset VCO and re-start again\n");
- if (cmu_type == PHY_CMU) {
- cmu_rd(ctx, cmu_type, CMU_REG16, &val);
- val = CMU_REG16_VCOCAL_WAIT_BTW_CODE_SET(val, 0x7);
- cmu_wr(ctx, cmu_type, CMU_REG16, val);
- }
-
- cmu_toggle1to0(ctx, cmu_type, CMU_REG0, CMU_REG0_PDOWN_MASK);
- cmu_toggle1to0(ctx, cmu_type, CMU_REG32,
- CMU_REG32_FORCE_VCOCAL_START_MASK);
-}
-
-static int xgene_phy_hw_init_sata(struct xgene_phy_ctx *ctx,
- enum clk_type_t clk_type, int ssc_enable)
-{
- void __iomem *sds_base = ctx->sds_base;
- u32 val;
- int i;
-
- /* Configure the PHY for operation */
- dev_dbg(ctx->dev, "Reset PHY\n");
- /* Place PHY into reset */
- writel(0x0, sds_base + SATA_ENET_SDS_RST_CTL);
- val = readl(sds_base + SATA_ENET_SDS_RST_CTL); /* Force a barrier */
- /* Release PHY lane from reset (active high) */
- writel(0x20, sds_base + SATA_ENET_SDS_RST_CTL);
- readl(sds_base + SATA_ENET_SDS_RST_CTL); /* Force a barrier */
- /* Release all PHY module out of reset except PHY main reset */
- writel(0xde, sds_base + SATA_ENET_SDS_RST_CTL);
- readl(sds_base + SATA_ENET_SDS_RST_CTL); /* Force a barrier */
-
- /* Set the operation speed */
- val = readl(sds_base + SATA_ENET_SDS_CTL1);
- val = CFG_I_SPD_SEL_CDR_OVR1_SET(val,
- ctx->sata_param.txspeed[ctx->sata_param.speed[0]]);
- writel(val, sds_base + SATA_ENET_SDS_CTL1);
-
- dev_dbg(ctx->dev, "Set the customer pin mode to SATA\n");
- val = readl(sds_base + SATA_ENET_SDS_CTL0);
- val = REGSPEC_CFG_I_CUSTOMER_PIN_MODE0_SET(val, 0x4421);
- writel(val, sds_base + SATA_ENET_SDS_CTL0);
-
- /* Configure the clock macro unit (CMU) clock type */
- xgene_phy_cfg_cmu_clk_type(ctx, PHY_CMU, clk_type);
-
- /* Configure the clock macro */
- xgene_phy_sata_cfg_cmu_core(ctx, PHY_CMU, clk_type);
-
- /* Enable SSC if enabled */
- if (ssc_enable)
- xgene_phy_ssc_enable(ctx, PHY_CMU);
-
- /* Configure PHY lanes */
- xgene_phy_sata_cfg_lanes(ctx);
-
- /* Set Rx/Tx 20-bit */
- val = readl(sds_base + SATA_ENET_SDS_PCS_CTL0);
- val = REGSPEC_CFG_I_RX_WORDMODE0_SET(val, 0x3);
- val = REGSPEC_CFG_I_TX_WORDMODE0_SET(val, 0x3);
- writel(val, sds_base + SATA_ENET_SDS_PCS_CTL0);
-
- /* Start PLL calibration and try for three times */
- i = 10;
- do {
- if (!xgene_phy_cal_rdy_chk(ctx, PHY_CMU, clk_type))
- break;
- /* If failed, toggle the VCO power signal and start again */
- xgene_phy_pdwn_force_vco(ctx, PHY_CMU, clk_type);
- } while (--i > 0);
- /* Even on failure, allow to continue any way */
- if (i <= 0)
- dev_err(ctx->dev, "PLL calibration failed\n");
-
- return 0;
-}
-
-static int xgene_phy_hw_initialize(struct xgene_phy_ctx *ctx,
- enum clk_type_t clk_type,
- int ssc_enable)
-{
- int rc;
-
- dev_dbg(ctx->dev, "PHY init clk type %d\n", clk_type);
-
- if (ctx->mode == MODE_SATA) {
- rc = xgene_phy_hw_init_sata(ctx, clk_type, ssc_enable);
- if (rc)
- return rc;
- } else {
- dev_err(ctx->dev, "Un-supported customer pin mode %d\n",
- ctx->mode);
- return -ENODEV;
- }
-
- return 0;
-}
-
-/*
- * Receiver Offset Calibration:
- *
- * Calibrate the receiver signal path offset in two steps - summar and
- * latch calibrations
- */
-static void xgene_phy_force_lat_summer_cal(struct xgene_phy_ctx *ctx, int lane)
-{
- int i;
- struct {
- u32 reg;
- u32 val;
- } serdes_reg[] = {
- {RXTX_REG38, 0x0},
- {RXTX_REG39, 0xff00},
- {RXTX_REG40, 0xffff},
- {RXTX_REG41, 0xffff},
- {RXTX_REG42, 0xffff},
- {RXTX_REG43, 0xffff},
- {RXTX_REG44, 0xffff},
- {RXTX_REG45, 0xffff},
- {RXTX_REG46, 0xffff},
- {RXTX_REG47, 0xfffc},
- {RXTX_REG48, 0x0},
- {RXTX_REG49, 0x0},
- {RXTX_REG50, 0x0},
- {RXTX_REG51, 0x0},
- {RXTX_REG52, 0x0},
- {RXTX_REG53, 0x0},
- {RXTX_REG54, 0x0},
- {RXTX_REG55, 0x0},
- };
-
- /* Start SUMMER calibration */
- serdes_setbits(ctx, lane, RXTX_REG127,
- RXTX_REG127_FORCE_SUM_CAL_START_MASK);
- /*
- * As per PHY design spec, the Summer calibration requires a minimum
- * of 100us to complete.
- */
- usleep_range(100, 500);
- serdes_clrbits(ctx, lane, RXTX_REG127,
- RXTX_REG127_FORCE_SUM_CAL_START_MASK);
- /*
- * As per PHY design spec, the auto calibration requires a minimum
- * of 100us to complete.
- */
- usleep_range(100, 500);
-
- /* Start latch calibration */
- serdes_setbits(ctx, lane, RXTX_REG127,
- RXTX_REG127_FORCE_LAT_CAL_START_MASK);
- /*
- * As per PHY design spec, the latch calibration requires a minimum
- * of 100us to complete.
- */
- usleep_range(100, 500);
- serdes_clrbits(ctx, lane, RXTX_REG127,
- RXTX_REG127_FORCE_LAT_CAL_START_MASK);
-
- /* Configure the PHY lane for calibration */
- serdes_wr(ctx, lane, RXTX_REG28, 0x7);
- serdes_wr(ctx, lane, RXTX_REG31, 0x7e00);
- serdes_clrbits(ctx, lane, RXTX_REG4,
- RXTX_REG4_TX_LOOPBACK_BUF_EN_MASK);
- serdes_clrbits(ctx, lane, RXTX_REG7,
- RXTX_REG7_LOOP_BACK_ENA_CTLE_MASK);
- for (i = 0; i < ARRAY_SIZE(serdes_reg); i++)
- serdes_wr(ctx, lane, serdes_reg[i].reg,
- serdes_reg[i].val);
-}
-
-static void xgene_phy_reset_rxd(struct xgene_phy_ctx *ctx, int lane)
-{
- /* Reset digital Rx */
- serdes_clrbits(ctx, lane, RXTX_REG7, RXTX_REG7_RESETB_RXD_MASK);
- /* As per PHY design spec, the reset requires a minimum of 100us. */
- usleep_range(100, 150);
- serdes_setbits(ctx, lane, RXTX_REG7, RXTX_REG7_RESETB_RXD_MASK);
-}
-
-static int xgene_phy_get_avg(int accum, int samples)
-{
- return (accum + (samples / 2)) / samples;
-}
-
-static void xgene_phy_gen_avg_val(struct xgene_phy_ctx *ctx, int lane)
-{
- int max_loop = 10;
- int avg_loop = 0;
- int lat_do = 0, lat_xo = 0, lat_eo = 0, lat_so = 0;
- int lat_de = 0, lat_xe = 0, lat_ee = 0, lat_se = 0;
- int sum_cal = 0;
- int lat_do_itr, lat_xo_itr, lat_eo_itr, lat_so_itr;
- int lat_de_itr, lat_xe_itr, lat_ee_itr, lat_se_itr;
- int sum_cal_itr;
- int fail_even;
- int fail_odd;
- u32 val;
-
- dev_dbg(ctx->dev, "Generating avg calibration value for lane %d\n",
- lane);
-
- /* Enable RX Hi-Z termination */
- serdes_setbits(ctx, lane, RXTX_REG12,
- RXTX_REG12_RX_DET_TERM_ENABLE_MASK);
- /* Turn off DFE */
- serdes_wr(ctx, lane, RXTX_REG28, 0x0000);
- /* DFE Presets to zero */
- serdes_wr(ctx, lane, RXTX_REG31, 0x0000);
-
- /*
- * Receiver Offset Calibration:
- * Calibrate the receiver signal path offset in two steps - summar
- * and latch calibration.
- * Runs the "Receiver Offset Calibration multiple times to determine
- * the average value to use.
- */
- while (avg_loop < max_loop) {
- /* Start the calibration */
- xgene_phy_force_lat_summer_cal(ctx, lane);
-
- serdes_rd(ctx, lane, RXTX_REG21, &val);
- lat_do_itr = RXTX_REG21_DO_LATCH_CALOUT_RD(val);
- lat_xo_itr = RXTX_REG21_XO_LATCH_CALOUT_RD(val);
- fail_odd = RXTX_REG21_LATCH_CAL_FAIL_ODD_RD(val);
-
- serdes_rd(ctx, lane, RXTX_REG22, &val);
- lat_eo_itr = RXTX_REG22_EO_LATCH_CALOUT_RD(val);
- lat_so_itr = RXTX_REG22_SO_LATCH_CALOUT_RD(val);
- fail_even = RXTX_REG22_LATCH_CAL_FAIL_EVEN_RD(val);
-
- serdes_rd(ctx, lane, RXTX_REG23, &val);
- lat_de_itr = RXTX_REG23_DE_LATCH_CALOUT_RD(val);
- lat_xe_itr = RXTX_REG23_XE_LATCH_CALOUT_RD(val);
-
- serdes_rd(ctx, lane, RXTX_REG24, &val);
- lat_ee_itr = RXTX_REG24_EE_LATCH_CALOUT_RD(val);
- lat_se_itr = RXTX_REG24_SE_LATCH_CALOUT_RD(val);
-
- serdes_rd(ctx, lane, RXTX_REG121, &val);
- sum_cal_itr = RXTX_REG121_SUMOS_CAL_CODE_RD(val);
-
- /* Check for failure. If passed, sum them for averaging */
- if ((fail_even == 0 || fail_even == 1) &&
- (fail_odd == 0 || fail_odd == 1)) {
- lat_do += lat_do_itr;
- lat_xo += lat_xo_itr;
- lat_eo += lat_eo_itr;
- lat_so += lat_so_itr;
- lat_de += lat_de_itr;
- lat_xe += lat_xe_itr;
- lat_ee += lat_ee_itr;
- lat_se += lat_se_itr;
- sum_cal += sum_cal_itr;
-
- dev_dbg(ctx->dev, "Iteration %d:\n", avg_loop);
- dev_dbg(ctx->dev, "DO 0x%x XO 0x%x EO 0x%x SO 0x%x\n",
- lat_do_itr, lat_xo_itr, lat_eo_itr,
- lat_so_itr);
- dev_dbg(ctx->dev, "DE 0x%x XE 0x%x EE 0x%x SE 0x%x\n",
- lat_de_itr, lat_xe_itr, lat_ee_itr,
- lat_se_itr);
- dev_dbg(ctx->dev, "SUM 0x%x\n", sum_cal_itr);
- ++avg_loop;
- } else {
- dev_err(ctx->dev,
- "Receiver calibration failed at %d loop\n",
- avg_loop);
- }
- xgene_phy_reset_rxd(ctx, lane);
- }
-
- /* Update latch manual calibration with average value */
- serdes_rd(ctx, lane, RXTX_REG127, &val);
- val = RXTX_REG127_DO_LATCH_MANCAL_SET(val,
- xgene_phy_get_avg(lat_do, max_loop));
- val = RXTX_REG127_XO_LATCH_MANCAL_SET(val,
- xgene_phy_get_avg(lat_xo, max_loop));
- serdes_wr(ctx, lane, RXTX_REG127, val);
-
- serdes_rd(ctx, lane, RXTX_REG128, &val);
- val = RXTX_REG128_EO_LATCH_MANCAL_SET(val,
- xgene_phy_get_avg(lat_eo, max_loop));
- val = RXTX_REG128_SO_LATCH_MANCAL_SET(val,
- xgene_phy_get_avg(lat_so, max_loop));
- serdes_wr(ctx, lane, RXTX_REG128, val);
-
- serdes_rd(ctx, lane, RXTX_REG129, &val);
- val = RXTX_REG129_DE_LATCH_MANCAL_SET(val,
- xgene_phy_get_avg(lat_de, max_loop));
- val = RXTX_REG129_XE_LATCH_MANCAL_SET(val,
- xgene_phy_get_avg(lat_xe, max_loop));
- serdes_wr(ctx, lane, RXTX_REG129, val);
-
- serdes_rd(ctx, lane, RXTX_REG130, &val);
- val = RXTX_REG130_EE_LATCH_MANCAL_SET(val,
- xgene_phy_get_avg(lat_ee, max_loop));
- val = RXTX_REG130_SE_LATCH_MANCAL_SET(val,
- xgene_phy_get_avg(lat_se, max_loop));
- serdes_wr(ctx, lane, RXTX_REG130, val);
-
- /* Update SUMMER calibration with average value */
- serdes_rd(ctx, lane, RXTX_REG14, &val);
- val = RXTX_REG14_CLTE_LATCAL_MAN_PROG_SET(val,
- xgene_phy_get_avg(sum_cal, max_loop));
- serdes_wr(ctx, lane, RXTX_REG14, val);
-
- dev_dbg(ctx->dev, "Average Value:\n");
- dev_dbg(ctx->dev, "DO 0x%x XO 0x%x EO 0x%x SO 0x%x\n",
- xgene_phy_get_avg(lat_do, max_loop),
- xgene_phy_get_avg(lat_xo, max_loop),
- xgene_phy_get_avg(lat_eo, max_loop),
- xgene_phy_get_avg(lat_so, max_loop));
- dev_dbg(ctx->dev, "DE 0x%x XE 0x%x EE 0x%x SE 0x%x\n",
- xgene_phy_get_avg(lat_de, max_loop),
- xgene_phy_get_avg(lat_xe, max_loop),
- xgene_phy_get_avg(lat_ee, max_loop),
- xgene_phy_get_avg(lat_se, max_loop));
- dev_dbg(ctx->dev, "SUM 0x%x\n",
- xgene_phy_get_avg(sum_cal, max_loop));
-
- serdes_rd(ctx, lane, RXTX_REG14, &val);
- val = RXTX_REG14_CTLE_LATCAL_MAN_ENA_SET(val, 0x1);
- serdes_wr(ctx, lane, RXTX_REG14, val);
- dev_dbg(ctx->dev, "Enable Manual Summer calibration\n");
-
- serdes_rd(ctx, lane, RXTX_REG127, &val);
- val = RXTX_REG127_LATCH_MAN_CAL_ENA_SET(val, 0x1);
- dev_dbg(ctx->dev, "Enable Manual Latch calibration\n");
- serdes_wr(ctx, lane, RXTX_REG127, val);
-
- /* Disable RX Hi-Z termination */
- serdes_rd(ctx, lane, RXTX_REG12, &val);
- val = RXTX_REG12_RX_DET_TERM_ENABLE_SET(val, 0);
- serdes_wr(ctx, lane, RXTX_REG12, val);
- /* Turn on DFE */
- serdes_wr(ctx, lane, RXTX_REG28, 0x0007);
- /* Set DFE preset */
- serdes_wr(ctx, lane, RXTX_REG31, 0x7e00);
-}
-
-static int xgene_phy_hw_init(struct phy *phy)
-{
- struct xgene_phy_ctx *ctx = phy_get_drvdata(phy);
- int rc;
- int i;
-
- rc = xgene_phy_hw_initialize(ctx, CLK_EXT_DIFF, SSC_DISABLE);
- if (rc) {
- dev_err(ctx->dev, "PHY initialize failed %d\n", rc);
- return rc;
- }
-
- /* Setup clock properly after PHY configuration */
- if (!IS_ERR(ctx->clk)) {
- /* HW requires an toggle of the clock */
- clk_prepare_enable(ctx->clk);
- clk_disable_unprepare(ctx->clk);
- clk_prepare_enable(ctx->clk);
- }
-
- /* Compute average value */
- for (i = 0; i < MAX_LANE; i++)
- xgene_phy_gen_avg_val(ctx, i);
-
- dev_dbg(ctx->dev, "PHY initialized\n");
- return 0;
-}
-
-static const struct phy_ops xgene_phy_ops = {
- .init = xgene_phy_hw_init,
- .owner = THIS_MODULE,
-};
-
-static struct phy *xgene_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
-{
- struct xgene_phy_ctx *ctx = dev_get_drvdata(dev);
-
- if (args->args_count <= 0)
- return ERR_PTR(-EINVAL);
- if (args->args[0] < MODE_SATA || args->args[0] >= MODE_MAX)
- return ERR_PTR(-EINVAL);
-
- ctx->mode = args->args[0];
- return ctx->phy;
-}
-
-static void xgene_phy_get_param(struct platform_device *pdev,
- const char *name, u32 *buffer,
- int count, u32 *default_val,
- u32 conv_factor)
-{
- int i;
-
- if (!of_property_read_u32_array(pdev->dev.of_node, name, buffer,
- count)) {
- for (i = 0; i < count; i++)
- buffer[i] /= conv_factor;
- return;
- }
- /* Does not exist, load default */
- for (i = 0; i < count; i++)
- buffer[i] = default_val[i % 3];
-}
-
-static int xgene_phy_probe(struct platform_device *pdev)
-{
- struct phy_provider *phy_provider;
- struct xgene_phy_ctx *ctx;
- struct resource *res;
- int rc = 0;
- u32 default_spd[] = DEFAULT_SATA_SPD_SEL;
- u32 default_txboost_gain[] = DEFAULT_SATA_TXBOOST_GAIN;
- u32 default_txeye_direction[] = DEFAULT_SATA_TXEYEDIRECTION;
- u32 default_txeye_tuning[] = DEFAULT_SATA_TXEYETUNING;
- u32 default_txamp[] = DEFAULT_SATA_TXAMP;
- u32 default_txcn1[] = DEFAULT_SATA_TXCN1;
- u32 default_txcn2[] = DEFAULT_SATA_TXCN2;
- u32 default_txcp1[] = DEFAULT_SATA_TXCP1;
- int i;
-
- ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
- if (!ctx)
- return -ENOMEM;
-
- ctx->dev = &pdev->dev;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- ctx->sds_base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(ctx->sds_base)) {
- rc = PTR_ERR(ctx->sds_base);
- goto error;
- }
-
- /* Retrieve optional clock */
- ctx->clk = clk_get(&pdev->dev, NULL);
-
- /* Load override paramaters */
- xgene_phy_get_param(pdev, "apm,tx-eye-tuning",
- ctx->sata_param.txeyetuning, 6, default_txeye_tuning, 1);
- xgene_phy_get_param(pdev, "apm,tx-eye-direction",
- ctx->sata_param.txeyedirection, 6, default_txeye_direction, 1);
- xgene_phy_get_param(pdev, "apm,tx-boost-gain",
- ctx->sata_param.txboostgain, 6, default_txboost_gain, 1);
- xgene_phy_get_param(pdev, "apm,tx-amplitude",
- ctx->sata_param.txamplitude, 6, default_txamp, 13300);
- xgene_phy_get_param(pdev, "apm,tx-pre-cursor1",
- ctx->sata_param.txprecursor_cn1, 6, default_txcn1, 18200);
- xgene_phy_get_param(pdev, "apm,tx-pre-cursor2",
- ctx->sata_param.txprecursor_cn2, 6, default_txcn2, 18200);
- xgene_phy_get_param(pdev, "apm,tx-post-cursor",
- ctx->sata_param.txpostcursor_cp1, 6, default_txcp1, 18200);
- xgene_phy_get_param(pdev, "apm,tx-speed",
- ctx->sata_param.txspeed, 3, default_spd, 1);
- for (i = 0; i < MAX_LANE; i++)
- ctx->sata_param.speed[i] = 2; /* Default to Gen3 */
-
- ctx->dev = &pdev->dev;
- platform_set_drvdata(pdev, ctx);
-
- ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops, NULL);
- if (IS_ERR(ctx->phy)) {
- dev_dbg(&pdev->dev, "Failed to create PHY\n");
- rc = PTR_ERR(ctx->phy);
- goto error;
- }
- phy_set_drvdata(ctx->phy, ctx);
-
- phy_provider = devm_of_phy_provider_register(ctx->dev,
- xgene_phy_xlate);
- if (IS_ERR(phy_provider)) {
- rc = PTR_ERR(phy_provider);
- goto error;
- }
-
- return 0;
-
-error:
- return rc;
-}
-
-static const struct of_device_id xgene_phy_of_match[] = {
- {.compatible = "apm,xgene-phy",},
- {},
-};
-MODULE_DEVICE_TABLE(of, xgene_phy_of_match);
-
-static struct platform_driver xgene_phy_driver = {
- .probe = xgene_phy_probe,
- .driver = {
- .name = "xgene-phy",
- .of_match_table = xgene_phy_of_match,
- },
-};
-module_platform_driver(xgene_phy_driver);
-
-MODULE_DESCRIPTION("APM X-Gene Multi-Purpose PHY driver");
-MODULE_AUTHOR("Loc Ho <lho@apm.com>");
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION("0.1");
+++ /dev/null
-/*
- * omap_control_phy.h - Header file for the PHY part of control module.
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Author: Kishon Vijay Abraham I <kishon@ti.com>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __OMAP_CONTROL_PHY_H__
-#define __OMAP_CONTROL_PHY_H__
-
-enum omap_control_phy_type {
- OMAP_CTRL_TYPE_OTGHS = 1, /* Mailbox OTGHS_CONTROL */
- OMAP_CTRL_TYPE_USB2, /* USB2_PHY, power down in CONTROL_DEV_CONF */
- OMAP_CTRL_TYPE_PIPE3, /* PIPE3 PHY, DPLL & seperate Rx/Tx power */
- OMAP_CTRL_TYPE_PCIE, /* RX TX control of ACSPCIE */
- OMAP_CTRL_TYPE_DRA7USB2, /* USB2 PHY, power and power_aux e.g. DRA7 */
- OMAP_CTRL_TYPE_AM437USB2, /* USB2 PHY, power e.g. AM437x */
-};
-
-struct omap_control_phy {
- struct device *dev;
-
- u32 __iomem *otghs_control;
- u32 __iomem *power;
- u32 __iomem *power_aux;
- u32 __iomem *pcie_pcs;
-
- struct clk *sys_clk;
-
- enum omap_control_phy_type type;
-};
-
-enum omap_control_usb_mode {
- USB_MODE_UNDEFINED = 0,
- USB_MODE_HOST,
- USB_MODE_DEVICE,
- USB_MODE_DISCONNECT,
-};
-
-#define OMAP_CTRL_DEV_PHY_PD BIT(0)
-
-#define OMAP_CTRL_DEV_AVALID BIT(0)
-#define OMAP_CTRL_DEV_BVALID BIT(1)
-#define OMAP_CTRL_DEV_VBUSVALID BIT(2)
-#define OMAP_CTRL_DEV_SESSEND BIT(3)
-#define OMAP_CTRL_DEV_IDDIG BIT(4)
-
-#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK 0x003FC000
-#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT 0xE
-
-#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK 0xFFC00000
-#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT 0x16
-
-#define OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON 0x3
-#define OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF 0x0
-
-#define OMAP_CTRL_PCIE_PCS_MASK 0xff
-#define OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT 0x8
-
-#define OMAP_CTRL_USB2_PHY_PD BIT(28)
-
-#define AM437X_CTRL_USB2_PHY_PD BIT(0)
-#define AM437X_CTRL_USB2_OTG_PD BIT(1)
-#define AM437X_CTRL_USB2_OTGVDET_EN BIT(19)
-#define AM437X_CTRL_USB2_OTGSESSEND_EN BIT(20)
-
-#if IS_ENABLED(CONFIG_OMAP_CONTROL_PHY)
-void omap_control_phy_power(struct device *dev, int on);
-void omap_control_usb_set_mode(struct device *dev,
- enum omap_control_usb_mode mode);
-void omap_control_pcie_pcs(struct device *dev, u8 id, u8 delay);
-#else
-
-static inline void omap_control_phy_power(struct device *dev, int on)
-{
-}
-
-static inline void omap_control_usb_set_mode(struct device *dev,
- enum omap_control_usb_mode mode)
-{
-}
-
-static inline void omap_control_pcie_pcs(struct device *dev, u8 id, u8 delay)
-{
-}
-#endif
-
-#endif /* __OMAP_CONTROL_PHY_H__ */
+++ /dev/null
-/*
- * omap_usb.h -- omap usb2 phy header file
- *
- * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Author: Kishon Vijay Abraham I <kishon@ti.com>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __DRIVERS_OMAP_USB2_H
-#define __DRIVERS_OMAP_USB2_H
-
-#include <linux/io.h>
-#include <linux/usb/otg.h>
-
-struct usb_dpll_params {
- u16 m;
- u8 n;
- u8 freq:3;
- u8 sd;
- u32 mf;
-};
-
-struct omap_usb {
- struct usb_phy phy;
- struct phy_companion *comparator;
- void __iomem *pll_ctrl_base;
- void __iomem *phy_base;
- struct device *dev;
- struct device *control_dev;
- struct clk *wkupclk;
- struct clk *optclk;
- u8 flags;
-};
-
-struct usb_phy_data {
- const char *label;
- u8 flags;
-};
-
-/* Driver Flags */
-#define OMAP_USB2_HAS_START_SRP (1 << 0)
-#define OMAP_USB2_HAS_SET_VBUS (1 << 1)
-#define OMAP_USB2_CALIBRATE_FALSE_DISCONNECT (1 << 2)
-
-#define phy_to_omapusb(x) container_of((x), struct omap_usb, phy)
-
-#if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE)
-extern int omap_usb2_set_comparator(struct phy_companion *comparator);
-#else
-static inline int omap_usb2_set_comparator(struct phy_companion *comparator)
-{
- return -ENODEV;
-}
-#endif
-
-static inline u32 omap_usb_readl(void __iomem *addr, unsigned offset)
-{
- return __raw_readl(addr + offset);
-}
-
-static inline void omap_usb_writel(void __iomem *addr, unsigned offset,
- u32 data)
-{
- __raw_writel(data, addr + offset);
-}
-
-#endif /* __DRIVERS_OMAP_USB_H */
+++ /dev/null
-/*
- * phy.h -- generic phy header file
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
- *
- * Author: Kishon Vijay Abraham I <kishon@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __DRIVERS_PHY_H
-#define __DRIVERS_PHY_H
-
-#include <linux/err.h>
-#include <linux/of.h>
-#include <linux/device.h>
-#include <linux/pm_runtime.h>
-#include <linux/regulator/consumer.h>
-
-struct phy;
-
-/**
- * struct phy_ops - set of function pointers for performing phy operations
- * @init: operation to be performed for initializing phy
- * @exit: operation to be performed while exiting
- * @power_on: powering on the phy
- * @power_off: powering off the phy
- * @owner: the module owner containing the ops
- */
-struct phy_ops {
- int (*init)(struct phy *phy);
- int (*exit)(struct phy *phy);
- int (*power_on)(struct phy *phy);
- int (*power_off)(struct phy *phy);
- struct module *owner;
-};
-
-/**
- * struct phy_attrs - represents phy attributes
- * @bus_width: Data path width implemented by PHY
- */
-struct phy_attrs {
- u32 bus_width;
-};
-
-/**
- * struct phy - represents the phy device
- * @dev: phy device
- * @id: id of the phy device
- * @ops: function pointers for performing phy operations
- * @init_data: list of PHY consumers (non-dt only)
- * @mutex: mutex to protect phy_ops
- * @init_count: used to protect when the PHY is used by multiple consumers
- * @power_count: used to protect when the PHY is used by multiple consumers
- * @phy_attrs: used to specify PHY specific attributes
- */
-struct phy {
- struct device dev;
- int id;
- const struct phy_ops *ops;
- struct phy_init_data *init_data;
- struct mutex mutex;
- int init_count;
- int power_count;
- struct phy_attrs attrs;
- struct regulator *pwr;
-};
-
-/**
- * struct phy_provider - represents the phy provider
- * @dev: phy provider device
- * @owner: the module owner having of_xlate
- * @of_xlate: function pointer to obtain phy instance from phy pointer
- * @list: to maintain a linked list of PHY providers
- */
-struct phy_provider {
- struct device *dev;
- struct module *owner;
- struct list_head list;
- struct phy * (*of_xlate)(struct device *dev,
- struct of_phandle_args *args);
-};
-
-/**
- * struct phy_consumer - represents the phy consumer
- * @dev_name: the device name of the controller that will use this PHY device
- * @port: name given to the consumer port
- */
-struct phy_consumer {
- const char *dev_name;
- const char *port;
-};
-
-/**
- * struct phy_init_data - contains the list of PHY consumers
- * @num_consumers: number of consumers for this PHY device
- * @consumers: list of PHY consumers
- */
-struct phy_init_data {
- unsigned int num_consumers;
- struct phy_consumer *consumers;
-};
-
-#define PHY_CONSUMER(_dev_name, _port) \
-{ \
- .dev_name = _dev_name, \
- .port = _port, \
-}
-
-#define to_phy(dev) (container_of((dev), struct phy, dev))
-
-#define of_phy_provider_register(dev, xlate) \
- __of_phy_provider_register((dev), THIS_MODULE, (xlate))
-
-#define devm_of_phy_provider_register(dev, xlate) \
- __devm_of_phy_provider_register((dev), THIS_MODULE, (xlate))
-
-static inline void phy_set_drvdata(struct phy *phy, void *data)
-{
- dev_set_drvdata(&phy->dev, data);
-}
-
-static inline void *phy_get_drvdata(struct phy *phy)
-{
- return dev_get_drvdata(&phy->dev);
-}
-
-#if IS_ENABLED(CONFIG_GENERIC_PHY)
-int phy_pm_runtime_get(struct phy *phy);
-int phy_pm_runtime_get_sync(struct phy *phy);
-int phy_pm_runtime_put(struct phy *phy);
-int phy_pm_runtime_put_sync(struct phy *phy);
-void phy_pm_runtime_allow(struct phy *phy);
-void phy_pm_runtime_forbid(struct phy *phy);
-int phy_init(struct phy *phy);
-int phy_exit(struct phy *phy);
-int phy_power_on(struct phy *phy);
-int phy_power_off(struct phy *phy);
-static inline int phy_get_bus_width(struct phy *phy)
-{
- return phy->attrs.bus_width;
-}
-static inline void phy_set_bus_width(struct phy *phy, int bus_width)
-{
- phy->attrs.bus_width = bus_width;
-}
-struct phy *phy_get(struct device *dev, const char *string);
-struct phy *phy_optional_get(struct device *dev, const char *string);
-struct phy *devm_phy_get(struct device *dev, const char *string);
-struct phy *devm_phy_optional_get(struct device *dev, const char *string);
-struct phy *devm_of_phy_get(struct device *dev, struct device_node *np,
- const char *con_id);
-void phy_put(struct phy *phy);
-void devm_phy_put(struct device *dev, struct phy *phy);
-struct phy *of_phy_get(struct device_node *np, const char *con_id);
-struct phy *of_phy_simple_xlate(struct device *dev,
- struct of_phandle_args *args);
-struct phy *phy_create(struct device *dev, struct device_node *node,
- const struct phy_ops *ops,
- struct phy_init_data *init_data);
-struct phy *devm_phy_create(struct device *dev, struct device_node *node,
- const struct phy_ops *ops, struct phy_init_data *init_data);
-void phy_destroy(struct phy *phy);
-void devm_phy_destroy(struct device *dev, struct phy *phy);
-struct phy_provider *__of_phy_provider_register(struct device *dev,
- struct module *owner, struct phy * (*of_xlate)(struct device *dev,
- struct of_phandle_args *args));
-struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
- struct module *owner, struct phy * (*of_xlate)(struct device *dev,
- struct of_phandle_args *args));
-void of_phy_provider_unregister(struct phy_provider *phy_provider);
-void devm_of_phy_provider_unregister(struct device *dev,
- struct phy_provider *phy_provider);
-#else
-static inline int phy_pm_runtime_get(struct phy *phy)
-{
- if (!phy)
- return 0;
- return -ENOSYS;
-}
-
-static inline int phy_pm_runtime_get_sync(struct phy *phy)
-{
- if (!phy)
- return 0;
- return -ENOSYS;
-}
-
-static inline int phy_pm_runtime_put(struct phy *phy)
-{
- if (!phy)
- return 0;
- return -ENOSYS;
-}
-
-static inline int phy_pm_runtime_put_sync(struct phy *phy)
-{
- if (!phy)
- return 0;
- return -ENOSYS;
-}
-
-static inline void phy_pm_runtime_allow(struct phy *phy)
-{
- return;
-}
-
-static inline void phy_pm_runtime_forbid(struct phy *phy)
-{
- return;
-}
-
-static inline int phy_init(struct phy *phy)
-{
- if (!phy)
- return 0;
- return -ENOSYS;
-}
-
-static inline int phy_exit(struct phy *phy)
-{
- if (!phy)
- return 0;
- return -ENOSYS;
-}
-
-static inline int phy_power_on(struct phy *phy)
-{
- if (!phy)
- return 0;
- return -ENOSYS;
-}
-
-static inline int phy_power_off(struct phy *phy)
-{
- if (!phy)
- return 0;
- return -ENOSYS;
-}
-
-static inline int phy_get_bus_width(struct phy *phy)
-{
- return -ENOSYS;
-}
-
-static inline void phy_set_bus_width(struct phy *phy, int bus_width)
-{
- return;
-}
-
-static inline struct phy *phy_get(struct device *dev, const char *string)
-{
- return ERR_PTR(-ENOSYS);
-}
-
-static inline struct phy *phy_optional_get(struct device *dev,
- const char *string)
-{
- return ERR_PTR(-ENOSYS);
-}
-
-static inline struct phy *devm_phy_get(struct device *dev, const char *string)
-{
- return ERR_PTR(-ENOSYS);
-}
-
-static inline struct phy *devm_phy_optional_get(struct device *dev,
- const char *string)
-{
- return ERR_PTR(-ENOSYS);
-}
-
-static inline struct phy *devm_of_phy_get(struct device *dev,
- struct device_node *np,
- const char *con_id)
-{
- return ERR_PTR(-ENOSYS);
-}
-
-static inline void phy_put(struct phy *phy)
-{
-}
-
-static inline void devm_phy_put(struct device *dev, struct phy *phy)
-{
-}
-
-static inline struct phy *of_phy_get(struct device_node *np, const char *con_id)
-{
- return ERR_PTR(-ENOSYS);
-}
-
-static inline struct phy *of_phy_simple_xlate(struct device *dev,
- struct of_phandle_args *args)
-{
- return ERR_PTR(-ENOSYS);
-}
-
-static inline struct phy *phy_create(struct device *dev,
- struct device_node *node,
- const struct phy_ops *ops,
- struct phy_init_data *init_data)
-{
- return ERR_PTR(-ENOSYS);
-}
-
-static inline struct phy *devm_phy_create(struct device *dev,
- struct device_node *node,
- const struct phy_ops *ops,
- struct phy_init_data *init_data)
-{
- return ERR_PTR(-ENOSYS);
-}
-
-static inline void phy_destroy(struct phy *phy)
-{
-}
-
-static inline void devm_phy_destroy(struct device *dev, struct phy *phy)
-{
-}
-
-static inline struct phy_provider *__of_phy_provider_register(
- struct device *dev, struct module *owner, struct phy * (*of_xlate)(
- struct device *dev, struct of_phandle_args *args))
-{
- return ERR_PTR(-ENOSYS);
-}
-
-static inline struct phy_provider *__devm_of_phy_provider_register(struct device
- *dev, struct module *owner, struct phy * (*of_xlate)(struct device *dev,
- struct of_phandle_args *args))
-{
- return ERR_PTR(-ENOSYS);
-}
-
-static inline void of_phy_provider_unregister(struct phy_provider *phy_provider)
-{
-}
-
-static inline void devm_of_phy_provider_unregister(struct device *dev,
- struct phy_provider *phy_provider)
-{
-}
-#endif
-
-#endif /* __DRIVERS_PHY_H */