linux/drivers/net/wireless/st/cw1200/fwio.c
<<
>>
Prefs
   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}
 524