cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fwio.c (12377B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Firmware I/O code for mac80211 ST-Ericsson CW1200 drivers
      4 *
      5 * Copyright (c) 2010, ST-Ericsson
      6 * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
      7 *
      8 * Based on:
      9 * ST-Ericsson UMAC CW1200 driver which is
     10 * Copyright (c) 2010, ST-Ericsson
     11 * Author: Ajitpal Singh <ajitpal.singh@stericsson.com>
     12 */
     13
     14#include <linux/vmalloc.h>
     15#include <linux/sched.h>
     16#include <linux/firmware.h>
     17
     18#include "cw1200.h"
     19#include "fwio.h"
     20#include "hwio.h"
     21#include "hwbus.h"
     22#include "bh.h"
     23
     24static int cw1200_get_hw_type(u32 config_reg_val, int *major_revision)
     25{
     26	int hw_type = -1;
     27	u32 silicon_type = (config_reg_val >> 24) & 0x7;
     28	u32 silicon_vers = (config_reg_val >> 31) & 0x1;
     29
     30	switch (silicon_type) {
     31	case 0x00:
     32		*major_revision = 1;
     33		hw_type = HIF_9000_SILICON_VERSATILE;
     34		break;
     35	case 0x01:
     36	case 0x02: /* CW1x00 */
     37	case 0x04: /* CW1x60 */
     38		*major_revision = silicon_type;
     39		if (silicon_vers)
     40			hw_type = HIF_8601_VERSATILE;
     41		else
     42			hw_type = HIF_8601_SILICON;
     43		break;
     44	default:
     45		break;
     46	}
     47
     48	return hw_type;
     49}
     50
     51static int cw1200_load_firmware_cw1200(struct cw1200_common *priv)
     52{
     53	int ret, block, num_blocks;
     54	unsigned i;
     55	u32 val32;
     56	u32 put = 0, get = 0;
     57	u8 *buf = NULL;
     58	const char *fw_path;
     59	const struct firmware *firmware = NULL;
     60
     61	/* Macroses are local. */
     62#define APB_WRITE(reg, val) \
     63	do { \
     64		ret = cw1200_apb_write_32(priv, CW1200_APB(reg), (val)); \
     65		if (ret < 0) \
     66			goto exit; \
     67	} while (0)
     68#define APB_WRITE2(reg, val) \
     69	do { \
     70		ret = cw1200_apb_write_32(priv, CW1200_APB(reg), (val)); \
     71		if (ret < 0) \
     72			goto free_buffer; \
     73	} while (0)
     74#define APB_READ(reg, val) \
     75	do { \
     76		ret = cw1200_apb_read_32(priv, CW1200_APB(reg), &(val)); \
     77		if (ret < 0) \
     78			goto free_buffer; \
     79	} while (0)
     80#define REG_WRITE(reg, val) \
     81	do { \
     82		ret = cw1200_reg_write_32(priv, (reg), (val)); \
     83		if (ret < 0) \
     84			goto exit; \
     85	} while (0)
     86#define REG_READ(reg, val) \
     87	do { \
     88		ret = cw1200_reg_read_32(priv, (reg), &(val)); \
     89		if (ret < 0) \
     90			goto exit; \
     91	} while (0)
     92
     93	switch (priv->hw_revision) {
     94	case CW1200_HW_REV_CUT10:
     95		fw_path = FIRMWARE_CUT10;
     96		if (!priv->sdd_path)
     97			priv->sdd_path = SDD_FILE_10;
     98		break;
     99	case CW1200_HW_REV_CUT11:
    100		fw_path = FIRMWARE_CUT11;
    101		if (!priv->sdd_path)
    102			priv->sdd_path = SDD_FILE_11;
    103		break;
    104	case CW1200_HW_REV_CUT20:
    105		fw_path = FIRMWARE_CUT20;
    106		if (!priv->sdd_path)
    107			priv->sdd_path = SDD_FILE_20;
    108		break;
    109	case CW1200_HW_REV_CUT22:
    110		fw_path = FIRMWARE_CUT22;
    111		if (!priv->sdd_path)
    112			priv->sdd_path = SDD_FILE_22;
    113		break;
    114	case CW1X60_HW_REV:
    115		fw_path = FIRMWARE_CW1X60;
    116		if (!priv->sdd_path)
    117			priv->sdd_path = SDD_FILE_CW1X60;
    118		break;
    119	default:
    120		pr_err("Invalid silicon revision %d.\n", priv->hw_revision);
    121		return -EINVAL;
    122	}
    123
    124	/* Initialize common registers */
    125	APB_WRITE(DOWNLOAD_IMAGE_SIZE_REG, DOWNLOAD_ARE_YOU_HERE);
    126	APB_WRITE(DOWNLOAD_PUT_REG, 0);
    127	APB_WRITE(DOWNLOAD_GET_REG, 0);
    128	APB_WRITE(DOWNLOAD_STATUS_REG, DOWNLOAD_PENDING);
    129	APB_WRITE(DOWNLOAD_FLAGS_REG, 0);
    130
    131	/* Write the NOP Instruction */
    132	REG_WRITE(ST90TDS_SRAM_BASE_ADDR_REG_ID, 0xFFF20000);
    133	REG_WRITE(ST90TDS_AHB_DPORT_REG_ID, 0xEAFFFFFE);
    134
    135	/* Release CPU from RESET */
    136	REG_READ(ST90TDS_CONFIG_REG_ID, val32);
    137	val32 &= ~ST90TDS_CONFIG_CPU_RESET_BIT;
    138	REG_WRITE(ST90TDS_CONFIG_REG_ID, val32);
    139
    140	/* Enable Clock */
    141	val32 &= ~ST90TDS_CONFIG_CPU_CLK_DIS_BIT;
    142	REG_WRITE(ST90TDS_CONFIG_REG_ID, val32);
    143
    144	/* Load a firmware file */
    145	ret = request_firmware(&firmware, fw_path, priv->pdev);
    146	if (ret) {
    147		pr_err("Can't load firmware file %s.\n", fw_path);
    148		goto exit;
    149	}
    150
    151	buf = kmalloc(DOWNLOAD_BLOCK_SIZE, GFP_KERNEL | GFP_DMA);
    152	if (!buf) {
    153		pr_err("Can't allocate firmware load buffer.\n");
    154		ret = -ENOMEM;
    155		goto firmware_release;
    156	}
    157
    158	/* Check if the bootloader is ready */
    159	for (i = 0; i < 100; i += 1 + i / 2) {
    160		APB_READ(DOWNLOAD_IMAGE_SIZE_REG, val32);
    161		if (val32 == DOWNLOAD_I_AM_HERE)
    162			break;
    163		mdelay(i);
    164	} /* End of for loop */
    165
    166	if (val32 != DOWNLOAD_I_AM_HERE) {
    167		pr_err("Bootloader is not ready.\n");
    168		ret = -ETIMEDOUT;
    169		goto free_buffer;
    170	}
    171
    172	/* Calculcate number of download blocks */
    173	num_blocks = (firmware->size - 1) / DOWNLOAD_BLOCK_SIZE + 1;
    174
    175	/* Updating the length in Download Ctrl Area */
    176	val32 = firmware->size; /* Explicit cast from size_t to u32 */
    177	APB_WRITE2(DOWNLOAD_IMAGE_SIZE_REG, val32);
    178
    179	/* Firmware downloading loop */
    180	for (block = 0; block < num_blocks; block++) {
    181		size_t tx_size;
    182		size_t block_size;
    183
    184		/* check the download status */
    185		APB_READ(DOWNLOAD_STATUS_REG, val32);
    186		if (val32 != DOWNLOAD_PENDING) {
    187			pr_err("Bootloader reported error %d.\n", val32);
    188			ret = -EIO;
    189			goto free_buffer;
    190		}
    191
    192		/* loop until put - get <= 24K */
    193		for (i = 0; i < 100; i++) {
    194			APB_READ(DOWNLOAD_GET_REG, get);
    195			if ((put - get) <=
    196			    (DOWNLOAD_FIFO_SIZE - DOWNLOAD_BLOCK_SIZE))
    197				break;
    198			mdelay(i);
    199		}
    200
    201		if ((put - get) > (DOWNLOAD_FIFO_SIZE - DOWNLOAD_BLOCK_SIZE)) {
    202			pr_err("Timeout waiting for FIFO.\n");
    203			ret = -ETIMEDOUT;
    204			goto free_buffer;
    205		}
    206
    207		/* calculate the block size */
    208		tx_size = block_size = min_t(size_t, firmware->size - put,
    209					DOWNLOAD_BLOCK_SIZE);
    210
    211		memcpy(buf, &firmware->data[put], block_size);
    212		if (block_size < DOWNLOAD_BLOCK_SIZE) {
    213			memset(&buf[block_size], 0,
    214			       DOWNLOAD_BLOCK_SIZE - block_size);
    215			tx_size = DOWNLOAD_BLOCK_SIZE;
    216		}
    217
    218		/* send the block to sram */
    219		ret = cw1200_apb_write(priv,
    220			CW1200_APB(DOWNLOAD_FIFO_OFFSET +
    221				   (put & (DOWNLOAD_FIFO_SIZE - 1))),
    222			buf, tx_size);
    223		if (ret < 0) {
    224			pr_err("Can't write firmware block @ %d!\n",
    225			       put & (DOWNLOAD_FIFO_SIZE - 1));
    226			goto free_buffer;
    227		}
    228
    229		/* update the put register */
    230		put += block_size;
    231		APB_WRITE2(DOWNLOAD_PUT_REG, put);
    232	} /* End of firmware download loop */
    233
    234	/* Wait for the download completion */
    235	for (i = 0; i < 300; i += 1 + i / 2) {
    236		APB_READ(DOWNLOAD_STATUS_REG, val32);
    237		if (val32 != DOWNLOAD_PENDING)
    238			break;
    239		mdelay(i);
    240	}
    241	if (val32 != DOWNLOAD_SUCCESS) {
    242		pr_err("Wait for download completion failed: 0x%.8X\n", val32);
    243		ret = -ETIMEDOUT;
    244		goto free_buffer;
    245	} else {
    246		pr_info("Firmware download completed.\n");
    247		ret = 0;
    248	}
    249
    250free_buffer:
    251	kfree(buf);
    252firmware_release:
    253	release_firmware(firmware);
    254exit:
    255	return ret;
    256
    257#undef APB_WRITE
    258#undef APB_WRITE2
    259#undef APB_READ
    260#undef REG_WRITE
    261#undef REG_READ
    262}
    263
    264
    265static int config_reg_read(struct cw1200_common *priv, u32 *val)
    266{
    267	switch (priv->hw_type) {
    268	case HIF_9000_SILICON_VERSATILE: {
    269		u16 val16;
    270		int ret = cw1200_reg_read_16(priv,
    271					     ST90TDS_CONFIG_REG_ID,
    272					     &val16);
    273		if (ret < 0)
    274			return ret;
    275		*val = val16;
    276		return 0;
    277	}
    278	case HIF_8601_VERSATILE:
    279	case HIF_8601_SILICON:
    280	default:
    281		cw1200_reg_read_32(priv, ST90TDS_CONFIG_REG_ID, val);
    282		break;
    283	}
    284	return 0;
    285}
    286
    287static int config_reg_write(struct cw1200_common *priv, u32 val)
    288{
    289	switch (priv->hw_type) {
    290	case HIF_9000_SILICON_VERSATILE:
    291		return cw1200_reg_write_16(priv,
    292					   ST90TDS_CONFIG_REG_ID,
    293					   (u16)val);
    294	case HIF_8601_VERSATILE:
    295	case HIF_8601_SILICON:
    296	default:
    297		return cw1200_reg_write_32(priv, ST90TDS_CONFIG_REG_ID, val);
    298	}
    299	return 0;
    300}
    301
    302int cw1200_load_firmware(struct cw1200_common *priv)
    303{
    304	int ret;
    305	int i;
    306	u32 val32;
    307	u16 val16;
    308	int major_revision = -1;
    309
    310	/* Read CONFIG Register */
    311	ret = cw1200_reg_read_32(priv, ST90TDS_CONFIG_REG_ID, &val32);
    312	if (ret < 0) {
    313		pr_err("Can't read config register.\n");
    314		goto out;
    315	}
    316
    317	if (val32 == 0 || val32 == 0xffffffff) {
    318		pr_err("Bad config register value (0x%08x)\n", val32);
    319		ret = -EIO;
    320		goto out;
    321	}
    322
    323	ret = cw1200_get_hw_type(val32, &major_revision);
    324	if (ret < 0) {
    325		pr_err("Can't deduce hardware type.\n");
    326		goto out;
    327	}
    328	priv->hw_type = ret;
    329
    330	/* Set DPLL Reg value, and read back to confirm writes work */
    331	ret = cw1200_reg_write_32(priv, ST90TDS_TSET_GEN_R_W_REG_ID,
    332				  cw1200_dpll_from_clk(priv->hw_refclk));
    333	if (ret < 0) {
    334		pr_err("Can't write DPLL register.\n");
    335		goto out;
    336	}
    337
    338	msleep(20);
    339
    340	ret = cw1200_reg_read_32(priv,
    341		ST90TDS_TSET_GEN_R_W_REG_ID, &val32);
    342	if (ret < 0) {
    343		pr_err("Can't read DPLL register.\n");
    344		goto out;
    345	}
    346
    347	if (val32 != cw1200_dpll_from_clk(priv->hw_refclk)) {
    348		pr_err("Unable to initialise DPLL register. Wrote 0x%.8X, Read 0x%.8X.\n",
    349		       cw1200_dpll_from_clk(priv->hw_refclk), val32);
    350		ret = -EIO;
    351		goto out;
    352	}
    353
    354	/* Set wakeup bit in device */
    355	ret = cw1200_reg_read_16(priv, ST90TDS_CONTROL_REG_ID, &val16);
    356	if (ret < 0) {
    357		pr_err("set_wakeup: can't read control register.\n");
    358		goto out;
    359	}
    360
    361	ret = cw1200_reg_write_16(priv, ST90TDS_CONTROL_REG_ID,
    362		val16 | ST90TDS_CONT_WUP_BIT);
    363	if (ret < 0) {
    364		pr_err("set_wakeup: can't write control register.\n");
    365		goto out;
    366	}
    367
    368	/* Wait for wakeup */
    369	for (i = 0; i < 300; i += (1 + i / 2)) {
    370		ret = cw1200_reg_read_16(priv,
    371			ST90TDS_CONTROL_REG_ID, &val16);
    372		if (ret < 0) {
    373			pr_err("wait_for_wakeup: can't read control register.\n");
    374			goto out;
    375		}
    376
    377		if (val16 & ST90TDS_CONT_RDY_BIT)
    378			break;
    379
    380		msleep(i);
    381	}
    382
    383	if ((val16 & ST90TDS_CONT_RDY_BIT) == 0) {
    384		pr_err("wait_for_wakeup: device is not responding.\n");
    385		ret = -ETIMEDOUT;
    386		goto out;
    387	}
    388
    389	switch (major_revision) {
    390	case 1:
    391		/* CW1200 Hardware detection logic : Check for CUT1.1 */
    392		ret = cw1200_ahb_read_32(priv, CW1200_CUT_ID_ADDR, &val32);
    393		if (ret) {
    394			pr_err("HW detection: can't read CUT ID.\n");
    395			goto out;
    396		}
    397
    398		switch (val32) {
    399		case CW1200_CUT_11_ID_STR:
    400			pr_info("CW1x00 Cut 1.1 silicon detected.\n");
    401			priv->hw_revision = CW1200_HW_REV_CUT11;
    402			break;
    403		default:
    404			pr_info("CW1x00 Cut 1.0 silicon detected.\n");
    405			priv->hw_revision = CW1200_HW_REV_CUT10;
    406			break;
    407		}
    408
    409		/* According to ST-E, CUT<2.0 has busted BA TID0-3.
    410		   Just disable it entirely...
    411		*/
    412		priv->ba_rx_tid_mask = 0;
    413		priv->ba_tx_tid_mask = 0;
    414		break;
    415	case 2: {
    416		u32 ar1, ar2, ar3;
    417		ret = cw1200_ahb_read_32(priv, CW1200_CUT2_ID_ADDR, &ar1);
    418		if (ret) {
    419			pr_err("(1) HW detection: can't read CUT ID\n");
    420			goto out;
    421		}
    422		ret = cw1200_ahb_read_32(priv, CW1200_CUT2_ID_ADDR + 4, &ar2);
    423		if (ret) {
    424			pr_err("(2) HW detection: can't read CUT ID.\n");
    425			goto out;
    426		}
    427
    428		ret = cw1200_ahb_read_32(priv, CW1200_CUT2_ID_ADDR + 8, &ar3);
    429		if (ret) {
    430			pr_err("(3) HW detection: can't read CUT ID.\n");
    431			goto out;
    432		}
    433
    434		if (ar1 == CW1200_CUT_22_ID_STR1 &&
    435		    ar2 == CW1200_CUT_22_ID_STR2 &&
    436		    ar3 == CW1200_CUT_22_ID_STR3) {
    437			pr_info("CW1x00 Cut 2.2 silicon detected.\n");
    438			priv->hw_revision = CW1200_HW_REV_CUT22;
    439		} else {
    440			pr_info("CW1x00 Cut 2.0 silicon detected.\n");
    441			priv->hw_revision = CW1200_HW_REV_CUT20;
    442		}
    443		break;
    444	}
    445	case 4:
    446		pr_info("CW1x60 silicon detected.\n");
    447		priv->hw_revision = CW1X60_HW_REV;
    448		break;
    449	default:
    450		pr_err("Unsupported silicon major revision %d.\n",
    451		       major_revision);
    452		ret = -ENOTSUPP;
    453		goto out;
    454	}
    455
    456	/* Checking for access mode */
    457	ret = config_reg_read(priv, &val32);
    458	if (ret < 0) {
    459		pr_err("Can't read config register.\n");
    460		goto out;
    461	}
    462
    463	if (!(val32 & ST90TDS_CONFIG_ACCESS_MODE_BIT)) {
    464		pr_err("Device is already in QUEUE mode!\n");
    465		ret = -EINVAL;
    466		goto out;
    467	}
    468
    469	switch (priv->hw_type)  {
    470	case HIF_8601_SILICON:
    471		if (priv->hw_revision == CW1X60_HW_REV) {
    472			pr_err("Can't handle CW1160/1260 firmware load yet.\n");
    473			ret = -ENOTSUPP;
    474			goto out;
    475		}
    476		ret = cw1200_load_firmware_cw1200(priv);
    477		break;
    478	default:
    479		pr_err("Can't perform firmware load for hw type %d.\n",
    480		       priv->hw_type);
    481		ret = -ENOTSUPP;
    482		goto out;
    483	}
    484	if (ret < 0) {
    485		pr_err("Firmware load error.\n");
    486		goto out;
    487	}
    488
    489	/* Enable interrupt signalling */
    490	priv->hwbus_ops->lock(priv->hwbus_priv);
    491	ret = __cw1200_irq_enable(priv, 1);
    492	priv->hwbus_ops->unlock(priv->hwbus_priv);
    493	if (ret < 0)
    494		goto unsubscribe;
    495
    496	/* Configure device for MESSSAGE MODE */
    497	ret = config_reg_read(priv, &val32);
    498	if (ret < 0) {
    499		pr_err("Can't read config register.\n");
    500		goto unsubscribe;
    501	}
    502	ret = config_reg_write(priv, val32 & ~ST90TDS_CONFIG_ACCESS_MODE_BIT);
    503	if (ret < 0) {
    504		pr_err("Can't write config register.\n");
    505		goto unsubscribe;
    506	}
    507
    508	/* Unless we read the CONFIG Register we are
    509	 * not able to get an interrupt
    510	 */
    511	mdelay(10);
    512	config_reg_read(priv, &val32);
    513
    514out:
    515	return ret;
    516
    517unsubscribe:
    518	/* Disable interrupt signalling */
    519	priv->hwbus_ops->lock(priv->hwbus_priv);
    520	ret = __cw1200_irq_enable(priv, 0);
    521	priv->hwbus_ops->unlock(priv->hwbus_priv);
    522	return ret;
    523}