diff options
author | Yaniv Gardi <ygardi@codeaurora.org> | 2015-01-15 09:32:35 -0500 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2015-01-20 13:43:24 -0500 |
commit | adaafaa393ef1900e23f7708e29d023f721c54b3 (patch) | |
tree | a665f01e63c6724b31209f2bc72dfcc64f24951d /drivers/phy/phy-qcom-ufs-i.h | |
parent | c7e09574d620246347a5fb87118e624d69c27f41 (diff) |
phy: qcom-ufs: add support for QUALCOMM Technologies UFS PHY drivers
This change adds a generic and common API support for ufs phy QUALCOMM
Technologies. This support provides common code and also points
to specific phy callbacks to differentiate between different behaviors
of frequent use-cases (like power on, power off, phy calibration etc).
Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
Reviewed-by: Dov Levenglick <dovl@codeaurora.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/phy/phy-qcom-ufs-i.h')
-rw-r--r-- | drivers/phy/phy-qcom-ufs-i.h | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h new file mode 100644 index 000000000000..dac200f4d639 --- /dev/null +++ b/drivers/phy/phy-qcom-ufs-i.h | |||
@@ -0,0 +1,118 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 and | ||
6 | * only version 2 as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #ifndef UFS_QCOM_PHY_I_H_ | ||
16 | #define UFS_QCOM_PHY_I_H_ | ||
17 | |||
18 | #include <linux/clk.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/phy/phy.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/io.h> | ||
23 | #include <linux/delay.h> | ||
24 | |||
25 | #define UFS_QCOM_PHY_NAME_LEN 30 | ||
26 | |||
27 | struct ufs_qcom_phy_calibration { | ||
28 | u32 reg_offset; | ||
29 | u32 cfg_value; | ||
30 | }; | ||
31 | |||
32 | struct ufs_qcom_phy_vreg { | ||
33 | const char *name; | ||
34 | struct regulator *reg; | ||
35 | int max_uA; | ||
36 | int min_uV; | ||
37 | int max_uV; | ||
38 | bool enabled; | ||
39 | bool is_always_on; | ||
40 | }; | ||
41 | |||
42 | struct ufs_qcom_phy { | ||
43 | struct list_head list; | ||
44 | struct device *dev; | ||
45 | void __iomem *mmio; | ||
46 | void __iomem *dev_ref_clk_ctrl_mmio; | ||
47 | struct clk *tx_iface_clk; | ||
48 | struct clk *rx_iface_clk; | ||
49 | bool is_iface_clk_enabled; | ||
50 | struct clk *ref_clk_src; | ||
51 | struct clk *ref_clk_parent; | ||
52 | struct clk *ref_clk; | ||
53 | bool is_ref_clk_enabled; | ||
54 | bool is_dev_ref_clk_enabled; | ||
55 | struct ufs_qcom_phy_vreg vdda_pll; | ||
56 | struct ufs_qcom_phy_vreg vdda_phy; | ||
57 | struct ufs_qcom_phy_vreg vddp_ref_clk; | ||
58 | unsigned int quirks; | ||
59 | |||
60 | /* | ||
61 | * If UFS link is put into Hibern8 and if UFS PHY analog hardware is | ||
62 | * power collapsed (by clearing UFS_PHY_POWER_DOWN_CONTROL), Hibern8 | ||
63 | * exit might fail even after powering on UFS PHY analog hardware. | ||
64 | * Enabling this quirk will help to solve above issue by doing | ||
65 | * custom PHY settings just before PHY analog power collapse. | ||
66 | */ | ||
67 | #define UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE BIT(0) | ||
68 | |||
69 | u8 host_ctrl_rev_major; | ||
70 | u16 host_ctrl_rev_minor; | ||
71 | u16 host_ctrl_rev_step; | ||
72 | |||
73 | char name[UFS_QCOM_PHY_NAME_LEN]; | ||
74 | struct ufs_qcom_phy_calibration *cached_regs; | ||
75 | int cached_regs_table_size; | ||
76 | bool is_powered_on; | ||
77 | struct ufs_qcom_phy_specific_ops *phy_spec_ops; | ||
78 | }; | ||
79 | |||
80 | /** | ||
81 | * struct ufs_qcom_phy_specific_ops - set of pointers to functions which have a | ||
82 | * specific implementation per phy. Each UFS phy, should implement | ||
83 | * those functions according to its spec and requirements | ||
84 | * @calibrate_phy: pointer to a function that calibrate the phy | ||
85 | * @start_serdes: pointer to a function that starts the serdes | ||
86 | * @is_physical_coding_sublayer_ready: pointer to a function that | ||
87 | * checks pcs readiness. returns 0 for success and non-zero for error. | ||
88 | * @set_tx_lane_enable: pointer to a function that enable tx lanes | ||
89 | * @power_control: pointer to a function that controls analog rail of phy | ||
90 | * and writes to QSERDES_RX_SIGDET_CNTRL attribute | ||
91 | */ | ||
92 | struct ufs_qcom_phy_specific_ops { | ||
93 | int (*calibrate_phy)(struct ufs_qcom_phy *phy, bool is_rate_B); | ||
94 | void (*start_serdes)(struct ufs_qcom_phy *phy); | ||
95 | int (*is_physical_coding_sublayer_ready)(struct ufs_qcom_phy *phy); | ||
96 | void (*set_tx_lane_enable)(struct ufs_qcom_phy *phy, u32 val); | ||
97 | void (*power_control)(struct ufs_qcom_phy *phy, bool val); | ||
98 | }; | ||
99 | |||
100 | struct ufs_qcom_phy *get_ufs_qcom_phy(struct phy *generic_phy); | ||
101 | int ufs_qcom_phy_power_on(struct phy *generic_phy); | ||
102 | int ufs_qcom_phy_power_off(struct phy *generic_phy); | ||
103 | int ufs_qcom_phy_exit(struct phy *generic_phy); | ||
104 | int ufs_qcom_phy_init_clks(struct phy *generic_phy, | ||
105 | struct ufs_qcom_phy *phy_common); | ||
106 | int ufs_qcom_phy_init_vregulators(struct phy *generic_phy, | ||
107 | struct ufs_qcom_phy *phy_common); | ||
108 | int ufs_qcom_phy_remove(struct phy *generic_phy, | ||
109 | struct ufs_qcom_phy *ufs_qcom_phy); | ||
110 | struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev, | ||
111 | struct ufs_qcom_phy *common_cfg, | ||
112 | struct phy_ops *ufs_qcom_phy_gen_ops, | ||
113 | struct ufs_qcom_phy_specific_ops *phy_spec_ops); | ||
114 | int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy, | ||
115 | struct ufs_qcom_phy_calibration *tbl_A, int tbl_size_A, | ||
116 | struct ufs_qcom_phy_calibration *tbl_B, int tbl_size_B, | ||
117 | bool is_rate_B); | ||
118 | #endif | ||