18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * This file is part of wl1271
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2008-2010 Nokia Corporation
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/module.h>
98c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h>
108c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/err.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include "../wlcore/wlcore.h"
158c2ecf20Sopenharmony_ci#include "../wlcore/debug.h"
168c2ecf20Sopenharmony_ci#include "../wlcore/io.h"
178c2ecf20Sopenharmony_ci#include "../wlcore/acx.h"
188c2ecf20Sopenharmony_ci#include "../wlcore/tx.h"
198c2ecf20Sopenharmony_ci#include "../wlcore/rx.h"
208c2ecf20Sopenharmony_ci#include "../wlcore/boot.h"
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include "wl12xx.h"
238c2ecf20Sopenharmony_ci#include "reg.h"
248c2ecf20Sopenharmony_ci#include "cmd.h"
258c2ecf20Sopenharmony_ci#include "acx.h"
268c2ecf20Sopenharmony_ci#include "scan.h"
278c2ecf20Sopenharmony_ci#include "event.h"
288c2ecf20Sopenharmony_ci#include "debugfs.h"
298c2ecf20Sopenharmony_ci#include "conf.h"
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistatic char *fref_param;
328c2ecf20Sopenharmony_cistatic char *tcxo_param;
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistatic struct wlcore_conf wl12xx_conf = {
358c2ecf20Sopenharmony_ci	.sg = {
368c2ecf20Sopenharmony_ci		.params = {
378c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_BT_MASTER_MIN_BR] = 10,
388c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_BT_MASTER_MAX_BR] = 180,
398c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_BT_SLAVE_MIN_BR] = 10,
408c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_BT_SLAVE_MAX_BR] = 180,
418c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_BT_MASTER_MIN_EDR] = 10,
428c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_BT_MASTER_MAX_EDR] = 80,
438c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_BT_SLAVE_MIN_EDR] = 10,
448c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_BT_SLAVE_MAX_EDR] = 80,
458c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_WLAN_PS_MASTER_BR] = 8,
468c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_WLAN_PS_SLAVE_BR] = 8,
478c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_WLAN_PS_MASTER_EDR] = 20,
488c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_WLAN_PS_SLAVE_EDR] = 20,
498c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR] = 20,
508c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR] = 35,
518c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR] = 16,
528c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR] = 35,
538c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR] = 32,
548c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR] = 50,
558c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR] = 28,
568c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR] = 50,
578c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR] = 10,
588c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR] = 20,
598c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_PASSIVE_SCAN_BT_BR] = 75,
608c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR] = 15,
618c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_PASSIVE_SCAN_BT_EDR] = 27,
628c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR] = 17,
638c2ecf20Sopenharmony_ci			/* active scan params */
648c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
658c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
668c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100,
678c2ecf20Sopenharmony_ci			/* passive scan params */
688c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_PASSIVE_SCAN_DUR_FACTOR_A2DP_BR] = 800,
698c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_PASSIVE_SCAN_DUR_FACTOR_A2DP_EDR] = 200,
708c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_PASSIVE_SCAN_DUR_FACTOR_HV3] = 200,
718c2ecf20Sopenharmony_ci			/* passive scan in dual antenna params */
728c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0,
738c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_BCN_HV3_COLL_THR_IN_PASSIVE_SCAN] = 0,
748c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_TX_RX_PROTECT_BW_IN_PASSIVE_SCAN] = 0,
758c2ecf20Sopenharmony_ci			/* general params */
768c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1,
778c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ANTENNA_CONFIGURATION] = 0,
788c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_BEACON_MISS_PERCENT] = 60,
798c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_DHCP_TIME] = 5000,
808c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_RXT] = 1200,
818c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_TXT] = 1000,
828c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_ADAPTIVE_RXT_TXT] = 1,
838c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_GENERAL_USAGE_BIT_MAP] = 3,
848c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_HV3_MAX_SERVED] = 6,
858c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_PS_POLL_TIMEOUT] = 10,
868c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_UPSD_TIMEOUT] = 10,
878c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2,
888c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_STA_RX_WINDOW_AFTER_DTIM] = 5,
898c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 30,
908c2ecf20Sopenharmony_ci			/* AP params */
918c2ecf20Sopenharmony_ci			[WL12XX_CONF_AP_BEACON_MISS_TX] = 3,
928c2ecf20Sopenharmony_ci			[WL12XX_CONF_AP_RX_WINDOW_AFTER_BEACON] = 10,
938c2ecf20Sopenharmony_ci			[WL12XX_CONF_AP_BEACON_WINDOW_INTERVAL] = 2,
948c2ecf20Sopenharmony_ci			[WL12XX_CONF_AP_CONNECTION_PROTECTION_TIME] = 0,
958c2ecf20Sopenharmony_ci			[WL12XX_CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25,
968c2ecf20Sopenharmony_ci			[WL12XX_CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25,
978c2ecf20Sopenharmony_ci			/* CTS Diluting params */
988c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH] = 0,
998c2ecf20Sopenharmony_ci			[WL12XX_CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER] = 0,
1008c2ecf20Sopenharmony_ci		},
1018c2ecf20Sopenharmony_ci		.state = CONF_SG_PROTECTIVE,
1028c2ecf20Sopenharmony_ci	},
1038c2ecf20Sopenharmony_ci	.rx = {
1048c2ecf20Sopenharmony_ci		.rx_msdu_life_time           = 512000,
1058c2ecf20Sopenharmony_ci		.packet_detection_threshold  = 0,
1068c2ecf20Sopenharmony_ci		.ps_poll_timeout             = 15,
1078c2ecf20Sopenharmony_ci		.upsd_timeout                = 15,
1088c2ecf20Sopenharmony_ci		.rts_threshold               = IEEE80211_MAX_RTS_THRESHOLD,
1098c2ecf20Sopenharmony_ci		.rx_cca_threshold            = 0,
1108c2ecf20Sopenharmony_ci		.irq_blk_threshold           = 0xFFFF,
1118c2ecf20Sopenharmony_ci		.irq_pkt_threshold           = 0,
1128c2ecf20Sopenharmony_ci		.irq_timeout                 = 600,
1138c2ecf20Sopenharmony_ci		.queue_type                  = CONF_RX_QUEUE_TYPE_LOW_PRIORITY,
1148c2ecf20Sopenharmony_ci	},
1158c2ecf20Sopenharmony_ci	.tx = {
1168c2ecf20Sopenharmony_ci		.tx_energy_detection         = 0,
1178c2ecf20Sopenharmony_ci		.sta_rc_conf                 = {
1188c2ecf20Sopenharmony_ci			.enabled_rates       = 0,
1198c2ecf20Sopenharmony_ci			.short_retry_limit   = 10,
1208c2ecf20Sopenharmony_ci			.long_retry_limit    = 10,
1218c2ecf20Sopenharmony_ci			.aflags              = 0,
1228c2ecf20Sopenharmony_ci		},
1238c2ecf20Sopenharmony_ci		.ac_conf_count               = 4,
1248c2ecf20Sopenharmony_ci		.ac_conf                     = {
1258c2ecf20Sopenharmony_ci			[CONF_TX_AC_BE] = {
1268c2ecf20Sopenharmony_ci				.ac          = CONF_TX_AC_BE,
1278c2ecf20Sopenharmony_ci				.cw_min      = 15,
1288c2ecf20Sopenharmony_ci				.cw_max      = 63,
1298c2ecf20Sopenharmony_ci				.aifsn       = 3,
1308c2ecf20Sopenharmony_ci				.tx_op_limit = 0,
1318c2ecf20Sopenharmony_ci			},
1328c2ecf20Sopenharmony_ci			[CONF_TX_AC_BK] = {
1338c2ecf20Sopenharmony_ci				.ac          = CONF_TX_AC_BK,
1348c2ecf20Sopenharmony_ci				.cw_min      = 15,
1358c2ecf20Sopenharmony_ci				.cw_max      = 63,
1368c2ecf20Sopenharmony_ci				.aifsn       = 7,
1378c2ecf20Sopenharmony_ci				.tx_op_limit = 0,
1388c2ecf20Sopenharmony_ci			},
1398c2ecf20Sopenharmony_ci			[CONF_TX_AC_VI] = {
1408c2ecf20Sopenharmony_ci				.ac          = CONF_TX_AC_VI,
1418c2ecf20Sopenharmony_ci				.cw_min      = 15,
1428c2ecf20Sopenharmony_ci				.cw_max      = 63,
1438c2ecf20Sopenharmony_ci				.aifsn       = CONF_TX_AIFS_PIFS,
1448c2ecf20Sopenharmony_ci				.tx_op_limit = 3008,
1458c2ecf20Sopenharmony_ci			},
1468c2ecf20Sopenharmony_ci			[CONF_TX_AC_VO] = {
1478c2ecf20Sopenharmony_ci				.ac          = CONF_TX_AC_VO,
1488c2ecf20Sopenharmony_ci				.cw_min      = 15,
1498c2ecf20Sopenharmony_ci				.cw_max      = 63,
1508c2ecf20Sopenharmony_ci				.aifsn       = CONF_TX_AIFS_PIFS,
1518c2ecf20Sopenharmony_ci				.tx_op_limit = 1504,
1528c2ecf20Sopenharmony_ci			},
1538c2ecf20Sopenharmony_ci		},
1548c2ecf20Sopenharmony_ci		.max_tx_retries = 100,
1558c2ecf20Sopenharmony_ci		.ap_aging_period = 300,
1568c2ecf20Sopenharmony_ci		.tid_conf_count = 4,
1578c2ecf20Sopenharmony_ci		.tid_conf = {
1588c2ecf20Sopenharmony_ci			[CONF_TX_AC_BE] = {
1598c2ecf20Sopenharmony_ci				.queue_id    = CONF_TX_AC_BE,
1608c2ecf20Sopenharmony_ci				.channel_type = CONF_CHANNEL_TYPE_EDCF,
1618c2ecf20Sopenharmony_ci				.tsid        = CONF_TX_AC_BE,
1628c2ecf20Sopenharmony_ci				.ps_scheme   = CONF_PS_SCHEME_LEGACY,
1638c2ecf20Sopenharmony_ci				.ack_policy  = CONF_ACK_POLICY_LEGACY,
1648c2ecf20Sopenharmony_ci				.apsd_conf   = {0, 0},
1658c2ecf20Sopenharmony_ci			},
1668c2ecf20Sopenharmony_ci			[CONF_TX_AC_BK] = {
1678c2ecf20Sopenharmony_ci				.queue_id    = CONF_TX_AC_BK,
1688c2ecf20Sopenharmony_ci				.channel_type = CONF_CHANNEL_TYPE_EDCF,
1698c2ecf20Sopenharmony_ci				.tsid        = CONF_TX_AC_BK,
1708c2ecf20Sopenharmony_ci				.ps_scheme   = CONF_PS_SCHEME_LEGACY,
1718c2ecf20Sopenharmony_ci				.ack_policy  = CONF_ACK_POLICY_LEGACY,
1728c2ecf20Sopenharmony_ci				.apsd_conf   = {0, 0},
1738c2ecf20Sopenharmony_ci			},
1748c2ecf20Sopenharmony_ci			[CONF_TX_AC_VI] = {
1758c2ecf20Sopenharmony_ci				.queue_id    = CONF_TX_AC_VI,
1768c2ecf20Sopenharmony_ci				.channel_type = CONF_CHANNEL_TYPE_EDCF,
1778c2ecf20Sopenharmony_ci				.tsid        = CONF_TX_AC_VI,
1788c2ecf20Sopenharmony_ci				.ps_scheme   = CONF_PS_SCHEME_LEGACY,
1798c2ecf20Sopenharmony_ci				.ack_policy  = CONF_ACK_POLICY_LEGACY,
1808c2ecf20Sopenharmony_ci				.apsd_conf   = {0, 0},
1818c2ecf20Sopenharmony_ci			},
1828c2ecf20Sopenharmony_ci			[CONF_TX_AC_VO] = {
1838c2ecf20Sopenharmony_ci				.queue_id    = CONF_TX_AC_VO,
1848c2ecf20Sopenharmony_ci				.channel_type = CONF_CHANNEL_TYPE_EDCF,
1858c2ecf20Sopenharmony_ci				.tsid        = CONF_TX_AC_VO,
1868c2ecf20Sopenharmony_ci				.ps_scheme   = CONF_PS_SCHEME_LEGACY,
1878c2ecf20Sopenharmony_ci				.ack_policy  = CONF_ACK_POLICY_LEGACY,
1888c2ecf20Sopenharmony_ci				.apsd_conf   = {0, 0},
1898c2ecf20Sopenharmony_ci			},
1908c2ecf20Sopenharmony_ci		},
1918c2ecf20Sopenharmony_ci		.frag_threshold              = IEEE80211_MAX_FRAG_THRESHOLD,
1928c2ecf20Sopenharmony_ci		.tx_compl_timeout            = 700,
1938c2ecf20Sopenharmony_ci		.tx_compl_threshold          = 4,
1948c2ecf20Sopenharmony_ci		.basic_rate                  = CONF_HW_BIT_RATE_1MBPS,
1958c2ecf20Sopenharmony_ci		.basic_rate_5                = CONF_HW_BIT_RATE_6MBPS,
1968c2ecf20Sopenharmony_ci		.tmpl_short_retry_limit      = 10,
1978c2ecf20Sopenharmony_ci		.tmpl_long_retry_limit       = 10,
1988c2ecf20Sopenharmony_ci		.tx_watchdog_timeout         = 5000,
1998c2ecf20Sopenharmony_ci		.slow_link_thold             = 3,
2008c2ecf20Sopenharmony_ci		.fast_link_thold             = 10,
2018c2ecf20Sopenharmony_ci	},
2028c2ecf20Sopenharmony_ci	.conn = {
2038c2ecf20Sopenharmony_ci		.wake_up_event               = CONF_WAKE_UP_EVENT_DTIM,
2048c2ecf20Sopenharmony_ci		.listen_interval             = 1,
2058c2ecf20Sopenharmony_ci		.suspend_wake_up_event       = CONF_WAKE_UP_EVENT_N_DTIM,
2068c2ecf20Sopenharmony_ci		.suspend_listen_interval     = 3,
2078c2ecf20Sopenharmony_ci		.bcn_filt_mode               = CONF_BCN_FILT_MODE_ENABLED,
2088c2ecf20Sopenharmony_ci		.bcn_filt_ie_count           = 3,
2098c2ecf20Sopenharmony_ci		.bcn_filt_ie = {
2108c2ecf20Sopenharmony_ci			[0] = {
2118c2ecf20Sopenharmony_ci				.ie          = WLAN_EID_CHANNEL_SWITCH,
2128c2ecf20Sopenharmony_ci				.rule        = CONF_BCN_RULE_PASS_ON_APPEARANCE,
2138c2ecf20Sopenharmony_ci			},
2148c2ecf20Sopenharmony_ci			[1] = {
2158c2ecf20Sopenharmony_ci				.ie          = WLAN_EID_HT_OPERATION,
2168c2ecf20Sopenharmony_ci				.rule        = CONF_BCN_RULE_PASS_ON_CHANGE,
2178c2ecf20Sopenharmony_ci			},
2188c2ecf20Sopenharmony_ci			[2] = {
2198c2ecf20Sopenharmony_ci				.ie	     = WLAN_EID_ERP_INFO,
2208c2ecf20Sopenharmony_ci				.rule	     = CONF_BCN_RULE_PASS_ON_CHANGE,
2218c2ecf20Sopenharmony_ci			},
2228c2ecf20Sopenharmony_ci		},
2238c2ecf20Sopenharmony_ci		.synch_fail_thold            = 12,
2248c2ecf20Sopenharmony_ci		.bss_lose_timeout            = 400,
2258c2ecf20Sopenharmony_ci		.beacon_rx_timeout           = 10000,
2268c2ecf20Sopenharmony_ci		.broadcast_timeout           = 20000,
2278c2ecf20Sopenharmony_ci		.rx_broadcast_in_ps          = 1,
2288c2ecf20Sopenharmony_ci		.ps_poll_threshold           = 10,
2298c2ecf20Sopenharmony_ci		.bet_enable                  = CONF_BET_MODE_ENABLE,
2308c2ecf20Sopenharmony_ci		.bet_max_consecutive         = 50,
2318c2ecf20Sopenharmony_ci		.psm_entry_retries           = 8,
2328c2ecf20Sopenharmony_ci		.psm_exit_retries            = 16,
2338c2ecf20Sopenharmony_ci		.psm_entry_nullfunc_retries  = 3,
2348c2ecf20Sopenharmony_ci		.dynamic_ps_timeout          = 1500,
2358c2ecf20Sopenharmony_ci		.forced_ps                   = false,
2368c2ecf20Sopenharmony_ci		.keep_alive_interval         = 55000,
2378c2ecf20Sopenharmony_ci		.max_listen_interval         = 20,
2388c2ecf20Sopenharmony_ci		.sta_sleep_auth              = WL1271_PSM_ILLEGAL,
2398c2ecf20Sopenharmony_ci		.suspend_rx_ba_activity      = 0,
2408c2ecf20Sopenharmony_ci	},
2418c2ecf20Sopenharmony_ci	.itrim = {
2428c2ecf20Sopenharmony_ci		.enable = false,
2438c2ecf20Sopenharmony_ci		.timeout = 50000,
2448c2ecf20Sopenharmony_ci	},
2458c2ecf20Sopenharmony_ci	.pm_config = {
2468c2ecf20Sopenharmony_ci		.host_clk_settling_time = 5000,
2478c2ecf20Sopenharmony_ci		.host_fast_wakeup_support = CONF_FAST_WAKEUP_DISABLE,
2488c2ecf20Sopenharmony_ci	},
2498c2ecf20Sopenharmony_ci	.roam_trigger = {
2508c2ecf20Sopenharmony_ci		.trigger_pacing               = 1,
2518c2ecf20Sopenharmony_ci		.avg_weight_rssi_beacon       = 20,
2528c2ecf20Sopenharmony_ci		.avg_weight_rssi_data         = 10,
2538c2ecf20Sopenharmony_ci		.avg_weight_snr_beacon        = 20,
2548c2ecf20Sopenharmony_ci		.avg_weight_snr_data          = 10,
2558c2ecf20Sopenharmony_ci	},
2568c2ecf20Sopenharmony_ci	.scan = {
2578c2ecf20Sopenharmony_ci		.min_dwell_time_active        = 7500,
2588c2ecf20Sopenharmony_ci		.max_dwell_time_active        = 30000,
2598c2ecf20Sopenharmony_ci		.min_dwell_time_active_long   = 25000,
2608c2ecf20Sopenharmony_ci		.max_dwell_time_active_long   = 50000,
2618c2ecf20Sopenharmony_ci		.dwell_time_passive           = 100000,
2628c2ecf20Sopenharmony_ci		.dwell_time_dfs               = 150000,
2638c2ecf20Sopenharmony_ci		.num_probe_reqs               = 2,
2648c2ecf20Sopenharmony_ci		.split_scan_timeout           = 50000,
2658c2ecf20Sopenharmony_ci	},
2668c2ecf20Sopenharmony_ci	.sched_scan = {
2678c2ecf20Sopenharmony_ci		/*
2688c2ecf20Sopenharmony_ci		 * Values are in TU/1000 but since sched scan FW command
2698c2ecf20Sopenharmony_ci		 * params are in TUs rounding up may occur.
2708c2ecf20Sopenharmony_ci		 */
2718c2ecf20Sopenharmony_ci		.base_dwell_time		= 7500,
2728c2ecf20Sopenharmony_ci		.max_dwell_time_delta		= 22500,
2738c2ecf20Sopenharmony_ci		/* based on 250bits per probe @1Mbps */
2748c2ecf20Sopenharmony_ci		.dwell_time_delta_per_probe	= 2000,
2758c2ecf20Sopenharmony_ci		/* based on 250bits per probe @6Mbps (plus a bit more) */
2768c2ecf20Sopenharmony_ci		.dwell_time_delta_per_probe_5	= 350,
2778c2ecf20Sopenharmony_ci		.dwell_time_passive		= 100000,
2788c2ecf20Sopenharmony_ci		.dwell_time_dfs			= 150000,
2798c2ecf20Sopenharmony_ci		.num_probe_reqs			= 2,
2808c2ecf20Sopenharmony_ci		.rssi_threshold			= -90,
2818c2ecf20Sopenharmony_ci		.snr_threshold			= 0,
2828c2ecf20Sopenharmony_ci	},
2838c2ecf20Sopenharmony_ci	.ht = {
2848c2ecf20Sopenharmony_ci		.rx_ba_win_size = 8,
2858c2ecf20Sopenharmony_ci		.tx_ba_win_size = 64,
2868c2ecf20Sopenharmony_ci		.inactivity_timeout = 10000,
2878c2ecf20Sopenharmony_ci		.tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP,
2888c2ecf20Sopenharmony_ci	},
2898c2ecf20Sopenharmony_ci	/*
2908c2ecf20Sopenharmony_ci	 * Memory config for wl127x chips is given in the
2918c2ecf20Sopenharmony_ci	 * wl12xx_default_priv_conf struct. The below configuration is
2928c2ecf20Sopenharmony_ci	 * for wl128x chips.
2938c2ecf20Sopenharmony_ci	 */
2948c2ecf20Sopenharmony_ci	.mem = {
2958c2ecf20Sopenharmony_ci		.num_stations                 = 1,
2968c2ecf20Sopenharmony_ci		.ssid_profiles                = 1,
2978c2ecf20Sopenharmony_ci		.rx_block_num                 = 40,
2988c2ecf20Sopenharmony_ci		.tx_min_block_num             = 40,
2998c2ecf20Sopenharmony_ci		.dynamic_memory               = 1,
3008c2ecf20Sopenharmony_ci		.min_req_tx_blocks            = 45,
3018c2ecf20Sopenharmony_ci		.min_req_rx_blocks            = 22,
3028c2ecf20Sopenharmony_ci		.tx_min                       = 27,
3038c2ecf20Sopenharmony_ci	},
3048c2ecf20Sopenharmony_ci	.fm_coex = {
3058c2ecf20Sopenharmony_ci		.enable                       = true,
3068c2ecf20Sopenharmony_ci		.swallow_period               = 5,
3078c2ecf20Sopenharmony_ci		.n_divider_fref_set_1         = 0xff,       /* default */
3088c2ecf20Sopenharmony_ci		.n_divider_fref_set_2         = 12,
3098c2ecf20Sopenharmony_ci		.m_divider_fref_set_1         = 0xffff,
3108c2ecf20Sopenharmony_ci		.m_divider_fref_set_2         = 148,	    /* default */
3118c2ecf20Sopenharmony_ci		.coex_pll_stabilization_time  = 0xffffffff, /* default */
3128c2ecf20Sopenharmony_ci		.ldo_stabilization_time       = 0xffff,     /* default */
3138c2ecf20Sopenharmony_ci		.fm_disturbed_band_margin     = 0xff,       /* default */
3148c2ecf20Sopenharmony_ci		.swallow_clk_diff             = 0xff,       /* default */
3158c2ecf20Sopenharmony_ci	},
3168c2ecf20Sopenharmony_ci	.rx_streaming = {
3178c2ecf20Sopenharmony_ci		.duration                      = 150,
3188c2ecf20Sopenharmony_ci		.queues                        = 0x1,
3198c2ecf20Sopenharmony_ci		.interval                      = 20,
3208c2ecf20Sopenharmony_ci		.always                        = 0,
3218c2ecf20Sopenharmony_ci	},
3228c2ecf20Sopenharmony_ci	.fwlog = {
3238c2ecf20Sopenharmony_ci		.mode                         = WL12XX_FWLOG_CONTINUOUS,
3248c2ecf20Sopenharmony_ci		.mem_blocks                   = 2,
3258c2ecf20Sopenharmony_ci		.severity                     = 0,
3268c2ecf20Sopenharmony_ci		.timestamp                    = WL12XX_FWLOG_TIMESTAMP_DISABLED,
3278c2ecf20Sopenharmony_ci		.output                       = WL12XX_FWLOG_OUTPUT_DBG_PINS,
3288c2ecf20Sopenharmony_ci		.threshold                    = 0,
3298c2ecf20Sopenharmony_ci	},
3308c2ecf20Sopenharmony_ci	.rate = {
3318c2ecf20Sopenharmony_ci		.rate_retry_score = 32000,
3328c2ecf20Sopenharmony_ci		.per_add = 8192,
3338c2ecf20Sopenharmony_ci		.per_th1 = 2048,
3348c2ecf20Sopenharmony_ci		.per_th2 = 4096,
3358c2ecf20Sopenharmony_ci		.max_per = 8100,
3368c2ecf20Sopenharmony_ci		.inverse_curiosity_factor = 5,
3378c2ecf20Sopenharmony_ci		.tx_fail_low_th = 4,
3388c2ecf20Sopenharmony_ci		.tx_fail_high_th = 10,
3398c2ecf20Sopenharmony_ci		.per_alpha_shift = 4,
3408c2ecf20Sopenharmony_ci		.per_add_shift = 13,
3418c2ecf20Sopenharmony_ci		.per_beta1_shift = 10,
3428c2ecf20Sopenharmony_ci		.per_beta2_shift = 8,
3438c2ecf20Sopenharmony_ci		.rate_check_up = 2,
3448c2ecf20Sopenharmony_ci		.rate_check_down = 12,
3458c2ecf20Sopenharmony_ci		.rate_retry_policy = {
3468c2ecf20Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00,
3478c2ecf20Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00,
3488c2ecf20Sopenharmony_ci			0x00, 0x00, 0x00,
3498c2ecf20Sopenharmony_ci		},
3508c2ecf20Sopenharmony_ci	},
3518c2ecf20Sopenharmony_ci	.hangover = {
3528c2ecf20Sopenharmony_ci		.recover_time               = 0,
3538c2ecf20Sopenharmony_ci		.hangover_period            = 20,
3548c2ecf20Sopenharmony_ci		.dynamic_mode               = 1,
3558c2ecf20Sopenharmony_ci		.early_termination_mode     = 1,
3568c2ecf20Sopenharmony_ci		.max_period                 = 20,
3578c2ecf20Sopenharmony_ci		.min_period                 = 1,
3588c2ecf20Sopenharmony_ci		.increase_delta             = 1,
3598c2ecf20Sopenharmony_ci		.decrease_delta             = 2,
3608c2ecf20Sopenharmony_ci		.quiet_time                 = 4,
3618c2ecf20Sopenharmony_ci		.increase_time              = 1,
3628c2ecf20Sopenharmony_ci		.window_size                = 16,
3638c2ecf20Sopenharmony_ci	},
3648c2ecf20Sopenharmony_ci	.recovery = {
3658c2ecf20Sopenharmony_ci		.bug_on_recovery	    = 0,
3668c2ecf20Sopenharmony_ci		.no_recovery		    = 0,
3678c2ecf20Sopenharmony_ci	},
3688c2ecf20Sopenharmony_ci};
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_cistatic struct wl12xx_priv_conf wl12xx_default_priv_conf = {
3718c2ecf20Sopenharmony_ci	.rf = {
3728c2ecf20Sopenharmony_ci		.tx_per_channel_power_compensation_2 = {
3738c2ecf20Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3748c2ecf20Sopenharmony_ci		},
3758c2ecf20Sopenharmony_ci		.tx_per_channel_power_compensation_5 = {
3768c2ecf20Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3778c2ecf20Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3788c2ecf20Sopenharmony_ci			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3798c2ecf20Sopenharmony_ci		},
3808c2ecf20Sopenharmony_ci	},
3818c2ecf20Sopenharmony_ci	.mem_wl127x = {
3828c2ecf20Sopenharmony_ci		.num_stations                 = 1,
3838c2ecf20Sopenharmony_ci		.ssid_profiles                = 1,
3848c2ecf20Sopenharmony_ci		.rx_block_num                 = 70,
3858c2ecf20Sopenharmony_ci		.tx_min_block_num             = 40,
3868c2ecf20Sopenharmony_ci		.dynamic_memory               = 1,
3878c2ecf20Sopenharmony_ci		.min_req_tx_blocks            = 100,
3888c2ecf20Sopenharmony_ci		.min_req_rx_blocks            = 22,
3898c2ecf20Sopenharmony_ci		.tx_min                       = 27,
3908c2ecf20Sopenharmony_ci	},
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci};
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci#define WL12XX_TX_HW_BLOCK_SPARE_DEFAULT        1
3958c2ecf20Sopenharmony_ci#define WL12XX_TX_HW_BLOCK_GEM_SPARE            2
3968c2ecf20Sopenharmony_ci#define WL12XX_TX_HW_BLOCK_SIZE                 252
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_cistatic const u8 wl12xx_rate_to_idx_2ghz[] = {
3998c2ecf20Sopenharmony_ci	/* MCS rates are used only with 11n */
4008c2ecf20Sopenharmony_ci	7,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS7_SGI */
4018c2ecf20Sopenharmony_ci	7,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS7 */
4028c2ecf20Sopenharmony_ci	6,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS6 */
4038c2ecf20Sopenharmony_ci	5,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS5 */
4048c2ecf20Sopenharmony_ci	4,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS4 */
4058c2ecf20Sopenharmony_ci	3,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS3 */
4068c2ecf20Sopenharmony_ci	2,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS2 */
4078c2ecf20Sopenharmony_ci	1,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS1 */
4088c2ecf20Sopenharmony_ci	0,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS0 */
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	11,                            /* WL12XX_CONF_HW_RXTX_RATE_54   */
4118c2ecf20Sopenharmony_ci	10,                            /* WL12XX_CONF_HW_RXTX_RATE_48   */
4128c2ecf20Sopenharmony_ci	9,                             /* WL12XX_CONF_HW_RXTX_RATE_36   */
4138c2ecf20Sopenharmony_ci	8,                             /* WL12XX_CONF_HW_RXTX_RATE_24   */
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	/* TI-specific rate */
4168c2ecf20Sopenharmony_ci	CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_22   */
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	7,                             /* WL12XX_CONF_HW_RXTX_RATE_18   */
4198c2ecf20Sopenharmony_ci	6,                             /* WL12XX_CONF_HW_RXTX_RATE_12   */
4208c2ecf20Sopenharmony_ci	3,                             /* WL12XX_CONF_HW_RXTX_RATE_11   */
4218c2ecf20Sopenharmony_ci	5,                             /* WL12XX_CONF_HW_RXTX_RATE_9    */
4228c2ecf20Sopenharmony_ci	4,                             /* WL12XX_CONF_HW_RXTX_RATE_6    */
4238c2ecf20Sopenharmony_ci	2,                             /* WL12XX_CONF_HW_RXTX_RATE_5_5  */
4248c2ecf20Sopenharmony_ci	1,                             /* WL12XX_CONF_HW_RXTX_RATE_2    */
4258c2ecf20Sopenharmony_ci	0                              /* WL12XX_CONF_HW_RXTX_RATE_1    */
4268c2ecf20Sopenharmony_ci};
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_cistatic const u8 wl12xx_rate_to_idx_5ghz[] = {
4298c2ecf20Sopenharmony_ci	/* MCS rates are used only with 11n */
4308c2ecf20Sopenharmony_ci	7,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS7_SGI */
4318c2ecf20Sopenharmony_ci	7,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS7 */
4328c2ecf20Sopenharmony_ci	6,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS6 */
4338c2ecf20Sopenharmony_ci	5,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS5 */
4348c2ecf20Sopenharmony_ci	4,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS4 */
4358c2ecf20Sopenharmony_ci	3,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS3 */
4368c2ecf20Sopenharmony_ci	2,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS2 */
4378c2ecf20Sopenharmony_ci	1,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS1 */
4388c2ecf20Sopenharmony_ci	0,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS0 */
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	7,                             /* WL12XX_CONF_HW_RXTX_RATE_54   */
4418c2ecf20Sopenharmony_ci	6,                             /* WL12XX_CONF_HW_RXTX_RATE_48   */
4428c2ecf20Sopenharmony_ci	5,                             /* WL12XX_CONF_HW_RXTX_RATE_36   */
4438c2ecf20Sopenharmony_ci	4,                             /* WL12XX_CONF_HW_RXTX_RATE_24   */
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci	/* TI-specific rate */
4468c2ecf20Sopenharmony_ci	CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_22   */
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	3,                             /* WL12XX_CONF_HW_RXTX_RATE_18   */
4498c2ecf20Sopenharmony_ci	2,                             /* WL12XX_CONF_HW_RXTX_RATE_12   */
4508c2ecf20Sopenharmony_ci	CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_11   */
4518c2ecf20Sopenharmony_ci	1,                             /* WL12XX_CONF_HW_RXTX_RATE_9    */
4528c2ecf20Sopenharmony_ci	0,                             /* WL12XX_CONF_HW_RXTX_RATE_6    */
4538c2ecf20Sopenharmony_ci	CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_5_5  */
4548c2ecf20Sopenharmony_ci	CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_2    */
4558c2ecf20Sopenharmony_ci	CONF_HW_RXTX_RATE_UNSUPPORTED  /* WL12XX_CONF_HW_RXTX_RATE_1    */
4568c2ecf20Sopenharmony_ci};
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_cistatic const u8 *wl12xx_band_rate_to_idx[] = {
4598c2ecf20Sopenharmony_ci	[NL80211_BAND_2GHZ] = wl12xx_rate_to_idx_2ghz,
4608c2ecf20Sopenharmony_ci	[NL80211_BAND_5GHZ] = wl12xx_rate_to_idx_5ghz
4618c2ecf20Sopenharmony_ci};
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_cienum wl12xx_hw_rates {
4648c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_MCS7_SGI = 0,
4658c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_MCS7,
4668c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_MCS6,
4678c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_MCS5,
4688c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_MCS4,
4698c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_MCS3,
4708c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_MCS2,
4718c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_MCS1,
4728c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_MCS0,
4738c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_54,
4748c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_48,
4758c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_36,
4768c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_24,
4778c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_22,
4788c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_18,
4798c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_12,
4808c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_11,
4818c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_9,
4828c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_6,
4838c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_5_5,
4848c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_2,
4858c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_1,
4868c2ecf20Sopenharmony_ci	WL12XX_CONF_HW_RXTX_RATE_MAX,
4878c2ecf20Sopenharmony_ci};
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_cistatic struct wlcore_partition_set wl12xx_ptable[PART_TABLE_LEN] = {
4908c2ecf20Sopenharmony_ci	[PART_DOWN] = {
4918c2ecf20Sopenharmony_ci		.mem = {
4928c2ecf20Sopenharmony_ci			.start = 0x00000000,
4938c2ecf20Sopenharmony_ci			.size  = 0x000177c0
4948c2ecf20Sopenharmony_ci		},
4958c2ecf20Sopenharmony_ci		.reg = {
4968c2ecf20Sopenharmony_ci			.start = REGISTERS_BASE,
4978c2ecf20Sopenharmony_ci			.size  = 0x00008800
4988c2ecf20Sopenharmony_ci		},
4998c2ecf20Sopenharmony_ci		.mem2 = {
5008c2ecf20Sopenharmony_ci			.start = 0x00000000,
5018c2ecf20Sopenharmony_ci			.size  = 0x00000000
5028c2ecf20Sopenharmony_ci		},
5038c2ecf20Sopenharmony_ci		.mem3 = {
5048c2ecf20Sopenharmony_ci			.start = 0x00000000,
5058c2ecf20Sopenharmony_ci			.size  = 0x00000000
5068c2ecf20Sopenharmony_ci		},
5078c2ecf20Sopenharmony_ci	},
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	[PART_BOOT] = { /* in wl12xx we can use a mix of work and down
5108c2ecf20Sopenharmony_ci			 * partition here */
5118c2ecf20Sopenharmony_ci		.mem = {
5128c2ecf20Sopenharmony_ci			.start = 0x00040000,
5138c2ecf20Sopenharmony_ci			.size  = 0x00014fc0
5148c2ecf20Sopenharmony_ci		},
5158c2ecf20Sopenharmony_ci		.reg = {
5168c2ecf20Sopenharmony_ci			.start = REGISTERS_BASE,
5178c2ecf20Sopenharmony_ci			.size  = 0x00008800
5188c2ecf20Sopenharmony_ci		},
5198c2ecf20Sopenharmony_ci		.mem2 = {
5208c2ecf20Sopenharmony_ci			.start = 0x00000000,
5218c2ecf20Sopenharmony_ci			.size  = 0x00000000
5228c2ecf20Sopenharmony_ci		},
5238c2ecf20Sopenharmony_ci		.mem3 = {
5248c2ecf20Sopenharmony_ci			.start = 0x00000000,
5258c2ecf20Sopenharmony_ci			.size  = 0x00000000
5268c2ecf20Sopenharmony_ci		},
5278c2ecf20Sopenharmony_ci	},
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	[PART_WORK] = {
5308c2ecf20Sopenharmony_ci		.mem = {
5318c2ecf20Sopenharmony_ci			.start = 0x00040000,
5328c2ecf20Sopenharmony_ci			.size  = 0x00014fc0
5338c2ecf20Sopenharmony_ci		},
5348c2ecf20Sopenharmony_ci		.reg = {
5358c2ecf20Sopenharmony_ci			.start = REGISTERS_BASE,
5368c2ecf20Sopenharmony_ci			.size  = 0x0000a000
5378c2ecf20Sopenharmony_ci		},
5388c2ecf20Sopenharmony_ci		.mem2 = {
5398c2ecf20Sopenharmony_ci			.start = 0x003004f8,
5408c2ecf20Sopenharmony_ci			.size  = 0x00000004
5418c2ecf20Sopenharmony_ci		},
5428c2ecf20Sopenharmony_ci		.mem3 = {
5438c2ecf20Sopenharmony_ci			.start = 0x00000000,
5448c2ecf20Sopenharmony_ci			.size  = 0x00040404
5458c2ecf20Sopenharmony_ci		},
5468c2ecf20Sopenharmony_ci	},
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	[PART_DRPW] = {
5498c2ecf20Sopenharmony_ci		.mem = {
5508c2ecf20Sopenharmony_ci			.start = 0x00040000,
5518c2ecf20Sopenharmony_ci			.size  = 0x00014fc0
5528c2ecf20Sopenharmony_ci		},
5538c2ecf20Sopenharmony_ci		.reg = {
5548c2ecf20Sopenharmony_ci			.start = DRPW_BASE,
5558c2ecf20Sopenharmony_ci			.size  = 0x00006000
5568c2ecf20Sopenharmony_ci		},
5578c2ecf20Sopenharmony_ci		.mem2 = {
5588c2ecf20Sopenharmony_ci			.start = 0x00000000,
5598c2ecf20Sopenharmony_ci			.size  = 0x00000000
5608c2ecf20Sopenharmony_ci		},
5618c2ecf20Sopenharmony_ci		.mem3 = {
5628c2ecf20Sopenharmony_ci			.start = 0x00000000,
5638c2ecf20Sopenharmony_ci			.size  = 0x00000000
5648c2ecf20Sopenharmony_ci		}
5658c2ecf20Sopenharmony_ci	}
5668c2ecf20Sopenharmony_ci};
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_cistatic const int wl12xx_rtable[REG_TABLE_LEN] = {
5698c2ecf20Sopenharmony_ci	[REG_ECPU_CONTROL]		= WL12XX_REG_ECPU_CONTROL,
5708c2ecf20Sopenharmony_ci	[REG_INTERRUPT_NO_CLEAR]	= WL12XX_REG_INTERRUPT_NO_CLEAR,
5718c2ecf20Sopenharmony_ci	[REG_INTERRUPT_ACK]		= WL12XX_REG_INTERRUPT_ACK,
5728c2ecf20Sopenharmony_ci	[REG_COMMAND_MAILBOX_PTR]	= WL12XX_REG_COMMAND_MAILBOX_PTR,
5738c2ecf20Sopenharmony_ci	[REG_EVENT_MAILBOX_PTR]		= WL12XX_REG_EVENT_MAILBOX_PTR,
5748c2ecf20Sopenharmony_ci	[REG_INTERRUPT_TRIG]		= WL12XX_REG_INTERRUPT_TRIG,
5758c2ecf20Sopenharmony_ci	[REG_INTERRUPT_MASK]		= WL12XX_REG_INTERRUPT_MASK,
5768c2ecf20Sopenharmony_ci	[REG_PC_ON_RECOVERY]		= WL12XX_SCR_PAD4,
5778c2ecf20Sopenharmony_ci	[REG_CHIP_ID_B]			= WL12XX_CHIP_ID_B,
5788c2ecf20Sopenharmony_ci	[REG_CMD_MBOX_ADDRESS]		= WL12XX_CMD_MBOX_ADDRESS,
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	/* data access memory addresses, used with partition translation */
5818c2ecf20Sopenharmony_ci	[REG_SLV_MEM_DATA]		= WL1271_SLV_MEM_DATA,
5828c2ecf20Sopenharmony_ci	[REG_SLV_REG_DATA]		= WL1271_SLV_REG_DATA,
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	/* raw data access memory addresses */
5858c2ecf20Sopenharmony_ci	[REG_RAW_FW_STATUS_ADDR]	= FW_STATUS_ADDR,
5868c2ecf20Sopenharmony_ci};
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci/* TODO: maybe move to a new header file? */
5898c2ecf20Sopenharmony_ci#define WL127X_FW_NAME_MULTI	"ti-connectivity/wl127x-fw-5-mr.bin"
5908c2ecf20Sopenharmony_ci#define WL127X_FW_NAME_SINGLE	"ti-connectivity/wl127x-fw-5-sr.bin"
5918c2ecf20Sopenharmony_ci#define WL127X_PLT_FW_NAME	"ti-connectivity/wl127x-fw-5-plt.bin"
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci#define WL128X_FW_NAME_MULTI	"ti-connectivity/wl128x-fw-5-mr.bin"
5948c2ecf20Sopenharmony_ci#define WL128X_FW_NAME_SINGLE	"ti-connectivity/wl128x-fw-5-sr.bin"
5958c2ecf20Sopenharmony_ci#define WL128X_PLT_FW_NAME	"ti-connectivity/wl128x-fw-5-plt.bin"
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_cistatic int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
5988c2ecf20Sopenharmony_ci{
5998c2ecf20Sopenharmony_ci	int ret;
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	if (wl->chip.id != CHIP_ID_128X_PG20) {
6028c2ecf20Sopenharmony_ci		struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
6038c2ecf20Sopenharmony_ci		struct wl12xx_priv *priv = wl->priv;
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci		/*
6068c2ecf20Sopenharmony_ci		 * Choose the block we want to read
6078c2ecf20Sopenharmony_ci		 * For aggregated packets, only the first memory block
6088c2ecf20Sopenharmony_ci		 * should be retrieved. The FW takes care of the rest.
6098c2ecf20Sopenharmony_ci		 */
6108c2ecf20Sopenharmony_ci		u32 mem_block = rx_desc & RX_MEM_BLOCK_MASK;
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci		priv->rx_mem_addr->addr = (mem_block << 8) +
6138c2ecf20Sopenharmony_ci			le32_to_cpu(wl_mem_map->packet_memory_pool_start);
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ci		priv->rx_mem_addr->addr_extra = priv->rx_mem_addr->addr + 4;
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci		ret = wlcore_write(wl, WL1271_SLV_REG_DATA, priv->rx_mem_addr,
6188c2ecf20Sopenharmony_ci				   sizeof(*priv->rx_mem_addr), false);
6198c2ecf20Sopenharmony_ci		if (ret < 0)
6208c2ecf20Sopenharmony_ci			return ret;
6218c2ecf20Sopenharmony_ci	}
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	return 0;
6248c2ecf20Sopenharmony_ci}
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_cistatic int wl12xx_identify_chip(struct wl1271 *wl)
6278c2ecf20Sopenharmony_ci{
6288c2ecf20Sopenharmony_ci	int ret = 0;
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	switch (wl->chip.id) {
6318c2ecf20Sopenharmony_ci	case CHIP_ID_127X_PG10:
6328c2ecf20Sopenharmony_ci		wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete",
6338c2ecf20Sopenharmony_ci			       wl->chip.id);
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci		wl->quirks |= WLCORE_QUIRK_LEGACY_NVS |
6368c2ecf20Sopenharmony_ci			      WLCORE_QUIRK_DUAL_PROBE_TMPL |
6378c2ecf20Sopenharmony_ci			      WLCORE_QUIRK_TKIP_HEADER_SPACE |
6388c2ecf20Sopenharmony_ci			      WLCORE_QUIRK_AP_ZERO_SESSION_ID;
6398c2ecf20Sopenharmony_ci		wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
6408c2ecf20Sopenharmony_ci		wl->mr_fw_name = WL127X_FW_NAME_MULTI;
6418c2ecf20Sopenharmony_ci		memcpy(&wl->conf.mem, &wl12xx_default_priv_conf.mem_wl127x,
6428c2ecf20Sopenharmony_ci		       sizeof(wl->conf.mem));
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci		/* read data preparation is only needed by wl127x */
6458c2ecf20Sopenharmony_ci		wl->ops->prepare_read = wl127x_prepare_read;
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci		wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER,
6488c2ecf20Sopenharmony_ci			      WL127X_IFTYPE_SR_VER,  WL127X_MAJOR_SR_VER,
6498c2ecf20Sopenharmony_ci			      WL127X_SUBTYPE_SR_VER, WL127X_MINOR_SR_VER,
6508c2ecf20Sopenharmony_ci			      WL127X_IFTYPE_MR_VER,  WL127X_MAJOR_MR_VER,
6518c2ecf20Sopenharmony_ci			      WL127X_SUBTYPE_MR_VER, WL127X_MINOR_MR_VER);
6528c2ecf20Sopenharmony_ci		break;
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	case CHIP_ID_127X_PG20:
6558c2ecf20Sopenharmony_ci		wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
6568c2ecf20Sopenharmony_ci			     wl->chip.id);
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci		wl->quirks |= WLCORE_QUIRK_LEGACY_NVS |
6598c2ecf20Sopenharmony_ci			      WLCORE_QUIRK_DUAL_PROBE_TMPL |
6608c2ecf20Sopenharmony_ci			      WLCORE_QUIRK_TKIP_HEADER_SPACE |
6618c2ecf20Sopenharmony_ci			      WLCORE_QUIRK_AP_ZERO_SESSION_ID;
6628c2ecf20Sopenharmony_ci		wl->plt_fw_name = WL127X_PLT_FW_NAME;
6638c2ecf20Sopenharmony_ci		wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
6648c2ecf20Sopenharmony_ci		wl->mr_fw_name = WL127X_FW_NAME_MULTI;
6658c2ecf20Sopenharmony_ci		memcpy(&wl->conf.mem, &wl12xx_default_priv_conf.mem_wl127x,
6668c2ecf20Sopenharmony_ci		       sizeof(wl->conf.mem));
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci		/* read data preparation is only needed by wl127x */
6698c2ecf20Sopenharmony_ci		wl->ops->prepare_read = wl127x_prepare_read;
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_ci		wlcore_set_min_fw_ver(wl, WL127X_CHIP_VER,
6728c2ecf20Sopenharmony_ci			      WL127X_IFTYPE_SR_VER,  WL127X_MAJOR_SR_VER,
6738c2ecf20Sopenharmony_ci			      WL127X_SUBTYPE_SR_VER, WL127X_MINOR_SR_VER,
6748c2ecf20Sopenharmony_ci			      WL127X_IFTYPE_MR_VER,  WL127X_MAJOR_MR_VER,
6758c2ecf20Sopenharmony_ci			      WL127X_SUBTYPE_MR_VER, WL127X_MINOR_MR_VER);
6768c2ecf20Sopenharmony_ci		break;
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	case CHIP_ID_128X_PG20:
6798c2ecf20Sopenharmony_ci		wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)",
6808c2ecf20Sopenharmony_ci			     wl->chip.id);
6818c2ecf20Sopenharmony_ci		wl->plt_fw_name = WL128X_PLT_FW_NAME;
6828c2ecf20Sopenharmony_ci		wl->sr_fw_name = WL128X_FW_NAME_SINGLE;
6838c2ecf20Sopenharmony_ci		wl->mr_fw_name = WL128X_FW_NAME_MULTI;
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci		/* wl128x requires TX blocksize alignment */
6868c2ecf20Sopenharmony_ci		wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN |
6878c2ecf20Sopenharmony_ci			      WLCORE_QUIRK_DUAL_PROBE_TMPL |
6888c2ecf20Sopenharmony_ci			      WLCORE_QUIRK_TKIP_HEADER_SPACE |
6898c2ecf20Sopenharmony_ci			      WLCORE_QUIRK_AP_ZERO_SESSION_ID;
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci		wlcore_set_min_fw_ver(wl, WL128X_CHIP_VER,
6928c2ecf20Sopenharmony_ci			      WL128X_IFTYPE_SR_VER,  WL128X_MAJOR_SR_VER,
6938c2ecf20Sopenharmony_ci			      WL128X_SUBTYPE_SR_VER, WL128X_MINOR_SR_VER,
6948c2ecf20Sopenharmony_ci			      WL128X_IFTYPE_MR_VER,  WL128X_MAJOR_MR_VER,
6958c2ecf20Sopenharmony_ci			      WL128X_SUBTYPE_MR_VER, WL128X_MINOR_MR_VER);
6968c2ecf20Sopenharmony_ci		break;
6978c2ecf20Sopenharmony_ci	case CHIP_ID_128X_PG10:
6988c2ecf20Sopenharmony_ci	default:
6998c2ecf20Sopenharmony_ci		wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
7008c2ecf20Sopenharmony_ci		ret = -ENODEV;
7018c2ecf20Sopenharmony_ci		goto out;
7028c2ecf20Sopenharmony_ci	}
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci	wl->fw_mem_block_size = 256;
7058c2ecf20Sopenharmony_ci	wl->fwlog_end = 0x2000000;
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	/* common settings */
7088c2ecf20Sopenharmony_ci	wl->scan_templ_id_2_4 = CMD_TEMPL_APP_PROBE_REQ_2_4_LEGACY;
7098c2ecf20Sopenharmony_ci	wl->scan_templ_id_5 = CMD_TEMPL_APP_PROBE_REQ_5_LEGACY;
7108c2ecf20Sopenharmony_ci	wl->sched_scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4;
7118c2ecf20Sopenharmony_ci	wl->sched_scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5;
7128c2ecf20Sopenharmony_ci	wl->max_channels_5 = WL12XX_MAX_CHANNELS_5GHZ;
7138c2ecf20Sopenharmony_ci	wl->ba_rx_session_count_max = WL12XX_RX_BA_MAX_SESSIONS;
7148c2ecf20Sopenharmony_ciout:
7158c2ecf20Sopenharmony_ci	return ret;
7168c2ecf20Sopenharmony_ci}
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_cistatic int __must_check wl12xx_top_reg_write(struct wl1271 *wl, int addr,
7198c2ecf20Sopenharmony_ci					     u16 val)
7208c2ecf20Sopenharmony_ci{
7218c2ecf20Sopenharmony_ci	int ret;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	/* write address >> 1 + 0x30000 to OCP_POR_CTR */
7248c2ecf20Sopenharmony_ci	addr = (addr >> 1) + 0x30000;
7258c2ecf20Sopenharmony_ci	ret = wlcore_write32(wl, WL12XX_OCP_POR_CTR, addr);
7268c2ecf20Sopenharmony_ci	if (ret < 0)
7278c2ecf20Sopenharmony_ci		goto out;
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	/* write value to OCP_POR_WDATA */
7308c2ecf20Sopenharmony_ci	ret = wlcore_write32(wl, WL12XX_OCP_DATA_WRITE, val);
7318c2ecf20Sopenharmony_ci	if (ret < 0)
7328c2ecf20Sopenharmony_ci		goto out;
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	/* write 1 to OCP_CMD */
7358c2ecf20Sopenharmony_ci	ret = wlcore_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE);
7368c2ecf20Sopenharmony_ci	if (ret < 0)
7378c2ecf20Sopenharmony_ci		goto out;
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ciout:
7408c2ecf20Sopenharmony_ci	return ret;
7418c2ecf20Sopenharmony_ci}
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_cistatic int __must_check wl12xx_top_reg_read(struct wl1271 *wl, int addr,
7448c2ecf20Sopenharmony_ci					    u16 *out)
7458c2ecf20Sopenharmony_ci{
7468c2ecf20Sopenharmony_ci	u32 val;
7478c2ecf20Sopenharmony_ci	int timeout = OCP_CMD_LOOP;
7488c2ecf20Sopenharmony_ci	int ret;
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	/* write address >> 1 + 0x30000 to OCP_POR_CTR */
7518c2ecf20Sopenharmony_ci	addr = (addr >> 1) + 0x30000;
7528c2ecf20Sopenharmony_ci	ret = wlcore_write32(wl, WL12XX_OCP_POR_CTR, addr);
7538c2ecf20Sopenharmony_ci	if (ret < 0)
7548c2ecf20Sopenharmony_ci		return ret;
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	/* write 2 to OCP_CMD */
7578c2ecf20Sopenharmony_ci	ret = wlcore_write32(wl, WL12XX_OCP_CMD, OCP_CMD_READ);
7588c2ecf20Sopenharmony_ci	if (ret < 0)
7598c2ecf20Sopenharmony_ci		return ret;
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci	/* poll for data ready */
7628c2ecf20Sopenharmony_ci	do {
7638c2ecf20Sopenharmony_ci		ret = wlcore_read32(wl, WL12XX_OCP_DATA_READ, &val);
7648c2ecf20Sopenharmony_ci		if (ret < 0)
7658c2ecf20Sopenharmony_ci			return ret;
7668c2ecf20Sopenharmony_ci	} while (!(val & OCP_READY_MASK) && --timeout);
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	if (!timeout) {
7698c2ecf20Sopenharmony_ci		wl1271_warning("Top register access timed out.");
7708c2ecf20Sopenharmony_ci		return -ETIMEDOUT;
7718c2ecf20Sopenharmony_ci	}
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	/* check data status and return if OK */
7748c2ecf20Sopenharmony_ci	if ((val & OCP_STATUS_MASK) != OCP_STATUS_OK) {
7758c2ecf20Sopenharmony_ci		wl1271_warning("Top register access returned error.");
7768c2ecf20Sopenharmony_ci		return -EIO;
7778c2ecf20Sopenharmony_ci	}
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_ci	if (out)
7808c2ecf20Sopenharmony_ci		*out = val & 0xffff;
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci	return 0;
7838c2ecf20Sopenharmony_ci}
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_cistatic int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
7868c2ecf20Sopenharmony_ci{
7878c2ecf20Sopenharmony_ci	u16 spare_reg;
7888c2ecf20Sopenharmony_ci	int ret;
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	/* Mask bits [2] & [8:4] in the sys_clk_cfg register */
7918c2ecf20Sopenharmony_ci	ret = wl12xx_top_reg_read(wl, WL_SPARE_REG, &spare_reg);
7928c2ecf20Sopenharmony_ci	if (ret < 0)
7938c2ecf20Sopenharmony_ci		return ret;
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci	if (spare_reg == 0xFFFF)
7968c2ecf20Sopenharmony_ci		return -EFAULT;
7978c2ecf20Sopenharmony_ci	spare_reg |= (BIT(3) | BIT(5) | BIT(6));
7988c2ecf20Sopenharmony_ci	ret = wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg);
7998c2ecf20Sopenharmony_ci	if (ret < 0)
8008c2ecf20Sopenharmony_ci		return ret;
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_ci	/* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */
8038c2ecf20Sopenharmony_ci	ret = wl12xx_top_reg_write(wl, SYS_CLK_CFG_REG,
8048c2ecf20Sopenharmony_ci				   WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF);
8058c2ecf20Sopenharmony_ci	if (ret < 0)
8068c2ecf20Sopenharmony_ci		return ret;
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci	/* Delay execution for 15msec, to let the HW settle */
8098c2ecf20Sopenharmony_ci	mdelay(15);
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_ci	return 0;
8128c2ecf20Sopenharmony_ci}
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_cistatic bool wl128x_is_tcxo_valid(struct wl1271 *wl)
8158c2ecf20Sopenharmony_ci{
8168c2ecf20Sopenharmony_ci	u16 tcxo_detection;
8178c2ecf20Sopenharmony_ci	int ret;
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	ret = wl12xx_top_reg_read(wl, TCXO_CLK_DETECT_REG, &tcxo_detection);
8208c2ecf20Sopenharmony_ci	if (ret < 0)
8218c2ecf20Sopenharmony_ci		return false;
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	if (tcxo_detection & TCXO_DET_FAILED)
8248c2ecf20Sopenharmony_ci		return false;
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci	return true;
8278c2ecf20Sopenharmony_ci}
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_cistatic bool wl128x_is_fref_valid(struct wl1271 *wl)
8308c2ecf20Sopenharmony_ci{
8318c2ecf20Sopenharmony_ci	u16 fref_detection;
8328c2ecf20Sopenharmony_ci	int ret;
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci	ret = wl12xx_top_reg_read(wl, FREF_CLK_DETECT_REG, &fref_detection);
8358c2ecf20Sopenharmony_ci	if (ret < 0)
8368c2ecf20Sopenharmony_ci		return false;
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	if (fref_detection & FREF_CLK_DETECT_FAIL)
8398c2ecf20Sopenharmony_ci		return false;
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	return true;
8428c2ecf20Sopenharmony_ci}
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_cistatic int wl128x_manually_configure_mcs_pll(struct wl1271 *wl)
8458c2ecf20Sopenharmony_ci{
8468c2ecf20Sopenharmony_ci	int ret;
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci	ret = wl12xx_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL);
8498c2ecf20Sopenharmony_ci	if (ret < 0)
8508c2ecf20Sopenharmony_ci		goto out;
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	ret = wl12xx_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL);
8538c2ecf20Sopenharmony_ci	if (ret < 0)
8548c2ecf20Sopenharmony_ci		goto out;
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci	ret = wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG,
8578c2ecf20Sopenharmony_ci				   MCS_PLL_CONFIG_REG_VAL);
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ciout:
8608c2ecf20Sopenharmony_ci	return ret;
8618c2ecf20Sopenharmony_ci}
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_cistatic int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
8648c2ecf20Sopenharmony_ci{
8658c2ecf20Sopenharmony_ci	u16 spare_reg;
8668c2ecf20Sopenharmony_ci	u16 pll_config;
8678c2ecf20Sopenharmony_ci	u8 input_freq;
8688c2ecf20Sopenharmony_ci	struct wl12xx_priv *priv = wl->priv;
8698c2ecf20Sopenharmony_ci	int ret;
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci	/* Mask bits [3:1] in the sys_clk_cfg register */
8728c2ecf20Sopenharmony_ci	ret = wl12xx_top_reg_read(wl, WL_SPARE_REG, &spare_reg);
8738c2ecf20Sopenharmony_ci	if (ret < 0)
8748c2ecf20Sopenharmony_ci		return ret;
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_ci	if (spare_reg == 0xFFFF)
8778c2ecf20Sopenharmony_ci		return -EFAULT;
8788c2ecf20Sopenharmony_ci	spare_reg |= BIT(2);
8798c2ecf20Sopenharmony_ci	ret = wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg);
8808c2ecf20Sopenharmony_ci	if (ret < 0)
8818c2ecf20Sopenharmony_ci		return ret;
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci	/* Handle special cases of the TCXO clock */
8848c2ecf20Sopenharmony_ci	if (priv->tcxo_clock == WL12XX_TCXOCLOCK_16_8 ||
8858c2ecf20Sopenharmony_ci	    priv->tcxo_clock == WL12XX_TCXOCLOCK_33_6)
8868c2ecf20Sopenharmony_ci		return wl128x_manually_configure_mcs_pll(wl);
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_ci	/* Set the input frequency according to the selected clock source */
8898c2ecf20Sopenharmony_ci	input_freq = (clk & 1) + 1;
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_ci	ret = wl12xx_top_reg_read(wl, MCS_PLL_CONFIG_REG, &pll_config);
8928c2ecf20Sopenharmony_ci	if (ret < 0)
8938c2ecf20Sopenharmony_ci		return ret;
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci	if (pll_config == 0xFFFF)
8968c2ecf20Sopenharmony_ci		return -EFAULT;
8978c2ecf20Sopenharmony_ci	pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT);
8988c2ecf20Sopenharmony_ci	pll_config |= MCS_PLL_ENABLE_HP;
8998c2ecf20Sopenharmony_ci	ret = wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config);
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci	return ret;
9028c2ecf20Sopenharmony_ci}
9038c2ecf20Sopenharmony_ci
9048c2ecf20Sopenharmony_ci/*
9058c2ecf20Sopenharmony_ci * WL128x has two clocks input - TCXO and FREF.
9068c2ecf20Sopenharmony_ci * TCXO is the main clock of the device, while FREF is used to sync
9078c2ecf20Sopenharmony_ci * between the GPS and the cellular modem.
9088c2ecf20Sopenharmony_ci * In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used
9098c2ecf20Sopenharmony_ci * as the WLAN/BT main clock.
9108c2ecf20Sopenharmony_ci */
9118c2ecf20Sopenharmony_cistatic int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
9128c2ecf20Sopenharmony_ci{
9138c2ecf20Sopenharmony_ci	struct wl12xx_priv *priv = wl->priv;
9148c2ecf20Sopenharmony_ci	u16 sys_clk_cfg;
9158c2ecf20Sopenharmony_ci	int ret;
9168c2ecf20Sopenharmony_ci
9178c2ecf20Sopenharmony_ci	/* For XTAL-only modes, FREF will be used after switching from TCXO */
9188c2ecf20Sopenharmony_ci	if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL ||
9198c2ecf20Sopenharmony_ci	    priv->ref_clock == WL12XX_REFCLOCK_38_XTAL) {
9208c2ecf20Sopenharmony_ci		if (!wl128x_switch_tcxo_to_fref(wl))
9218c2ecf20Sopenharmony_ci			return -EINVAL;
9228c2ecf20Sopenharmony_ci		goto fref_clk;
9238c2ecf20Sopenharmony_ci	}
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci	/* Query the HW, to determine which clock source we should use */
9268c2ecf20Sopenharmony_ci	ret = wl12xx_top_reg_read(wl, SYS_CLK_CFG_REG, &sys_clk_cfg);
9278c2ecf20Sopenharmony_ci	if (ret < 0)
9288c2ecf20Sopenharmony_ci		return ret;
9298c2ecf20Sopenharmony_ci
9308c2ecf20Sopenharmony_ci	if (sys_clk_cfg == 0xFFFF)
9318c2ecf20Sopenharmony_ci		return -EINVAL;
9328c2ecf20Sopenharmony_ci	if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF)
9338c2ecf20Sopenharmony_ci		goto fref_clk;
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_ci	/* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */
9368c2ecf20Sopenharmony_ci	if (priv->tcxo_clock == WL12XX_TCXOCLOCK_16_368 ||
9378c2ecf20Sopenharmony_ci	    priv->tcxo_clock == WL12XX_TCXOCLOCK_32_736) {
9388c2ecf20Sopenharmony_ci		if (!wl128x_switch_tcxo_to_fref(wl))
9398c2ecf20Sopenharmony_ci			return -EINVAL;
9408c2ecf20Sopenharmony_ci		goto fref_clk;
9418c2ecf20Sopenharmony_ci	}
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_ci	/* TCXO clock is selected */
9448c2ecf20Sopenharmony_ci	if (!wl128x_is_tcxo_valid(wl))
9458c2ecf20Sopenharmony_ci		return -EINVAL;
9468c2ecf20Sopenharmony_ci	*selected_clock = priv->tcxo_clock;
9478c2ecf20Sopenharmony_ci	goto config_mcs_pll;
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_cifref_clk:
9508c2ecf20Sopenharmony_ci	/* FREF clock is selected */
9518c2ecf20Sopenharmony_ci	if (!wl128x_is_fref_valid(wl))
9528c2ecf20Sopenharmony_ci		return -EINVAL;
9538c2ecf20Sopenharmony_ci	*selected_clock = priv->ref_clock;
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ciconfig_mcs_pll:
9568c2ecf20Sopenharmony_ci	return wl128x_configure_mcs_pll(wl, *selected_clock);
9578c2ecf20Sopenharmony_ci}
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_cistatic int wl127x_boot_clk(struct wl1271 *wl)
9608c2ecf20Sopenharmony_ci{
9618c2ecf20Sopenharmony_ci	struct wl12xx_priv *priv = wl->priv;
9628c2ecf20Sopenharmony_ci	u32 pause;
9638c2ecf20Sopenharmony_ci	u32 clk;
9648c2ecf20Sopenharmony_ci	int ret;
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci	if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3)
9678c2ecf20Sopenharmony_ci		wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION;
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_ci	if (priv->ref_clock == CONF_REF_CLK_19_2_E ||
9708c2ecf20Sopenharmony_ci	    priv->ref_clock == CONF_REF_CLK_38_4_E ||
9718c2ecf20Sopenharmony_ci	    priv->ref_clock == CONF_REF_CLK_38_4_M_XTAL)
9728c2ecf20Sopenharmony_ci		/* ref clk: 19.2/38.4/38.4-XTAL */
9738c2ecf20Sopenharmony_ci		clk = 0x3;
9748c2ecf20Sopenharmony_ci	else if (priv->ref_clock == CONF_REF_CLK_26_E ||
9758c2ecf20Sopenharmony_ci		 priv->ref_clock == CONF_REF_CLK_26_M_XTAL ||
9768c2ecf20Sopenharmony_ci		 priv->ref_clock == CONF_REF_CLK_52_E)
9778c2ecf20Sopenharmony_ci		/* ref clk: 26/52 */
9788c2ecf20Sopenharmony_ci		clk = 0x5;
9798c2ecf20Sopenharmony_ci	else
9808c2ecf20Sopenharmony_ci		return -EINVAL;
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci	if (priv->ref_clock != CONF_REF_CLK_19_2_E) {
9838c2ecf20Sopenharmony_ci		u16 val;
9848c2ecf20Sopenharmony_ci		/* Set clock type (open drain) */
9858c2ecf20Sopenharmony_ci		ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE, &val);
9868c2ecf20Sopenharmony_ci		if (ret < 0)
9878c2ecf20Sopenharmony_ci			goto out;
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_ci		val &= FREF_CLK_TYPE_BITS;
9908c2ecf20Sopenharmony_ci		ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val);
9918c2ecf20Sopenharmony_ci		if (ret < 0)
9928c2ecf20Sopenharmony_ci			goto out;
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci		/* Set clock pull mode (no pull) */
9958c2ecf20Sopenharmony_ci		ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_PULL, &val);
9968c2ecf20Sopenharmony_ci		if (ret < 0)
9978c2ecf20Sopenharmony_ci			goto out;
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_ci		val |= NO_PULL;
10008c2ecf20Sopenharmony_ci		ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val);
10018c2ecf20Sopenharmony_ci		if (ret < 0)
10028c2ecf20Sopenharmony_ci			goto out;
10038c2ecf20Sopenharmony_ci	} else {
10048c2ecf20Sopenharmony_ci		u16 val;
10058c2ecf20Sopenharmony_ci		/* Set clock polarity */
10068c2ecf20Sopenharmony_ci		ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_POLARITY, &val);
10078c2ecf20Sopenharmony_ci		if (ret < 0)
10088c2ecf20Sopenharmony_ci			goto out;
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_ci		val &= FREF_CLK_POLARITY_BITS;
10118c2ecf20Sopenharmony_ci		val |= CLK_REQ_OUTN_SEL;
10128c2ecf20Sopenharmony_ci		ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
10138c2ecf20Sopenharmony_ci		if (ret < 0)
10148c2ecf20Sopenharmony_ci			goto out;
10158c2ecf20Sopenharmony_ci	}
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci	ret = wlcore_write32(wl, WL12XX_PLL_PARAMETERS, clk);
10188c2ecf20Sopenharmony_ci	if (ret < 0)
10198c2ecf20Sopenharmony_ci		goto out;
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci	ret = wlcore_read32(wl, WL12XX_PLL_PARAMETERS, &pause);
10228c2ecf20Sopenharmony_ci	if (ret < 0)
10238c2ecf20Sopenharmony_ci		goto out;
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci	wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci	pause &= ~(WU_COUNTER_PAUSE_VAL);
10288c2ecf20Sopenharmony_ci	pause |= WU_COUNTER_PAUSE_VAL;
10298c2ecf20Sopenharmony_ci	ret = wlcore_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause);
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ciout:
10328c2ecf20Sopenharmony_ci	return ret;
10338c2ecf20Sopenharmony_ci}
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_cistatic int wl1271_boot_soft_reset(struct wl1271 *wl)
10368c2ecf20Sopenharmony_ci{
10378c2ecf20Sopenharmony_ci	unsigned long timeout;
10388c2ecf20Sopenharmony_ci	u32 boot_data;
10398c2ecf20Sopenharmony_ci	int ret = 0;
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci	/* perform soft reset */
10428c2ecf20Sopenharmony_ci	ret = wlcore_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
10438c2ecf20Sopenharmony_ci	if (ret < 0)
10448c2ecf20Sopenharmony_ci		goto out;
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci	/* SOFT_RESET is self clearing */
10478c2ecf20Sopenharmony_ci	timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
10488c2ecf20Sopenharmony_ci	while (1) {
10498c2ecf20Sopenharmony_ci		ret = wlcore_read32(wl, WL12XX_SLV_SOFT_RESET, &boot_data);
10508c2ecf20Sopenharmony_ci		if (ret < 0)
10518c2ecf20Sopenharmony_ci			goto out;
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ci		wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
10548c2ecf20Sopenharmony_ci		if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
10558c2ecf20Sopenharmony_ci			break;
10568c2ecf20Sopenharmony_ci
10578c2ecf20Sopenharmony_ci		if (time_after(jiffies, timeout)) {
10588c2ecf20Sopenharmony_ci			/* 1.2 check pWhalBus->uSelfClearTime if the
10598c2ecf20Sopenharmony_ci			 * timeout was reached */
10608c2ecf20Sopenharmony_ci			wl1271_error("soft reset timeout");
10618c2ecf20Sopenharmony_ci			return -1;
10628c2ecf20Sopenharmony_ci		}
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci		udelay(SOFT_RESET_STALL_TIME);
10658c2ecf20Sopenharmony_ci	}
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_ci	/* disable Rx/Tx */
10688c2ecf20Sopenharmony_ci	ret = wlcore_write32(wl, WL12XX_ENABLE, 0x0);
10698c2ecf20Sopenharmony_ci	if (ret < 0)
10708c2ecf20Sopenharmony_ci		goto out;
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci	/* disable auto calibration on start*/
10738c2ecf20Sopenharmony_ci	ret = wlcore_write32(wl, WL12XX_SPARE_A2, 0xffff);
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ciout:
10768c2ecf20Sopenharmony_ci	return ret;
10778c2ecf20Sopenharmony_ci}
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_cistatic int wl12xx_pre_boot(struct wl1271 *wl)
10808c2ecf20Sopenharmony_ci{
10818c2ecf20Sopenharmony_ci	struct wl12xx_priv *priv = wl->priv;
10828c2ecf20Sopenharmony_ci	int ret = 0;
10838c2ecf20Sopenharmony_ci	u32 clk;
10848c2ecf20Sopenharmony_ci	int selected_clock = -1;
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_ci	if (wl->chip.id == CHIP_ID_128X_PG20) {
10878c2ecf20Sopenharmony_ci		ret = wl128x_boot_clk(wl, &selected_clock);
10888c2ecf20Sopenharmony_ci		if (ret < 0)
10898c2ecf20Sopenharmony_ci			goto out;
10908c2ecf20Sopenharmony_ci	} else {
10918c2ecf20Sopenharmony_ci		ret = wl127x_boot_clk(wl);
10928c2ecf20Sopenharmony_ci		if (ret < 0)
10938c2ecf20Sopenharmony_ci			goto out;
10948c2ecf20Sopenharmony_ci	}
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_ci	/* Continue the ELP wake up sequence */
10978c2ecf20Sopenharmony_ci	ret = wlcore_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
10988c2ecf20Sopenharmony_ci	if (ret < 0)
10998c2ecf20Sopenharmony_ci		goto out;
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci	udelay(500);
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_ci	ret = wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
11048c2ecf20Sopenharmony_ci	if (ret < 0)
11058c2ecf20Sopenharmony_ci		goto out;
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci	/* Read-modify-write DRPW_SCRATCH_START register (see next state)
11088c2ecf20Sopenharmony_ci	   to be used by DRPw FW. The RTRIM value will be added by the FW
11098c2ecf20Sopenharmony_ci	   before taking DRPw out of reset */
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ci	ret = wlcore_read32(wl, WL12XX_DRPW_SCRATCH_START, &clk);
11128c2ecf20Sopenharmony_ci	if (ret < 0)
11138c2ecf20Sopenharmony_ci		goto out;
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_ci	wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_ci	if (wl->chip.id == CHIP_ID_128X_PG20)
11188c2ecf20Sopenharmony_ci		clk |= ((selected_clock & 0x3) << 1) << 4;
11198c2ecf20Sopenharmony_ci	else
11208c2ecf20Sopenharmony_ci		clk |= (priv->ref_clock << 1) << 4;
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ci	ret = wlcore_write32(wl, WL12XX_DRPW_SCRATCH_START, clk);
11238c2ecf20Sopenharmony_ci	if (ret < 0)
11248c2ecf20Sopenharmony_ci		goto out;
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_ci	ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
11278c2ecf20Sopenharmony_ci	if (ret < 0)
11288c2ecf20Sopenharmony_ci		goto out;
11298c2ecf20Sopenharmony_ci
11308c2ecf20Sopenharmony_ci	/* Disable interrupts */
11318c2ecf20Sopenharmony_ci	ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
11328c2ecf20Sopenharmony_ci	if (ret < 0)
11338c2ecf20Sopenharmony_ci		goto out;
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_ci	ret = wl1271_boot_soft_reset(wl);
11368c2ecf20Sopenharmony_ci	if (ret < 0)
11378c2ecf20Sopenharmony_ci		goto out;
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ciout:
11408c2ecf20Sopenharmony_ci	return ret;
11418c2ecf20Sopenharmony_ci}
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_cistatic int wl12xx_pre_upload(struct wl1271 *wl)
11448c2ecf20Sopenharmony_ci{
11458c2ecf20Sopenharmony_ci	u32 tmp;
11468c2ecf20Sopenharmony_ci	u16 polarity;
11478c2ecf20Sopenharmony_ci	int ret;
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_ci	/* write firmware's last address (ie. it's length) to
11508c2ecf20Sopenharmony_ci	 * ACX_EEPROMLESS_IND_REG */
11518c2ecf20Sopenharmony_ci	wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG");
11528c2ecf20Sopenharmony_ci
11538c2ecf20Sopenharmony_ci	ret = wlcore_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND);
11548c2ecf20Sopenharmony_ci	if (ret < 0)
11558c2ecf20Sopenharmony_ci		goto out;
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci	ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &tmp);
11588c2ecf20Sopenharmony_ci	if (ret < 0)
11598c2ecf20Sopenharmony_ci		goto out;
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_ci	wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_ci	/* 6. read the EEPROM parameters */
11648c2ecf20Sopenharmony_ci	ret = wlcore_read32(wl, WL12XX_SCR_PAD2, &tmp);
11658c2ecf20Sopenharmony_ci	if (ret < 0)
11668c2ecf20Sopenharmony_ci		goto out;
11678c2ecf20Sopenharmony_ci
11688c2ecf20Sopenharmony_ci	/* WL1271: The reference driver skips steps 7 to 10 (jumps directly
11698c2ecf20Sopenharmony_ci	 * to upload_fw) */
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci	if (wl->chip.id == CHIP_ID_128X_PG20) {
11728c2ecf20Sopenharmony_ci		ret = wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA);
11738c2ecf20Sopenharmony_ci		if (ret < 0)
11748c2ecf20Sopenharmony_ci			goto out;
11758c2ecf20Sopenharmony_ci	}
11768c2ecf20Sopenharmony_ci
11778c2ecf20Sopenharmony_ci	/* polarity must be set before the firmware is loaded */
11788c2ecf20Sopenharmony_ci	ret = wl12xx_top_reg_read(wl, OCP_REG_POLARITY, &polarity);
11798c2ecf20Sopenharmony_ci	if (ret < 0)
11808c2ecf20Sopenharmony_ci		goto out;
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_ci	/* We use HIGH polarity, so unset the LOW bit */
11838c2ecf20Sopenharmony_ci	polarity &= ~POLARITY_LOW;
11848c2ecf20Sopenharmony_ci	ret = wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity);
11858c2ecf20Sopenharmony_ci
11868c2ecf20Sopenharmony_ciout:
11878c2ecf20Sopenharmony_ci	return ret;
11888c2ecf20Sopenharmony_ci}
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_cistatic int wl12xx_enable_interrupts(struct wl1271 *wl)
11918c2ecf20Sopenharmony_ci{
11928c2ecf20Sopenharmony_ci	int ret;
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci	ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK,
11958c2ecf20Sopenharmony_ci			       WL12XX_ACX_ALL_EVENTS_VECTOR);
11968c2ecf20Sopenharmony_ci	if (ret < 0)
11978c2ecf20Sopenharmony_ci		goto out;
11988c2ecf20Sopenharmony_ci
11998c2ecf20Sopenharmony_ci	wlcore_enable_interrupts(wl);
12008c2ecf20Sopenharmony_ci	ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK,
12018c2ecf20Sopenharmony_ci			       WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK));
12028c2ecf20Sopenharmony_ci	if (ret < 0)
12038c2ecf20Sopenharmony_ci		goto disable_interrupts;
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci	ret = wlcore_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL);
12068c2ecf20Sopenharmony_ci	if (ret < 0)
12078c2ecf20Sopenharmony_ci		goto disable_interrupts;
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci	return ret;
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_cidisable_interrupts:
12128c2ecf20Sopenharmony_ci	wlcore_disable_interrupts(wl);
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ciout:
12158c2ecf20Sopenharmony_ci	return ret;
12168c2ecf20Sopenharmony_ci}
12178c2ecf20Sopenharmony_ci
12188c2ecf20Sopenharmony_cistatic int wl12xx_boot(struct wl1271 *wl)
12198c2ecf20Sopenharmony_ci{
12208c2ecf20Sopenharmony_ci	int ret;
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci	ret = wl12xx_pre_boot(wl);
12238c2ecf20Sopenharmony_ci	if (ret < 0)
12248c2ecf20Sopenharmony_ci		goto out;
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci	ret = wlcore_boot_upload_nvs(wl);
12278c2ecf20Sopenharmony_ci	if (ret < 0)
12288c2ecf20Sopenharmony_ci		goto out;
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	ret = wl12xx_pre_upload(wl);
12318c2ecf20Sopenharmony_ci	if (ret < 0)
12328c2ecf20Sopenharmony_ci		goto out;
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_ci	ret = wlcore_boot_upload_firmware(wl);
12358c2ecf20Sopenharmony_ci	if (ret < 0)
12368c2ecf20Sopenharmony_ci		goto out;
12378c2ecf20Sopenharmony_ci
12388c2ecf20Sopenharmony_ci	wl->event_mask = BSS_LOSE_EVENT_ID |
12398c2ecf20Sopenharmony_ci		REGAINED_BSS_EVENT_ID |
12408c2ecf20Sopenharmony_ci		SCAN_COMPLETE_EVENT_ID |
12418c2ecf20Sopenharmony_ci		ROLE_STOP_COMPLETE_EVENT_ID |
12428c2ecf20Sopenharmony_ci		RSSI_SNR_TRIGGER_0_EVENT_ID |
12438c2ecf20Sopenharmony_ci		PSPOLL_DELIVERY_FAILURE_EVENT_ID |
12448c2ecf20Sopenharmony_ci		SOFT_GEMINI_SENSE_EVENT_ID |
12458c2ecf20Sopenharmony_ci		PERIODIC_SCAN_REPORT_EVENT_ID |
12468c2ecf20Sopenharmony_ci		PERIODIC_SCAN_COMPLETE_EVENT_ID |
12478c2ecf20Sopenharmony_ci		DUMMY_PACKET_EVENT_ID |
12488c2ecf20Sopenharmony_ci		PEER_REMOVE_COMPLETE_EVENT_ID |
12498c2ecf20Sopenharmony_ci		BA_SESSION_RX_CONSTRAINT_EVENT_ID |
12508c2ecf20Sopenharmony_ci		REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
12518c2ecf20Sopenharmony_ci		INACTIVE_STA_EVENT_ID |
12528c2ecf20Sopenharmony_ci		CHANNEL_SWITCH_COMPLETE_EVENT_ID;
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_ci	wl->ap_event_mask = MAX_TX_RETRY_EVENT_ID;
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci	ret = wlcore_boot_run_firmware(wl);
12578c2ecf20Sopenharmony_ci	if (ret < 0)
12588c2ecf20Sopenharmony_ci		goto out;
12598c2ecf20Sopenharmony_ci
12608c2ecf20Sopenharmony_ci	ret = wl12xx_enable_interrupts(wl);
12618c2ecf20Sopenharmony_ci
12628c2ecf20Sopenharmony_ciout:
12638c2ecf20Sopenharmony_ci	return ret;
12648c2ecf20Sopenharmony_ci}
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_cistatic int wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
12678c2ecf20Sopenharmony_ci			       void *buf, size_t len)
12688c2ecf20Sopenharmony_ci{
12698c2ecf20Sopenharmony_ci	int ret;
12708c2ecf20Sopenharmony_ci
12718c2ecf20Sopenharmony_ci	ret = wlcore_write(wl, cmd_box_addr, buf, len, false);
12728c2ecf20Sopenharmony_ci	if (ret < 0)
12738c2ecf20Sopenharmony_ci		return ret;
12748c2ecf20Sopenharmony_ci
12758c2ecf20Sopenharmony_ci	ret = wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD);
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_ci	return ret;
12788c2ecf20Sopenharmony_ci}
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_cistatic int wl12xx_ack_event(struct wl1271 *wl)
12818c2ecf20Sopenharmony_ci{
12828c2ecf20Sopenharmony_ci	return wlcore_write_reg(wl, REG_INTERRUPT_TRIG,
12838c2ecf20Sopenharmony_ci				WL12XX_INTR_TRIG_EVENT_ACK);
12848c2ecf20Sopenharmony_ci}
12858c2ecf20Sopenharmony_ci
12868c2ecf20Sopenharmony_cistatic u32 wl12xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks)
12878c2ecf20Sopenharmony_ci{
12888c2ecf20Sopenharmony_ci	u32 blk_size = WL12XX_TX_HW_BLOCK_SIZE;
12898c2ecf20Sopenharmony_ci	u32 align_len = wlcore_calc_packet_alignment(wl, len);
12908c2ecf20Sopenharmony_ci
12918c2ecf20Sopenharmony_ci	return (align_len + blk_size - 1) / blk_size + spare_blks;
12928c2ecf20Sopenharmony_ci}
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_cistatic void
12958c2ecf20Sopenharmony_ciwl12xx_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
12968c2ecf20Sopenharmony_ci			  u32 blks, u32 spare_blks)
12978c2ecf20Sopenharmony_ci{
12988c2ecf20Sopenharmony_ci	if (wl->chip.id == CHIP_ID_128X_PG20) {
12998c2ecf20Sopenharmony_ci		desc->wl128x_mem.total_mem_blocks = blks;
13008c2ecf20Sopenharmony_ci	} else {
13018c2ecf20Sopenharmony_ci		desc->wl127x_mem.extra_blocks = spare_blks;
13028c2ecf20Sopenharmony_ci		desc->wl127x_mem.total_mem_blocks = blks;
13038c2ecf20Sopenharmony_ci	}
13048c2ecf20Sopenharmony_ci}
13058c2ecf20Sopenharmony_ci
13068c2ecf20Sopenharmony_cistatic void
13078c2ecf20Sopenharmony_ciwl12xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
13088c2ecf20Sopenharmony_ci			    struct sk_buff *skb)
13098c2ecf20Sopenharmony_ci{
13108c2ecf20Sopenharmony_ci	u32 aligned_len = wlcore_calc_packet_alignment(wl, skb->len);
13118c2ecf20Sopenharmony_ci
13128c2ecf20Sopenharmony_ci	if (wl->chip.id == CHIP_ID_128X_PG20) {
13138c2ecf20Sopenharmony_ci		desc->wl128x_mem.extra_bytes = aligned_len - skb->len;
13148c2ecf20Sopenharmony_ci		desc->length = cpu_to_le16(aligned_len >> 2);
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_ci		wl1271_debug(DEBUG_TX,
13178c2ecf20Sopenharmony_ci			     "tx_fill_hdr: hlid: %d len: %d life: %d mem: %d extra: %d",
13188c2ecf20Sopenharmony_ci			     desc->hlid,
13198c2ecf20Sopenharmony_ci			     le16_to_cpu(desc->length),
13208c2ecf20Sopenharmony_ci			     le16_to_cpu(desc->life_time),
13218c2ecf20Sopenharmony_ci			     desc->wl128x_mem.total_mem_blocks,
13228c2ecf20Sopenharmony_ci			     desc->wl128x_mem.extra_bytes);
13238c2ecf20Sopenharmony_ci	} else {
13248c2ecf20Sopenharmony_ci		/* calculate number of padding bytes */
13258c2ecf20Sopenharmony_ci		int pad = aligned_len - skb->len;
13268c2ecf20Sopenharmony_ci		desc->tx_attr |=
13278c2ecf20Sopenharmony_ci			cpu_to_le16(pad << TX_HW_ATTR_OFST_LAST_WORD_PAD);
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_ci		/* Store the aligned length in terms of words */
13308c2ecf20Sopenharmony_ci		desc->length = cpu_to_le16(aligned_len >> 2);
13318c2ecf20Sopenharmony_ci
13328c2ecf20Sopenharmony_ci		wl1271_debug(DEBUG_TX,
13338c2ecf20Sopenharmony_ci			     "tx_fill_hdr: pad: %d hlid: %d len: %d life: %d mem: %d",
13348c2ecf20Sopenharmony_ci			     pad, desc->hlid,
13358c2ecf20Sopenharmony_ci			     le16_to_cpu(desc->length),
13368c2ecf20Sopenharmony_ci			     le16_to_cpu(desc->life_time),
13378c2ecf20Sopenharmony_ci			     desc->wl127x_mem.total_mem_blocks);
13388c2ecf20Sopenharmony_ci	}
13398c2ecf20Sopenharmony_ci}
13408c2ecf20Sopenharmony_ci
13418c2ecf20Sopenharmony_cistatic enum wl_rx_buf_align
13428c2ecf20Sopenharmony_ciwl12xx_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc)
13438c2ecf20Sopenharmony_ci{
13448c2ecf20Sopenharmony_ci	if (rx_desc & RX_BUF_UNALIGNED_PAYLOAD)
13458c2ecf20Sopenharmony_ci		return WLCORE_RX_BUF_UNALIGNED;
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci	return WLCORE_RX_BUF_ALIGNED;
13488c2ecf20Sopenharmony_ci}
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_cistatic u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data,
13518c2ecf20Sopenharmony_ci				    u32 data_len)
13528c2ecf20Sopenharmony_ci{
13538c2ecf20Sopenharmony_ci	struct wl1271_rx_descriptor *desc = rx_data;
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci	/* invalid packet */
13568c2ecf20Sopenharmony_ci	if (data_len < sizeof(*desc) ||
13578c2ecf20Sopenharmony_ci	    data_len < sizeof(*desc) + desc->pad_len)
13588c2ecf20Sopenharmony_ci		return 0;
13598c2ecf20Sopenharmony_ci
13608c2ecf20Sopenharmony_ci	return data_len - sizeof(*desc) - desc->pad_len;
13618c2ecf20Sopenharmony_ci}
13628c2ecf20Sopenharmony_ci
13638c2ecf20Sopenharmony_cistatic int wl12xx_tx_delayed_compl(struct wl1271 *wl)
13648c2ecf20Sopenharmony_ci{
13658c2ecf20Sopenharmony_ci	if (wl->fw_status->tx_results_counter ==
13668c2ecf20Sopenharmony_ci	    (wl->tx_results_count & 0xff))
13678c2ecf20Sopenharmony_ci		return 0;
13688c2ecf20Sopenharmony_ci
13698c2ecf20Sopenharmony_ci	return wlcore_tx_complete(wl);
13708c2ecf20Sopenharmony_ci}
13718c2ecf20Sopenharmony_ci
13728c2ecf20Sopenharmony_cistatic int wl12xx_hw_init(struct wl1271 *wl)
13738c2ecf20Sopenharmony_ci{
13748c2ecf20Sopenharmony_ci	int ret;
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	if (wl->chip.id == CHIP_ID_128X_PG20) {
13778c2ecf20Sopenharmony_ci		u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE;
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_ci		ret = wl128x_cmd_general_parms(wl);
13808c2ecf20Sopenharmony_ci		if (ret < 0)
13818c2ecf20Sopenharmony_ci			goto out;
13828c2ecf20Sopenharmony_ci
13838c2ecf20Sopenharmony_ci		/*
13848c2ecf20Sopenharmony_ci		 * If we are in calibrator based auto detect then we got the FEM nr
13858c2ecf20Sopenharmony_ci		 * in wl->fem_manuf. No need to continue further
13868c2ecf20Sopenharmony_ci		 */
13878c2ecf20Sopenharmony_ci		if (wl->plt_mode == PLT_FEM_DETECT)
13888c2ecf20Sopenharmony_ci			goto out;
13898c2ecf20Sopenharmony_ci
13908c2ecf20Sopenharmony_ci		ret = wl128x_cmd_radio_parms(wl);
13918c2ecf20Sopenharmony_ci		if (ret < 0)
13928c2ecf20Sopenharmony_ci			goto out;
13938c2ecf20Sopenharmony_ci
13948c2ecf20Sopenharmony_ci		if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN)
13958c2ecf20Sopenharmony_ci			/* Enable SDIO padding */
13968c2ecf20Sopenharmony_ci			host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK;
13978c2ecf20Sopenharmony_ci
13988c2ecf20Sopenharmony_ci		/* Must be before wl1271_acx_init_mem_config() */
13998c2ecf20Sopenharmony_ci		ret = wl1271_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap);
14008c2ecf20Sopenharmony_ci		if (ret < 0)
14018c2ecf20Sopenharmony_ci			goto out;
14028c2ecf20Sopenharmony_ci	} else {
14038c2ecf20Sopenharmony_ci		ret = wl1271_cmd_general_parms(wl);
14048c2ecf20Sopenharmony_ci		if (ret < 0)
14058c2ecf20Sopenharmony_ci			goto out;
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_ci		/*
14088c2ecf20Sopenharmony_ci		 * If we are in calibrator based auto detect then we got the FEM nr
14098c2ecf20Sopenharmony_ci		 * in wl->fem_manuf. No need to continue further
14108c2ecf20Sopenharmony_ci		 */
14118c2ecf20Sopenharmony_ci		if (wl->plt_mode == PLT_FEM_DETECT)
14128c2ecf20Sopenharmony_ci			goto out;
14138c2ecf20Sopenharmony_ci
14148c2ecf20Sopenharmony_ci		ret = wl1271_cmd_radio_parms(wl);
14158c2ecf20Sopenharmony_ci		if (ret < 0)
14168c2ecf20Sopenharmony_ci			goto out;
14178c2ecf20Sopenharmony_ci		ret = wl1271_cmd_ext_radio_parms(wl);
14188c2ecf20Sopenharmony_ci		if (ret < 0)
14198c2ecf20Sopenharmony_ci			goto out;
14208c2ecf20Sopenharmony_ci	}
14218c2ecf20Sopenharmony_ciout:
14228c2ecf20Sopenharmony_ci	return ret;
14238c2ecf20Sopenharmony_ci}
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_cistatic void wl12xx_convert_fw_status(struct wl1271 *wl, void *raw_fw_status,
14268c2ecf20Sopenharmony_ci				     struct wl_fw_status *fw_status)
14278c2ecf20Sopenharmony_ci{
14288c2ecf20Sopenharmony_ci	struct wl12xx_fw_status *int_fw_status = raw_fw_status;
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci	fw_status->intr = le32_to_cpu(int_fw_status->intr);
14318c2ecf20Sopenharmony_ci	fw_status->fw_rx_counter = int_fw_status->fw_rx_counter;
14328c2ecf20Sopenharmony_ci	fw_status->drv_rx_counter = int_fw_status->drv_rx_counter;
14338c2ecf20Sopenharmony_ci	fw_status->tx_results_counter = int_fw_status->tx_results_counter;
14348c2ecf20Sopenharmony_ci	fw_status->rx_pkt_descs = int_fw_status->rx_pkt_descs;
14358c2ecf20Sopenharmony_ci
14368c2ecf20Sopenharmony_ci	fw_status->fw_localtime = le32_to_cpu(int_fw_status->fw_localtime);
14378c2ecf20Sopenharmony_ci	fw_status->link_ps_bitmap = le32_to_cpu(int_fw_status->link_ps_bitmap);
14388c2ecf20Sopenharmony_ci	fw_status->link_fast_bitmap =
14398c2ecf20Sopenharmony_ci			le32_to_cpu(int_fw_status->link_fast_bitmap);
14408c2ecf20Sopenharmony_ci	fw_status->total_released_blks =
14418c2ecf20Sopenharmony_ci			le32_to_cpu(int_fw_status->total_released_blks);
14428c2ecf20Sopenharmony_ci	fw_status->tx_total = le32_to_cpu(int_fw_status->tx_total);
14438c2ecf20Sopenharmony_ci
14448c2ecf20Sopenharmony_ci	fw_status->counters.tx_released_pkts =
14458c2ecf20Sopenharmony_ci			int_fw_status->counters.tx_released_pkts;
14468c2ecf20Sopenharmony_ci	fw_status->counters.tx_lnk_free_pkts =
14478c2ecf20Sopenharmony_ci			int_fw_status->counters.tx_lnk_free_pkts;
14488c2ecf20Sopenharmony_ci	fw_status->counters.tx_voice_released_blks =
14498c2ecf20Sopenharmony_ci			int_fw_status->counters.tx_voice_released_blks;
14508c2ecf20Sopenharmony_ci	fw_status->counters.tx_last_rate =
14518c2ecf20Sopenharmony_ci			int_fw_status->counters.tx_last_rate;
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci	fw_status->log_start_addr = le32_to_cpu(int_fw_status->log_start_addr);
14548c2ecf20Sopenharmony_ci}
14558c2ecf20Sopenharmony_ci
14568c2ecf20Sopenharmony_cistatic u32 wl12xx_sta_get_ap_rate_mask(struct wl1271 *wl,
14578c2ecf20Sopenharmony_ci				       struct wl12xx_vif *wlvif)
14588c2ecf20Sopenharmony_ci{
14598c2ecf20Sopenharmony_ci	return wlvif->rate_set;
14608c2ecf20Sopenharmony_ci}
14618c2ecf20Sopenharmony_ci
14628c2ecf20Sopenharmony_cistatic void wl12xx_conf_init(struct wl1271 *wl)
14638c2ecf20Sopenharmony_ci{
14648c2ecf20Sopenharmony_ci	struct wl12xx_priv *priv = wl->priv;
14658c2ecf20Sopenharmony_ci
14668c2ecf20Sopenharmony_ci	/* apply driver default configuration */
14678c2ecf20Sopenharmony_ci	memcpy(&wl->conf, &wl12xx_conf, sizeof(wl12xx_conf));
14688c2ecf20Sopenharmony_ci
14698c2ecf20Sopenharmony_ci	/* apply default private configuration */
14708c2ecf20Sopenharmony_ci	memcpy(&priv->conf, &wl12xx_default_priv_conf, sizeof(priv->conf));
14718c2ecf20Sopenharmony_ci}
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_cistatic bool wl12xx_mac_in_fuse(struct wl1271 *wl)
14748c2ecf20Sopenharmony_ci{
14758c2ecf20Sopenharmony_ci	bool supported = false;
14768c2ecf20Sopenharmony_ci	u8 major, minor;
14778c2ecf20Sopenharmony_ci
14788c2ecf20Sopenharmony_ci	if (wl->chip.id == CHIP_ID_128X_PG20) {
14798c2ecf20Sopenharmony_ci		major = WL128X_PG_GET_MAJOR(wl->hw_pg_ver);
14808c2ecf20Sopenharmony_ci		minor = WL128X_PG_GET_MINOR(wl->hw_pg_ver);
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_ci		/* in wl128x we have the MAC address if the PG is >= (2, 1) */
14838c2ecf20Sopenharmony_ci		if (major > 2 || (major == 2 && minor >= 1))
14848c2ecf20Sopenharmony_ci			supported = true;
14858c2ecf20Sopenharmony_ci	} else {
14868c2ecf20Sopenharmony_ci		major = WL127X_PG_GET_MAJOR(wl->hw_pg_ver);
14878c2ecf20Sopenharmony_ci		minor = WL127X_PG_GET_MINOR(wl->hw_pg_ver);
14888c2ecf20Sopenharmony_ci
14898c2ecf20Sopenharmony_ci		/* in wl127x we have the MAC address if the PG is >= (3, 1) */
14908c2ecf20Sopenharmony_ci		if (major == 3 && minor >= 1)
14918c2ecf20Sopenharmony_ci			supported = true;
14928c2ecf20Sopenharmony_ci	}
14938c2ecf20Sopenharmony_ci
14948c2ecf20Sopenharmony_ci	wl1271_debug(DEBUG_PROBE,
14958c2ecf20Sopenharmony_ci		     "PG Ver major = %d minor = %d, MAC %s present",
14968c2ecf20Sopenharmony_ci		     major, minor, supported ? "is" : "is not");
14978c2ecf20Sopenharmony_ci
14988c2ecf20Sopenharmony_ci	return supported;
14998c2ecf20Sopenharmony_ci}
15008c2ecf20Sopenharmony_ci
15018c2ecf20Sopenharmony_cistatic int wl12xx_get_fuse_mac(struct wl1271 *wl)
15028c2ecf20Sopenharmony_ci{
15038c2ecf20Sopenharmony_ci	u32 mac1, mac2;
15048c2ecf20Sopenharmony_ci	int ret;
15058c2ecf20Sopenharmony_ci
15068c2ecf20Sopenharmony_ci	/* Device may be in ELP from the bootloader or kexec */
15078c2ecf20Sopenharmony_ci	ret = wlcore_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
15088c2ecf20Sopenharmony_ci	if (ret < 0)
15098c2ecf20Sopenharmony_ci		goto out;
15108c2ecf20Sopenharmony_ci
15118c2ecf20Sopenharmony_ci	usleep_range(500000, 700000);
15128c2ecf20Sopenharmony_ci
15138c2ecf20Sopenharmony_ci	ret = wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
15148c2ecf20Sopenharmony_ci	if (ret < 0)
15158c2ecf20Sopenharmony_ci		goto out;
15168c2ecf20Sopenharmony_ci
15178c2ecf20Sopenharmony_ci	ret = wlcore_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1, &mac1);
15188c2ecf20Sopenharmony_ci	if (ret < 0)
15198c2ecf20Sopenharmony_ci		goto out;
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_ci	ret = wlcore_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2, &mac2);
15228c2ecf20Sopenharmony_ci	if (ret < 0)
15238c2ecf20Sopenharmony_ci		goto out;
15248c2ecf20Sopenharmony_ci
15258c2ecf20Sopenharmony_ci	/* these are the two parts of the BD_ADDR */
15268c2ecf20Sopenharmony_ci	wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) +
15278c2ecf20Sopenharmony_ci		((mac1 & 0xff000000) >> 24);
15288c2ecf20Sopenharmony_ci	wl->fuse_nic_addr = mac1 & 0xffffff;
15298c2ecf20Sopenharmony_ci
15308c2ecf20Sopenharmony_ci	ret = wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
15318c2ecf20Sopenharmony_ci
15328c2ecf20Sopenharmony_ciout:
15338c2ecf20Sopenharmony_ci	return ret;
15348c2ecf20Sopenharmony_ci}
15358c2ecf20Sopenharmony_ci
15368c2ecf20Sopenharmony_cistatic int wl12xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
15378c2ecf20Sopenharmony_ci{
15388c2ecf20Sopenharmony_ci	u16 die_info;
15398c2ecf20Sopenharmony_ci	int ret;
15408c2ecf20Sopenharmony_ci
15418c2ecf20Sopenharmony_ci	if (wl->chip.id == CHIP_ID_128X_PG20)
15428c2ecf20Sopenharmony_ci		ret = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1,
15438c2ecf20Sopenharmony_ci					  &die_info);
15448c2ecf20Sopenharmony_ci	else
15458c2ecf20Sopenharmony_ci		ret = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1,
15468c2ecf20Sopenharmony_ci					  &die_info);
15478c2ecf20Sopenharmony_ci
15488c2ecf20Sopenharmony_ci	if (ret >= 0 && ver)
15498c2ecf20Sopenharmony_ci		*ver = (s8)((die_info & PG_VER_MASK) >> PG_VER_OFFSET);
15508c2ecf20Sopenharmony_ci
15518c2ecf20Sopenharmony_ci	return ret;
15528c2ecf20Sopenharmony_ci}
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_cistatic int wl12xx_get_mac(struct wl1271 *wl)
15558c2ecf20Sopenharmony_ci{
15568c2ecf20Sopenharmony_ci	if (wl12xx_mac_in_fuse(wl))
15578c2ecf20Sopenharmony_ci		return wl12xx_get_fuse_mac(wl);
15588c2ecf20Sopenharmony_ci
15598c2ecf20Sopenharmony_ci	return 0;
15608c2ecf20Sopenharmony_ci}
15618c2ecf20Sopenharmony_ci
15628c2ecf20Sopenharmony_cistatic void wl12xx_set_tx_desc_csum(struct wl1271 *wl,
15638c2ecf20Sopenharmony_ci				    struct wl1271_tx_hw_descr *desc,
15648c2ecf20Sopenharmony_ci				    struct sk_buff *skb)
15658c2ecf20Sopenharmony_ci{
15668c2ecf20Sopenharmony_ci	desc->wl12xx_reserved = 0;
15678c2ecf20Sopenharmony_ci}
15688c2ecf20Sopenharmony_ci
15698c2ecf20Sopenharmony_cistatic int wl12xx_plt_init(struct wl1271 *wl)
15708c2ecf20Sopenharmony_ci{
15718c2ecf20Sopenharmony_ci	int ret;
15728c2ecf20Sopenharmony_ci
15738c2ecf20Sopenharmony_ci	ret = wl->ops->boot(wl);
15748c2ecf20Sopenharmony_ci	if (ret < 0)
15758c2ecf20Sopenharmony_ci		goto out;
15768c2ecf20Sopenharmony_ci
15778c2ecf20Sopenharmony_ci	ret = wl->ops->hw_init(wl);
15788c2ecf20Sopenharmony_ci	if (ret < 0)
15798c2ecf20Sopenharmony_ci		goto out_irq_disable;
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_ci	/*
15828c2ecf20Sopenharmony_ci	 * If we are in calibrator based auto detect then we got the FEM nr
15838c2ecf20Sopenharmony_ci	 * in wl->fem_manuf. No need to continue further
15848c2ecf20Sopenharmony_ci	 */
15858c2ecf20Sopenharmony_ci	if (wl->plt_mode == PLT_FEM_DETECT)
15868c2ecf20Sopenharmony_ci		goto out;
15878c2ecf20Sopenharmony_ci
15888c2ecf20Sopenharmony_ci	ret = wl1271_acx_init_mem_config(wl);
15898c2ecf20Sopenharmony_ci	if (ret < 0)
15908c2ecf20Sopenharmony_ci		goto out_irq_disable;
15918c2ecf20Sopenharmony_ci
15928c2ecf20Sopenharmony_ci	ret = wl12xx_acx_mem_cfg(wl);
15938c2ecf20Sopenharmony_ci	if (ret < 0)
15948c2ecf20Sopenharmony_ci		goto out_free_memmap;
15958c2ecf20Sopenharmony_ci
15968c2ecf20Sopenharmony_ci	/* Enable data path */
15978c2ecf20Sopenharmony_ci	ret = wl1271_cmd_data_path(wl, 1);
15988c2ecf20Sopenharmony_ci	if (ret < 0)
15998c2ecf20Sopenharmony_ci		goto out_free_memmap;
16008c2ecf20Sopenharmony_ci
16018c2ecf20Sopenharmony_ci	/* Configure for CAM power saving (ie. always active) */
16028c2ecf20Sopenharmony_ci	ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
16038c2ecf20Sopenharmony_ci	if (ret < 0)
16048c2ecf20Sopenharmony_ci		goto out_free_memmap;
16058c2ecf20Sopenharmony_ci
16068c2ecf20Sopenharmony_ci	/* configure PM */
16078c2ecf20Sopenharmony_ci	ret = wl1271_acx_pm_config(wl);
16088c2ecf20Sopenharmony_ci	if (ret < 0)
16098c2ecf20Sopenharmony_ci		goto out_free_memmap;
16108c2ecf20Sopenharmony_ci
16118c2ecf20Sopenharmony_ci	goto out;
16128c2ecf20Sopenharmony_ci
16138c2ecf20Sopenharmony_ciout_free_memmap:
16148c2ecf20Sopenharmony_ci	kfree(wl->target_mem_map);
16158c2ecf20Sopenharmony_ci	wl->target_mem_map = NULL;
16168c2ecf20Sopenharmony_ci
16178c2ecf20Sopenharmony_ciout_irq_disable:
16188c2ecf20Sopenharmony_ci	mutex_unlock(&wl->mutex);
16198c2ecf20Sopenharmony_ci	/* Unlocking the mutex in the middle of handling is
16208c2ecf20Sopenharmony_ci	   inherently unsafe. In this case we deem it safe to do,
16218c2ecf20Sopenharmony_ci	   because we need to let any possibly pending IRQ out of
16228c2ecf20Sopenharmony_ci	   the system (and while we are WL1271_STATE_OFF the IRQ
16238c2ecf20Sopenharmony_ci	   work function will not do anything.) Also, any other
16248c2ecf20Sopenharmony_ci	   possible concurrent operations will fail due to the
16258c2ecf20Sopenharmony_ci	   current state, hence the wl1271 struct should be safe. */
16268c2ecf20Sopenharmony_ci	wlcore_disable_interrupts(wl);
16278c2ecf20Sopenharmony_ci	mutex_lock(&wl->mutex);
16288c2ecf20Sopenharmony_ciout:
16298c2ecf20Sopenharmony_ci	return ret;
16308c2ecf20Sopenharmony_ci}
16318c2ecf20Sopenharmony_ci
16328c2ecf20Sopenharmony_cistatic int wl12xx_get_spare_blocks(struct wl1271 *wl, bool is_gem)
16338c2ecf20Sopenharmony_ci{
16348c2ecf20Sopenharmony_ci	if (is_gem)
16358c2ecf20Sopenharmony_ci		return WL12XX_TX_HW_BLOCK_GEM_SPARE;
16368c2ecf20Sopenharmony_ci
16378c2ecf20Sopenharmony_ci	return WL12XX_TX_HW_BLOCK_SPARE_DEFAULT;
16388c2ecf20Sopenharmony_ci}
16398c2ecf20Sopenharmony_ci
16408c2ecf20Sopenharmony_cistatic int wl12xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
16418c2ecf20Sopenharmony_ci			  struct ieee80211_vif *vif,
16428c2ecf20Sopenharmony_ci			  struct ieee80211_sta *sta,
16438c2ecf20Sopenharmony_ci			  struct ieee80211_key_conf *key_conf)
16448c2ecf20Sopenharmony_ci{
16458c2ecf20Sopenharmony_ci	return wlcore_set_key(wl, cmd, vif, sta, key_conf);
16468c2ecf20Sopenharmony_ci}
16478c2ecf20Sopenharmony_ci
16488c2ecf20Sopenharmony_cistatic int wl12xx_set_peer_cap(struct wl1271 *wl,
16498c2ecf20Sopenharmony_ci			       struct ieee80211_sta_ht_cap *ht_cap,
16508c2ecf20Sopenharmony_ci			       bool allow_ht_operation,
16518c2ecf20Sopenharmony_ci			       u32 rate_set, u8 hlid)
16528c2ecf20Sopenharmony_ci{
16538c2ecf20Sopenharmony_ci	return wl1271_acx_set_ht_capabilities(wl, ht_cap, allow_ht_operation,
16548c2ecf20Sopenharmony_ci					      hlid);
16558c2ecf20Sopenharmony_ci}
16568c2ecf20Sopenharmony_ci
16578c2ecf20Sopenharmony_cistatic bool wl12xx_lnk_high_prio(struct wl1271 *wl, u8 hlid,
16588c2ecf20Sopenharmony_ci				 struct wl1271_link *lnk)
16598c2ecf20Sopenharmony_ci{
16608c2ecf20Sopenharmony_ci	u8 thold;
16618c2ecf20Sopenharmony_ci
16628c2ecf20Sopenharmony_ci	if (test_bit(hlid, &wl->fw_fast_lnk_map))
16638c2ecf20Sopenharmony_ci		thold = wl->conf.tx.fast_link_thold;
16648c2ecf20Sopenharmony_ci	else
16658c2ecf20Sopenharmony_ci		thold = wl->conf.tx.slow_link_thold;
16668c2ecf20Sopenharmony_ci
16678c2ecf20Sopenharmony_ci	return lnk->allocated_pkts < thold;
16688c2ecf20Sopenharmony_ci}
16698c2ecf20Sopenharmony_ci
16708c2ecf20Sopenharmony_cistatic bool wl12xx_lnk_low_prio(struct wl1271 *wl, u8 hlid,
16718c2ecf20Sopenharmony_ci				struct wl1271_link *lnk)
16728c2ecf20Sopenharmony_ci{
16738c2ecf20Sopenharmony_ci	/* any link is good for low priority */
16748c2ecf20Sopenharmony_ci	return true;
16758c2ecf20Sopenharmony_ci}
16768c2ecf20Sopenharmony_ci
16778c2ecf20Sopenharmony_cistatic u32 wl12xx_convert_hwaddr(struct wl1271 *wl, u32 hwaddr)
16788c2ecf20Sopenharmony_ci{
16798c2ecf20Sopenharmony_ci	return hwaddr << 5;
16808c2ecf20Sopenharmony_ci}
16818c2ecf20Sopenharmony_ci
16828c2ecf20Sopenharmony_cistatic int wl12xx_setup(struct wl1271 *wl);
16838c2ecf20Sopenharmony_ci
16848c2ecf20Sopenharmony_cistatic struct wlcore_ops wl12xx_ops = {
16858c2ecf20Sopenharmony_ci	.setup			= wl12xx_setup,
16868c2ecf20Sopenharmony_ci	.identify_chip		= wl12xx_identify_chip,
16878c2ecf20Sopenharmony_ci	.boot			= wl12xx_boot,
16888c2ecf20Sopenharmony_ci	.plt_init		= wl12xx_plt_init,
16898c2ecf20Sopenharmony_ci	.trigger_cmd		= wl12xx_trigger_cmd,
16908c2ecf20Sopenharmony_ci	.ack_event		= wl12xx_ack_event,
16918c2ecf20Sopenharmony_ci	.wait_for_event		= wl12xx_wait_for_event,
16928c2ecf20Sopenharmony_ci	.process_mailbox_events	= wl12xx_process_mailbox_events,
16938c2ecf20Sopenharmony_ci	.calc_tx_blocks		= wl12xx_calc_tx_blocks,
16948c2ecf20Sopenharmony_ci	.set_tx_desc_blocks	= wl12xx_set_tx_desc_blocks,
16958c2ecf20Sopenharmony_ci	.set_tx_desc_data_len	= wl12xx_set_tx_desc_data_len,
16968c2ecf20Sopenharmony_ci	.get_rx_buf_align	= wl12xx_get_rx_buf_align,
16978c2ecf20Sopenharmony_ci	.get_rx_packet_len	= wl12xx_get_rx_packet_len,
16988c2ecf20Sopenharmony_ci	.tx_immediate_compl	= NULL,
16998c2ecf20Sopenharmony_ci	.tx_delayed_compl	= wl12xx_tx_delayed_compl,
17008c2ecf20Sopenharmony_ci	.hw_init		= wl12xx_hw_init,
17018c2ecf20Sopenharmony_ci	.init_vif		= NULL,
17028c2ecf20Sopenharmony_ci	.convert_fw_status	= wl12xx_convert_fw_status,
17038c2ecf20Sopenharmony_ci	.sta_get_ap_rate_mask	= wl12xx_sta_get_ap_rate_mask,
17048c2ecf20Sopenharmony_ci	.get_pg_ver		= wl12xx_get_pg_ver,
17058c2ecf20Sopenharmony_ci	.get_mac		= wl12xx_get_mac,
17068c2ecf20Sopenharmony_ci	.set_tx_desc_csum	= wl12xx_set_tx_desc_csum,
17078c2ecf20Sopenharmony_ci	.set_rx_csum		= NULL,
17088c2ecf20Sopenharmony_ci	.ap_get_mimo_wide_rate_mask = NULL,
17098c2ecf20Sopenharmony_ci	.debugfs_init		= wl12xx_debugfs_add_files,
17108c2ecf20Sopenharmony_ci	.scan_start		= wl12xx_scan_start,
17118c2ecf20Sopenharmony_ci	.scan_stop		= wl12xx_scan_stop,
17128c2ecf20Sopenharmony_ci	.sched_scan_start	= wl12xx_sched_scan_start,
17138c2ecf20Sopenharmony_ci	.sched_scan_stop	= wl12xx_scan_sched_scan_stop,
17148c2ecf20Sopenharmony_ci	.get_spare_blocks	= wl12xx_get_spare_blocks,
17158c2ecf20Sopenharmony_ci	.set_key		= wl12xx_set_key,
17168c2ecf20Sopenharmony_ci	.channel_switch		= wl12xx_cmd_channel_switch,
17178c2ecf20Sopenharmony_ci	.pre_pkt_send		= NULL,
17188c2ecf20Sopenharmony_ci	.set_peer_cap		= wl12xx_set_peer_cap,
17198c2ecf20Sopenharmony_ci	.convert_hwaddr		= wl12xx_convert_hwaddr,
17208c2ecf20Sopenharmony_ci	.lnk_high_prio		= wl12xx_lnk_high_prio,
17218c2ecf20Sopenharmony_ci	.lnk_low_prio		= wl12xx_lnk_low_prio,
17228c2ecf20Sopenharmony_ci	.interrupt_notify	= NULL,
17238c2ecf20Sopenharmony_ci	.rx_ba_filter		= NULL,
17248c2ecf20Sopenharmony_ci	.ap_sleep		= NULL,
17258c2ecf20Sopenharmony_ci};
17268c2ecf20Sopenharmony_ci
17278c2ecf20Sopenharmony_cistatic struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
17288c2ecf20Sopenharmony_ci	.cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 |
17298c2ecf20Sopenharmony_ci	       (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT),
17308c2ecf20Sopenharmony_ci	.ht_supported = true,
17318c2ecf20Sopenharmony_ci	.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K,
17328c2ecf20Sopenharmony_ci	.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8,
17338c2ecf20Sopenharmony_ci	.mcs = {
17348c2ecf20Sopenharmony_ci		.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
17358c2ecf20Sopenharmony_ci		.rx_highest = cpu_to_le16(72),
17368c2ecf20Sopenharmony_ci		.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
17378c2ecf20Sopenharmony_ci		},
17388c2ecf20Sopenharmony_ci};
17398c2ecf20Sopenharmony_ci
17408c2ecf20Sopenharmony_cistatic const struct ieee80211_iface_limit wl12xx_iface_limits[] = {
17418c2ecf20Sopenharmony_ci	{
17428c2ecf20Sopenharmony_ci		.max = 3,
17438c2ecf20Sopenharmony_ci		.types = BIT(NL80211_IFTYPE_STATION),
17448c2ecf20Sopenharmony_ci	},
17458c2ecf20Sopenharmony_ci	{
17468c2ecf20Sopenharmony_ci		.max = 1,
17478c2ecf20Sopenharmony_ci		.types = BIT(NL80211_IFTYPE_AP) |
17488c2ecf20Sopenharmony_ci			 BIT(NL80211_IFTYPE_P2P_GO) |
17498c2ecf20Sopenharmony_ci			 BIT(NL80211_IFTYPE_P2P_CLIENT),
17508c2ecf20Sopenharmony_ci	},
17518c2ecf20Sopenharmony_ci};
17528c2ecf20Sopenharmony_ci
17538c2ecf20Sopenharmony_cistatic const struct ieee80211_iface_combination
17548c2ecf20Sopenharmony_ciwl12xx_iface_combinations[] = {
17558c2ecf20Sopenharmony_ci	{
17568c2ecf20Sopenharmony_ci		.max_interfaces = 3,
17578c2ecf20Sopenharmony_ci		.limits = wl12xx_iface_limits,
17588c2ecf20Sopenharmony_ci		.n_limits = ARRAY_SIZE(wl12xx_iface_limits),
17598c2ecf20Sopenharmony_ci		.num_different_channels = 1,
17608c2ecf20Sopenharmony_ci	},
17618c2ecf20Sopenharmony_ci};
17628c2ecf20Sopenharmony_ci
17638c2ecf20Sopenharmony_cistatic const struct wl12xx_clock wl12xx_refclock_table[] = {
17648c2ecf20Sopenharmony_ci	{ 19200000,	false,	WL12XX_REFCLOCK_19	},
17658c2ecf20Sopenharmony_ci	{ 26000000,	false,	WL12XX_REFCLOCK_26	},
17668c2ecf20Sopenharmony_ci	{ 26000000,	true,	WL12XX_REFCLOCK_26_XTAL	},
17678c2ecf20Sopenharmony_ci	{ 38400000,	false,	WL12XX_REFCLOCK_38	},
17688c2ecf20Sopenharmony_ci	{ 38400000,	true,	WL12XX_REFCLOCK_38_XTAL	},
17698c2ecf20Sopenharmony_ci	{ 52000000,	false,	WL12XX_REFCLOCK_52	},
17708c2ecf20Sopenharmony_ci	{ 0,		false,	0 }
17718c2ecf20Sopenharmony_ci};
17728c2ecf20Sopenharmony_ci
17738c2ecf20Sopenharmony_cistatic const struct wl12xx_clock wl12xx_tcxoclock_table[] = {
17748c2ecf20Sopenharmony_ci	{ 16368000,	true,	WL12XX_TCXOCLOCK_16_368	},
17758c2ecf20Sopenharmony_ci	{ 16800000,	true,	WL12XX_TCXOCLOCK_16_8	},
17768c2ecf20Sopenharmony_ci	{ 19200000,	true,	WL12XX_TCXOCLOCK_19_2	},
17778c2ecf20Sopenharmony_ci	{ 26000000,	true,	WL12XX_TCXOCLOCK_26	},
17788c2ecf20Sopenharmony_ci	{ 32736000,	true,	WL12XX_TCXOCLOCK_32_736	},
17798c2ecf20Sopenharmony_ci	{ 33600000,	true,	WL12XX_TCXOCLOCK_33_6	},
17808c2ecf20Sopenharmony_ci	{ 38400000,	true,	WL12XX_TCXOCLOCK_38_4	},
17818c2ecf20Sopenharmony_ci	{ 52000000,	true,	WL12XX_TCXOCLOCK_52	},
17828c2ecf20Sopenharmony_ci	{ 0,		false,	0 }
17838c2ecf20Sopenharmony_ci};
17848c2ecf20Sopenharmony_ci
17858c2ecf20Sopenharmony_cistatic int wl12xx_get_clock_idx(const struct wl12xx_clock *table,
17868c2ecf20Sopenharmony_ci				u32 freq, bool xtal)
17878c2ecf20Sopenharmony_ci{
17888c2ecf20Sopenharmony_ci	int i;
17898c2ecf20Sopenharmony_ci
17908c2ecf20Sopenharmony_ci	for (i = 0; table[i].freq != 0; i++)
17918c2ecf20Sopenharmony_ci		if ((table[i].freq == freq) && (table[i].xtal == xtal))
17928c2ecf20Sopenharmony_ci			return table[i].hw_idx;
17938c2ecf20Sopenharmony_ci
17948c2ecf20Sopenharmony_ci	return -EINVAL;
17958c2ecf20Sopenharmony_ci}
17968c2ecf20Sopenharmony_ci
17978c2ecf20Sopenharmony_cistatic int wl12xx_setup(struct wl1271 *wl)
17988c2ecf20Sopenharmony_ci{
17998c2ecf20Sopenharmony_ci	struct wl12xx_priv *priv = wl->priv;
18008c2ecf20Sopenharmony_ci	struct wlcore_platdev_data *pdev_data = dev_get_platdata(&wl->pdev->dev);
18018c2ecf20Sopenharmony_ci
18028c2ecf20Sopenharmony_ci	BUILD_BUG_ON(WL12XX_MAX_LINKS > WLCORE_MAX_LINKS);
18038c2ecf20Sopenharmony_ci	BUILD_BUG_ON(WL12XX_MAX_AP_STATIONS > WL12XX_MAX_LINKS);
18048c2ecf20Sopenharmony_ci	BUILD_BUG_ON(WL12XX_CONF_SG_PARAMS_MAX > WLCORE_CONF_SG_PARAMS_MAX);
18058c2ecf20Sopenharmony_ci
18068c2ecf20Sopenharmony_ci	wl->rtable = wl12xx_rtable;
18078c2ecf20Sopenharmony_ci	wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS;
18088c2ecf20Sopenharmony_ci	wl->num_rx_desc = WL12XX_NUM_RX_DESCRIPTORS;
18098c2ecf20Sopenharmony_ci	wl->num_links = WL12XX_MAX_LINKS;
18108c2ecf20Sopenharmony_ci	wl->max_ap_stations = WL12XX_MAX_AP_STATIONS;
18118c2ecf20Sopenharmony_ci	wl->iface_combinations = wl12xx_iface_combinations;
18128c2ecf20Sopenharmony_ci	wl->n_iface_combinations = ARRAY_SIZE(wl12xx_iface_combinations);
18138c2ecf20Sopenharmony_ci	wl->num_mac_addr = WL12XX_NUM_MAC_ADDRESSES;
18148c2ecf20Sopenharmony_ci	wl->band_rate_to_idx = wl12xx_band_rate_to_idx;
18158c2ecf20Sopenharmony_ci	wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX;
18168c2ecf20Sopenharmony_ci	wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0;
18178c2ecf20Sopenharmony_ci	wl->fw_status_len = sizeof(struct wl12xx_fw_status);
18188c2ecf20Sopenharmony_ci	wl->fw_status_priv_len = 0;
18198c2ecf20Sopenharmony_ci	wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics);
18208c2ecf20Sopenharmony_ci	wl->ofdm_only_ap = true;
18218c2ecf20Sopenharmony_ci	wlcore_set_ht_cap(wl, NL80211_BAND_2GHZ, &wl12xx_ht_cap);
18228c2ecf20Sopenharmony_ci	wlcore_set_ht_cap(wl, NL80211_BAND_5GHZ, &wl12xx_ht_cap);
18238c2ecf20Sopenharmony_ci	wl12xx_conf_init(wl);
18248c2ecf20Sopenharmony_ci
18258c2ecf20Sopenharmony_ci	if (!fref_param) {
18268c2ecf20Sopenharmony_ci		priv->ref_clock = wl12xx_get_clock_idx(wl12xx_refclock_table,
18278c2ecf20Sopenharmony_ci						pdev_data->ref_clock_freq,
18288c2ecf20Sopenharmony_ci						pdev_data->ref_clock_xtal);
18298c2ecf20Sopenharmony_ci		if (priv->ref_clock < 0) {
18308c2ecf20Sopenharmony_ci			wl1271_error("Invalid ref_clock frequency (%d Hz, %s)",
18318c2ecf20Sopenharmony_ci				     pdev_data->ref_clock_freq,
18328c2ecf20Sopenharmony_ci				     pdev_data->ref_clock_xtal ?
18338c2ecf20Sopenharmony_ci				     "XTAL" : "not XTAL");
18348c2ecf20Sopenharmony_ci
18358c2ecf20Sopenharmony_ci			return priv->ref_clock;
18368c2ecf20Sopenharmony_ci		}
18378c2ecf20Sopenharmony_ci	} else {
18388c2ecf20Sopenharmony_ci		if (!strcmp(fref_param, "19.2"))
18398c2ecf20Sopenharmony_ci			priv->ref_clock = WL12XX_REFCLOCK_19;
18408c2ecf20Sopenharmony_ci		else if (!strcmp(fref_param, "26"))
18418c2ecf20Sopenharmony_ci			priv->ref_clock = WL12XX_REFCLOCK_26;
18428c2ecf20Sopenharmony_ci		else if (!strcmp(fref_param, "26x"))
18438c2ecf20Sopenharmony_ci			priv->ref_clock = WL12XX_REFCLOCK_26_XTAL;
18448c2ecf20Sopenharmony_ci		else if (!strcmp(fref_param, "38.4"))
18458c2ecf20Sopenharmony_ci			priv->ref_clock = WL12XX_REFCLOCK_38;
18468c2ecf20Sopenharmony_ci		else if (!strcmp(fref_param, "38.4x"))
18478c2ecf20Sopenharmony_ci			priv->ref_clock = WL12XX_REFCLOCK_38_XTAL;
18488c2ecf20Sopenharmony_ci		else if (!strcmp(fref_param, "52"))
18498c2ecf20Sopenharmony_ci			priv->ref_clock = WL12XX_REFCLOCK_52;
18508c2ecf20Sopenharmony_ci		else
18518c2ecf20Sopenharmony_ci			wl1271_error("Invalid fref parameter %s", fref_param);
18528c2ecf20Sopenharmony_ci	}
18538c2ecf20Sopenharmony_ci
18548c2ecf20Sopenharmony_ci	if (!tcxo_param && pdev_data->tcxo_clock_freq) {
18558c2ecf20Sopenharmony_ci		priv->tcxo_clock = wl12xx_get_clock_idx(wl12xx_tcxoclock_table,
18568c2ecf20Sopenharmony_ci						pdev_data->tcxo_clock_freq,
18578c2ecf20Sopenharmony_ci						true);
18588c2ecf20Sopenharmony_ci		if (priv->tcxo_clock < 0) {
18598c2ecf20Sopenharmony_ci			wl1271_error("Invalid tcxo_clock frequency (%d Hz)",
18608c2ecf20Sopenharmony_ci				     pdev_data->tcxo_clock_freq);
18618c2ecf20Sopenharmony_ci
18628c2ecf20Sopenharmony_ci			return priv->tcxo_clock;
18638c2ecf20Sopenharmony_ci		}
18648c2ecf20Sopenharmony_ci	} else if (tcxo_param) {
18658c2ecf20Sopenharmony_ci		if (!strcmp(tcxo_param, "19.2"))
18668c2ecf20Sopenharmony_ci			priv->tcxo_clock = WL12XX_TCXOCLOCK_19_2;
18678c2ecf20Sopenharmony_ci		else if (!strcmp(tcxo_param, "26"))
18688c2ecf20Sopenharmony_ci			priv->tcxo_clock = WL12XX_TCXOCLOCK_26;
18698c2ecf20Sopenharmony_ci		else if (!strcmp(tcxo_param, "38.4"))
18708c2ecf20Sopenharmony_ci			priv->tcxo_clock = WL12XX_TCXOCLOCK_38_4;
18718c2ecf20Sopenharmony_ci		else if (!strcmp(tcxo_param, "52"))
18728c2ecf20Sopenharmony_ci			priv->tcxo_clock = WL12XX_TCXOCLOCK_52;
18738c2ecf20Sopenharmony_ci		else if (!strcmp(tcxo_param, "16.368"))
18748c2ecf20Sopenharmony_ci			priv->tcxo_clock = WL12XX_TCXOCLOCK_16_368;
18758c2ecf20Sopenharmony_ci		else if (!strcmp(tcxo_param, "32.736"))
18768c2ecf20Sopenharmony_ci			priv->tcxo_clock = WL12XX_TCXOCLOCK_32_736;
18778c2ecf20Sopenharmony_ci		else if (!strcmp(tcxo_param, "16.8"))
18788c2ecf20Sopenharmony_ci			priv->tcxo_clock = WL12XX_TCXOCLOCK_16_8;
18798c2ecf20Sopenharmony_ci		else if (!strcmp(tcxo_param, "33.6"))
18808c2ecf20Sopenharmony_ci			priv->tcxo_clock = WL12XX_TCXOCLOCK_33_6;
18818c2ecf20Sopenharmony_ci		else
18828c2ecf20Sopenharmony_ci			wl1271_error("Invalid tcxo parameter %s", tcxo_param);
18838c2ecf20Sopenharmony_ci	}
18848c2ecf20Sopenharmony_ci
18858c2ecf20Sopenharmony_ci	priv->rx_mem_addr = kmalloc(sizeof(*priv->rx_mem_addr), GFP_KERNEL);
18868c2ecf20Sopenharmony_ci	if (!priv->rx_mem_addr)
18878c2ecf20Sopenharmony_ci		return -ENOMEM;
18888c2ecf20Sopenharmony_ci
18898c2ecf20Sopenharmony_ci	return 0;
18908c2ecf20Sopenharmony_ci}
18918c2ecf20Sopenharmony_ci
18928c2ecf20Sopenharmony_cistatic int wl12xx_probe(struct platform_device *pdev)
18938c2ecf20Sopenharmony_ci{
18948c2ecf20Sopenharmony_ci	struct wl1271 *wl;
18958c2ecf20Sopenharmony_ci	struct ieee80211_hw *hw;
18968c2ecf20Sopenharmony_ci	int ret;
18978c2ecf20Sopenharmony_ci
18988c2ecf20Sopenharmony_ci	hw = wlcore_alloc_hw(sizeof(struct wl12xx_priv),
18998c2ecf20Sopenharmony_ci			     WL12XX_AGGR_BUFFER_SIZE,
19008c2ecf20Sopenharmony_ci			     sizeof(struct wl12xx_event_mailbox));
19018c2ecf20Sopenharmony_ci	if (IS_ERR(hw)) {
19028c2ecf20Sopenharmony_ci		wl1271_error("can't allocate hw");
19038c2ecf20Sopenharmony_ci		ret = PTR_ERR(hw);
19048c2ecf20Sopenharmony_ci		goto out;
19058c2ecf20Sopenharmony_ci	}
19068c2ecf20Sopenharmony_ci
19078c2ecf20Sopenharmony_ci	wl = hw->priv;
19088c2ecf20Sopenharmony_ci	wl->ops = &wl12xx_ops;
19098c2ecf20Sopenharmony_ci	wl->ptable = wl12xx_ptable;
19108c2ecf20Sopenharmony_ci	ret = wlcore_probe(wl, pdev);
19118c2ecf20Sopenharmony_ci	if (ret)
19128c2ecf20Sopenharmony_ci		goto out_free;
19138c2ecf20Sopenharmony_ci
19148c2ecf20Sopenharmony_ci	return ret;
19158c2ecf20Sopenharmony_ci
19168c2ecf20Sopenharmony_ciout_free:
19178c2ecf20Sopenharmony_ci	wlcore_free_hw(wl);
19188c2ecf20Sopenharmony_ciout:
19198c2ecf20Sopenharmony_ci	return ret;
19208c2ecf20Sopenharmony_ci}
19218c2ecf20Sopenharmony_ci
19228c2ecf20Sopenharmony_cistatic int wl12xx_remove(struct platform_device *pdev)
19238c2ecf20Sopenharmony_ci{
19248c2ecf20Sopenharmony_ci	struct wl1271 *wl = platform_get_drvdata(pdev);
19258c2ecf20Sopenharmony_ci	struct wl12xx_priv *priv;
19268c2ecf20Sopenharmony_ci
19278c2ecf20Sopenharmony_ci	if (!wl)
19288c2ecf20Sopenharmony_ci		goto out;
19298c2ecf20Sopenharmony_ci	priv = wl->priv;
19308c2ecf20Sopenharmony_ci
19318c2ecf20Sopenharmony_ci	kfree(priv->rx_mem_addr);
19328c2ecf20Sopenharmony_ci
19338c2ecf20Sopenharmony_ciout:
19348c2ecf20Sopenharmony_ci	return wlcore_remove(pdev);
19358c2ecf20Sopenharmony_ci}
19368c2ecf20Sopenharmony_ci
19378c2ecf20Sopenharmony_cistatic const struct platform_device_id wl12xx_id_table[] = {
19388c2ecf20Sopenharmony_ci	{ "wl12xx", 0 },
19398c2ecf20Sopenharmony_ci	{  } /* Terminating Entry */
19408c2ecf20Sopenharmony_ci};
19418c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(platform, wl12xx_id_table);
19428c2ecf20Sopenharmony_ci
19438c2ecf20Sopenharmony_cistatic struct platform_driver wl12xx_driver = {
19448c2ecf20Sopenharmony_ci	.probe		= wl12xx_probe,
19458c2ecf20Sopenharmony_ci	.remove		= wl12xx_remove,
19468c2ecf20Sopenharmony_ci	.id_table	= wl12xx_id_table,
19478c2ecf20Sopenharmony_ci	.driver = {
19488c2ecf20Sopenharmony_ci		.name	= "wl12xx_driver",
19498c2ecf20Sopenharmony_ci	}
19508c2ecf20Sopenharmony_ci};
19518c2ecf20Sopenharmony_ci
19528c2ecf20Sopenharmony_cimodule_platform_driver(wl12xx_driver);
19538c2ecf20Sopenharmony_ci
19548c2ecf20Sopenharmony_cimodule_param_named(fref, fref_param, charp, 0);
19558c2ecf20Sopenharmony_ciMODULE_PARM_DESC(fref, "FREF clock: 19.2, 26, 26x, 38.4, 38.4x, 52");
19568c2ecf20Sopenharmony_ci
19578c2ecf20Sopenharmony_cimodule_param_named(tcxo, tcxo_param, charp, 0);
19588c2ecf20Sopenharmony_ciMODULE_PARM_DESC(tcxo,
19598c2ecf20Sopenharmony_ci		 "TCXO clock: 19.2, 26, 38.4, 52, 16.368, 32.736, 16.8, 33.6");
19608c2ecf20Sopenharmony_ci
19618c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
19628c2ecf20Sopenharmony_ciMODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
19638c2ecf20Sopenharmony_ciMODULE_FIRMWARE(WL127X_FW_NAME_SINGLE);
19648c2ecf20Sopenharmony_ciMODULE_FIRMWARE(WL127X_FW_NAME_MULTI);
19658c2ecf20Sopenharmony_ciMODULE_FIRMWARE(WL127X_PLT_FW_NAME);
19668c2ecf20Sopenharmony_ciMODULE_FIRMWARE(WL128X_FW_NAME_SINGLE);
19678c2ecf20Sopenharmony_ciMODULE_FIRMWARE(WL128X_FW_NAME_MULTI);
19688c2ecf20Sopenharmony_ciMODULE_FIRMWARE(WL128X_PLT_FW_NAME);
1969