Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Firmware loading.
0004  *
0005  * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
0006  * Copyright (c) 2010, ST-Ericsson
0007  */
0008 #include <linux/firmware.h>
0009 #include <linux/slab.h>
0010 #include <linux/mm.h>
0011 #include <linux/bitfield.h>
0012 
0013 #include "fwio.h"
0014 #include "wfx.h"
0015 #include "hwio.h"
0016 
0017 /* Addresses below are in SRAM area */
0018 #define WFX_DNLD_FIFO             0x09004000
0019 #define     DNLD_BLOCK_SIZE           0x0400
0020 #define     DNLD_FIFO_SIZE            0x8000 /* (32 * DNLD_BLOCK_SIZE) */
0021 /* Download Control Area (DCA) */
0022 #define WFX_DCA_IMAGE_SIZE        0x0900C000
0023 #define WFX_DCA_PUT               0x0900C004
0024 #define WFX_DCA_GET               0x0900C008
0025 #define WFX_DCA_HOST_STATUS       0x0900C00C
0026 #define     HOST_READY                0x87654321
0027 #define     HOST_INFO_READ            0xA753BD99
0028 #define     HOST_UPLOAD_PENDING       0xABCDDCBA
0029 #define     HOST_UPLOAD_COMPLETE      0xD4C64A99
0030 #define     HOST_OK_TO_JUMP           0x174FC882
0031 #define WFX_DCA_NCP_STATUS        0x0900C010
0032 #define     NCP_NOT_READY             0x12345678
0033 #define     NCP_READY                 0x87654321
0034 #define     NCP_INFO_READY            0xBD53EF99
0035 #define     NCP_DOWNLOAD_PENDING      0xABCDDCBA
0036 #define     NCP_DOWNLOAD_COMPLETE     0xCAFEFECA
0037 #define     NCP_AUTH_OK               0xD4C64A99
0038 #define     NCP_AUTH_FAIL             0x174FC882
0039 #define     NCP_PUB_KEY_RDY           0x7AB41D19
0040 #define WFX_DCA_FW_SIGNATURE      0x0900C014
0041 #define     FW_SIGNATURE_SIZE         0x40
0042 #define WFX_DCA_FW_HASH           0x0900C054
0043 #define     FW_HASH_SIZE              0x08
0044 #define WFX_DCA_FW_VERSION        0x0900C05C
0045 #define     FW_VERSION_SIZE           0x04
0046 #define WFX_DCA_RESERVED          0x0900C060
0047 #define     DCA_RESERVED_SIZE         0x20
0048 #define WFX_STATUS_INFO           0x0900C080
0049 #define WFX_BOOTLOADER_LABEL      0x0900C084
0050 #define     BOOTLOADER_LABEL_SIZE     0x3C
0051 #define WFX_PTE_INFO              0x0900C0C0
0052 #define     PTE_INFO_KEYSET_IDX       0x0D
0053 #define     PTE_INFO_SIZE             0x10
0054 #define WFX_ERR_INFO              0x0900C0D0
0055 #define     ERR_INVALID_SEC_TYPE      0x05
0056 #define     ERR_SIG_VERIF_FAILED      0x0F
0057 #define     ERR_AES_CTRL_KEY          0x10
0058 #define     ERR_ECC_PUB_KEY           0x11
0059 #define     ERR_MAC_KEY               0x18
0060 
0061 #define DCA_TIMEOUT  50 /* milliseconds */
0062 #define WAKEUP_TIMEOUT 200 /* milliseconds */
0063 
0064 static const char * const fwio_errors[] = {
0065     [ERR_INVALID_SEC_TYPE] = "Invalid section type or wrong encryption",
0066     [ERR_SIG_VERIF_FAILED] = "Signature verification failed",
0067     [ERR_AES_CTRL_KEY]     = "AES control key not initialized",
0068     [ERR_ECC_PUB_KEY]      = "ECC public key not initialized",
0069     [ERR_MAC_KEY]          = "MAC key not initialized",
0070 };
0071 
0072 /* request_firmware() allocate data using vmalloc(). It is not compatible with underlying hardware
0073  * that use DMA. Function below detect this case and allocate a bounce buffer if necessary.
0074  *
0075  * Notice that, in doubt, you can enable CONFIG_DEBUG_SG to ask kernel to detect this problem at
0076  * runtime  (else, kernel silently fail).
0077  *
0078  * NOTE: it may also be possible to use 'pages' from struct firmware and avoid bounce buffer
0079  */
0080 static int wfx_sram_write_dma_safe(struct wfx_dev *wdev, u32 addr, const u8 *buf, size_t len)
0081 {
0082     int ret;
0083     const u8 *tmp;
0084 
0085     if (!virt_addr_valid(buf)) {
0086         tmp = kmemdup(buf, len, GFP_KERNEL);
0087         if (!tmp)
0088             return -ENOMEM;
0089     } else {
0090         tmp = buf;
0091     }
0092     ret = wfx_sram_buf_write(wdev, addr, tmp, len);
0093     if (tmp != buf)
0094         kfree(tmp);
0095     return ret;
0096 }
0097 
0098 static int get_firmware(struct wfx_dev *wdev, u32 keyset_chip,
0099             const struct firmware **fw, int *file_offset)
0100 {
0101     int keyset_file;
0102     char filename[256];
0103     const char *data;
0104     int ret;
0105 
0106     snprintf(filename, sizeof(filename), "%s_%02X.sec",
0107          wdev->pdata.file_fw, keyset_chip);
0108     ret = firmware_request_nowarn(fw, filename, wdev->dev);
0109     if (ret) {
0110         dev_info(wdev->dev, "can't load %s, falling back to %s.sec\n",
0111              filename, wdev->pdata.file_fw);
0112         snprintf(filename, sizeof(filename), "%s.sec", wdev->pdata.file_fw);
0113         ret = request_firmware(fw, filename, wdev->dev);
0114         if (ret) {
0115             dev_err(wdev->dev, "can't load %s\n", filename);
0116             *fw = NULL;
0117             return ret;
0118         }
0119     }
0120 
0121     data = (*fw)->data;
0122     if (memcmp(data, "KEYSET", 6) != 0) {
0123         /* Legacy firmware format */
0124         *file_offset = 0;
0125         keyset_file = 0x90;
0126     } else {
0127         *file_offset = 8;
0128         keyset_file = (hex_to_bin(data[6]) * 16) | hex_to_bin(data[7]);
0129         if (keyset_file < 0) {
0130             dev_err(wdev->dev, "%s corrupted\n", filename);
0131             release_firmware(*fw);
0132             *fw = NULL;
0133             return -EINVAL;
0134         }
0135     }
0136     if (keyset_file != keyset_chip) {
0137         dev_err(wdev->dev, "firmware keyset is incompatible with chip (file: 0x%02X, chip: 0x%02X)\n",
0138             keyset_file, keyset_chip);
0139         release_firmware(*fw);
0140         *fw = NULL;
0141         return -ENODEV;
0142     }
0143     wdev->keyset = keyset_file;
0144     return 0;
0145 }
0146 
0147 static int wait_ncp_status(struct wfx_dev *wdev, u32 status)
0148 {
0149     ktime_t now, start;
0150     u32 reg;
0151     int ret;
0152 
0153     start = ktime_get();
0154     for (;;) {
0155         ret = wfx_sram_reg_read(wdev, WFX_DCA_NCP_STATUS, &reg);
0156         if (ret < 0)
0157             return -EIO;
0158         now = ktime_get();
0159         if (reg == status)
0160             break;
0161         if (ktime_after(now, ktime_add_ms(start, DCA_TIMEOUT)))
0162             return -ETIMEDOUT;
0163     }
0164     if (ktime_compare(now, start))
0165         dev_dbg(wdev->dev, "chip answer after %lldus\n", ktime_us_delta(now, start));
0166     else
0167         dev_dbg(wdev->dev, "chip answer immediately\n");
0168     return 0;
0169 }
0170 
0171 static int upload_firmware(struct wfx_dev *wdev, const u8 *data, size_t len)
0172 {
0173     int ret;
0174     u32 offs, bytes_done = 0;
0175     ktime_t now, start;
0176 
0177     if (len % DNLD_BLOCK_SIZE) {
0178         dev_err(wdev->dev, "firmware size is not aligned. Buffer overrun will occur\n");
0179         return -EIO;
0180     }
0181     offs = 0;
0182     while (offs < len) {
0183         start = ktime_get();
0184         for (;;) {
0185             now = ktime_get();
0186             if (offs + DNLD_BLOCK_SIZE - bytes_done < DNLD_FIFO_SIZE)
0187                 break;
0188             if (ktime_after(now, ktime_add_ms(start, DCA_TIMEOUT)))
0189                 return -ETIMEDOUT;
0190             ret = wfx_sram_reg_read(wdev, WFX_DCA_GET, &bytes_done);
0191             if (ret < 0)
0192                 return ret;
0193         }
0194         if (ktime_compare(now, start))
0195             dev_dbg(wdev->dev, "answer after %lldus\n", ktime_us_delta(now, start));
0196 
0197         ret = wfx_sram_write_dma_safe(wdev, WFX_DNLD_FIFO + (offs % DNLD_FIFO_SIZE),
0198                           data + offs, DNLD_BLOCK_SIZE);
0199         if (ret < 0)
0200             return ret;
0201 
0202         /* The device seems to not support writing 0 in this register during first loop */
0203         offs += DNLD_BLOCK_SIZE;
0204         ret = wfx_sram_reg_write(wdev, WFX_DCA_PUT, offs);
0205         if (ret < 0)
0206             return ret;
0207     }
0208     return 0;
0209 }
0210 
0211 static void print_boot_status(struct wfx_dev *wdev)
0212 {
0213     u32 reg;
0214 
0215     wfx_sram_reg_read(wdev, WFX_STATUS_INFO, &reg);
0216     if (reg == 0x12345678)
0217         return;
0218     wfx_sram_reg_read(wdev, WFX_ERR_INFO, &reg);
0219     if (reg < ARRAY_SIZE(fwio_errors) && fwio_errors[reg])
0220         dev_info(wdev->dev, "secure boot: %s\n", fwio_errors[reg]);
0221     else
0222         dev_info(wdev->dev, "secure boot: Error %#02x\n", reg);
0223 }
0224 
0225 static int load_firmware_secure(struct wfx_dev *wdev)
0226 {
0227     const struct firmware *fw = NULL;
0228     int header_size;
0229     int fw_offset;
0230     ktime_t start;
0231     u8 *buf;
0232     int ret;
0233 
0234     BUILD_BUG_ON(PTE_INFO_SIZE > BOOTLOADER_LABEL_SIZE);
0235     buf = kmalloc(BOOTLOADER_LABEL_SIZE + 1, GFP_KERNEL);
0236     if (!buf)
0237         return -ENOMEM;
0238 
0239     wfx_sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_READY);
0240     ret = wait_ncp_status(wdev, NCP_INFO_READY);
0241     if (ret)
0242         goto error;
0243 
0244     wfx_sram_buf_read(wdev, WFX_BOOTLOADER_LABEL, buf, BOOTLOADER_LABEL_SIZE);
0245     buf[BOOTLOADER_LABEL_SIZE] = 0;
0246     dev_dbg(wdev->dev, "bootloader: \"%s\"\n", buf);
0247 
0248     wfx_sram_buf_read(wdev, WFX_PTE_INFO, buf, PTE_INFO_SIZE);
0249     ret = get_firmware(wdev, buf[PTE_INFO_KEYSET_IDX], &fw, &fw_offset);
0250     if (ret)
0251         goto error;
0252     header_size = fw_offset + FW_SIGNATURE_SIZE + FW_HASH_SIZE;
0253 
0254     wfx_sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_INFO_READ);
0255     ret = wait_ncp_status(wdev, NCP_READY);
0256     if (ret)
0257         goto error;
0258 
0259     wfx_sram_reg_write(wdev, WFX_DNLD_FIFO, 0xFFFFFFFF); /* Fifo init */
0260     wfx_sram_write_dma_safe(wdev, WFX_DCA_FW_VERSION, "\x01\x00\x00\x00", FW_VERSION_SIZE);
0261     wfx_sram_write_dma_safe(wdev, WFX_DCA_FW_SIGNATURE, fw->data + fw_offset,
0262                 FW_SIGNATURE_SIZE);
0263     wfx_sram_write_dma_safe(wdev, WFX_DCA_FW_HASH, fw->data + fw_offset + FW_SIGNATURE_SIZE,
0264                 FW_HASH_SIZE);
0265     wfx_sram_reg_write(wdev, WFX_DCA_IMAGE_SIZE, fw->size - header_size);
0266     wfx_sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_UPLOAD_PENDING);
0267     ret = wait_ncp_status(wdev, NCP_DOWNLOAD_PENDING);
0268     if (ret)
0269         goto error;
0270 
0271     start = ktime_get();
0272     ret = upload_firmware(wdev, fw->data + header_size, fw->size - header_size);
0273     if (ret)
0274         goto error;
0275     dev_dbg(wdev->dev, "firmware load after %lldus\n",
0276         ktime_us_delta(ktime_get(), start));
0277 
0278     wfx_sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_UPLOAD_COMPLETE);
0279     ret = wait_ncp_status(wdev, NCP_AUTH_OK);
0280     /* Legacy ROM support */
0281     if (ret < 0)
0282         ret = wait_ncp_status(wdev, NCP_PUB_KEY_RDY);
0283     if (ret < 0)
0284         goto error;
0285     wfx_sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_OK_TO_JUMP);
0286 
0287 error:
0288     kfree(buf);
0289     release_firmware(fw);
0290     if (ret)
0291         print_boot_status(wdev);
0292     return ret;
0293 }
0294 
0295 static int init_gpr(struct wfx_dev *wdev)
0296 {
0297     int ret, i;
0298     static const struct {
0299         int index;
0300         u32 value;
0301     } gpr_init[] = {
0302         { 0x07, 0x208775 },
0303         { 0x08, 0x2EC020 },
0304         { 0x09, 0x3C3C3C },
0305         { 0x0B, 0x322C44 },
0306         { 0x0C, 0xA06497 },
0307     };
0308 
0309     for (i = 0; i < ARRAY_SIZE(gpr_init); i++) {
0310         ret = wfx_igpr_reg_write(wdev, gpr_init[i].index, gpr_init[i].value);
0311         if (ret < 0)
0312             return ret;
0313         dev_dbg(wdev->dev, "  index %02x: %08x\n", gpr_init[i].index, gpr_init[i].value);
0314     }
0315     return 0;
0316 }
0317 
0318 int wfx_init_device(struct wfx_dev *wdev)
0319 {
0320     int ret;
0321     int hw_revision, hw_type;
0322     int wakeup_timeout = 50; /* ms */
0323     ktime_t now, start;
0324     u32 reg;
0325 
0326     reg = CFG_DIRECT_ACCESS_MODE | CFG_CPU_RESET | CFG_BYTE_ORDER_ABCD;
0327     if (wdev->pdata.use_rising_clk)
0328         reg |= CFG_CLK_RISE_EDGE;
0329     ret = wfx_config_reg_write(wdev, reg);
0330     if (ret < 0) {
0331         dev_err(wdev->dev, "bus returned an error during first write access. Host configuration error?\n");
0332         return -EIO;
0333     }
0334 
0335     ret = wfx_config_reg_read(wdev, &reg);
0336     if (ret < 0) {
0337         dev_err(wdev->dev, "bus returned an error during first read access. Bus configuration error?\n");
0338         return -EIO;
0339     }
0340     if (reg == 0 || reg == ~0) {
0341         dev_err(wdev->dev, "chip mute. Bus configuration error or chip wasn't reset?\n");
0342         return -EIO;
0343     }
0344     dev_dbg(wdev->dev, "initial config register value: %08x\n", reg);
0345 
0346     hw_revision = FIELD_GET(CFG_DEVICE_ID_MAJOR, reg);
0347     if (hw_revision == 0) {
0348         dev_err(wdev->dev, "bad hardware revision number: %d\n", hw_revision);
0349         return -ENODEV;
0350     }
0351     hw_type = FIELD_GET(CFG_DEVICE_ID_TYPE, reg);
0352     if (hw_type == 1) {
0353         dev_notice(wdev->dev, "development hardware detected\n");
0354         wakeup_timeout = 2000;
0355     }
0356 
0357     ret = init_gpr(wdev);
0358     if (ret < 0)
0359         return ret;
0360 
0361     ret = wfx_control_reg_write(wdev, CTRL_WLAN_WAKEUP);
0362     if (ret < 0)
0363         return -EIO;
0364     start = ktime_get();
0365     for (;;) {
0366         ret = wfx_control_reg_read(wdev, &reg);
0367         now = ktime_get();
0368         if (reg & CTRL_WLAN_READY)
0369             break;
0370         if (ktime_after(now, ktime_add_ms(start, wakeup_timeout))) {
0371             dev_err(wdev->dev, "chip didn't wake up. Chip wasn't reset?\n");
0372             return -ETIMEDOUT;
0373         }
0374     }
0375     dev_dbg(wdev->dev, "chip wake up after %lldus\n", ktime_us_delta(now, start));
0376 
0377     ret = wfx_config_reg_write_bits(wdev, CFG_CPU_RESET, 0);
0378     if (ret < 0)
0379         return ret;
0380     ret = load_firmware_secure(wdev);
0381     if (ret < 0)
0382         return ret;
0383     return wfx_config_reg_write_bits(wdev,
0384                      CFG_DIRECT_ACCESS_MODE |
0385                      CFG_IRQ_ENABLE_DATA |
0386                      CFG_IRQ_ENABLE_WRDY,
0387                      CFG_IRQ_ENABLE_DATA);
0388 }