1
1
// SPDX-License-Identifier: BSD-3-Clause-Clear
2
2
/*
3
3
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
4
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4
5
*/
5
6
6
7
#include <linux/module.h>
12
13
#include "debug.h"
13
14
#include "hif.h"
14
15
#include <linux/remoteproc.h>
16
+ #include "pcic.h"
15
17
16
18
static const struct of_device_id ath11k_ahb_of_match [] = {
17
19
/* TODO: Should we change the compatible string to something similar
@@ -23,18 +25,14 @@ static const struct of_device_id ath11k_ahb_of_match[] = {
23
25
{ .compatible = "qcom,ipq6018-wifi" ,
24
26
.data = (void * )ATH11K_HW_IPQ6018_HW10 ,
25
27
},
28
+ { .compatible = "qcom,wcn6750-wifi" ,
29
+ .data = (void * )ATH11K_HW_WCN6750_HW10 ,
30
+ },
26
31
{ }
27
32
};
28
33
29
34
MODULE_DEVICE_TABLE (of , ath11k_ahb_of_match );
30
35
31
- static const struct ath11k_bus_params ath11k_ahb_bus_params = {
32
- .mhi_support = false,
33
- .m3_fw_support = false,
34
- .fixed_bdf_addr = true,
35
- .fixed_mem_region = true,
36
- };
37
-
38
36
#define ATH11K_IRQ_CE0_OFFSET 4
39
37
40
38
static const char * irq_name [ATH11K_IRQ_NUM_MAX ] = {
@@ -134,6 +132,16 @@ enum ext_irq_num {
134
132
tcl2host_status_ring ,
135
133
};
136
134
135
+ static int
136
+ ath11k_ahb_get_msi_irq_wcn6750 (struct ath11k_base * ab , unsigned int vector )
137
+ {
138
+ return ab -> pci .msi .irqs [vector ];
139
+ }
140
+
141
+ static const struct ath11k_pci_ops ath11k_ahb_pci_ops_wcn6750 = {
142
+ .get_msi_irq = ath11k_ahb_get_msi_irq_wcn6750 ,
143
+ };
144
+
137
145
static inline u32 ath11k_ahb_read32 (struct ath11k_base * ab , u32 offset )
138
146
{
139
147
return ioread32 (ab -> mem + offset );
@@ -401,6 +409,9 @@ static void ath11k_ahb_free_irq(struct ath11k_base *ab)
401
409
int irq_idx ;
402
410
int i ;
403
411
412
+ if (ab -> hw_params .hybrid_bus_type )
413
+ return ath11k_pcic_free_irq (ab );
414
+
404
415
for (i = 0 ; i < ab -> hw_params .ce_count ; i ++ ) {
405
416
if (ath11k_ce_get_attr_flags (ab , i ) & CE_ATTR_DIS_INTR )
406
417
continue ;
@@ -555,6 +566,9 @@ static int ath11k_ahb_config_irq(struct ath11k_base *ab)
555
566
int irq , irq_idx , i ;
556
567
int ret ;
557
568
569
+ if (ab -> hw_params .hybrid_bus_type )
570
+ return ath11k_pcic_config_irq (ab );
571
+
558
572
/* Configure CE irqs */
559
573
for (i = 0 ; i < ab -> hw_params .ce_count ; i ++ ) {
560
574
struct ath11k_ce_pipe * ce_pipe = & ab -> ce .ce_pipe [i ];
@@ -624,7 +638,7 @@ static int ath11k_ahb_map_service_to_pipe(struct ath11k_base *ab, u16 service_id
624
638
return 0 ;
625
639
}
626
640
627
- static const struct ath11k_hif_ops ath11k_ahb_hif_ops = {
641
+ static const struct ath11k_hif_ops ath11k_ahb_hif_ops_ipq8074 = {
628
642
.start = ath11k_ahb_start ,
629
643
.stop = ath11k_ahb_stop ,
630
644
.read32 = ath11k_ahb_read32 ,
@@ -636,6 +650,20 @@ static const struct ath11k_hif_ops ath11k_ahb_hif_ops = {
636
650
.power_up = ath11k_ahb_power_up ,
637
651
};
638
652
653
+ static const struct ath11k_hif_ops ath11k_ahb_hif_ops_wcn6750 = {
654
+ .start = ath11k_pcic_start ,
655
+ .stop = ath11k_pcic_stop ,
656
+ .read32 = ath11k_pcic_read32 ,
657
+ .write32 = ath11k_pcic_write32 ,
658
+ .irq_enable = ath11k_pcic_ext_irq_enable ,
659
+ .irq_disable = ath11k_pcic_ext_irq_disable ,
660
+ .get_msi_address = ath11k_pcic_get_msi_address ,
661
+ .get_user_msi_vector = ath11k_pcic_get_user_msi_assignment ,
662
+ .map_service_to_pipe = ath11k_pcic_map_service_to_pipe ,
663
+ .power_down = ath11k_ahb_power_down ,
664
+ .power_up = ath11k_ahb_power_up ,
665
+ };
666
+
639
667
static int ath11k_core_get_rproc (struct ath11k_base * ab )
640
668
{
641
669
struct ath11k_ahb * ab_ahb = ath11k_ahb_priv (ab );
@@ -658,12 +686,84 @@ static int ath11k_core_get_rproc(struct ath11k_base *ab)
658
686
return 0 ;
659
687
}
660
688
689
+ static int ath11k_ahb_setup_msi_resources (struct ath11k_base * ab )
690
+ {
691
+ struct platform_device * pdev = ab -> pdev ;
692
+ phys_addr_t msi_addr_pa ;
693
+ dma_addr_t msi_addr_iova ;
694
+ struct resource * res ;
695
+ int int_prop ;
696
+ int ret ;
697
+ int i ;
698
+
699
+ ret = ath11k_pcic_init_msi_config (ab );
700
+ if (ret ) {
701
+ ath11k_err (ab , "failed to init msi config: %d\n" , ret );
702
+ return ret ;
703
+ }
704
+
705
+ res = platform_get_resource (pdev , IORESOURCE_MEM , 0 );
706
+ if (!res ) {
707
+ ath11k_err (ab , "failed to fetch msi_addr\n" );
708
+ return - ENOENT ;
709
+ }
710
+
711
+ msi_addr_pa = res -> start ;
712
+ msi_addr_iova = dma_map_resource (ab -> dev , msi_addr_pa , PAGE_SIZE ,
713
+ DMA_FROM_DEVICE , 0 );
714
+ if (dma_mapping_error (ab -> dev , msi_addr_iova ))
715
+ return - ENOMEM ;
716
+
717
+ ab -> pci .msi .addr_lo = lower_32_bits (msi_addr_iova );
718
+ ab -> pci .msi .addr_hi = upper_32_bits (msi_addr_iova );
719
+
720
+ ret = of_property_read_u32_index (ab -> dev -> of_node , "interrupts" , 1 , & int_prop );
721
+ if (ret )
722
+ return ret ;
723
+
724
+ ab -> pci .msi .ep_base_data = int_prop + 32 ;
725
+
726
+ for (i = 0 ; i < ab -> pci .msi .config -> total_vectors ; i ++ ) {
727
+ res = platform_get_resource (pdev , IORESOURCE_IRQ , i );
728
+ if (!res )
729
+ return - ENODEV ;
730
+
731
+ ab -> pci .msi .irqs [i ] = res -> start ;
732
+ }
733
+
734
+ set_bit (ATH11K_FLAG_MULTI_MSI_VECTORS , & ab -> dev_flags );
735
+
736
+ return 0 ;
737
+ }
738
+
739
+ static int ath11k_ahb_setup_resources (struct ath11k_base * ab )
740
+ {
741
+ struct platform_device * pdev = ab -> pdev ;
742
+ struct resource * mem_res ;
743
+ void __iomem * mem ;
744
+
745
+ if (ab -> hw_params .hybrid_bus_type )
746
+ return ath11k_ahb_setup_msi_resources (ab );
747
+
748
+ mem = devm_platform_get_and_ioremap_resource (pdev , 0 , & mem_res );
749
+ if (IS_ERR (mem )) {
750
+ dev_err (& pdev -> dev , "ioremap error\n" );
751
+ return PTR_ERR (mem );
752
+ }
753
+
754
+ ab -> mem = mem ;
755
+ ab -> mem_len = resource_size (mem_res );
756
+
757
+ return 0 ;
758
+ }
759
+
661
760
static int ath11k_ahb_probe (struct platform_device * pdev )
662
761
{
663
762
struct ath11k_base * ab ;
664
763
const struct of_device_id * of_id ;
665
- struct resource * mem_res ;
666
- void __iomem * mem ;
764
+ const struct ath11k_hif_ops * hif_ops ;
765
+ const struct ath11k_pci_ops * pci_ops ;
766
+ enum ath11k_hw_rev hw_rev ;
667
767
int ret ;
668
768
669
769
of_id = of_match_device (ath11k_ahb_of_match , & pdev -> dev );
@@ -672,10 +772,21 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
672
772
return - EINVAL ;
673
773
}
674
774
675
- mem = devm_platform_get_and_ioremap_resource (pdev , 0 , & mem_res );
676
- if (IS_ERR (mem )) {
677
- dev_err (& pdev -> dev , "ioremap error\n" );
678
- return PTR_ERR (mem );
775
+ hw_rev = (enum ath11k_hw_rev )of_id -> data ;
776
+
777
+ switch (hw_rev ) {
778
+ case ATH11K_HW_IPQ8074 :
779
+ case ATH11K_HW_IPQ6018_HW10 :
780
+ hif_ops = & ath11k_ahb_hif_ops_ipq8074 ;
781
+ pci_ops = NULL ;
782
+ break ;
783
+ case ATH11K_HW_WCN6750_HW10 :
784
+ hif_ops = & ath11k_ahb_hif_ops_wcn6750 ;
785
+ pci_ops = & ath11k_ahb_pci_ops_wcn6750 ;
786
+ break ;
787
+ default :
788
+ dev_err (& pdev -> dev , "unsupported device type %d\n" , hw_rev );
789
+ return - EOPNOTSUPP ;
679
790
}
680
791
681
792
ret = dma_set_mask_and_coherent (& pdev -> dev , DMA_BIT_MASK (32 ));
@@ -685,20 +796,22 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
685
796
}
686
797
687
798
ab = ath11k_core_alloc (& pdev -> dev , sizeof (struct ath11k_ahb ),
688
- ATH11K_BUS_AHB ,
689
- & ath11k_ahb_bus_params );
799
+ ATH11K_BUS_AHB );
690
800
if (!ab ) {
691
801
dev_err (& pdev -> dev , "failed to allocate ath11k base\n" );
692
802
return - ENOMEM ;
693
803
}
694
804
695
- ab -> hif .ops = & ath11k_ahb_hif_ops ;
805
+ ab -> hif .ops = hif_ops ;
806
+ ab -> pci .ops = pci_ops ;
696
807
ab -> pdev = pdev ;
697
- ab -> hw_rev = (enum ath11k_hw_rev )of_id -> data ;
698
- ab -> mem = mem ;
699
- ab -> mem_len = resource_size (mem_res );
808
+ ab -> hw_rev = hw_rev ;
700
809
platform_set_drvdata (pdev , ab );
701
810
811
+ ret = ath11k_ahb_setup_resources (ab );
812
+ if (ret )
813
+ goto err_core_free ;
814
+
702
815
ret = ath11k_core_pre_init (ab );
703
816
if (ret )
704
817
goto err_core_free ;
0 commit comments