2 ******************************************************************************
4 * @file ecrnx_platform.c
6 * Copyright (C) ESWIN 2015-2020
8 ******************************************************************************
11 #include <linux/module.h>
12 #include <linux/firmware.h>
13 #include <linux/delay.h>
15 #include "ecrnx_platform.h"
16 #include "reg_access.h"
18 #include "ecrnx_main.h"
20 #ifndef CONFIG_ECRNX_ESWIN
21 #include "ecrnx_pci.h"
22 #ifndef CONFIG_ECRNX_FHOST
24 #endif /* !CONFIG_ECRNX_FHOST */
25 #endif /* CONFIG_ECRNX_ESWIN */
27 #if defined(CONFIG_ECRNX_ESWIN_SDIO)
29 #include "ecrnx_sdio.h"
30 #elif defined(CONFIG_ECRNX_ESWIN_USB)
32 #include "ecrnx_usb.h"
34 #ifdef CONFIG_ECRNX_WIFO_CAIL
36 #include "ecrnx_amt.h"
39 #ifdef CONFIG_ECRNX_TL4
41 * ecrnx_plat_tl4_fw_upload() - Load the requested FW into embedded side.
43 * @ecrnx_plat: pointer to platform structure
44 * @fw_addr: Virtual address where the fw must be loaded
45 * @filename: Name of the fw.
47 * Load a fw, stored as a hex file, into the specified address
49 static int ecrnx_plat_tl4_fw_upload(struct ecrnx_plat *ecrnx_plat, u8* fw_addr,
52 struct device *dev = ecrnx_platform_get_dev(ecrnx_plat);
53 const struct firmware *fw;
62 err = request_firmware(&fw, filename, dev);
69 /* Copy the file on the Embedded side */
70 dev_dbg(dev, "\n### Now copy %s firmware, @ = %p\n", filename, fw_addr);
72 /* Walk through all the lines of the configuration file */
73 while (remain >= 16) {
76 if (sscanf(file_data, "%c:%08X %04X", &typ0, &addr0, &dat0) != 3)
78 if ((addr0 & 0x01) != 0) {
86 (sscanf(file_data, "%c:%08X %04X", &typ1, &addr1, &dat1) != 3) ||
87 (typ1 != typ0) || (addr1 != (addr0 + 1))) {
99 offset += 2*(addr1 - 3);
101 offset += 2*(addr1 + 1);
103 data = dat1 | (dat0 << 16);
105 offset = 2*(addr1 - 1);
106 data = dat0 | (dat1 << 16);
108 dst = (u32 *)(fw_addr + offset);
112 release_firmware(fw);
119 * ecrnx_plat_bin_fw_upload() - Load the requested binary FW into embedded side.
121 * @ecrnx_plat: pointer to platform structure
122 * @fw_addr: Virtual address where the fw must be loaded
123 * @filename: Name of the fw.
125 * Load a fw, stored as a binary file, into the specified address
127 #ifndef CONFIG_ECRNX_ESWIN
128 static int ecrnx_plat_bin_fw_upload(struct ecrnx_plat *ecrnx_plat, u8* fw_addr,
131 const struct firmware *fw;
132 struct device *dev = ecrnx_platform_get_dev(ecrnx_plat);
134 unsigned int i, size;
137 err = request_firmware(&fw, filename, dev);
142 /* Copy the file on the Embedded side */
143 dev_dbg(dev, "\n### Now copy %s firmware, @ = %p\n", filename, fw_addr);
145 src = (u32 *)fw->data;
146 dst = (u32 *)fw_addr;
147 size = (unsigned int)fw->size;
149 /* check potential platform bug on multiple stores vs memcpy */
150 for (i = 0; i < size; i += 4) {
154 release_firmware(fw);
160 #ifndef CONFIG_ECRNX_TL4
161 #define IHEX_REC_DATA 0
162 #define IHEX_REC_EOF 1
163 #define IHEX_REC_EXT_SEG_ADD 2
164 #define IHEX_REC_START_SEG_ADD 3
165 #define IHEX_REC_EXT_LIN_ADD 4
166 #define IHEX_REC_START_LIN_ADD 5
169 * ecrnx_plat_ihex_fw_upload() - Load the requested intel hex 8 FW into embedded side.
171 * @ecrnx_plat: pointer to platform structure
172 * @fw_addr: Virtual address where the fw must be loaded
173 * @filename: Name of the fw.
175 * Load a fw, stored as a ihex file, into the specified address.
177 #ifndef CONFIG_ECRNX_ESWIN
178 static int ecrnx_plat_ihex_fw_upload(struct ecrnx_plat *ecrnx_plat, u8* fw_addr,
181 const struct firmware *fw;
182 struct device *dev = ecrnx_platform_get_dev(ecrnx_plat);
185 u16 haddr, segaddr, addr;
187 u8 load_fw, byte_count, checksum, csum, rec_type;
191 err = request_firmware(&fw, filename, dev);
196 /* Copy the file on the Embedded side */
197 dev_dbg(dev, "\n### Now copy %s firmware, @ = %p\n", filename, fw_addr);
200 end = src + (unsigned int)fw->size;
208 #define IHEX_READ8(_val, _cs) { \
210 strncpy(hex_buff, src, 2); \
211 if (kstrtou8(hex_buff, 16, &_val)) \
218 #define IHEX_READ16(_val) { \
220 strncpy(hex_buff, src, 4); \
221 if (kstrtou16(hex_buff, 16, &_val)) \
224 csum += (_val & 0xff) + (_val >> 8); \
227 #define IHEX_READ32(_val) { \
229 strncpy(hex_buff, src, 8); \
230 if (kstrtouint(hex_buff, 16, &_val)) \
233 csum += (_val & 0xff) + ((_val >> 8) & 0xff) + \
234 ((_val >> 16) & 0xff) + (_val >> 24); \
237 #define IHEX_READ32_PAD(_val, _nb) { \
238 memset(hex_buff, '0', 8); \
240 strncpy(hex_buff, src, (2 * _nb)); \
241 if (kstrtouint(hex_buff, 16, &_val)) \
244 csum += (_val & 0xff) + ((_val >> 8) & 0xff) + \
245 ((_val >> 16) & 0xff) + (_val >> 24); \
248 /* loop until end of file is read*/
253 /* Find next colon start code */
254 while (*src != ':') {
256 if ((src + 3) >= end) /* 3 = : + rec_len */
261 /* Read record len */
262 IHEX_READ8(byte_count, 1);
263 if ((src + (byte_count * 2) + 8) >= end) /* 8 = rec_addr + rec_type + chksum */
266 /* Read record addr */
269 /* Read record type */
270 IHEX_READ8(rec_type, 1);
275 /* Update destination address */
276 dst = (u32 *) (fw_addr + hwaddr + addr);
280 if (byte_count >= 4) {
284 IHEX_READ32_PAD(val, byte_count);
287 *dst++ = __swab32(val);
297 case IHEX_REC_EXT_SEG_ADD: /* Extended Segment Address */
299 IHEX_READ16(segaddr);
300 hwaddr = (haddr << 16) + (segaddr << 4);
303 case IHEX_REC_EXT_LIN_ADD: /* Extended Linear Address */
306 hwaddr = (haddr << 16) + (segaddr << 4);
309 case IHEX_REC_START_LIN_ADD: /* Start Linear Address */
312 IHEX_READ32(val); /* need to read for checksum */
315 case IHEX_REC_START_SEG_ADD:
318 dev_err(dev, "ihex: record type %d not supported\n", rec_type);
323 /* Read and compare checksum */
324 IHEX_READ8(checksum, 0);
325 if (checksum != (u8)(~csum + 1))
332 #undef IHEX_READ32_PAD
335 release_firmware(fw);
338 dev_err(dev, "%s: Invalid ihex record around line %d\n", filename, rec_idx);
342 #endif /* CONFIG_ECRNX_TL4 */
345 #ifndef CONFIG_ECRNX_ESWIN
346 #ifndef CONFIG_ECRNX_SDM
348 * ecrnx_plat_get_rf() - Retrun the RF used in the platform
350 * @ecrnx_plat: pointer to platform structure
352 static u32 ecrnx_plat_get_rf(struct ecrnx_plat *ecrnx_plat)
355 ver = ECRNX_REG_READ(ecrnx_plat, ECRNX_ADDR_SYSTEM, MDM_HDMCONFIG_ADDR);
357 ver = __MDM_PHYCFG_FROM_VERS(ver);
358 WARN(((ver != MDM_PHY_CONFIG_TRIDENT) &&
359 (ver != MDM_PHY_CONFIG_CATAXIA) &&
360 (ver != MDM_PHY_CONFIG_KARST)),
361 "Unknown PHY version 0x%08x\n", ver);
368 * ecrnx_plat_get_clkctrl_addr() - Return the clock control register address
370 * @ecrnx_plat: platform data
372 #ifndef CONFIG_ECRNX_SDM
373 #ifndef CONFIG_ECRNX_ESWIN
374 static u32 ecrnx_plat_get_clkctrl_addr(struct ecrnx_plat *ecrnx_plat)
377 if (ecrnx_plat_get_rf(ecrnx_plat) == MDM_PHY_CONFIG_TRIDENT)
378 return MDM_MEMCLKCTRL0_ADDR;
379 regval = ECRNX_REG_READ(ecrnx_plat, ECRNX_ADDR_SYSTEM, SYSCTRL_SIGNATURE_ADDR);
380 if (__FPGA_TYPE(regval) == 0xC0CA)
381 return CRM_CLKGATEFCTRL0_ADDR;
383 return MDM_CLKGATEFCTRL0_ADDR;
385 #endif /* CONFIG_ECRNX_SDM */
389 * ecrnx_plat_stop_agcfsm() - Stop a AGC state machine
391 * @ecrnx_plat: pointer to platform structure
392 * @agg_reg: Address of the agccntl register (within ECRNX_ADDR_SYSTEM)
393 * @agcctl: Updated with value of the agccntl rgister before stop
394 * @memclk: Updated with value of the clock register before stop
395 * @agc_ver: Version of the AGC load procedure
396 * @clkctrladdr: Indicates which AGC clock register should be accessed
398 #ifndef CONFIG_ECRNX_ESWIN
399 static void ecrnx_plat_stop_agcfsm(struct ecrnx_plat *ecrnx_plat, int agc_reg,
400 u32 *agcctl, u32 *memclk, u8 agc_ver,
403 /* First read agcctnl and clock registers */
404 *memclk = ECRNX_REG_READ(ecrnx_plat, ECRNX_ADDR_SYSTEM, clkctrladdr);
406 /* Stop state machine : xxAGCCNTL0[AGCFSMRESET]=1 */
407 *agcctl = ECRNX_REG_READ(ecrnx_plat, ECRNX_ADDR_SYSTEM, agc_reg);
408 ECRNX_REG_WRITE((*agcctl) | BIT(12), ecrnx_plat, ECRNX_ADDR_SYSTEM, agc_reg);
412 /* CLKGATEFCTRL0[AGCCLKFORCE]=1 */
413 ECRNX_REG_WRITE((*memclk) | BIT(29), ecrnx_plat, ECRNX_ADDR_SYSTEM,
416 /* MEMCLKCTRL0[AGCMEMCLKCTRL]=0 */
417 ECRNX_REG_WRITE((*memclk) & ~BIT(3), ecrnx_plat, ECRNX_ADDR_SYSTEM,
424 * ecrnx_plat_start_agcfsm() - Restart a AGC state machine
426 * @ecrnx_plat: pointer to platform structure
427 * @agg_reg: Address of the agccntl register (within ECRNX_ADDR_SYSTEM)
428 * @agcctl: value of the agccntl register to restore
429 * @memclk: value of the clock register to restore
430 * @agc_ver: Version of the AGC load procedure
431 * @clkctrladdr: Indicates which AGC clock register should be accessed
433 #ifndef CONFIG_ECRNX_ESWIN
434 static void ecrnx_plat_start_agcfsm(struct ecrnx_plat *ecrnx_plat, int agc_reg,
435 u32 agcctl, u32 memclk, u8 agc_ver,
441 /* CLKGATEFCTRL0[AGCCLKFORCE]=0 */
442 ECRNX_REG_WRITE(memclk & ~BIT(29), ecrnx_plat, ECRNX_ADDR_SYSTEM,
445 /* MEMCLKCTRL0[AGCMEMCLKCTRL]=1 */
446 ECRNX_REG_WRITE(memclk | BIT(3), ecrnx_plat, ECRNX_ADDR_SYSTEM,
449 /* Restart state machine: xxAGCCNTL0[AGCFSMRESET]=0 */
450 ECRNX_REG_WRITE(agcctl & ~BIT(12), ecrnx_plat, ECRNX_ADDR_SYSTEM, agc_reg);
456 * ecrnx_plat_get_agc_load_version() - Return the agc load protocol version and the
457 * address of the clock control register
459 * @ecrnx_plat: platform data
461 * @clkctrladdr: returned clock control register address
464 #ifndef CONFIG_ECRNX_ESWIN
465 #ifndef CONFIG_ECRNX_SDM
466 static u8 ecrnx_plat_get_agc_load_version(struct ecrnx_plat *ecrnx_plat, u32 rf,
473 *clkctrladdr = ecrnx_plat_get_clkctrl_addr(ecrnx_plat);
474 /* Trident and Elma PHY use old method */
475 if (rf == MDM_PHY_CONFIG_TRIDENT)
478 /* Get the FPGA signature */
479 regval = ECRNX_REG_READ(ecrnx_plat, ECRNX_ADDR_SYSTEM, SYSCTRL_SIGNATURE_ADDR);
482 /* Read RIU version register */
483 agc_ver = ECRNX_REG_READ(ecrnx_plat, ECRNX_ADDR_SYSTEM, RIU_ECRNXVERSION_ADDR);
484 agc_load_ver = __RIU_AGCLOAD_FROM_VERS(agc_ver);
488 #endif /* CONFIG_ECRNX_SDM */
492 * ecrnx_plat_agc_load() - Load AGC ucode
494 * @ecrnx_plat: platform data
496 #ifndef CONFIG_ECRNX_ESWIN
497 static int ecrnx_plat_agc_load(struct ecrnx_plat *ecrnx_plat)
500 #ifndef CONFIG_ECRNX_SDM
501 u32 agc = 0, agcctl, memclk;
503 u32 rf = ecrnx_plat_get_rf(ecrnx_plat);
507 case MDM_PHY_CONFIG_TRIDENT:
508 agc = AGC_ECRNXAGCCNTL_ADDR;
510 case MDM_PHY_CONFIG_CATAXIA:
511 case MDM_PHY_CONFIG_KARST:
512 agc = RIU_ECRNXAGCCNTL_ADDR;
518 agc_ver = ecrnx_plat_get_agc_load_version(ecrnx_plat, rf, &clkctrladdr);
520 ecrnx_plat_stop_agcfsm(ecrnx_plat, agc, &agcctl, &memclk, agc_ver, clkctrladdr);
522 ret = ecrnx_plat_bin_fw_upload(ecrnx_plat,
523 ECRNX_ADDR(ecrnx_plat, ECRNX_ADDR_SYSTEM, PHY_AGC_UCODE_ADDR),
526 if (!ret && (agc_ver == 1)) {
527 /* Run BIST to ensure that the AGC RAM was correctly loaded */
528 ECRNX_REG_WRITE(BIT(28), ecrnx_plat, ECRNX_ADDR_SYSTEM,
529 RIU_ECRNXDYNAMICCONFIG_ADDR);
530 while (ECRNX_REG_READ(ecrnx_plat, ECRNX_ADDR_SYSTEM,
531 RIU_ECRNXDYNAMICCONFIG_ADDR) & BIT(28));
533 if (!(ECRNX_REG_READ(ecrnx_plat, ECRNX_ADDR_SYSTEM,
534 RIU_AGCMEMBISTSTAT_ADDR) & BIT(0))) {
535 dev_err(ecrnx_platform_get_dev(ecrnx_plat),
536 "AGC RAM not loaded correctly 0x%08x\n",
537 ECRNX_REG_READ(ecrnx_plat, ECRNX_ADDR_SYSTEM,
538 RIU_AGCMEMSIGNATURESTAT_ADDR));
543 ecrnx_plat_start_agcfsm(ecrnx_plat, agc, agcctl, memclk, agc_ver, clkctrladdr);
551 * ecrnx_ldpc_load() - Load LDPC RAM
553 * @ecrnx_hw: Main driver data
555 #ifndef CONFIG_ECRNX_ESWIN
556 static int ecrnx_ldpc_load(struct ecrnx_hw *ecrnx_hw)
558 #ifndef CONFIG_ECRNX_SDM
559 struct ecrnx_plat *ecrnx_plat = ecrnx_hw->plat;
560 u32 rf = ecrnx_plat_get_rf(ecrnx_plat);
561 u32 phy_feat = ECRNX_REG_READ(ecrnx_plat, ECRNX_ADDR_SYSTEM, MDM_HDMCONFIG_ADDR);
562 u32 phy_vers = ECRNX_REG_READ(ecrnx_plat, ECRNX_ADDR_SYSTEM, MDM_HDMVERSION_ADDR);
564 if (((rf != MDM_PHY_CONFIG_KARST) && (rf != MDM_PHY_CONFIG_CATAXIA)) ||
565 (phy_feat & (MDM_LDPCDEC_BIT | MDM_LDPCENC_BIT)) !=
566 (MDM_LDPCDEC_BIT | MDM_LDPCENC_BIT)) {
569 if (__MDM_VERSION(phy_vers) > 30) {
573 if (ecrnx_plat_bin_fw_upload(ecrnx_plat,
574 ECRNX_ADDR(ecrnx_plat, ECRNX_ADDR_SYSTEM, PHY_LDPC_RAM_ADDR),
575 ECRNX_LDPC_RAM_NAME)) {
582 ecrnx_hw->mod_params->ldpc_on = false;
584 #endif /* CONFIG_ECRNX_SDM */
589 * ecrnx_plat_lmac_load() - Load FW code
591 * @ecrnx_plat: platform data
593 #ifndef CONFIG_ECRNX_ESWIN
594 static int ecrnx_plat_lmac_load(struct ecrnx_plat *ecrnx_plat)
598 #ifdef CONFIG_ECRNX_TL4
599 ret = ecrnx_plat_tl4_fw_upload(ecrnx_plat,
600 ECRNX_ADDR(ecrnx_plat, ECRNX_ADDR_CPU, RAM_LMAC_FW_ADDR),
603 ret = ecrnx_plat_ihex_fw_upload(ecrnx_plat,
604 ECRNX_ADDR(ecrnx_plat, ECRNX_ADDR_CPU, RAM_LMAC_FW_ADDR),
608 ret = ecrnx_plat_bin_fw_upload(ecrnx_plat,
609 ECRNX_ADDR(ecrnx_plat, ECRNX_ADDR_CPU, RAM_LMAC_FW_ADDR),
619 * ecrnx_rf_fw_load() - Load RF FW if any
621 * @ecrnx_hw: Main driver data
623 #ifndef CONFIG_ECRNX_ESWIN
624 static int ecrnx_plat_rf_fw_load(struct ecrnx_hw *ecrnx_hw)
626 #ifndef CONFIG_ECRNX_SDM
627 struct ecrnx_plat *ecrnx_plat = ecrnx_hw->plat;
628 u32 rf = ecrnx_plat_get_rf(ecrnx_plat);
629 struct device *dev = ecrnx_platform_get_dev(ecrnx_plat);
630 const struct firmware *fw;
637 // Today only Cataxia has a FW to load
638 if (rf != MDM_PHY_CONFIG_CATAXIA)
641 err = request_firmware(&fw, ECRNX_CATAXIA_FW_NAME, dev);
644 dev_err(dev, "Make sure your board has up-to-date packages.");
645 dev_err(dev, "Run \"sudo smart update\" \"sudo smart upgrade\" commands.\n");
649 file_data = fw->data;
652 // Get address of clock control register
653 clkctrladdr = ecrnx_plat_get_clkctrl_addr(ecrnx_plat);
656 clkforce = ECRNX_REG_READ(ecrnx_plat, ECRNX_ADDR_SYSTEM, clkctrladdr);
657 ECRNX_REG_WRITE(clkforce | BIT(27), ecrnx_plat, ECRNX_ADDR_SYSTEM, clkctrladdr);
661 ECRNX_REG_WRITE(0x00003100, ecrnx_plat, ECRNX_ADDR_SYSTEM, RC_SYSTEM_CONFIGURATION_ADDR);
665 ECRNX_REG_WRITE(0x00133100, ecrnx_plat, ECRNX_ADDR_SYSTEM, RC_SYSTEM_CONFIGURATION_ADDR);
669 ECRNX_REG_WRITE(0x00103100, ecrnx_plat, ECRNX_ADDR_SYSTEM, RC_SYSTEM_CONFIGURATION_ADDR);
673 ECRNX_REG_WRITE(0xC1010001, ecrnx_plat, ECRNX_ADDR_SYSTEM, RC_ACCES_TO_CATAXIA_REG_ADDR);
676 /* Walk through all the lines of the FW file */
677 while (remain >= 10) {
680 if (sscanf(file_data, "0x%08X", &data) != 1)
689 ECRNX_REG_WRITE(data, ecrnx_plat, ECRNX_ADDR_SYSTEM, RC_ACCES_TO_CATAXIA_REG_ADDR);
694 ECRNX_REG_WRITE(0xE0010011, ecrnx_plat, ECRNX_ADDR_SYSTEM, RC_ACCES_TO_CATAXIA_REG_ADDR);
698 ECRNX_REG_WRITE(clkforce, ecrnx_plat, ECRNX_ADDR_SYSTEM, clkctrladdr);
700 release_firmware(fw);
702 #endif /* CONFIG_ECRNX_SDM */
708 * ecrnx_plat_mpif_sel() - Select the MPIF according to the FPGA signature
710 * @ecrnx_plat: platform data
712 #ifndef CONFIG_ECRNX_ESWIN
713 static void ecrnx_plat_mpif_sel(struct ecrnx_plat *ecrnx_plat)
715 #ifndef CONFIG_ECRNX_SDM
719 /* Get the FPGA signature */
720 regval = ECRNX_REG_READ(ecrnx_plat, ECRNX_ADDR_SYSTEM, SYSCTRL_SIGNATURE_ADDR);
721 type = __FPGA_TYPE(regval);
723 /* Check if we need to switch to the old MPIF or not */
724 if ((type != 0xCAFE) && (type != 0XC0CA) && (regval & 0xF) < 0x3)
726 /* A old FPGA A is used, so configure the FPGA B to use the old MPIF */
727 ECRNX_REG_WRITE(0x3, ecrnx_plat, ECRNX_ADDR_SYSTEM, FPGAB_MPIF_SEL_ADDR);
734 * ecrnx_platform_reset() - Reset the platform
736 * @ecrnx_plat: platform data
738 #ifndef CONFIG_ECRNX_ESWIN
739 static int ecrnx_platform_reset(struct ecrnx_plat *ecrnx_plat)
743 /* the doc states that SOFT implies FPGA_B_RESET
744 * adding FPGA_B_RESET is clearer */
745 ECRNX_REG_WRITE(SOFT_RESET | FPGA_B_RESET, ecrnx_plat,
746 ECRNX_ADDR_SYSTEM, SYSCTRL_MISC_CNTL_ADDR);
749 regval = ECRNX_REG_READ(ecrnx_plat, ECRNX_ADDR_SYSTEM, SYSCTRL_MISC_CNTL_ADDR);
751 if (regval & SOFT_RESET) {
752 dev_err(ecrnx_platform_get_dev(ecrnx_plat), "reset: failed\n");
756 ECRNX_REG_WRITE(regval & ~FPGA_B_RESET, ecrnx_plat,
757 ECRNX_ADDR_SYSTEM, SYSCTRL_MISC_CNTL_ADDR);
764 * rwmx_platform_save_config() - Save hardware config before reload
766 * @ecrnx_plat: Pointer to platform data
768 * Return configuration registers values.
770 #ifndef CONFIG_ECRNX_ESWIN
771 static void* ecrnx_term_save_config(struct ecrnx_plat *ecrnx_plat)
774 u32 *reg_value, *res;
777 if (ecrnx_plat->get_config_reg) {
778 size = ecrnx_plat->get_config_reg(ecrnx_plat, ®_list);
784 res = kmalloc(sizeof(u32) * size, GFP_KERNEL);
789 for (i = 0; i < size; i++) {
790 *reg_value++ = ECRNX_REG_READ(ecrnx_plat, ECRNX_ADDR_SYSTEM,
799 * rwmx_platform_restore_config() - Restore hardware config after reload
801 * @ecrnx_plat: Pointer to platform data
802 * @reg_value: Pointer of value to restore
803 * (obtained with rwmx_platform_save_config())
805 * Restore configuration registers value.
807 #ifndef CONFIG_ECRNX_ESWIN
808 static void ecrnx_term_restore_config(struct ecrnx_plat *ecrnx_plat,
814 if (!reg_value || !ecrnx_plat->get_config_reg)
817 size = ecrnx_plat->get_config_reg(ecrnx_plat, ®_list);
819 for (i = 0; i < size; i++) {
820 ECRNX_REG_WRITE(*reg_value++, ecrnx_plat, ECRNX_ADDR_SYSTEM,
826 #ifndef CONFIG_ECRNX_ESWIN
827 static int ecrnx_check_fw_compatibility(struct ecrnx_hw *ecrnx_hw)
831 struct ipc_shared_env_tag *shared = ecrnx_hw->ipc_env->shared;
832 #ifdef CONFIG_ECRNX_SOFTMAC
833 struct wiphy *wiphy = ecrnx_hw->hw->wiphy;
834 #else //CONFIG_ECRNX_SOFTMAC
835 struct wiphy *wiphy = ecrnx_hw->wiphy;
836 #endif //CONFIG_ECRNX_SOFTMAC
837 #ifdef CONFIG_ECRNX_OLD_IPC
838 int ipc_shared_version = 10;
839 #else //CONFIG_ECRNX_OLD_IPC
840 int ipc_shared_version = 11;
841 #endif //CONFIG_ECRNX_OLD_IPC
843 if(shared->comp_info.ipc_shared_version != ipc_shared_version)
845 wiphy_err(wiphy, "Different versions of IPC shared version between driver and FW (%d != %d)\n ",
846 ipc_shared_version, shared->comp_info.ipc_shared_version);
850 if(shared->comp_info.radarbuf_cnt != IPC_RADARBUF_CNT)
852 wiphy_err(wiphy, "Different number of host buffers available for Radar events handling "\
853 "between driver and FW (%d != %d)\n", IPC_RADARBUF_CNT,
854 shared->comp_info.radarbuf_cnt);
858 if(shared->comp_info.unsuprxvecbuf_cnt != IPC_UNSUPRXVECBUF_CNT)
860 wiphy_err(wiphy, "Different number of host buffers available for unsupported Rx vectors "\
861 "handling between driver and FW (%d != %d)\n", IPC_UNSUPRXVECBUF_CNT,
862 shared->comp_info.unsuprxvecbuf_cnt);
866 #ifdef CONFIG_ECRNX_FULLMAC
867 if(shared->comp_info.rxdesc_cnt != IPC_RXDESC_CNT)
869 wiphy_err(wiphy, "Different number of shared descriptors available for Data RX handling "\
870 "between driver and FW (%d != %d)\n", IPC_RXDESC_CNT,
871 shared->comp_info.rxdesc_cnt);
874 #endif /* CONFIG_ECRNX_FULLMAC */
876 if(shared->comp_info.rxbuf_cnt != IPC_RXBUF_CNT)
878 wiphy_err(wiphy, "Different number of host buffers available for Data Rx handling "\
879 "between driver and FW (%d != %d)\n", IPC_RXBUF_CNT,
880 shared->comp_info.rxbuf_cnt);
884 if(shared->comp_info.msge2a_buf_cnt != IPC_MSGE2A_BUF_CNT)
886 wiphy_err(wiphy, "Different number of host buffers available for Emb->App MSGs "\
887 "sending between driver and FW (%d != %d)\n", IPC_MSGE2A_BUF_CNT,
888 shared->comp_info.msge2a_buf_cnt);
892 if(shared->comp_info.dbgbuf_cnt != IPC_DBGBUF_CNT)
894 wiphy_err(wiphy, "Different number of host buffers available for debug messages "\
895 "sending between driver and FW (%d != %d)\n", IPC_DBGBUF_CNT,
896 shared->comp_info.dbgbuf_cnt);
900 if(shared->comp_info.bk_txq != NX_TXDESC_CNT0)
902 wiphy_err(wiphy, "Driver and FW have different sizes of BK TX queue (%d != %d)\n",
903 NX_TXDESC_CNT0, shared->comp_info.bk_txq);
907 if(shared->comp_info.be_txq != NX_TXDESC_CNT1)
909 wiphy_err(wiphy, "Driver and FW have different sizes of BE TX queue (%d != %d)\n",
910 NX_TXDESC_CNT1, shared->comp_info.be_txq);
914 if(shared->comp_info.vi_txq != NX_TXDESC_CNT2)
916 wiphy_err(wiphy, "Driver and FW have different sizes of VI TX queue (%d != %d)\n",
917 NX_TXDESC_CNT2, shared->comp_info.vi_txq);
921 if(shared->comp_info.vo_txq != NX_TXDESC_CNT3)
923 wiphy_err(wiphy, "Driver and FW have different sizes of VO TX queue (%d != %d)\n",
924 NX_TXDESC_CNT3, shared->comp_info.vo_txq);
929 if(shared->comp_info.bcn_txq != NX_TXDESC_CNT4)
931 wiphy_err(wiphy, "Driver and FW have different sizes of BCN TX queue (%d != %d)\n",
932 NX_TXDESC_CNT4, shared->comp_info.bcn_txq);
936 if (shared->comp_info.bcn_txq > 0)
938 wiphy_err(wiphy, "BCMC enabled in firmware but disabled in driver\n");
941 #endif /* NX_TXQ_CNT == 5 */
943 if(shared->comp_info.ipc_shared_size != sizeof(ipc_shared_env))
945 wiphy_err(wiphy, "Different sizes of IPC shared between driver and FW (%zd != %d)\n",
946 sizeof(ipc_shared_env), shared->comp_info.ipc_shared_size);
950 if(shared->comp_info.msg_api != MSG_API_VER)
952 wiphy_err(wiphy, "Different supported message API versions between "\
953 "driver and FW (%d != %d)\n", MSG_API_VER, shared->comp_info.msg_api);
959 #endif /* !CONFIG_ECRNX_ESWIN */
962 * ecrnx_platform_on() - Start the platform
964 * @ecrnx_hw: Main driver data
965 * @config: Config to restore (NULL if nothing to restore)
967 * It starts the platform :
968 * - load fw and ucodes
971 * - enable link communication/IRQ
973 * Called by 802.11 part
975 int ecrnx_platform_on(struct ecrnx_hw *ecrnx_hw, void *config)
980 ECRNX_DBG("%s entry!!", __func__);
981 shared_ram = kzalloc(sizeof(struct ipc_shared_env_tag), GFP_KERNEL);
985 if ((ret = ecrnx_ipc_init(ecrnx_hw, shared_ram)))
988 ECRNX_DBG("%s exit!!", __func__);
993 * ecrnx_platform_off() - Stop the platform
995 * @ecrnx_hw: Main driver data
996 * @config: Updated with pointer to config, to be able to restore it with
997 * ecrnx_platform_on(). It's up to the caller to free the config. Set to NULL
998 * if configuration is not needed.
1000 * Called by 802.11 part
1002 void ecrnx_platform_off(struct ecrnx_hw *ecrnx_hw, void **config)
1004 ecrnx_ipc_deinit(ecrnx_hw);
1005 #if defined(CONFIG_ECRNX_ESWIN_SDIO)
1006 ecrnx_sdio_deinit(ecrnx_hw);
1007 #elif defined(CONFIG_ECRNX_ESWIN_USB)
1008 ecrnx_usb_deinit(ecrnx_hw);
1010 #error "config error drv";
1015 * ecrnx_platform_init() - Initialize the platform
1017 * @ecrnx_plat: platform data (already updated by platform driver)
1018 * @platform_data: Pointer to store the main driver data pointer (aka ecrnx_hw)
1019 * That will be set as driver data for the platform driver
1020 * Return: 0 on success, < 0 otherwise
1022 * Called by the platform driver after it has been probed
1024 int ecrnx_platform_init(void *ecrnx_plat, void **platform_data)
1026 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1027 #if defined CONFIG_ECRNX_SOFTMAC
1028 return ecrnx_mac80211_init(ecrnx_plat, platform_data);
1029 #elif defined CONFIG_ECRNX_FULLMAC
1030 #ifdef CONFIG_ECRNX_WIFO_CAIL
1031 if (amt_mode == true) {
1032 return ecrnx_amt_init();
1036 return ecrnx_cfg80211_init(ecrnx_plat, platform_data);
1037 #elif defined CONFIG_ECRNX_FHOST
1038 return ecrnx_fhost_init(ecrnx_plat, platform_data);
1043 * ecrnx_platform_deinit() - Deinitialize the platform
1045 * @ecrnx_hw: main driver data
1047 * Called by the platform driver after it is removed
1049 void ecrnx_platform_deinit(struct ecrnx_hw *ecrnx_hw)
1051 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1053 #if defined CONFIG_ECRNX_SOFTMAC
1054 ecrnx_mac80211_deinit(ecrnx_hw);
1055 #elif defined CONFIG_ECRNX_FULLMAC
1056 #ifdef CONFIG_ECRNX_WIFO_CAIL
1057 if (amt_mode == true) {
1062 ecrnx_cfg80211_deinit(ecrnx_hw);
1063 #elif defined CONFIG_ECRNX_FHOST
1064 ecrnx_fhost_deinit(ecrnx_hw);
1070 * ecrnx_platform_register_drv() - Register all possible platform drivers
1072 int ecrnx_platform_register_drv(void)
1074 #if defined(CONFIG_ECRNX_ESWIN_SDIO)
1075 return ecrnx_sdio_register_drv();
1076 #elif defined(CONFIG_ECRNX_ESWIN_USB)
1077 return ecrnx_usb_register_drv();
1079 #error "config error drv"
1085 * ecrnx_platform_unregister_drv() - Unegister all platform drivers
1087 void ecrnx_platform_unregister_drv(void)
1089 #if defined(CONFIG_ECRNX_ESWIN_SDIO)
1090 return ecrnx_sdio_unregister_drv();
1091 #elif defined(CONFIG_ECRNX_ESWIN_USB)
1092 return ecrnx_usb_unregister_drv();
1094 #error "config error drv"
1099 #ifndef CONFIG_ECRNX_SDM
1100 MODULE_FIRMWARE(ECRNX_AGC_FW_NAME);
1101 MODULE_FIRMWARE(ECRNX_FCU_FW_NAME);
1102 MODULE_FIRMWARE(ECRNX_LDPC_RAM_NAME);
1104 MODULE_FIRMWARE(ECRNX_MAC_FW_NAME);
1105 #ifndef CONFIG_ECRNX_TL4
1106 MODULE_FIRMWARE(ECRNX_MAC_FW_NAME2);