@@ -24,13 +24,16 @@ struct pwrseq_qcom_wcn_pdata {
2424 unsigned int pwup_delay_ms ;
2525 unsigned int gpio_enable_delay_ms ;
2626 const struct pwrseq_target_data * * targets ;
27+ bool has_vddio ; /* separate VDD IO regulator */
28+ int (* match )(struct pwrseq_device * pwrseq , struct device * dev );
2729};
2830
2931struct pwrseq_qcom_wcn_ctx {
3032 struct pwrseq_device * pwrseq ;
3133 struct device_node * of_node ;
3234 const struct pwrseq_qcom_wcn_pdata * pdata ;
3335 struct regulator_bulk_data * regs ;
36+ struct regulator * vddio ;
3437 struct gpio_desc * bt_gpio ;
3538 struct gpio_desc * wlan_gpio ;
3639 struct gpio_desc * xo_clk_gpio ;
@@ -53,6 +56,26 @@ static void pwrseq_qcom_wcn_ensure_gpio_delay(struct pwrseq_qcom_wcn_ctx *ctx)
5356 msleep (ctx -> pdata -> gpio_enable_delay_ms - diff_msecs );
5457}
5558
59+ static int pwrseq_qcom_wcn_vddio_enable (struct pwrseq_device * pwrseq )
60+ {
61+ struct pwrseq_qcom_wcn_ctx * ctx = pwrseq_device_get_drvdata (pwrseq );
62+
63+ return regulator_enable (ctx -> vddio );
64+ }
65+
66+ static int pwrseq_qcom_wcn_vddio_disable (struct pwrseq_device * pwrseq )
67+ {
68+ struct pwrseq_qcom_wcn_ctx * ctx = pwrseq_device_get_drvdata (pwrseq );
69+
70+ return regulator_disable (ctx -> vddio );
71+ }
72+
73+ static const struct pwrseq_unit_data pwrseq_qcom_wcn_vddio_unit_data = {
74+ .name = "vddio-enable" ,
75+ .enable = pwrseq_qcom_wcn_vddio_enable ,
76+ .disable = pwrseq_qcom_wcn_vddio_disable ,
77+ };
78+
5679static int pwrseq_qcom_wcn_vregs_enable (struct pwrseq_device * pwrseq )
5780{
5881 struct pwrseq_qcom_wcn_ctx * ctx = pwrseq_device_get_drvdata (pwrseq );
@@ -95,6 +118,19 @@ static const struct pwrseq_unit_data pwrseq_qcom_wcn_clk_unit_data = {
95118 .disable = pwrseq_qcom_wcn_clk_disable ,
96119};
97120
121+ static const struct pwrseq_unit_data * pwrseq_qcom_wcn3990_unit_deps [] = {
122+ & pwrseq_qcom_wcn_vddio_unit_data ,
123+ & pwrseq_qcom_wcn_vregs_unit_data ,
124+ NULL ,
125+ };
126+
127+ static const struct pwrseq_unit_data pwrseq_qcom_wcn3990_unit_data = {
128+ .name = "clock-enable" ,
129+ .deps = pwrseq_qcom_wcn3990_unit_deps ,
130+ .enable = pwrseq_qcom_wcn_clk_enable ,
131+ .disable = pwrseq_qcom_wcn_clk_disable ,
132+ };
133+
98134static const struct pwrseq_unit_data * pwrseq_qcom_wcn_unit_deps [] = {
99135 & pwrseq_qcom_wcn_vregs_unit_data ,
100136 & pwrseq_qcom_wcn_clk_unit_data ,
@@ -230,6 +266,17 @@ static const struct pwrseq_target_data pwrseq_qcom_wcn_wlan_target_data = {
230266 .post_enable = pwrseq_qcom_wcn_pwup_delay ,
231267};
232268
269+ /* There are no separate BT and WLAN enablement pins */
270+ static const struct pwrseq_target_data pwrseq_qcom_wcn3990_bt_target_data = {
271+ .name = "bluetooth" ,
272+ .unit = & pwrseq_qcom_wcn3990_unit_data ,
273+ };
274+
275+ static const struct pwrseq_target_data pwrseq_qcom_wcn3990_wlan_target_data = {
276+ .name = "wlan" ,
277+ .unit = & pwrseq_qcom_wcn3990_unit_data ,
278+ };
279+
233280static const struct pwrseq_target_data pwrseq_qcom_wcn6855_bt_target_data = {
234281 .name = "bluetooth" ,
235282 .unit = & pwrseq_qcom_wcn6855_bt_unit_data ,
@@ -248,6 +295,12 @@ static const struct pwrseq_target_data *pwrseq_qcom_wcn_targets[] = {
248295 NULL
249296};
250297
298+ static const struct pwrseq_target_data * pwrseq_qcom_wcn3990_targets [] = {
299+ & pwrseq_qcom_wcn3990_bt_target_data ,
300+ & pwrseq_qcom_wcn3990_wlan_target_data ,
301+ NULL
302+ };
303+
251304static const struct pwrseq_target_data * pwrseq_qcom_wcn6855_targets [] = {
252305 & pwrseq_qcom_wcn6855_bt_target_data ,
253306 & pwrseq_qcom_wcn6855_wlan_target_data ,
@@ -273,6 +326,26 @@ static const struct pwrseq_qcom_wcn_pdata pwrseq_qca6390_of_data = {
273326 .targets = pwrseq_qcom_wcn_targets ,
274327};
275328
329+ static const char * const pwrseq_wcn3990_vregs [] = {
330+ /* vddio is handled separately */
331+ "vddxo" ,
332+ "vddrf" ,
333+ "vddch0" ,
334+ "vddch1" ,
335+ };
336+
337+ static int pwrseq_qcom_wcn3990_match (struct pwrseq_device * pwrseq ,
338+ struct device * dev );
339+
340+ static const struct pwrseq_qcom_wcn_pdata pwrseq_wcn3990_of_data = {
341+ .vregs = pwrseq_wcn3990_vregs ,
342+ .num_vregs = ARRAY_SIZE (pwrseq_wcn3990_vregs ),
343+ .pwup_delay_ms = 50 ,
344+ .targets = pwrseq_qcom_wcn3990_targets ,
345+ .has_vddio = true,
346+ .match = pwrseq_qcom_wcn3990_match ,
347+ };
348+
276349static const char * const pwrseq_wcn6750_vregs [] = {
277350 "vddaon" ,
278351 "vddasd" ,
@@ -329,8 +402,9 @@ static const struct pwrseq_qcom_wcn_pdata pwrseq_wcn7850_of_data = {
329402 .targets = pwrseq_qcom_wcn_targets ,
330403};
331404
332- static int pwrseq_qcom_wcn_match (struct pwrseq_device * pwrseq ,
333- struct device * dev )
405+ static int pwrseq_qcom_wcn_match_regulator (struct pwrseq_device * pwrseq ,
406+ struct device * dev ,
407+ const char * name )
334408{
335409 struct pwrseq_qcom_wcn_ctx * ctx = pwrseq_device_get_drvdata (pwrseq );
336410 struct device_node * dev_node = dev -> of_node ;
@@ -341,11 +415,11 @@ static int pwrseq_qcom_wcn_match(struct pwrseq_device *pwrseq,
341415 * 'vddaon-supply' property and whether it leads us to the right
342416 * device.
343417 */
344- if (!of_property_present (dev_node , "vddaon-supply" ))
418+ if (!of_property_present (dev_node , name ))
345419 return PWRSEQ_NO_MATCH ;
346420
347421 struct device_node * reg_node __free (device_node ) =
348- of_parse_phandle (dev_node , "vddaon-supply" , 0 );
422+ of_parse_phandle (dev_node , name , 0 );
349423 if (!reg_node )
350424 return PWRSEQ_NO_MATCH ;
351425
@@ -361,6 +435,26 @@ static int pwrseq_qcom_wcn_match(struct pwrseq_device *pwrseq,
361435 return PWRSEQ_MATCH_OK ;
362436}
363437
438+ static int pwrseq_qcom_wcn_match (struct pwrseq_device * pwrseq ,
439+ struct device * dev )
440+ {
441+ return pwrseq_qcom_wcn_match_regulator (pwrseq , dev , "vddaon-supply" );
442+ }
443+
444+ static int pwrseq_qcom_wcn3990_match (struct pwrseq_device * pwrseq ,
445+ struct device * dev )
446+ {
447+ int ret ;
448+
449+ /* BT device */
450+ ret = pwrseq_qcom_wcn_match_regulator (pwrseq , dev , "vddio-supply" );
451+ if (ret == PWRSEQ_MATCH_OK )
452+ return ret ;
453+
454+ /* WiFi device match */
455+ return pwrseq_qcom_wcn_match_regulator (pwrseq , dev , "vdd-1.8-xo-supply" );
456+ }
457+
364458static int pwrseq_qcom_wcn_probe (struct platform_device * pdev )
365459{
366460 struct device * dev = & pdev -> dev ;
@@ -392,6 +486,12 @@ static int pwrseq_qcom_wcn_probe(struct platform_device *pdev)
392486 return dev_err_probe (dev , ret ,
393487 "Failed to get all regulators\n" );
394488
489+ if (ctx -> pdata -> has_vddio ) {
490+ ctx -> vddio = devm_regulator_get (dev , "vddio" );
491+ if (IS_ERR (ctx -> vddio ))
492+ return dev_err_probe (dev , ret , "Failed to get VDDIO\n" );
493+ }
494+
395495 ctx -> bt_gpio = devm_gpiod_get_optional (dev , "bt-enable" , GPIOD_OUT_LOW );
396496 if (IS_ERR (ctx -> bt_gpio ))
397497 return dev_err_probe (dev , PTR_ERR (ctx -> bt_gpio ),
@@ -433,7 +533,7 @@ static int pwrseq_qcom_wcn_probe(struct platform_device *pdev)
433533 config .parent = dev ;
434534 config .owner = THIS_MODULE ;
435535 config .drvdata = ctx ;
436- config .match = pwrseq_qcom_wcn_match ;
536+ config .match = ctx -> pdata -> match ? : pwrseq_qcom_wcn_match ;
437537 config .targets = ctx -> pdata -> targets ;
438538
439539 ctx -> pwrseq = devm_pwrseq_device_register (dev , & config );
@@ -445,6 +545,26 @@ static int pwrseq_qcom_wcn_probe(struct platform_device *pdev)
445545}
446546
447547static const struct of_device_id pwrseq_qcom_wcn_of_match [] = {
548+ {
549+ .compatible = "qcom,wcn3950-pmu" ,
550+ .data = & pwrseq_wcn3990_of_data ,
551+ },
552+ {
553+ .compatible = "qcom,wcn3988-pmu" ,
554+ .data = & pwrseq_wcn3990_of_data ,
555+ },
556+ {
557+ .compatible = "qcom,wcn3990-pmu" ,
558+ .data = & pwrseq_wcn3990_of_data ,
559+ },
560+ {
561+ .compatible = "qcom,wcn3991-pmu" ,
562+ .data = & pwrseq_wcn3990_of_data ,
563+ },
564+ {
565+ .compatible = "qcom,wcn3998-pmu" ,
566+ .data = & pwrseq_wcn3990_of_data ,
567+ },
448568 {
449569 .compatible = "qcom,qca6390-pmu" ,
450570 .data = & pwrseq_qca6390_of_data ,
0 commit comments