11// SPDX-License-Identifier: BSD-3-Clause-Clear
22/*
33 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
4- * Copyright (c) 2022-2025 Qualcomm Innovation Center , Inc. All rights reserved .
4+ * Copyright (c) Qualcomm Technologies , Inc. and/or its subsidiaries .
55 */
66
77#include <linux/dma-mapping.h>
1616#include "debug.h"
1717#include "hif.h"
1818
19- static const struct of_device_id ath12k_ahb_of_match [] = {
20- { .compatible = "qcom,ipq5332-wifi" ,
21- .data = (void * )ATH12K_HW_IPQ5332_HW10 ,
22- },
23- { }
24- };
25-
26- MODULE_DEVICE_TABLE (of , ath12k_ahb_of_match );
27-
2819#define ATH12K_IRQ_CE0_OFFSET 4
2920#define ATH12K_MAX_UPDS 1
3021#define ATH12K_UPD_IRQ_WRD_LEN 18
22+
23+ static struct ath12k_ahb_driver * ath12k_ahb_family_drivers [ATH12K_DEVICE_FAMILY_MAX ];
3124static const char ath12k_userpd_irq [][9 ] = {"spawn" ,
3225 "ready" ,
3326 "stop-ack" };
@@ -130,15 +123,15 @@ enum ext_irq_num {
130123
131124static u32 ath12k_ahb_read32 (struct ath12k_base * ab , u32 offset )
132125{
133- if (ab -> ce_remap && offset < HAL_SEQ_WCSS_CMEM_OFFSET )
126+ if (ab -> ce_remap && offset < ab -> cmem_offset )
134127 return ioread32 (ab -> mem_ce + offset );
135128 return ioread32 (ab -> mem + offset );
136129}
137130
138131static void ath12k_ahb_write32 (struct ath12k_base * ab , u32 offset ,
139132 u32 value )
140133{
141- if (ab -> ce_remap && offset < HAL_SEQ_WCSS_CMEM_OFFSET )
134+ if (ab -> ce_remap && offset < ab -> cmem_offset )
142135 iowrite32 (value , ab -> mem_ce + offset );
143136 else
144137 iowrite32 (value , ab -> mem + offset );
@@ -531,9 +524,10 @@ static int ath12k_ahb_ext_grp_napi_poll(struct napi_struct *napi, int budget)
531524 struct ath12k_ext_irq_grp ,
532525 napi );
533526 struct ath12k_base * ab = irq_grp -> ab ;
527+ struct ath12k_dp * dp = ath12k_ab_to_dp (ab );
534528 int work_done ;
535529
536- work_done = ath12k_dp_service_srng (ab , irq_grp , budget );
530+ work_done = ath12k_dp_service_srng (dp , irq_grp , budget );
537531 if (work_done < budget ) {
538532 napi_complete_done (napi , work_done );
539533 ath12k_ahb_ext_grp_enable (irq_grp );
@@ -563,12 +557,10 @@ static int ath12k_ahb_config_ext_irq(struct ath12k_base *ab)
563557{
564558 const struct ath12k_hw_ring_mask * ring_mask ;
565559 struct ath12k_ext_irq_grp * irq_grp ;
566- const struct hal_ops * hal_ops ;
567560 int i , j , irq , irq_idx , ret ;
568561 u32 num_irq ;
569562
570563 ring_mask = ab -> hw_params -> ring_mask ;
571- hal_ops = ab -> hw_params -> hal_ops ;
572564 for (i = 0 ; i < ATH12K_EXT_IRQ_GRP_NUM_MAX ; i ++ ) {
573565 irq_grp = & ab -> ext_irq_grp [i ];
574566 num_irq = 0 ;
@@ -588,7 +580,7 @@ static int ath12k_ahb_config_ext_irq(struct ath12k_base *ab)
588580 * tcl_to_wbm_rbm_map point to the same ring number.
589581 */
590582 if (ring_mask -> tx [i ] &
591- BIT (hal_ops -> tcl_to_wbm_rbm_map [j ].wbm_ring_num )) {
583+ BIT (ab -> hal . tcl_to_wbm_rbm_map [j ].wbm_ring_num )) {
592584 irq_grp -> irqs [num_irq ++ ] =
593585 wbm2host_tx_completions_ring1 - j ;
594586 }
@@ -698,7 +690,7 @@ static int ath12k_ahb_map_service_to_pipe(struct ath12k_base *ab, u16 service_id
698690 return 0 ;
699691}
700692
701- static const struct ath12k_hif_ops ath12k_ahb_hif_ops_ipq5332 = {
693+ static const struct ath12k_hif_ops ath12k_ahb_hif_ops = {
702694 .start = ath12k_ahb_start ,
703695 .stop = ath12k_ahb_stop ,
704696 .read32 = ath12k_ahb_read32 ,
@@ -935,7 +927,8 @@ static int ath12k_ahb_resource_init(struct ath12k_base *ab)
935927 goto err_mem_unmap ;
936928 }
937929 ab -> ce_remap = true;
938- ab -> ce_remap_base_addr = HAL_IPQ5332_CE_WFSS_REG_BASE ;
930+ ab -> cmem_offset = ce_remap -> cmem_offset ;
931+ ab -> ce_remap_base_addr = ce_remap -> base ;
939932 }
940933
941934 ab_ahb -> xo_clk = devm_clk_get (ab -> dev , "xo" );
@@ -988,13 +981,34 @@ static void ath12k_ahb_resource_deinit(struct ath12k_base *ab)
988981 ab_ahb -> xo_clk = NULL ;
989982}
990983
984+ static enum ath12k_device_family
985+ ath12k_ahb_get_device_family (const struct platform_device * pdev )
986+ {
987+ enum ath12k_device_family device_family_id ;
988+ struct ath12k_ahb_driver * driver ;
989+ const struct of_device_id * of_id ;
990+
991+ for (device_family_id = ATH12K_DEVICE_FAMILY_START ;
992+ device_family_id < ATH12K_DEVICE_FAMILY_MAX ; device_family_id ++ ) {
993+ driver = ath12k_ahb_family_drivers [device_family_id ];
994+ if (driver ) {
995+ of_id = of_match_device (driver -> id_table , & pdev -> dev );
996+ if (of_id ) {
997+ /* Found the driver */
998+ return device_family_id ;
999+ }
1000+ }
1001+ }
1002+
1003+ return ATH12K_DEVICE_FAMILY_MAX ;
1004+ }
1005+
9911006static int ath12k_ahb_probe (struct platform_device * pdev )
9921007{
993- struct ath12k_base * ab ;
994- const struct ath12k_hif_ops * hif_ops ;
1008+ enum ath12k_device_family device_id ;
9951009 struct ath12k_ahb * ab_ahb ;
996- enum ath12k_hw_rev hw_rev ;
997- u32 addr , userpd_id ;
1010+ struct ath12k_base * ab ;
1011+ u32 addr ;
9981012 int ret ;
9991013
10001014 ret = dma_set_mask_and_coherent (& pdev -> dev , DMA_BIT_MASK (32 ));
@@ -1008,25 +1022,32 @@ static int ath12k_ahb_probe(struct platform_device *pdev)
10081022 if (!ab )
10091023 return - ENOMEM ;
10101024
1011- hw_rev = (enum ath12k_hw_rev )(kernel_ulong_t )of_device_get_match_data (& pdev -> dev );
1012- switch (hw_rev ) {
1013- case ATH12K_HW_IPQ5332_HW10 :
1014- hif_ops = & ath12k_ahb_hif_ops_ipq5332 ;
1015- userpd_id = ATH12K_IPQ5332_USERPD_ID ;
1016- break ;
1017- default :
1018- ret = - EOPNOTSUPP ;
1025+ ab_ahb = ath12k_ab_to_ahb (ab );
1026+ ab_ahb -> ab = ab ;
1027+ ab -> hif .ops = & ath12k_ahb_hif_ops ;
1028+ ab -> pdev = pdev ;
1029+ platform_set_drvdata (pdev , ab );
1030+
1031+ device_id = ath12k_ahb_get_device_family (pdev );
1032+ if (device_id >= ATH12K_DEVICE_FAMILY_MAX ) {
1033+ ath12k_err (ab , "failed to get device family: %d\n" , device_id );
1034+ ret = - EINVAL ;
10191035 goto err_core_free ;
10201036 }
10211037
1022- ab -> hif .ops = hif_ops ;
1023- ab -> pdev = pdev ;
1024- ab -> hw_rev = hw_rev ;
1025- ab -> target_mem_mode = ATH12K_QMI_MEMORY_MODE_DEFAULT ;
1026- platform_set_drvdata (pdev , ab );
1027- ab_ahb = ath12k_ab_to_ahb (ab );
1028- ab_ahb -> ab = ab ;
1029- ab_ahb -> userpd_id = userpd_id ;
1038+ ath12k_dbg (ab , ATH12K_DBG_AHB , "AHB device family id: %d\n" , device_id );
1039+
1040+ ab_ahb -> device_family_ops = & ath12k_ahb_family_drivers [device_id ]-> ops ;
1041+
1042+ /* Call device specific probe. This is the callback that can
1043+ * be used to override any ops in future
1044+ * probe is validated for NULL during registration.
1045+ */
1046+ ret = ab_ahb -> device_family_ops -> probe (pdev );
1047+ if (ret ) {
1048+ ath12k_err (ab , "failed to probe device: %d\n" , ret );
1049+ goto err_core_free ;
1050+ }
10301051
10311052 /* Set fixed_mem_region to true for platforms that support fixed memory
10321053 * reservation from DT. If memory is reserved from DT for FW, ath12k driver
@@ -1065,14 +1086,26 @@ static int ath12k_ahb_probe(struct platform_device *pdev)
10651086 goto err_rproc_deconfigure ;
10661087 }
10671088
1089+ /* Invoke arch_init here so that arch-specific init operations
1090+ * can utilize already initialized ab fields, such as HAL SRNGs.
1091+ */
1092+ ret = ab_ahb -> device_family_ops -> arch_init (ab );
1093+ if (ret ) {
1094+ ath12k_err (ab , "AHB arch_init failed %d\n" , ret );
1095+ goto err_rproc_deconfigure ;
1096+ }
1097+
10681098 ret = ath12k_core_init (ab );
10691099 if (ret ) {
10701100 ath12k_err (ab , "failed to init core: %d\n" , ret );
1071- goto err_rproc_deconfigure ;
1101+ goto err_deinit_arch ;
10721102 }
10731103
10741104 return 0 ;
10751105
1106+ err_deinit_arch :
1107+ ab_ahb -> device_family_ops -> arch_deinit (ab );
1108+
10761109err_rproc_deconfigure :
10771110 ath12k_ahb_deconfigure_rproc (ab );
10781111
@@ -1111,11 +1144,13 @@ static void ath12k_ahb_remove_prepare(struct ath12k_base *ab)
11111144static void ath12k_ahb_free_resources (struct ath12k_base * ab )
11121145{
11131146 struct platform_device * pdev = ab -> pdev ;
1147+ struct ath12k_ahb * ab_ahb = ath12k_ab_to_ahb (ab );
11141148
11151149 ath12k_hal_srng_deinit (ab );
11161150 ath12k_ce_free_pipes (ab );
11171151 ath12k_ahb_resource_deinit (ab );
11181152 ath12k_ahb_deconfigure_rproc (ab );
1153+ ab_ahb -> device_family_ops -> arch_deinit (ab );
11191154 ath12k_core_free (ab );
11201155 platform_set_drvdata (pdev , NULL );
11211156}
@@ -1136,21 +1171,47 @@ static void ath12k_ahb_remove(struct platform_device *pdev)
11361171 ath12k_ahb_free_resources (ab );
11371172}
11381173
1139- static struct platform_driver ath12k_ahb_driver = {
1140- .driver = {
1141- .name = "ath12k_ahb" ,
1142- .of_match_table = ath12k_ahb_of_match ,
1143- },
1144- .probe = ath12k_ahb_probe ,
1145- .remove = ath12k_ahb_remove ,
1146- };
1147-
1148- int ath12k_ahb_init (void )
1174+ int ath12k_ahb_register_driver (const enum ath12k_device_family device_id ,
1175+ struct ath12k_ahb_driver * driver )
11491176{
1150- return platform_driver_register (& ath12k_ahb_driver );
1177+ struct platform_driver * ahb_driver ;
1178+
1179+ if (device_id >= ATH12K_DEVICE_FAMILY_MAX )
1180+ return - EINVAL ;
1181+
1182+ if (!driver || !driver -> ops .probe ||
1183+ !driver -> ops .arch_init || !driver -> ops .arch_deinit )
1184+ return - EINVAL ;
1185+
1186+ if (ath12k_ahb_family_drivers [device_id ]) {
1187+ pr_err ("Driver already registered for id %d\n" , device_id );
1188+ return - EALREADY ;
1189+ }
1190+
1191+ ath12k_ahb_family_drivers [device_id ] = driver ;
1192+
1193+ ahb_driver = & ath12k_ahb_family_drivers [device_id ]-> driver ;
1194+ ahb_driver -> driver .name = driver -> name ;
1195+ ahb_driver -> driver .of_match_table = driver -> id_table ;
1196+ ahb_driver -> probe = ath12k_ahb_probe ;
1197+ ahb_driver -> remove = ath12k_ahb_remove ;
1198+
1199+ return platform_driver_register (ahb_driver );
11511200}
1201+ EXPORT_SYMBOL (ath12k_ahb_register_driver );
11521202
1153- void ath12k_ahb_exit ( void )
1203+ void ath12k_ahb_unregister_driver ( const enum ath12k_device_family device_id )
11541204{
1155- platform_driver_unregister (& ath12k_ahb_driver );
1205+ struct platform_driver * ahb_driver ;
1206+
1207+ if (device_id >= ATH12K_DEVICE_FAMILY_MAX )
1208+ return ;
1209+
1210+ if (!ath12k_ahb_family_drivers [device_id ])
1211+ return ;
1212+
1213+ ahb_driver = & ath12k_ahb_family_drivers [device_id ]-> driver ;
1214+ platform_driver_unregister (ahb_driver );
1215+ ath12k_ahb_family_drivers [device_id ] = NULL ;
11561216}
1217+ EXPORT_SYMBOL (ath12k_ahb_unregister_driver );
0 commit comments