linux/drivers/soc/fsl/qe/qe.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2006-2010 Freescale Semiconductor, Inc. All rights reserved.
   3 *
   4 * Authors:     Shlomi Gridish <gridish@freescale.com>
   5 *              Li Yang <leoli@freescale.com>
   6 * Based on cpm2_common.c from Dan Malek (dmalek@jlc.net)
   7 *
   8 * Description:
   9 * General Purpose functions for the global management of the
  10 * QUICC Engine (QE).
  11 *
  12 * This program is free software; you can redistribute  it and/or modify it
  13 * under  the terms of  the GNU General  Public License as published by the
  14 * Free Software Foundation;  either version 2 of the  License, or (at your
  15 * option) any later version.
  16 */
  17#include <linux/errno.h>
  18#include <linux/sched.h>
  19#include <linux/kernel.h>
  20#include <linux/param.h>
  21#include <linux/string.h>
  22#include <linux/spinlock.h>
  23#include <linux/mm.h>
  24#include <linux/interrupt.h>
  25#include <linux/module.h>
  26#include <linux/delay.h>
  27#include <linux/ioport.h>
  28#include <linux/crc32.h>
  29#include <linux/mod_devicetable.h>
  30#include <linux/of_platform.h>
  31#include <asm/irq.h>
  32#include <asm/page.h>
  33#include <asm/pgtable.h>
  34#include <soc/fsl/qe/immap_qe.h>
  35#include <soc/fsl/qe/qe.h>
  36#include <asm/prom.h>
  37#include <asm/rheap.h>
  38
  39static void qe_snums_init(void);
  40static int qe_sdma_init(void);
  41
  42static DEFINE_SPINLOCK(qe_lock);
  43DEFINE_SPINLOCK(cmxgcr_lock);
  44EXPORT_SYMBOL(cmxgcr_lock);
  45
  46/* QE snum state */
  47enum qe_snum_state {
  48        QE_SNUM_STATE_USED,
  49        QE_SNUM_STATE_FREE
  50};
  51
  52/* QE snum */
  53struct qe_snum {
  54        u8 num;
  55        enum qe_snum_state state;
  56};
  57
  58/* We allocate this here because it is used almost exclusively for
  59 * the communication processor devices.
  60 */
  61struct qe_immap __iomem *qe_immr;
  62EXPORT_SYMBOL(qe_immr);
  63
  64static struct qe_snum snums[QE_NUM_OF_SNUM];    /* Dynamically allocated SNUMs */
  65static unsigned int qe_num_of_snum;
  66
  67static phys_addr_t qebase = -1;
  68
  69static phys_addr_t get_qe_base(void)
  70{
  71        struct device_node *qe;
  72        int ret;
  73        struct resource res;
  74
  75        if (qebase != -1)
  76                return qebase;
  77
  78        qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
  79        if (!qe) {
  80                qe = of_find_node_by_type(NULL, "qe");
  81                if (!qe)
  82                        return qebase;
  83        }
  84
  85        ret = of_address_to_resource(qe, 0, &res);
  86        if (!ret)
  87                qebase = res.start;
  88        of_node_put(qe);
  89
  90        return qebase;
  91}
  92
  93void qe_reset(void)
  94{
  95        if (qe_immr == NULL)
  96                qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE);
  97
  98        qe_snums_init();
  99
 100        qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
 101                     QE_CR_PROTOCOL_UNSPECIFIED, 0);
 102
 103        /* Reclaim the MURAM memory for our use. */
 104        qe_muram_init();
 105
 106        if (qe_sdma_init())
 107                panic("sdma init failed!");
 108}
 109
 110int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input)
 111{
 112        unsigned long flags;
 113        u8 mcn_shift = 0, dev_shift = 0;
 114        u32 ret;
 115
 116        spin_lock_irqsave(&qe_lock, flags);
 117        if (cmd == QE_RESET) {
 118                out_be32(&qe_immr->cp.cecr, (u32) (cmd | QE_CR_FLG));
 119        } else {
 120                if (cmd == QE_ASSIGN_PAGE) {
 121                        /* Here device is the SNUM, not sub-block */
 122                        dev_shift = QE_CR_SNUM_SHIFT;
 123                } else if (cmd == QE_ASSIGN_RISC) {
 124                        /* Here device is the SNUM, and mcnProtocol is
 125                         * e_QeCmdRiscAssignment value */
 126                        dev_shift = QE_CR_SNUM_SHIFT;
 127                        mcn_shift = QE_CR_MCN_RISC_ASSIGN_SHIFT;
 128                } else {
 129                        if (device == QE_CR_SUBBLOCK_USB)
 130                                mcn_shift = QE_CR_MCN_USB_SHIFT;
 131                        else
 132                                mcn_shift = QE_CR_MCN_NORMAL_SHIFT;
 133                }
 134
 135                out_be32(&qe_immr->cp.cecdr, cmd_input);
 136                out_be32(&qe_immr->cp.cecr,
 137                         (cmd | QE_CR_FLG | ((u32) device << dev_shift) | (u32)
 138                          mcn_protocol << mcn_shift));
 139        }
 140
 141        /* wait for the QE_CR_FLG to clear */
 142        ret = spin_event_timeout((in_be32(&qe_immr->cp.cecr) & QE_CR_FLG) == 0,
 143                           100, 0);
 144        /* On timeout (e.g. failure), the expression will be false (ret == 0),
 145           otherwise it will be true (ret == 1). */
 146        spin_unlock_irqrestore(&qe_lock, flags);
 147
 148        return ret == 1;
 149}
 150EXPORT_SYMBOL(qe_issue_cmd);
 151
 152/* Set a baud rate generator. This needs lots of work. There are
 153 * 16 BRGs, which can be connected to the QE channels or output
 154 * as clocks. The BRGs are in two different block of internal
 155 * memory mapped space.
 156 * The BRG clock is the QE clock divided by 2.
 157 * It was set up long ago during the initial boot phase and is
 158 * is given to us.
 159 * Baud rate clocks are zero-based in the driver code (as that maps
 160 * to port numbers). Documentation uses 1-based numbering.
 161 */
 162static unsigned int brg_clk = 0;
 163
 164#define CLK_GRAN        (1000)
 165#define CLK_GRAN_LIMIT  (5)
 166
 167unsigned int qe_get_brg_clk(void)
 168{
 169        struct device_node *qe;
 170        int size;
 171        const u32 *prop;
 172        unsigned int mod;
 173
 174        if (brg_clk)
 175                return brg_clk;
 176
 177        qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
 178        if (!qe) {
 179                qe = of_find_node_by_type(NULL, "qe");
 180                if (!qe)
 181                        return brg_clk;
 182        }
 183
 184        prop = of_get_property(qe, "brg-frequency", &size);
 185        if (prop && size == sizeof(*prop))
 186                brg_clk = *prop;
 187
 188        of_node_put(qe);
 189
 190        /* round this if near to a multiple of CLK_GRAN */
 191        mod = brg_clk % CLK_GRAN;
 192        if (mod) {
 193                if (mod < CLK_GRAN_LIMIT)
 194                        brg_clk -= mod;
 195                else if (mod > (CLK_GRAN - CLK_GRAN_LIMIT))
 196                        brg_clk += CLK_GRAN - mod;
 197        }
 198
 199        return brg_clk;
 200}
 201EXPORT_SYMBOL(qe_get_brg_clk);
 202
 203#define PVR_VER_836x    0x8083
 204#define PVR_VER_832x    0x8084
 205
 206/* Program the BRG to the given sampling rate and multiplier
 207 *
 208 * @brg: the BRG, QE_BRG1 - QE_BRG16
 209 * @rate: the desired sampling rate
 210 * @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or
 211 * GUMR_L[TDCR].  E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01,
 212 * then 'multiplier' should be 8.
 213 */
 214int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
 215{
 216        u32 divisor, tempval;
 217        u32 div16 = 0;
 218
 219        if ((brg < QE_BRG1) || (brg > QE_BRG16))
 220                return -EINVAL;
 221
 222        divisor = qe_get_brg_clk() / (rate * multiplier);
 223
 224        if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
 225                div16 = QE_BRGC_DIV16;
 226                divisor /= 16;
 227        }
 228
 229        /* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says
 230           that the BRG divisor must be even if you're not using divide-by-16
 231           mode. */
 232        if (pvr_version_is(PVR_VER_836x) || pvr_version_is(PVR_VER_832x))
 233                if (!div16 && (divisor & 1) && (divisor > 3))
 234                        divisor++;
 235
 236        tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
 237                QE_BRGC_ENABLE | div16;
 238
 239        out_be32(&qe_immr->brg.brgc[brg - QE_BRG1], tempval);
 240
 241        return 0;
 242}
 243EXPORT_SYMBOL(qe_setbrg);
 244
 245/* Convert a string to a QE clock source enum
 246 *
 247 * This function takes a string, typically from a property in the device
 248 * tree, and returns the corresponding "enum qe_clock" value.
 249*/
 250enum qe_clock qe_clock_source(const char *source)
 251{
 252        unsigned int i;
 253
 254        if (strcasecmp(source, "none") == 0)
 255                return QE_CLK_NONE;
 256
 257        if (strcmp(source, "tsync_pin") == 0)
 258                return QE_TSYNC_PIN;
 259
 260        if (strcmp(source, "rsync_pin") == 0)
 261                return QE_RSYNC_PIN;
 262
 263        if (strncasecmp(source, "brg", 3) == 0) {
 264                i = simple_strtoul(source + 3, NULL, 10);
 265                if ((i >= 1) && (i <= 16))
 266                        return (QE_BRG1 - 1) + i;
 267                else
 268                        return QE_CLK_DUMMY;
 269        }
 270
 271        if (strncasecmp(source, "clk", 3) == 0) {
 272                i = simple_strtoul(source + 3, NULL, 10);
 273                if ((i >= 1) && (i <= 24))
 274                        return (QE_CLK1 - 1) + i;
 275                else
 276                        return QE_CLK_DUMMY;
 277        }
 278
 279        return QE_CLK_DUMMY;
 280}
 281EXPORT_SYMBOL(qe_clock_source);
 282
 283/* Initialize SNUMs (thread serial numbers) according to
 284 * QE Module Control chapter, SNUM table
 285 */
 286static void qe_snums_init(void)
 287{
 288        int i;
 289        static const u8 snum_init_76[] = {
 290                0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
 291                0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
 292                0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
 293                0xD8, 0xD9, 0xE8, 0xE9, 0x44, 0x45, 0x4C, 0x4D,
 294                0x54, 0x55, 0x5C, 0x5D, 0x64, 0x65, 0x6C, 0x6D,
 295                0x74, 0x75, 0x7C, 0x7D, 0x84, 0x85, 0x8C, 0x8D,
 296                0x94, 0x95, 0x9C, 0x9D, 0xA4, 0xA5, 0xAC, 0xAD,
 297                0xB4, 0xB5, 0xBC, 0xBD, 0xC4, 0xC5, 0xCC, 0xCD,
 298                0xD4, 0xD5, 0xDC, 0xDD, 0xE4, 0xE5, 0xEC, 0xED,
 299                0xF4, 0xF5, 0xFC, 0xFD,
 300        };
 301        static const u8 snum_init_46[] = {
 302                0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
 303                0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
 304                0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
 305                0xD8, 0xD9, 0xE8, 0xE9, 0x08, 0x09, 0x18, 0x19,
 306                0x28, 0x29, 0x38, 0x39, 0x48, 0x49, 0x58, 0x59,
 307                0x68, 0x69, 0x78, 0x79, 0x80, 0x81,
 308        };
 309        static const u8 *snum_init;
 310
 311        qe_num_of_snum = qe_get_num_of_snums();
 312
 313        if (qe_num_of_snum == 76)
 314                snum_init = snum_init_76;
 315        else
 316                snum_init = snum_init_46;
 317
 318        for (i = 0; i < qe_num_of_snum; i++) {
 319                snums[i].num = snum_init[i];
 320                snums[i].state = QE_SNUM_STATE_FREE;
 321        }
 322}
 323
 324int qe_get_snum(void)
 325{
 326        unsigned long flags;
 327        int snum = -EBUSY;
 328        int i;
 329
 330        spin_lock_irqsave(&qe_lock, flags);
 331        for (i = 0; i < qe_num_of_snum; i++) {
 332                if (snums[i].state == QE_SNUM_STATE_FREE) {
 333                        snums[i].state = QE_SNUM_STATE_USED;
 334                        snum = snums[i].num;
 335                        break;
 336                }
 337        }
 338        spin_unlock_irqrestore(&qe_lock, flags);
 339
 340        return snum;
 341}
 342EXPORT_SYMBOL(qe_get_snum);
 343
 344void qe_put_snum(u8 snum)
 345{
 346        int i;
 347
 348        for (i = 0; i < qe_num_of_snum; i++) {
 349                if (snums[i].num == snum) {
 350                        snums[i].state = QE_SNUM_STATE_FREE;
 351                        break;
 352                }
 353        }
 354}
 355EXPORT_SYMBOL(qe_put_snum);
 356
 357static int qe_sdma_init(void)
 358{
 359        struct sdma __iomem *sdma = &qe_immr->sdma;
 360        static unsigned long sdma_buf_offset = (unsigned long)-ENOMEM;
 361
 362        if (!sdma)
 363                return -ENODEV;
 364
 365        /* allocate 2 internal temporary buffers (512 bytes size each) for
 366         * the SDMA */
 367        if (IS_ERR_VALUE(sdma_buf_offset)) {
 368                sdma_buf_offset = qe_muram_alloc(512 * 2, 4096);
 369                if (IS_ERR_VALUE(sdma_buf_offset))
 370                        return -ENOMEM;
 371        }
 372
 373        out_be32(&sdma->sdebcr, (u32) sdma_buf_offset & QE_SDEBCR_BA_MASK);
 374        out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK |
 375                                        (0x1 << QE_SDMR_CEN_SHIFT)));
 376
 377        return 0;
 378}
 379
 380/* The maximum number of RISCs we support */
 381#define MAX_QE_RISC     4
 382
 383/* Firmware information stored here for qe_get_firmware_info() */
 384static struct qe_firmware_info qe_firmware_info;
 385
 386/*
 387 * Set to 1 if QE firmware has been uploaded, and therefore
 388 * qe_firmware_info contains valid data.
 389 */
 390static int qe_firmware_uploaded;
 391
 392/*
 393 * Upload a QE microcode
 394 *
 395 * This function is a worker function for qe_upload_firmware().  It does
 396 * the actual uploading of the microcode.
 397 */
 398static void qe_upload_microcode(const void *base,
 399        const struct qe_microcode *ucode)
 400{
 401        const __be32 *code = base + be32_to_cpu(ucode->code_offset);
 402        unsigned int i;
 403
 404        if (ucode->major || ucode->minor || ucode->revision)
 405                printk(KERN_INFO "qe-firmware: "
 406                        "uploading microcode '%s' version %u.%u.%u\n",
 407                        ucode->id, ucode->major, ucode->minor, ucode->revision);
 408        else
 409                printk(KERN_INFO "qe-firmware: "
 410                        "uploading microcode '%s'\n", ucode->id);
 411
 412        /* Use auto-increment */
 413        out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
 414                QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
 415
 416        for (i = 0; i < be32_to_cpu(ucode->count); i++)
 417                out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
 418        
 419        /* Set I-RAM Ready Register */
 420        out_be32(&qe_immr->iram.iready, be32_to_cpu(QE_IRAM_READY));
 421}
 422
 423/*
 424 * Upload a microcode to the I-RAM at a specific address.
 425 *
 426 * See Documentation/powerpc/qe_firmware.txt for information on QE microcode
 427 * uploading.
 428 *
 429 * Currently, only version 1 is supported, so the 'version' field must be
 430 * set to 1.
 431 *
 432 * The SOC model and revision are not validated, they are only displayed for
 433 * informational purposes.
 434 *
 435 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
 436 * all of the microcode structures, minus the CRC.
 437 *
 438 * 'length' is the size that the structure says it is, including the CRC.
 439 */
 440int qe_upload_firmware(const struct qe_firmware *firmware)
 441{
 442        unsigned int i;
 443        unsigned int j;
 444        u32 crc;
 445        size_t calc_size = sizeof(struct qe_firmware);
 446        size_t length;
 447        const struct qe_header *hdr;
 448
 449        if (!firmware) {
 450                printk(KERN_ERR "qe-firmware: invalid pointer\n");
 451                return -EINVAL;
 452        }
 453
 454        hdr = &firmware->header;
 455        length = be32_to_cpu(hdr->length);
 456
 457        /* Check the magic */
 458        if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
 459            (hdr->magic[2] != 'F')) {
 460                printk(KERN_ERR "qe-firmware: not a microcode\n");
 461                return -EPERM;
 462        }
 463
 464        /* Check the version */
 465        if (hdr->version != 1) {
 466                printk(KERN_ERR "qe-firmware: unsupported version\n");
 467                return -EPERM;
 468        }
 469
 470        /* Validate some of the fields */
 471        if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
 472                printk(KERN_ERR "qe-firmware: invalid data\n");
 473                return -EINVAL;
 474        }
 475
 476        /* Validate the length and check if there's a CRC */
 477        calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
 478
 479        for (i = 0; i < firmware->count; i++)
 480                /*
 481                 * For situations where the second RISC uses the same microcode
 482                 * as the first, the 'code_offset' and 'count' fields will be
 483                 * zero, so it's okay to add those.
 484                 */
 485                calc_size += sizeof(__be32) *
 486                        be32_to_cpu(firmware->microcode[i].count);
 487
 488        /* Validate the length */
 489        if (length != calc_size + sizeof(__be32)) {
 490                printk(KERN_ERR "qe-firmware: invalid length\n");
 491                return -EPERM;
 492        }
 493
 494        /* Validate the CRC */
 495        crc = be32_to_cpu(*(__be32 *)((void *)firmware + calc_size));
 496        if (crc != crc32(0, firmware, calc_size)) {
 497                printk(KERN_ERR "qe-firmware: firmware CRC is invalid\n");
 498                return -EIO;
 499        }
 500
 501        /*
 502         * If the microcode calls for it, split the I-RAM.
 503         */
 504        if (!firmware->split)
 505                setbits16(&qe_immr->cp.cercr, QE_CP_CERCR_CIR);
 506
 507        if (firmware->soc.model)
 508                printk(KERN_INFO
 509                        "qe-firmware: firmware '%s' for %u V%u.%u\n",
 510                        firmware->id, be16_to_cpu(firmware->soc.model),
 511                        firmware->soc.major, firmware->soc.minor);
 512        else
 513                printk(KERN_INFO "qe-firmware: firmware '%s'\n",
 514                        firmware->id);
 515
 516        /*
 517         * The QE only supports one microcode per RISC, so clear out all the
 518         * saved microcode information and put in the new.
 519         */
 520        memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
 521        strlcpy(qe_firmware_info.id, firmware->id, sizeof(qe_firmware_info.id));
 522        qe_firmware_info.extended_modes = firmware->extended_modes;
 523        memcpy(qe_firmware_info.vtraps, firmware->vtraps,
 524                sizeof(firmware->vtraps));
 525
 526        /* Loop through each microcode. */
 527        for (i = 0; i < firmware->count; i++) {
 528                const struct qe_microcode *ucode = &firmware->microcode[i];
 529
 530                /* Upload a microcode if it's present */
 531                if (ucode->code_offset)
 532                        qe_upload_microcode(firmware, ucode);
 533
 534                /* Program the traps for this processor */
 535                for (j = 0; j < 16; j++) {
 536                        u32 trap = be32_to_cpu(ucode->traps[j]);
 537
 538                        if (trap)
 539                                out_be32(&qe_immr->rsp[i].tibcr[j], trap);
 540                }
 541
 542                /* Enable traps */
 543                out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
 544        }
 545
 546        qe_firmware_uploaded = 1;
 547
 548        return 0;
 549}
 550EXPORT_SYMBOL(qe_upload_firmware);
 551
 552/*
 553 * Get info on the currently-loaded firmware
 554 *
 555 * This function also checks the device tree to see if the boot loader has
 556 * uploaded a firmware already.
 557 */
 558struct qe_firmware_info *qe_get_firmware_info(void)
 559{
 560        static int initialized;
 561        struct property *prop;
 562        struct device_node *qe;
 563        struct device_node *fw = NULL;
 564        const char *sprop;
 565        unsigned int i;
 566
 567        /*
 568         * If we haven't checked yet, and a driver hasn't uploaded a firmware
 569         * yet, then check the device tree for information.
 570         */
 571        if (qe_firmware_uploaded)
 572                return &qe_firmware_info;
 573
 574        if (initialized)
 575                return NULL;
 576
 577        initialized = 1;
 578
 579        /*
 580         * Newer device trees have an "fsl,qe" compatible property for the QE
 581         * node, but we still need to support older device trees.
 582        */
 583        qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
 584        if (!qe) {
 585                qe = of_find_node_by_type(NULL, "qe");
 586                if (!qe)
 587                        return NULL;
 588        }
 589
 590        /* Find the 'firmware' child node */
 591        for_each_child_of_node(qe, fw) {
 592                if (strcmp(fw->name, "firmware") == 0)
 593                        break;
 594        }
 595
 596        of_node_put(qe);
 597
 598        /* Did we find the 'firmware' node? */
 599        if (!fw)
 600                return NULL;
 601
 602        qe_firmware_uploaded = 1;
 603
 604        /* Copy the data into qe_firmware_info*/
 605        sprop = of_get_property(fw, "id", NULL);
 606        if (sprop)
 607                strlcpy(qe_firmware_info.id, sprop,
 608                        sizeof(qe_firmware_info.id));
 609
 610        prop = of_find_property(fw, "extended-modes", NULL);
 611        if (prop && (prop->length == sizeof(u64))) {
 612                const u64 *iprop = prop->value;
 613
 614                qe_firmware_info.extended_modes = *iprop;
 615        }
 616
 617        prop = of_find_property(fw, "virtual-traps", NULL);
 618        if (prop && (prop->length == 32)) {
 619                const u32 *iprop = prop->value;
 620
 621                for (i = 0; i < ARRAY_SIZE(qe_firmware_info.vtraps); i++)
 622                        qe_firmware_info.vtraps[i] = iprop[i];
 623        }
 624
 625        of_node_put(fw);
 626
 627        return &qe_firmware_info;
 628}
 629EXPORT_SYMBOL(qe_get_firmware_info);
 630
 631unsigned int qe_get_num_of_risc(void)
 632{
 633        struct device_node *qe;
 634        int size;
 635        unsigned int num_of_risc = 0;
 636        const u32 *prop;
 637
 638        qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
 639        if (!qe) {
 640                /* Older devices trees did not have an "fsl,qe"
 641                 * compatible property, so we need to look for
 642                 * the QE node by name.
 643                 */
 644                qe = of_find_node_by_type(NULL, "qe");
 645                if (!qe)
 646                        return num_of_risc;
 647        }
 648
 649        prop = of_get_property(qe, "fsl,qe-num-riscs", &size);
 650        if (prop && size == sizeof(*prop))
 651                num_of_risc = *prop;
 652
 653        of_node_put(qe);
 654
 655        return num_of_risc;
 656}
 657EXPORT_SYMBOL(qe_get_num_of_risc);
 658
 659unsigned int qe_get_num_of_snums(void)
 660{
 661        struct device_node *qe;
 662        int size;
 663        unsigned int num_of_snums;
 664        const u32 *prop;
 665
 666        num_of_snums = 28; /* The default number of snum for threads is 28 */
 667        qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
 668        if (!qe) {
 669                /* Older devices trees did not have an "fsl,qe"
 670                 * compatible property, so we need to look for
 671                 * the QE node by name.
 672                 */
 673                qe = of_find_node_by_type(NULL, "qe");
 674                if (!qe)
 675                        return num_of_snums;
 676        }
 677
 678        prop = of_get_property(qe, "fsl,qe-num-snums", &size);
 679        if (prop && size == sizeof(*prop)) {
 680                num_of_snums = *prop;
 681                if ((num_of_snums < 28) || (num_of_snums > QE_NUM_OF_SNUM)) {
 682                        /* No QE ever has fewer than 28 SNUMs */
 683                        pr_err("QE: number of snum is invalid\n");
 684                        of_node_put(qe);
 685                        return -EINVAL;
 686                }
 687        }
 688
 689        of_node_put(qe);
 690
 691        return num_of_snums;
 692}
 693EXPORT_SYMBOL(qe_get_num_of_snums);
 694
 695static int __init qe_init(void)
 696{
 697        struct device_node *np;
 698
 699        np = of_find_compatible_node(NULL, NULL, "fsl,qe");
 700        if (!np)
 701                return -ENODEV;
 702        qe_reset();
 703        of_node_put(np);
 704        return 0;
 705}
 706subsys_initcall(qe_init);
 707
 708#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx)
 709static int qe_resume(struct platform_device *ofdev)
 710{
 711        if (!qe_alive_during_sleep())
 712                qe_reset();
 713        return 0;
 714}
 715
 716static int qe_probe(struct platform_device *ofdev)
 717{
 718        return 0;
 719}
 720
 721static const struct of_device_id qe_ids[] = {
 722        { .compatible = "fsl,qe", },
 723        { },
 724};
 725
 726static struct platform_driver qe_driver = {
 727        .driver = {
 728                .name = "fsl-qe",
 729                .of_match_table = qe_ids,
 730        },
 731        .probe = qe_probe,
 732        .resume = qe_resume,
 733};
 734
 735builtin_platform_driver(qe_driver);
 736#endif /* defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx) */
 737