xref: /openbmc/linux/drivers/net/wireless/silabs/wfx/fwio.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1  // SPDX-License-Identifier: GPL-2.0-only
2  /*
3   * Firmware loading.
4   *
5   * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
6   * Copyright (c) 2010, ST-Ericsson
7   */
8  #include <linux/firmware.h>
9  #include <linux/slab.h>
10  #include <linux/mm.h>
11  #include <linux/bitfield.h>
12  
13  #include "fwio.h"
14  #include "wfx.h"
15  #include "hwio.h"
16  
17  /* Addresses below are in SRAM area */
18  #define WFX_DNLD_FIFO             0x09004000
19  #define     DNLD_BLOCK_SIZE           0x0400
20  #define     DNLD_FIFO_SIZE            0x8000 /* (32 * DNLD_BLOCK_SIZE) */
21  /* Download Control Area (DCA) */
22  #define WFX_DCA_IMAGE_SIZE        0x0900C000
23  #define WFX_DCA_PUT               0x0900C004
24  #define WFX_DCA_GET               0x0900C008
25  #define WFX_DCA_HOST_STATUS       0x0900C00C
26  #define     HOST_READY                0x87654321
27  #define     HOST_INFO_READ            0xA753BD99
28  #define     HOST_UPLOAD_PENDING       0xABCDDCBA
29  #define     HOST_UPLOAD_COMPLETE      0xD4C64A99
30  #define     HOST_OK_TO_JUMP           0x174FC882
31  #define WFX_DCA_NCP_STATUS        0x0900C010
32  #define     NCP_NOT_READY             0x12345678
33  #define     NCP_READY                 0x87654321
34  #define     NCP_INFO_READY            0xBD53EF99
35  #define     NCP_DOWNLOAD_PENDING      0xABCDDCBA
36  #define     NCP_DOWNLOAD_COMPLETE     0xCAFEFECA
37  #define     NCP_AUTH_OK               0xD4C64A99
38  #define     NCP_AUTH_FAIL             0x174FC882
39  #define     NCP_PUB_KEY_RDY           0x7AB41D19
40  #define WFX_DCA_FW_SIGNATURE      0x0900C014
41  #define     FW_SIGNATURE_SIZE         0x40
42  #define WFX_DCA_FW_HASH           0x0900C054
43  #define     FW_HASH_SIZE              0x08
44  #define WFX_DCA_FW_VERSION        0x0900C05C
45  #define     FW_VERSION_SIZE           0x04
46  #define WFX_DCA_RESERVED          0x0900C060
47  #define     DCA_RESERVED_SIZE         0x20
48  #define WFX_STATUS_INFO           0x0900C080
49  #define WFX_BOOTLOADER_LABEL      0x0900C084
50  #define     BOOTLOADER_LABEL_SIZE     0x3C
51  #define WFX_PTE_INFO              0x0900C0C0
52  #define     PTE_INFO_KEYSET_IDX       0x0D
53  #define     PTE_INFO_SIZE             0x10
54  #define WFX_ERR_INFO              0x0900C0D0
55  #define     ERR_INVALID_SEC_TYPE      0x05
56  #define     ERR_SIG_VERIF_FAILED      0x0F
57  #define     ERR_AES_CTRL_KEY          0x10
58  #define     ERR_ECC_PUB_KEY           0x11
59  #define     ERR_MAC_KEY               0x18
60  
61  #define DCA_TIMEOUT  50 /* milliseconds */
62  #define WAKEUP_TIMEOUT 200 /* milliseconds */
63  
64  static const char * const fwio_errors[] = {
65  	[ERR_INVALID_SEC_TYPE] = "Invalid section type or wrong encryption",
66  	[ERR_SIG_VERIF_FAILED] = "Signature verification failed",
67  	[ERR_AES_CTRL_KEY]     = "AES control key not initialized",
68  	[ERR_ECC_PUB_KEY]      = "ECC public key not initialized",
69  	[ERR_MAC_KEY]          = "MAC key not initialized",
70  };
71  
72  /* request_firmware() allocate data using vmalloc(). It is not compatible with underlying hardware
73   * that use DMA. Function below detect this case and allocate a bounce buffer if necessary.
74   *
75   * Notice that, in doubt, you can enable CONFIG_DEBUG_SG to ask kernel to detect this problem at
76   * runtime  (else, kernel silently fail).
77   *
78   * NOTE: it may also be possible to use 'pages' from struct firmware and avoid bounce buffer
79   */
wfx_sram_write_dma_safe(struct wfx_dev * wdev,u32 addr,const u8 * buf,size_t len)80  static int wfx_sram_write_dma_safe(struct wfx_dev *wdev, u32 addr, const u8 *buf, size_t len)
81  {
82  	int ret;
83  	const u8 *tmp;
84  
85  	if (!virt_addr_valid(buf)) {
86  		tmp = kmemdup(buf, len, GFP_KERNEL);
87  		if (!tmp)
88  			return -ENOMEM;
89  	} else {
90  		tmp = buf;
91  	}
92  	ret = wfx_sram_buf_write(wdev, addr, tmp, len);
93  	if (tmp != buf)
94  		kfree(tmp);
95  	return ret;
96  }
97  
get_firmware(struct wfx_dev * wdev,u32 keyset_chip,const struct firmware ** fw,int * file_offset)98  static int get_firmware(struct wfx_dev *wdev, u32 keyset_chip,
99  			const struct firmware **fw, int *file_offset)
100  {
101  	int keyset_file;
102  	char filename[256];
103  	const char *data;
104  	int ret;
105  
106  	snprintf(filename, sizeof(filename), "%s_%02X.sec",
107  		 wdev->pdata.file_fw, keyset_chip);
108  	ret = firmware_request_nowarn(fw, filename, wdev->dev);
109  	if (ret) {
110  		dev_info(wdev->dev, "can't load %s, falling back to %s.sec\n",
111  			 filename, wdev->pdata.file_fw);
112  		snprintf(filename, sizeof(filename), "%s.sec", wdev->pdata.file_fw);
113  		ret = request_firmware(fw, filename, wdev->dev);
114  		if (ret) {
115  			dev_err(wdev->dev, "can't load %s\n", filename);
116  			*fw = NULL;
117  			return ret;
118  		}
119  	}
120  
121  	data = (*fw)->data;
122  	if (memcmp(data, "KEYSET", 6) != 0) {
123  		/* Legacy firmware format */
124  		*file_offset = 0;
125  		keyset_file = 0x90;
126  	} else {
127  		*file_offset = 8;
128  		keyset_file = (hex_to_bin(data[6]) * 16) | hex_to_bin(data[7]);
129  		if (keyset_file < 0) {
130  			dev_err(wdev->dev, "%s corrupted\n", filename);
131  			release_firmware(*fw);
132  			*fw = NULL;
133  			return -EINVAL;
134  		}
135  	}
136  	if (keyset_file != keyset_chip) {
137  		dev_err(wdev->dev, "firmware keyset is incompatible with chip (file: 0x%02X, chip: 0x%02X)\n",
138  			keyset_file, keyset_chip);
139  		release_firmware(*fw);
140  		*fw = NULL;
141  		return -ENODEV;
142  	}
143  	wdev->keyset = keyset_file;
144  	return 0;
145  }
146  
wait_ncp_status(struct wfx_dev * wdev,u32 status)147  static int wait_ncp_status(struct wfx_dev *wdev, u32 status)
148  {
149  	ktime_t now, start;
150  	u32 reg;
151  	int ret;
152  
153  	start = ktime_get();
154  	for (;;) {
155  		ret = wfx_sram_reg_read(wdev, WFX_DCA_NCP_STATUS, &reg);
156  		if (ret < 0)
157  			return -EIO;
158  		now = ktime_get();
159  		if (reg == status)
160  			break;
161  		if (ktime_after(now, ktime_add_ms(start, DCA_TIMEOUT)))
162  			return -ETIMEDOUT;
163  	}
164  	if (ktime_compare(now, start))
165  		dev_dbg(wdev->dev, "chip answer after %lldus\n", ktime_us_delta(now, start));
166  	else
167  		dev_dbg(wdev->dev, "chip answer immediately\n");
168  	return 0;
169  }
170  
upload_firmware(struct wfx_dev * wdev,const u8 * data,size_t len)171  static int upload_firmware(struct wfx_dev *wdev, const u8 *data, size_t len)
172  {
173  	int ret;
174  	u32 offs, bytes_done = 0;
175  	ktime_t now, start;
176  
177  	if (len % DNLD_BLOCK_SIZE) {
178  		dev_err(wdev->dev, "firmware size is not aligned. Buffer overrun will occur\n");
179  		return -EIO;
180  	}
181  	offs = 0;
182  	while (offs < len) {
183  		start = ktime_get();
184  		for (;;) {
185  			now = ktime_get();
186  			if (offs + DNLD_BLOCK_SIZE - bytes_done < DNLD_FIFO_SIZE)
187  				break;
188  			if (ktime_after(now, ktime_add_ms(start, DCA_TIMEOUT)))
189  				return -ETIMEDOUT;
190  			ret = wfx_sram_reg_read(wdev, WFX_DCA_GET, &bytes_done);
191  			if (ret < 0)
192  				return ret;
193  		}
194  		if (ktime_compare(now, start))
195  			dev_dbg(wdev->dev, "answer after %lldus\n", ktime_us_delta(now, start));
196  
197  		ret = wfx_sram_write_dma_safe(wdev, WFX_DNLD_FIFO + (offs % DNLD_FIFO_SIZE),
198  					      data + offs, DNLD_BLOCK_SIZE);
199  		if (ret < 0)
200  			return ret;
201  
202  		/* The device seems to not support writing 0 in this register during first loop */
203  		offs += DNLD_BLOCK_SIZE;
204  		ret = wfx_sram_reg_write(wdev, WFX_DCA_PUT, offs);
205  		if (ret < 0)
206  			return ret;
207  	}
208  	return 0;
209  }
210  
print_boot_status(struct wfx_dev * wdev)211  static void print_boot_status(struct wfx_dev *wdev)
212  {
213  	u32 reg;
214  
215  	wfx_sram_reg_read(wdev, WFX_STATUS_INFO, &reg);
216  	if (reg == 0x12345678)
217  		return;
218  	wfx_sram_reg_read(wdev, WFX_ERR_INFO, &reg);
219  	if (reg < ARRAY_SIZE(fwio_errors) && fwio_errors[reg])
220  		dev_info(wdev->dev, "secure boot: %s\n", fwio_errors[reg]);
221  	else
222  		dev_info(wdev->dev, "secure boot: Error %#02x\n", reg);
223  }
224  
load_firmware_secure(struct wfx_dev * wdev)225  static int load_firmware_secure(struct wfx_dev *wdev)
226  {
227  	const struct firmware *fw = NULL;
228  	int header_size;
229  	int fw_offset;
230  	ktime_t start;
231  	u8 *buf;
232  	int ret;
233  
234  	BUILD_BUG_ON(PTE_INFO_SIZE > BOOTLOADER_LABEL_SIZE);
235  	buf = kmalloc(BOOTLOADER_LABEL_SIZE + 1, GFP_KERNEL);
236  	if (!buf)
237  		return -ENOMEM;
238  
239  	wfx_sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_READY);
240  	ret = wait_ncp_status(wdev, NCP_INFO_READY);
241  	if (ret)
242  		goto error;
243  
244  	wfx_sram_buf_read(wdev, WFX_BOOTLOADER_LABEL, buf, BOOTLOADER_LABEL_SIZE);
245  	buf[BOOTLOADER_LABEL_SIZE] = 0;
246  	dev_dbg(wdev->dev, "bootloader: \"%s\"\n", buf);
247  
248  	wfx_sram_buf_read(wdev, WFX_PTE_INFO, buf, PTE_INFO_SIZE);
249  	ret = get_firmware(wdev, buf[PTE_INFO_KEYSET_IDX], &fw, &fw_offset);
250  	if (ret)
251  		goto error;
252  	header_size = fw_offset + FW_SIGNATURE_SIZE + FW_HASH_SIZE;
253  
254  	wfx_sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_INFO_READ);
255  	ret = wait_ncp_status(wdev, NCP_READY);
256  	if (ret)
257  		goto error;
258  
259  	wfx_sram_reg_write(wdev, WFX_DNLD_FIFO, 0xFFFFFFFF); /* Fifo init */
260  	wfx_sram_write_dma_safe(wdev, WFX_DCA_FW_VERSION, "\x01\x00\x00\x00", FW_VERSION_SIZE);
261  	wfx_sram_write_dma_safe(wdev, WFX_DCA_FW_SIGNATURE, fw->data + fw_offset,
262  				FW_SIGNATURE_SIZE);
263  	wfx_sram_write_dma_safe(wdev, WFX_DCA_FW_HASH, fw->data + fw_offset + FW_SIGNATURE_SIZE,
264  				FW_HASH_SIZE);
265  	wfx_sram_reg_write(wdev, WFX_DCA_IMAGE_SIZE, fw->size - header_size);
266  	wfx_sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_UPLOAD_PENDING);
267  	ret = wait_ncp_status(wdev, NCP_DOWNLOAD_PENDING);
268  	if (ret)
269  		goto error;
270  
271  	start = ktime_get();
272  	ret = upload_firmware(wdev, fw->data + header_size, fw->size - header_size);
273  	if (ret)
274  		goto error;
275  	dev_dbg(wdev->dev, "firmware load after %lldus\n",
276  		ktime_us_delta(ktime_get(), start));
277  
278  	wfx_sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_UPLOAD_COMPLETE);
279  	ret = wait_ncp_status(wdev, NCP_AUTH_OK);
280  	/* Legacy ROM support */
281  	if (ret < 0)
282  		ret = wait_ncp_status(wdev, NCP_PUB_KEY_RDY);
283  	if (ret < 0)
284  		goto error;
285  	wfx_sram_reg_write(wdev, WFX_DCA_HOST_STATUS, HOST_OK_TO_JUMP);
286  
287  error:
288  	kfree(buf);
289  	release_firmware(fw);
290  	if (ret)
291  		print_boot_status(wdev);
292  	return ret;
293  }
294  
init_gpr(struct wfx_dev * wdev)295  static int init_gpr(struct wfx_dev *wdev)
296  {
297  	int ret, i;
298  	static const struct {
299  		int index;
300  		u32 value;
301  	} gpr_init[] = {
302  		{ 0x07, 0x208775 },
303  		{ 0x08, 0x2EC020 },
304  		{ 0x09, 0x3C3C3C },
305  		{ 0x0B, 0x322C44 },
306  		{ 0x0C, 0xA06497 },
307  	};
308  
309  	for (i = 0; i < ARRAY_SIZE(gpr_init); i++) {
310  		ret = wfx_igpr_reg_write(wdev, gpr_init[i].index, gpr_init[i].value);
311  		if (ret < 0)
312  			return ret;
313  		dev_dbg(wdev->dev, "  index %02x: %08x\n", gpr_init[i].index, gpr_init[i].value);
314  	}
315  	return 0;
316  }
317  
wfx_init_device(struct wfx_dev * wdev)318  int wfx_init_device(struct wfx_dev *wdev)
319  {
320  	int ret;
321  	int hw_revision, hw_type;
322  	int wakeup_timeout = 50; /* ms */
323  	ktime_t now, start;
324  	u32 reg;
325  
326  	reg = CFG_DIRECT_ACCESS_MODE | CFG_CPU_RESET | CFG_BYTE_ORDER_ABCD;
327  	if (wdev->pdata.use_rising_clk)
328  		reg |= CFG_CLK_RISE_EDGE;
329  	ret = wfx_config_reg_write(wdev, reg);
330  	if (ret < 0) {
331  		dev_err(wdev->dev, "bus returned an error during first write access. Host configuration error?\n");
332  		return -EIO;
333  	}
334  
335  	ret = wfx_config_reg_read(wdev, &reg);
336  	if (ret < 0) {
337  		dev_err(wdev->dev, "bus returned an error during first read access. Bus configuration error?\n");
338  		return -EIO;
339  	}
340  	if (reg == 0 || reg == ~0) {
341  		dev_err(wdev->dev, "chip mute. Bus configuration error or chip wasn't reset?\n");
342  		return -EIO;
343  	}
344  	dev_dbg(wdev->dev, "initial config register value: %08x\n", reg);
345  
346  	hw_revision = FIELD_GET(CFG_DEVICE_ID_MAJOR, reg);
347  	if (hw_revision == 0) {
348  		dev_err(wdev->dev, "bad hardware revision number: %d\n", hw_revision);
349  		return -ENODEV;
350  	}
351  	hw_type = FIELD_GET(CFG_DEVICE_ID_TYPE, reg);
352  	if (hw_type == 1) {
353  		dev_notice(wdev->dev, "development hardware detected\n");
354  		wakeup_timeout = 2000;
355  	}
356  
357  	ret = init_gpr(wdev);
358  	if (ret < 0)
359  		return ret;
360  
361  	ret = wfx_control_reg_write(wdev, CTRL_WLAN_WAKEUP);
362  	if (ret < 0)
363  		return -EIO;
364  	start = ktime_get();
365  	for (;;) {
366  		ret = wfx_control_reg_read(wdev, &reg);
367  		now = ktime_get();
368  		if (reg & CTRL_WLAN_READY)
369  			break;
370  		if (ktime_after(now, ktime_add_ms(start, wakeup_timeout))) {
371  			dev_err(wdev->dev, "chip didn't wake up. Chip wasn't reset?\n");
372  			return -ETIMEDOUT;
373  		}
374  	}
375  	dev_dbg(wdev->dev, "chip wake up after %lldus\n", ktime_us_delta(now, start));
376  
377  	ret = wfx_config_reg_write_bits(wdev, CFG_CPU_RESET, 0);
378  	if (ret < 0)
379  		return ret;
380  	ret = load_firmware_secure(wdev);
381  	if (ret < 0)
382  		return ret;
383  	return wfx_config_reg_write_bits(wdev,
384  					 CFG_DIRECT_ACCESS_MODE |
385  					 CFG_IRQ_ENABLE_DATA |
386  					 CFG_IRQ_ENABLE_WRDY,
387  					 CFG_IRQ_ENABLE_DATA);
388  }
389