55 */
66
77#include <linux/device.h>
8+ #include <linux/delay.h>
9+ #include <linux/gpio/consumer.h>
810#include <linux/mod_devicetable.h>
911#include <linux/module.h>
1012#include <linux/of.h>
1113#include <linux/of_graph.h>
14+ #include <linux/of_platform.h>
1215#include <linux/platform_device.h>
1316#include <linux/pwrseq/provider.h>
1417#include <linux/regulator/consumer.h>
@@ -25,16 +28,18 @@ struct pwrseq_pcie_m2_ctx {
2528 struct regulator_bulk_data * regs ;
2629 size_t num_vregs ;
2730 struct notifier_block nb ;
31+ struct gpio_desc * w_disable1_gpio ;
32+ struct gpio_desc * w_disable2_gpio ;
2833};
2934
30- static int pwrseq_pcie_m2_m_vregs_enable (struct pwrseq_device * pwrseq )
35+ static int pwrseq_pcie_m2_vregs_enable (struct pwrseq_device * pwrseq )
3136{
3237 struct pwrseq_pcie_m2_ctx * ctx = pwrseq_device_get_drvdata (pwrseq );
3338
3439 return regulator_bulk_enable (ctx -> num_vregs , ctx -> regs );
3540}
3641
37- static int pwrseq_pcie_m2_m_vregs_disable (struct pwrseq_device * pwrseq )
42+ static int pwrseq_pcie_m2_vregs_disable (struct pwrseq_device * pwrseq )
3843{
3944 struct pwrseq_pcie_m2_ctx * ctx = pwrseq_device_get_drvdata (pwrseq );
4045
@@ -43,30 +48,106 @@ static int pwrseq_pcie_m2_m_vregs_disable(struct pwrseq_device *pwrseq)
4348
4449static const struct pwrseq_unit_data pwrseq_pcie_m2_vregs_unit_data = {
4550 .name = "regulators-enable" ,
46- .enable = pwrseq_pcie_m2_m_vregs_enable ,
47- .disable = pwrseq_pcie_m2_m_vregs_disable ,
51+ .enable = pwrseq_pcie_m2_vregs_enable ,
52+ .disable = pwrseq_pcie_m2_vregs_disable ,
4853};
4954
50- static const struct pwrseq_unit_data * pwrseq_pcie_m2_m_unit_deps [] = {
55+ static const struct pwrseq_unit_data * pwrseq_pcie_m2_unit_deps [] = {
5156 & pwrseq_pcie_m2_vregs_unit_data ,
5257 NULL
5358};
5459
60+ static int pwrseq_pci_m2_e_uart_enable (struct pwrseq_device * pwrseq )
61+ {
62+ struct pwrseq_pcie_m2_ctx * ctx = pwrseq_device_get_drvdata (pwrseq );
63+
64+ return gpiod_set_value_cansleep (ctx -> w_disable2_gpio , 0 );
65+ }
66+
67+ static int pwrseq_pci_m2_e_uart_disable (struct pwrseq_device * pwrseq )
68+ {
69+ struct pwrseq_pcie_m2_ctx * ctx = pwrseq_device_get_drvdata (pwrseq );
70+
71+ return gpiod_set_value_cansleep (ctx -> w_disable2_gpio , 1 );
72+ }
73+
74+ static const struct pwrseq_unit_data pwrseq_pcie_m2_e_uart_unit_data = {
75+ .name = "uart-enable" ,
76+ .deps = pwrseq_pcie_m2_unit_deps ,
77+ .enable = pwrseq_pci_m2_e_uart_enable ,
78+ .disable = pwrseq_pci_m2_e_uart_disable ,
79+ };
80+
81+ static int pwrseq_pci_m2_e_pcie_enable (struct pwrseq_device * pwrseq )
82+ {
83+ struct pwrseq_pcie_m2_ctx * ctx = pwrseq_device_get_drvdata (pwrseq );
84+
85+ return gpiod_set_value_cansleep (ctx -> w_disable1_gpio , 0 );
86+ }
87+
88+ static int pwrseq_pci_m2_e_pcie_disable (struct pwrseq_device * pwrseq )
89+ {
90+ struct pwrseq_pcie_m2_ctx * ctx = pwrseq_device_get_drvdata (pwrseq );
91+
92+ return gpiod_set_value_cansleep (ctx -> w_disable1_gpio , 1 );
93+ }
94+
95+ static const struct pwrseq_unit_data pwrseq_pcie_m2_e_pcie_unit_data = {
96+ .name = "pcie-enable" ,
97+ .deps = pwrseq_pcie_m2_unit_deps ,
98+ .enable = pwrseq_pci_m2_e_pcie_enable ,
99+ .disable = pwrseq_pci_m2_e_pcie_disable ,
100+ };
101+
55102static const struct pwrseq_unit_data pwrseq_pcie_m2_m_pcie_unit_data = {
56103 .name = "pcie-enable" ,
57- .deps = pwrseq_pcie_m2_m_unit_deps ,
104+ .deps = pwrseq_pcie_m2_unit_deps ,
105+ };
106+
107+ static int pwrseq_pcie_m2_e_pwup_delay (struct pwrseq_device * pwrseq )
108+ {
109+ /*
110+ * FIXME: This delay is only required for some Qcom WLAN/BT cards like
111+ * WCN7850 and not for all devices. But currently, there is no way to
112+ * identify the device model before enumeration.
113+ */
114+ msleep (50 );
115+
116+ return 0 ;
117+ }
118+
119+ static const struct pwrseq_target_data pwrseq_pcie_m2_e_uart_target_data = {
120+ .name = "uart" ,
121+ .unit = & pwrseq_pcie_m2_e_uart_unit_data ,
122+ .post_enable = pwrseq_pcie_m2_e_pwup_delay ,
123+ };
124+
125+ static const struct pwrseq_target_data pwrseq_pcie_m2_e_pcie_target_data = {
126+ .name = "pcie" ,
127+ .unit = & pwrseq_pcie_m2_e_pcie_unit_data ,
128+ .post_enable = pwrseq_pcie_m2_e_pwup_delay ,
58129};
59130
60131static const struct pwrseq_target_data pwrseq_pcie_m2_m_pcie_target_data = {
61132 .name = "pcie" ,
62133 .unit = & pwrseq_pcie_m2_m_pcie_unit_data ,
63134};
64135
136+ static const struct pwrseq_target_data * pwrseq_pcie_m2_e_targets [] = {
137+ & pwrseq_pcie_m2_e_pcie_target_data ,
138+ & pwrseq_pcie_m2_e_uart_target_data ,
139+ NULL
140+ };
141+
65142static const struct pwrseq_target_data * pwrseq_pcie_m2_m_targets [] = {
66143 & pwrseq_pcie_m2_m_pcie_target_data ,
67144 NULL
68145};
69146
147+ static const struct pwrseq_pcie_m2_pdata pwrseq_pcie_m2_e_of_data = {
148+ .targets = pwrseq_pcie_m2_e_targets ,
149+ };
150+
70151static const struct pwrseq_pcie_m2_pdata pwrseq_pcie_m2_m_of_data = {
71152 .targets = pwrseq_pcie_m2_m_targets ,
72153};
@@ -125,6 +206,16 @@ static int pwrseq_pcie_m2_probe(struct platform_device *pdev)
125206 return dev_err_probe (dev , ret ,
126207 "Failed to get all regulators\n" );
127208
209+ ctx -> w_disable1_gpio = devm_gpiod_get_optional (dev , "w-disable1" , GPIOD_OUT_HIGH );
210+ if (IS_ERR (ctx -> w_disable1_gpio ))
211+ return dev_err_probe (dev , PTR_ERR (ctx -> w_disable1_gpio ),
212+ "Failed to get the W_DISABLE_1# GPIO\n" );
213+
214+ ctx -> w_disable2_gpio = devm_gpiod_get_optional (dev , "w-disable2" , GPIOD_OUT_HIGH );
215+ if (IS_ERR (ctx -> w_disable2_gpio ))
216+ return dev_err_probe (dev , PTR_ERR (ctx -> w_disable2_gpio ),
217+ "Failed to get the W_DISABLE_2# GPIO\n" );
218+
128219 ctx -> num_vregs = ret ;
129220
130221 ret = devm_add_action_or_reset (dev , pwrseq_pcie_m2_free_regulators , ctx );
@@ -150,6 +241,10 @@ static const struct of_device_id pwrseq_pcie_m2_of_match[] = {
150241 .compatible = "pcie-m2-m-connector" ,
151242 .data = & pwrseq_pcie_m2_m_of_data ,
152243 },
244+ {
245+ .compatible = "pcie-m2-e-connector" ,
246+ .data = & pwrseq_pcie_m2_e_of_data ,
247+ },
153248 { }
154249};
155250MODULE_DEVICE_TABLE (of , pwrseq_pcie_m2_of_match );
0 commit comments