uboot/drivers/qe/qe.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2006-2009 Freescale Semiconductor, Inc.
   3 *
   4 * Dave Liu <daveliu@freescale.com>
   5 * based on source code of Shlomi Gridish
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public License as
   9 * published by the Free Software Foundation; either version 2 of
  10 * the License, or (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20 * MA 02111-1307 USA
  21 */
  22
  23#include "common.h"
  24#include <command.h>
  25#include "asm/errno.h"
  26#include "asm/io.h"
  27#include "asm/immap_qe.h"
  28#include "qe.h"
  29
  30qe_map_t                *qe_immr = NULL;
  31static qe_snum_t        snums[QE_NUM_OF_SNUM];
  32
  33DECLARE_GLOBAL_DATA_PTR;
  34
  35void qe_issue_cmd(uint cmd, uint sbc, u8 mcn, u32 cmd_data)
  36{
  37        u32 cecr;
  38
  39        if (cmd == QE_RESET) {
  40                out_be32(&qe_immr->cp.cecr,(u32) (cmd | QE_CR_FLG));
  41        } else {
  42                out_be32(&qe_immr->cp.cecdr, cmd_data);
  43                out_be32(&qe_immr->cp.cecr, (sbc | QE_CR_FLG |
  44                         ((u32) mcn<<QE_CR_PROTOCOL_SHIFT) | cmd));
  45        }
  46        /* Wait for the QE_CR_FLG to clear */
  47        do {
  48                cecr = in_be32(&qe_immr->cp.cecr);
  49        } while (cecr & QE_CR_FLG);
  50
  51        return;
  52}
  53
  54uint qe_muram_alloc(uint size, uint align)
  55{
  56        uint    retloc;
  57        uint    align_mask, off;
  58        uint    savebase;
  59
  60        align_mask = align - 1;
  61        savebase = gd->mp_alloc_base;
  62
  63        if ((off = (gd->mp_alloc_base & align_mask)) != 0)
  64                gd->mp_alloc_base += (align - off);
  65
  66        if ((off = size & align_mask) != 0)
  67                size += (align - off);
  68
  69        if ((gd->mp_alloc_base + size) >= gd->mp_alloc_top) {
  70                gd->mp_alloc_base = savebase;
  71                printf("%s: ran out of ram.\n",  __FUNCTION__);
  72        }
  73
  74        retloc = gd->mp_alloc_base;
  75        gd->mp_alloc_base += size;
  76
  77        memset((void *)&qe_immr->muram[retloc], 0, size);
  78
  79        __asm__ __volatile__("sync");
  80
  81        return retloc;
  82}
  83
  84void *qe_muram_addr(uint offset)
  85{
  86        return (void *)&qe_immr->muram[offset];
  87}
  88
  89static void qe_sdma_init(void)
  90{
  91        volatile sdma_t *p;
  92        uint            sdma_buffer_base;
  93
  94        p = (volatile sdma_t *)&qe_immr->sdma;
  95
  96        /* All of DMA transaction in bus 1 */
  97        out_be32(&p->sdaqr, 0);
  98        out_be32(&p->sdaqmr, 0);
  99
 100        /* Allocate 2KB temporary buffer for sdma */
 101        sdma_buffer_base = qe_muram_alloc(2048, 4096);
 102        out_be32(&p->sdwbcr, sdma_buffer_base & QE_SDEBCR_BA_MASK);
 103
 104        /* Clear sdma status */
 105        out_be32(&p->sdsr, 0x03000000);
 106
 107        /* Enable global mode on bus 1, and 2KB buffer size */
 108        out_be32(&p->sdmr, QE_SDMR_GLB_1_MSK | (0x3 << QE_SDMR_CEN_SHIFT));
 109}
 110
 111/* This table is a list of the serial numbers of the Threads, taken from the
 112 * "SNUM Table" chart in the QE Reference Manual. The order is not important,
 113 * we just need to know what the SNUMs are for the threads.
 114 */
 115static u8 thread_snum[] = {
 116        0x04, 0x05, 0x0c, 0x0d,
 117        0x14, 0x15, 0x1c, 0x1d,
 118        0x24, 0x25, 0x2c, 0x2d,
 119        0x34, 0x35, 0x88, 0x89,
 120        0x98, 0x99, 0xa8, 0xa9,
 121        0xb8, 0xb9, 0xc8, 0xc9,
 122        0xd8, 0xd9, 0xe8, 0xe9,
 123        0x08, 0x09, 0x18, 0x19,
 124        0x28, 0x29, 0x38, 0x39,
 125        0x48, 0x49, 0x58, 0x59,
 126        0x68, 0x69, 0x78, 0x79,
 127        0x80, 0x81
 128};
 129
 130static void qe_snums_init(void)
 131{
 132        int     i;
 133
 134        for (i = 0; i < QE_NUM_OF_SNUM; i++) {
 135                snums[i].state = QE_SNUM_STATE_FREE;
 136                snums[i].num   = thread_snum[i];
 137        }
 138}
 139
 140int qe_get_snum(void)
 141{
 142        int     snum = -EBUSY;
 143        int     i;
 144
 145        for (i = 0; i < QE_NUM_OF_SNUM; i++) {
 146                if (snums[i].state == QE_SNUM_STATE_FREE) {
 147                        snums[i].state = QE_SNUM_STATE_USED;
 148                        snum = snums[i].num;
 149                        break;
 150                }
 151        }
 152
 153        return snum;
 154}
 155
 156void qe_put_snum(u8 snum)
 157{
 158        int     i;
 159
 160        for (i = 0; i < QE_NUM_OF_SNUM; i++) {
 161                if (snums[i].num == snum) {
 162                        snums[i].state = QE_SNUM_STATE_FREE;
 163                        break;
 164                }
 165        }
 166}
 167
 168void qe_init(uint qe_base)
 169{
 170        /* Init the QE IMMR base */
 171        qe_immr = (qe_map_t *)qe_base;
 172
 173#ifdef CONFIG_SYS_QE_FMAN_FW_IN_NOR
 174        /*
 175         * Upload microcode to IRAM for those SOCs which do not have ROM in QE.
 176         */
 177        qe_upload_firmware((const void *)CONFIG_SYS_QE_FMAN_FW_ADDR);
 178
 179        /* enable the microcode in IRAM */
 180        out_be32(&qe_immr->iram.iready,QE_IRAM_READY);
 181#endif
 182
 183        gd->mp_alloc_base = QE_DATAONLY_BASE;
 184        gd->mp_alloc_top = gd->mp_alloc_base + QE_DATAONLY_SIZE;
 185
 186        qe_sdma_init();
 187        qe_snums_init();
 188}
 189
 190void qe_reset(void)
 191{
 192        qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
 193                         (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
 194}
 195
 196void qe_assign_page(uint snum, uint para_ram_base)
 197{
 198        u32     cecr;
 199
 200        out_be32(&qe_immr->cp.cecdr, para_ram_base);
 201        out_be32(&qe_immr->cp.cecr, ((u32) snum<<QE_CR_ASSIGN_PAGE_SNUM_SHIFT)
 202                                         | QE_CR_FLG | QE_ASSIGN_PAGE);
 203
 204        /* Wait for the QE_CR_FLG to clear */
 205        do {
 206                cecr = in_be32(&qe_immr->cp.cecr);
 207        } while (cecr & QE_CR_FLG );
 208
 209        return;
 210}
 211
 212/*
 213 * brg: 0~15 as BRG1~BRG16
 214   rate: baud rate
 215 * BRG input clock comes from the BRGCLK (internal clock generated from
 216   the QE clock, it is one-half of the QE clock), If need the clock source
 217   from CLKn pin, we have te change the function.
 218 */
 219
 220#define BRG_CLK         (gd->brg_clk)
 221
 222int qe_set_brg(uint brg, uint rate)
 223{
 224        volatile uint   *bp;
 225        u32             divisor;
 226        int             div16 = 0;
 227
 228        if (brg >= QE_NUM_OF_BRGS)
 229                return -EINVAL;
 230        bp = (uint *)&qe_immr->brg.brgc1;
 231        bp += brg;
 232
 233        divisor = (BRG_CLK / rate);
 234        if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
 235                div16 = 1;
 236                divisor /= 16;
 237        }
 238
 239        *bp = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE;
 240        __asm__ __volatile__("sync");
 241
 242        if (div16) {
 243                *bp |= QE_BRGC_DIV16;
 244                __asm__ __volatile__("sync");
 245        }
 246
 247        return 0;
 248}
 249
 250/* Set ethernet MII clock master
 251*/
 252int qe_set_mii_clk_src(int ucc_num)
 253{
 254        u32     cmxgcr;
 255
 256        /* check if the UCC number is in range. */
 257        if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0)) {
 258                printf("%s: ucc num not in ranges\n", __FUNCTION__);
 259                return -EINVAL;
 260        }
 261
 262        cmxgcr = in_be32(&qe_immr->qmx.cmxgcr);
 263        cmxgcr &= ~QE_CMXGCR_MII_ENET_MNG_MASK;
 264        cmxgcr |= (ucc_num <<QE_CMXGCR_MII_ENET_MNG_SHIFT);
 265        out_be32(&qe_immr->qmx.cmxgcr, cmxgcr);
 266
 267        return 0;
 268}
 269
 270/* Firmware information stored here for qe_get_firmware_info() */
 271static struct qe_firmware_info qe_firmware_info;
 272
 273/*
 274 * Set to 1 if QE firmware has been uploaded, and therefore
 275 * qe_firmware_info contains valid data.
 276 */
 277static int qe_firmware_uploaded;
 278
 279/*
 280 * Upload a QE microcode
 281 *
 282 * This function is a worker function for qe_upload_firmware().  It does
 283 * the actual uploading of the microcode.
 284 */
 285static void qe_upload_microcode(const void *base,
 286        const struct qe_microcode *ucode)
 287{
 288        const u32 *code = base + be32_to_cpu(ucode->code_offset);
 289        unsigned int i;
 290
 291        if (ucode->major || ucode->minor || ucode->revision)
 292                printf("QE: uploading microcode '%s' version %u.%u.%u\n",
 293                        ucode->id, ucode->major, ucode->minor, ucode->revision);
 294        else
 295                printf("QE: uploading microcode '%s'\n", ucode->id);
 296
 297        /* Use auto-increment */
 298        out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
 299                QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
 300
 301        for (i = 0; i < be32_to_cpu(ucode->count); i++)
 302                out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
 303}
 304
 305/*
 306 * Upload a microcode to the I-RAM at a specific address.
 307 *
 308 * See docs/README.qe_firmware for information on QE microcode uploading.
 309 *
 310 * Currently, only version 1 is supported, so the 'version' field must be
 311 * set to 1.
 312 *
 313 * The SOC model and revision are not validated, they are only displayed for
 314 * informational purposes.
 315 *
 316 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
 317 * all of the microcode structures, minus the CRC.
 318 *
 319 * 'length' is the size that the structure says it is, including the CRC.
 320 */
 321int qe_upload_firmware(const struct qe_firmware *firmware)
 322{
 323        unsigned int i;
 324        unsigned int j;
 325        u32 crc;
 326        size_t calc_size = sizeof(struct qe_firmware);
 327        size_t length;
 328        const struct qe_header *hdr;
 329
 330        if (!firmware) {
 331                printf("Invalid address\n");
 332                return -EINVAL;
 333        }
 334
 335        hdr = &firmware->header;
 336        length = be32_to_cpu(hdr->length);
 337
 338        /* Check the magic */
 339        if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
 340            (hdr->magic[2] != 'F')) {
 341                printf("Not a microcode\n");
 342                return -EPERM;
 343        }
 344
 345        /* Check the version */
 346        if (hdr->version != 1) {
 347                printf("Unsupported version\n");
 348                return -EPERM;
 349        }
 350
 351        /* Validate some of the fields */
 352        if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
 353                printf("Invalid data\n");
 354                return -EINVAL;
 355        }
 356
 357        /* Validate the length and check if there's a CRC */
 358        calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
 359
 360        for (i = 0; i < firmware->count; i++)
 361                /*
 362                 * For situations where the second RISC uses the same microcode
 363                 * as the first, the 'code_offset' and 'count' fields will be
 364                 * zero, so it's okay to add those.
 365                 */
 366                calc_size += sizeof(u32) *
 367                        be32_to_cpu(firmware->microcode[i].count);
 368
 369        /* Validate the length */
 370        if (length != calc_size + sizeof(u32)) {
 371                printf("Invalid length\n");
 372                return -EPERM;
 373        }
 374
 375        /*
 376         * Validate the CRC.  We would normally call crc32_no_comp(), but that
 377         * function isn't available unless you turn on JFFS support.
 378         */
 379        crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
 380        if (crc != (crc32(-1, (const void *) firmware, calc_size) ^ -1)) {
 381                printf("Firmware CRC is invalid\n");
 382                return -EIO;
 383        }
 384
 385        /*
 386         * If the microcode calls for it, split the I-RAM.
 387         */
 388        if (!firmware->split) {
 389                out_be16(&qe_immr->cp.cercr,
 390                        in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
 391        }
 392
 393        if (firmware->soc.model)
 394                printf("Firmware '%s' for %u V%u.%u\n",
 395                        firmware->id, be16_to_cpu(firmware->soc.model),
 396                        firmware->soc.major, firmware->soc.minor);
 397        else
 398                printf("Firmware '%s'\n", firmware->id);
 399
 400        /*
 401         * The QE only supports one microcode per RISC, so clear out all the
 402         * saved microcode information and put in the new.
 403         */
 404        memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
 405        strcpy(qe_firmware_info.id, (char *)firmware->id);
 406        qe_firmware_info.extended_modes = firmware->extended_modes;
 407        memcpy(qe_firmware_info.vtraps, firmware->vtraps,
 408                sizeof(firmware->vtraps));
 409        qe_firmware_uploaded = 1;
 410
 411        /* Loop through each microcode. */
 412        for (i = 0; i < firmware->count; i++) {
 413                const struct qe_microcode *ucode = &firmware->microcode[i];
 414
 415                /* Upload a microcode if it's present */
 416                if (ucode->code_offset)
 417                        qe_upload_microcode(firmware, ucode);
 418
 419                /* Program the traps for this processor */
 420                for (j = 0; j < 16; j++) {
 421                        u32 trap = be32_to_cpu(ucode->traps[j]);
 422
 423                        if (trap)
 424                                out_be32(&qe_immr->rsp[i].tibcr[j], trap);
 425                }
 426
 427                /* Enable traps */
 428                out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
 429        }
 430
 431        return 0;
 432}
 433
 434struct qe_firmware_info *qe_get_firmware_info(void)
 435{
 436        return qe_firmware_uploaded ? &qe_firmware_info : NULL;
 437}
 438
 439static int qe_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 440{
 441        ulong addr;
 442
 443        if (argc < 3)
 444                return cmd_usage(cmdtp);
 445
 446        if (strcmp(argv[1], "fw") == 0) {
 447                addr = simple_strtoul(argv[2], NULL, 16);
 448
 449                if (!addr) {
 450                        printf("Invalid address\n");
 451                        return -EINVAL;
 452                }
 453
 454                /*
 455                 * If a length was supplied, compare that with the 'length'
 456                 * field.
 457                 */
 458
 459                if (argc > 3) {
 460                        ulong length = simple_strtoul(argv[3], NULL, 16);
 461                        struct qe_firmware *firmware = (void *) addr;
 462
 463                        if (length != be32_to_cpu(firmware->header.length)) {
 464                                printf("Length mismatch\n");
 465                                return -EINVAL;
 466                        }
 467                }
 468
 469                return qe_upload_firmware((const struct qe_firmware *) addr);
 470        }
 471
 472        return cmd_usage(cmdtp);
 473}
 474
 475U_BOOT_CMD(
 476        qe, 4, 0, qe_cmd,
 477        "QUICC Engine commands",
 478        "fw <addr> [<length>] - Upload firmware binary at address <addr> to "
 479                "the QE,\n"
 480        "\twith optional length <length> verification."
 481);
 482