Commit | Line | Data |
---|---|---|
adaafaa3 YG |
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 |