| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2006-2010 Freescale Semiconductor, Inc. All rights reserved. |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 8 | 9 | * Description: |
|---|
| 9 | 10 | * General Purpose functions for the global management of the |
|---|
| 10 | 11 | * 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 | 12 | */ |
|---|
| 13 | +#include <linux/bitmap.h> |
|---|
| 17 | 14 | #include <linux/errno.h> |
|---|
| 18 | 15 | #include <linux/sched.h> |
|---|
| 19 | 16 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 25 | 22 | #include <linux/module.h> |
|---|
| 26 | 23 | #include <linux/delay.h> |
|---|
| 27 | 24 | #include <linux/ioport.h> |
|---|
| 25 | +#include <linux/iopoll.h> |
|---|
| 28 | 26 | #include <linux/crc32.h> |
|---|
| 29 | 27 | #include <linux/mod_devicetable.h> |
|---|
| 30 | 28 | #include <linux/of_platform.h> |
|---|
| 31 | | -#include <asm/irq.h> |
|---|
| 32 | | -#include <asm/page.h> |
|---|
| 33 | | -#include <asm/pgtable.h> |
|---|
| 34 | 29 | #include <soc/fsl/qe/immap_qe.h> |
|---|
| 35 | 30 | #include <soc/fsl/qe/qe.h> |
|---|
| 36 | | -#include <asm/prom.h> |
|---|
| 37 | | -#include <asm/rheap.h> |
|---|
| 38 | 31 | |
|---|
| 39 | 32 | static void qe_snums_init(void); |
|---|
| 40 | 33 | static int qe_sdma_init(void); |
|---|
| .. | .. |
|---|
| 43 | 36 | DEFINE_SPINLOCK(cmxgcr_lock); |
|---|
| 44 | 37 | EXPORT_SYMBOL(cmxgcr_lock); |
|---|
| 45 | 38 | |
|---|
| 46 | | -/* QE snum state */ |
|---|
| 47 | | -enum qe_snum_state { |
|---|
| 48 | | - QE_SNUM_STATE_USED, |
|---|
| 49 | | - QE_SNUM_STATE_FREE |
|---|
| 50 | | -}; |
|---|
| 51 | | - |
|---|
| 52 | | -/* QE snum */ |
|---|
| 53 | | -struct qe_snum { |
|---|
| 54 | | - u8 num; |
|---|
| 55 | | - enum qe_snum_state state; |
|---|
| 56 | | -}; |
|---|
| 57 | | - |
|---|
| 58 | 39 | /* We allocate this here because it is used almost exclusively for |
|---|
| 59 | 40 | * the communication processor devices. |
|---|
| 60 | 41 | */ |
|---|
| 61 | 42 | struct qe_immap __iomem *qe_immr; |
|---|
| 62 | 43 | EXPORT_SYMBOL(qe_immr); |
|---|
| 63 | 44 | |
|---|
| 64 | | -static struct qe_snum snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */ |
|---|
| 45 | +static u8 snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */ |
|---|
| 46 | +static DECLARE_BITMAP(snum_state, QE_NUM_OF_SNUM); |
|---|
| 65 | 47 | static unsigned int qe_num_of_snum; |
|---|
| 66 | 48 | |
|---|
| 67 | 49 | static phys_addr_t qebase = -1; |
|---|
| 50 | + |
|---|
| 51 | +static struct device_node *qe_get_device_node(void) |
|---|
| 52 | +{ |
|---|
| 53 | + struct device_node *qe; |
|---|
| 54 | + |
|---|
| 55 | + /* |
|---|
| 56 | + * Newer device trees have an "fsl,qe" compatible property for the QE |
|---|
| 57 | + * node, but we still need to support older device trees. |
|---|
| 58 | + */ |
|---|
| 59 | + qe = of_find_compatible_node(NULL, NULL, "fsl,qe"); |
|---|
| 60 | + if (qe) |
|---|
| 61 | + return qe; |
|---|
| 62 | + return of_find_node_by_type(NULL, "qe"); |
|---|
| 63 | +} |
|---|
| 68 | 64 | |
|---|
| 69 | 65 | static phys_addr_t get_qe_base(void) |
|---|
| 70 | 66 | { |
|---|
| .. | .. |
|---|
| 75 | 71 | if (qebase != -1) |
|---|
| 76 | 72 | return qebase; |
|---|
| 77 | 73 | |
|---|
| 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 | | - } |
|---|
| 74 | + qe = qe_get_device_node(); |
|---|
| 75 | + if (!qe) |
|---|
| 76 | + return qebase; |
|---|
| 84 | 77 | |
|---|
| 85 | 78 | ret = of_address_to_resource(qe, 0, &res); |
|---|
| 86 | 79 | if (!ret) |
|---|
| .. | .. |
|---|
| 111 | 104 | { |
|---|
| 112 | 105 | unsigned long flags; |
|---|
| 113 | 106 | u8 mcn_shift = 0, dev_shift = 0; |
|---|
| 114 | | - u32 ret; |
|---|
| 107 | + u32 val; |
|---|
| 108 | + int ret; |
|---|
| 115 | 109 | |
|---|
| 116 | 110 | spin_lock_irqsave(&qe_lock, flags); |
|---|
| 117 | 111 | if (cmd == QE_RESET) { |
|---|
| 118 | | - out_be32(&qe_immr->cp.cecr, (u32) (cmd | QE_CR_FLG)); |
|---|
| 112 | + qe_iowrite32be((u32)(cmd | QE_CR_FLG), &qe_immr->cp.cecr); |
|---|
| 119 | 113 | } else { |
|---|
| 120 | 114 | if (cmd == QE_ASSIGN_PAGE) { |
|---|
| 121 | 115 | /* Here device is the SNUM, not sub-block */ |
|---|
| .. | .. |
|---|
| 132 | 126 | mcn_shift = QE_CR_MCN_NORMAL_SHIFT; |
|---|
| 133 | 127 | } |
|---|
| 134 | 128 | |
|---|
| 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)); |
|---|
| 129 | + qe_iowrite32be(cmd_input, &qe_immr->cp.cecdr); |
|---|
| 130 | + qe_iowrite32be((cmd | QE_CR_FLG | ((u32)device << dev_shift) | (u32)mcn_protocol << mcn_shift), |
|---|
| 131 | + &qe_immr->cp.cecr); |
|---|
| 139 | 132 | } |
|---|
| 140 | 133 | |
|---|
| 141 | 134 | /* 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). */ |
|---|
| 135 | + ret = readx_poll_timeout_atomic(qe_ioread32be, &qe_immr->cp.cecr, val, |
|---|
| 136 | + (val & QE_CR_FLG) == 0, 0, 100); |
|---|
| 137 | + /* On timeout, ret is -ETIMEDOUT, otherwise it will be 0. */ |
|---|
| 146 | 138 | spin_unlock_irqrestore(&qe_lock, flags); |
|---|
| 147 | 139 | |
|---|
| 148 | | - return ret == 1; |
|---|
| 140 | + return ret == 0; |
|---|
| 149 | 141 | } |
|---|
| 150 | 142 | EXPORT_SYMBOL(qe_issue_cmd); |
|---|
| 151 | 143 | |
|---|
| .. | .. |
|---|
| 167 | 159 | unsigned int qe_get_brg_clk(void) |
|---|
| 168 | 160 | { |
|---|
| 169 | 161 | struct device_node *qe; |
|---|
| 170 | | - int size; |
|---|
| 171 | | - const u32 *prop; |
|---|
| 162 | + u32 brg; |
|---|
| 172 | 163 | unsigned int mod; |
|---|
| 173 | 164 | |
|---|
| 174 | 165 | if (brg_clk) |
|---|
| 175 | 166 | return brg_clk; |
|---|
| 176 | 167 | |
|---|
| 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 | | - } |
|---|
| 168 | + qe = qe_get_device_node(); |
|---|
| 169 | + if (!qe) |
|---|
| 170 | + return brg_clk; |
|---|
| 183 | 171 | |
|---|
| 184 | | - prop = of_get_property(qe, "brg-frequency", &size); |
|---|
| 185 | | - if (prop && size == sizeof(*prop)) |
|---|
| 186 | | - brg_clk = *prop; |
|---|
| 172 | + if (!of_property_read_u32(qe, "brg-frequency", &brg)) |
|---|
| 173 | + brg_clk = brg; |
|---|
| 187 | 174 | |
|---|
| 188 | 175 | of_node_put(qe); |
|---|
| 189 | 176 | |
|---|
| .. | .. |
|---|
| 202 | 189 | |
|---|
| 203 | 190 | #define PVR_VER_836x 0x8083 |
|---|
| 204 | 191 | #define PVR_VER_832x 0x8084 |
|---|
| 192 | + |
|---|
| 193 | +static bool qe_general4_errata(void) |
|---|
| 194 | +{ |
|---|
| 195 | +#ifdef CONFIG_PPC32 |
|---|
| 196 | + return pvr_version_is(PVR_VER_836x) || pvr_version_is(PVR_VER_832x); |
|---|
| 197 | +#endif |
|---|
| 198 | + return false; |
|---|
| 199 | +} |
|---|
| 205 | 200 | |
|---|
| 206 | 201 | /* Program the BRG to the given sampling rate and multiplier |
|---|
| 207 | 202 | * |
|---|
| .. | .. |
|---|
| 229 | 224 | /* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says |
|---|
| 230 | 225 | that the BRG divisor must be even if you're not using divide-by-16 |
|---|
| 231 | 226 | mode. */ |
|---|
| 232 | | - if (pvr_version_is(PVR_VER_836x) || pvr_version_is(PVR_VER_832x)) |
|---|
| 227 | + if (qe_general4_errata()) |
|---|
| 233 | 228 | if (!div16 && (divisor & 1) && (divisor > 3)) |
|---|
| 234 | 229 | divisor++; |
|---|
| 235 | 230 | |
|---|
| 236 | 231 | tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | |
|---|
| 237 | 232 | QE_BRGC_ENABLE | div16; |
|---|
| 238 | 233 | |
|---|
| 239 | | - out_be32(&qe_immr->brg.brgc[brg - QE_BRG1], tempval); |
|---|
| 234 | + qe_iowrite32be(tempval, &qe_immr->brg.brgc[brg - QE_BRG1]); |
|---|
| 240 | 235 | |
|---|
| 241 | 236 | return 0; |
|---|
| 242 | 237 | } |
|---|
| .. | .. |
|---|
| 285 | 280 | */ |
|---|
| 286 | 281 | static void qe_snums_init(void) |
|---|
| 287 | 282 | { |
|---|
| 288 | | - int i; |
|---|
| 289 | 283 | static const u8 snum_init_76[] = { |
|---|
| 290 | 284 | 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D, |
|---|
| 291 | 285 | 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89, |
|---|
| .. | .. |
|---|
| 306 | 300 | 0x28, 0x29, 0x38, 0x39, 0x48, 0x49, 0x58, 0x59, |
|---|
| 307 | 301 | 0x68, 0x69, 0x78, 0x79, 0x80, 0x81, |
|---|
| 308 | 302 | }; |
|---|
| 309 | | - static const u8 *snum_init; |
|---|
| 303 | + struct device_node *qe; |
|---|
| 304 | + const u8 *snum_init; |
|---|
| 305 | + int i; |
|---|
| 310 | 306 | |
|---|
| 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; |
|---|
| 307 | + bitmap_zero(snum_state, QE_NUM_OF_SNUM); |
|---|
| 308 | + qe_num_of_snum = 28; /* The default number of snum for threads is 28 */ |
|---|
| 309 | + qe = qe_get_device_node(); |
|---|
| 310 | + if (qe) { |
|---|
| 311 | + i = of_property_read_variable_u8_array(qe, "fsl,qe-snums", |
|---|
| 312 | + snums, 1, QE_NUM_OF_SNUM); |
|---|
| 313 | + if (i > 0) { |
|---|
| 314 | + of_node_put(qe); |
|---|
| 315 | + qe_num_of_snum = i; |
|---|
| 316 | + return; |
|---|
| 317 | + } |
|---|
| 318 | + /* |
|---|
| 319 | + * Fall back to legacy binding of using the value of |
|---|
| 320 | + * fsl,qe-num-snums to choose one of the static arrays |
|---|
| 321 | + * above. |
|---|
| 322 | + */ |
|---|
| 323 | + of_property_read_u32(qe, "fsl,qe-num-snums", &qe_num_of_snum); |
|---|
| 324 | + of_node_put(qe); |
|---|
| 321 | 325 | } |
|---|
| 326 | + |
|---|
| 327 | + if (qe_num_of_snum == 76) { |
|---|
| 328 | + snum_init = snum_init_76; |
|---|
| 329 | + } else if (qe_num_of_snum == 28 || qe_num_of_snum == 46) { |
|---|
| 330 | + snum_init = snum_init_46; |
|---|
| 331 | + } else { |
|---|
| 332 | + pr_err("QE: unsupported value of fsl,qe-num-snums: %u\n", qe_num_of_snum); |
|---|
| 333 | + return; |
|---|
| 334 | + } |
|---|
| 335 | + memcpy(snums, snum_init, qe_num_of_snum); |
|---|
| 322 | 336 | } |
|---|
| 323 | 337 | |
|---|
| 324 | 338 | int qe_get_snum(void) |
|---|
| .. | .. |
|---|
| 328 | 342 | int i; |
|---|
| 329 | 343 | |
|---|
| 330 | 344 | 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 | | - } |
|---|
| 345 | + i = find_first_zero_bit(snum_state, qe_num_of_snum); |
|---|
| 346 | + if (i < qe_num_of_snum) { |
|---|
| 347 | + set_bit(i, snum_state); |
|---|
| 348 | + snum = snums[i]; |
|---|
| 337 | 349 | } |
|---|
| 338 | 350 | spin_unlock_irqrestore(&qe_lock, flags); |
|---|
| 339 | 351 | |
|---|
| .. | .. |
|---|
| 343 | 355 | |
|---|
| 344 | 356 | void qe_put_snum(u8 snum) |
|---|
| 345 | 357 | { |
|---|
| 346 | | - int i; |
|---|
| 358 | + const u8 *p = memchr(snums, snum, qe_num_of_snum); |
|---|
| 347 | 359 | |
|---|
| 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 | | - } |
|---|
| 360 | + if (p) |
|---|
| 361 | + clear_bit(p - snums, snum_state); |
|---|
| 354 | 362 | } |
|---|
| 355 | 363 | EXPORT_SYMBOL(qe_put_snum); |
|---|
| 356 | 364 | |
|---|
| 357 | 365 | static int qe_sdma_init(void) |
|---|
| 358 | 366 | { |
|---|
| 359 | 367 | struct sdma __iomem *sdma = &qe_immr->sdma; |
|---|
| 360 | | - static unsigned long sdma_buf_offset = (unsigned long)-ENOMEM; |
|---|
| 361 | | - |
|---|
| 362 | | - if (!sdma) |
|---|
| 363 | | - return -ENODEV; |
|---|
| 368 | + static s32 sdma_buf_offset = -ENOMEM; |
|---|
| 364 | 369 | |
|---|
| 365 | 370 | /* allocate 2 internal temporary buffers (512 bytes size each) for |
|---|
| 366 | 371 | * the SDMA */ |
|---|
| 367 | | - if (IS_ERR_VALUE(sdma_buf_offset)) { |
|---|
| 372 | + if (sdma_buf_offset < 0) { |
|---|
| 368 | 373 | sdma_buf_offset = qe_muram_alloc(512 * 2, 4096); |
|---|
| 369 | | - if (IS_ERR_VALUE(sdma_buf_offset)) |
|---|
| 374 | + if (sdma_buf_offset < 0) |
|---|
| 370 | 375 | return -ENOMEM; |
|---|
| 371 | 376 | } |
|---|
| 372 | 377 | |
|---|
| 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))); |
|---|
| 378 | + qe_iowrite32be((u32)sdma_buf_offset & QE_SDEBCR_BA_MASK, |
|---|
| 379 | + &sdma->sdebcr); |
|---|
| 380 | + qe_iowrite32be((QE_SDMR_GLB_1_MSK | (0x1 << QE_SDMR_CEN_SHIFT)), |
|---|
| 381 | + &sdma->sdmr); |
|---|
| 376 | 382 | |
|---|
| 377 | 383 | return 0; |
|---|
| 378 | 384 | } |
|---|
| .. | .. |
|---|
| 410 | 416 | "uploading microcode '%s'\n", ucode->id); |
|---|
| 411 | 417 | |
|---|
| 412 | 418 | /* 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); |
|---|
| 419 | + qe_iowrite32be(be32_to_cpu(ucode->iram_offset) | QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR, |
|---|
| 420 | + &qe_immr->iram.iadd); |
|---|
| 415 | 421 | |
|---|
| 416 | 422 | for (i = 0; i < be32_to_cpu(ucode->count); i++) |
|---|
| 417 | | - out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i])); |
|---|
| 423 | + qe_iowrite32be(be32_to_cpu(code[i]), &qe_immr->iram.idata); |
|---|
| 418 | 424 | |
|---|
| 419 | 425 | /* Set I-RAM Ready Register */ |
|---|
| 420 | | - out_be32(&qe_immr->iram.iready, be32_to_cpu(QE_IRAM_READY)); |
|---|
| 426 | + qe_iowrite32be(QE_IRAM_READY, &qe_immr->iram.iready); |
|---|
| 421 | 427 | } |
|---|
| 422 | 428 | |
|---|
| 423 | 429 | /* |
|---|
| 424 | 430 | * Upload a microcode to the I-RAM at a specific address. |
|---|
| 425 | 431 | * |
|---|
| 426 | | - * See Documentation/powerpc/qe_firmware.txt for information on QE microcode |
|---|
| 432 | + * See Documentation/powerpc/qe_firmware.rst for information on QE microcode |
|---|
| 427 | 433 | * uploading. |
|---|
| 428 | 434 | * |
|---|
| 429 | 435 | * Currently, only version 1 is supported, so the 'version' field must be |
|---|
| .. | .. |
|---|
| 442 | 448 | unsigned int i; |
|---|
| 443 | 449 | unsigned int j; |
|---|
| 444 | 450 | u32 crc; |
|---|
| 445 | | - size_t calc_size = sizeof(struct qe_firmware); |
|---|
| 451 | + size_t calc_size; |
|---|
| 446 | 452 | size_t length; |
|---|
| 447 | 453 | const struct qe_header *hdr; |
|---|
| 448 | 454 | |
|---|
| .. | .. |
|---|
| 474 | 480 | } |
|---|
| 475 | 481 | |
|---|
| 476 | 482 | /* Validate the length and check if there's a CRC */ |
|---|
| 477 | | - calc_size += (firmware->count - 1) * sizeof(struct qe_microcode); |
|---|
| 483 | + calc_size = struct_size(firmware, microcode, firmware->count); |
|---|
| 478 | 484 | |
|---|
| 479 | 485 | for (i = 0; i < firmware->count; i++) |
|---|
| 480 | 486 | /* |
|---|
| .. | .. |
|---|
| 502 | 508 | * If the microcode calls for it, split the I-RAM. |
|---|
| 503 | 509 | */ |
|---|
| 504 | 510 | if (!firmware->split) |
|---|
| 505 | | - setbits16(&qe_immr->cp.cercr, QE_CP_CERCR_CIR); |
|---|
| 511 | + qe_setbits_be16(&qe_immr->cp.cercr, QE_CP_CERCR_CIR); |
|---|
| 506 | 512 | |
|---|
| 507 | 513 | if (firmware->soc.model) |
|---|
| 508 | 514 | printk(KERN_INFO |
|---|
| .. | .. |
|---|
| 519 | 525 | */ |
|---|
| 520 | 526 | memset(&qe_firmware_info, 0, sizeof(qe_firmware_info)); |
|---|
| 521 | 527 | strlcpy(qe_firmware_info.id, firmware->id, sizeof(qe_firmware_info.id)); |
|---|
| 522 | | - qe_firmware_info.extended_modes = firmware->extended_modes; |
|---|
| 528 | + qe_firmware_info.extended_modes = be64_to_cpu(firmware->extended_modes); |
|---|
| 523 | 529 | memcpy(qe_firmware_info.vtraps, firmware->vtraps, |
|---|
| 524 | 530 | sizeof(firmware->vtraps)); |
|---|
| 525 | 531 | |
|---|
| .. | .. |
|---|
| 536 | 542 | u32 trap = be32_to_cpu(ucode->traps[j]); |
|---|
| 537 | 543 | |
|---|
| 538 | 544 | if (trap) |
|---|
| 539 | | - out_be32(&qe_immr->rsp[i].tibcr[j], trap); |
|---|
| 545 | + qe_iowrite32be(trap, |
|---|
| 546 | + &qe_immr->rsp[i].tibcr[j]); |
|---|
| 540 | 547 | } |
|---|
| 541 | 548 | |
|---|
| 542 | 549 | /* Enable traps */ |
|---|
| 543 | | - out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr)); |
|---|
| 550 | + qe_iowrite32be(be32_to_cpu(ucode->eccr), |
|---|
| 551 | + &qe_immr->rsp[i].eccr); |
|---|
| 544 | 552 | } |
|---|
| 545 | 553 | |
|---|
| 546 | 554 | qe_firmware_uploaded = 1; |
|---|
| .. | .. |
|---|
| 558 | 566 | struct qe_firmware_info *qe_get_firmware_info(void) |
|---|
| 559 | 567 | { |
|---|
| 560 | 568 | static int initialized; |
|---|
| 561 | | - struct property *prop; |
|---|
| 562 | 569 | struct device_node *qe; |
|---|
| 563 | 570 | struct device_node *fw = NULL; |
|---|
| 564 | 571 | const char *sprop; |
|---|
| 565 | | - unsigned int i; |
|---|
| 566 | 572 | |
|---|
| 567 | 573 | /* |
|---|
| 568 | 574 | * If we haven't checked yet, and a driver hasn't uploaded a firmware |
|---|
| .. | .. |
|---|
| 576 | 582 | |
|---|
| 577 | 583 | initialized = 1; |
|---|
| 578 | 584 | |
|---|
| 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 | | - } |
|---|
| 585 | + qe = qe_get_device_node(); |
|---|
| 586 | + if (!qe) |
|---|
| 587 | + return NULL; |
|---|
| 589 | 588 | |
|---|
| 590 | 589 | /* Find the 'firmware' child node */ |
|---|
| 591 | | - for_each_child_of_node(qe, fw) { |
|---|
| 592 | | - if (strcmp(fw->name, "firmware") == 0) |
|---|
| 593 | | - break; |
|---|
| 594 | | - } |
|---|
| 595 | | - |
|---|
| 590 | + fw = of_get_child_by_name(qe, "firmware"); |
|---|
| 596 | 591 | of_node_put(qe); |
|---|
| 597 | 592 | |
|---|
| 598 | 593 | /* Did we find the 'firmware' node? */ |
|---|
| .. | .. |
|---|
| 607 | 602 | strlcpy(qe_firmware_info.id, sprop, |
|---|
| 608 | 603 | sizeof(qe_firmware_info.id)); |
|---|
| 609 | 604 | |
|---|
| 610 | | - prop = of_find_property(fw, "extended-modes", NULL); |
|---|
| 611 | | - if (prop && (prop->length == sizeof(u64))) { |
|---|
| 612 | | - const u64 *iprop = prop->value; |
|---|
| 605 | + of_property_read_u64(fw, "extended-modes", |
|---|
| 606 | + &qe_firmware_info.extended_modes); |
|---|
| 613 | 607 | |
|---|
| 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 | | - } |
|---|
| 608 | + of_property_read_u32_array(fw, "virtual-traps", qe_firmware_info.vtraps, |
|---|
| 609 | + ARRAY_SIZE(qe_firmware_info.vtraps)); |
|---|
| 624 | 610 | |
|---|
| 625 | 611 | of_node_put(fw); |
|---|
| 626 | 612 | |
|---|
| .. | .. |
|---|
| 631 | 617 | unsigned int qe_get_num_of_risc(void) |
|---|
| 632 | 618 | { |
|---|
| 633 | 619 | struct device_node *qe; |
|---|
| 634 | | - int size; |
|---|
| 635 | 620 | unsigned int num_of_risc = 0; |
|---|
| 636 | | - const u32 *prop; |
|---|
| 637 | 621 | |
|---|
| 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 | | - } |
|---|
| 622 | + qe = qe_get_device_node(); |
|---|
| 623 | + if (!qe) |
|---|
| 624 | + return num_of_risc; |
|---|
| 648 | 625 | |
|---|
| 649 | | - prop = of_get_property(qe, "fsl,qe-num-riscs", &size); |
|---|
| 650 | | - if (prop && size == sizeof(*prop)) |
|---|
| 651 | | - num_of_risc = *prop; |
|---|
| 626 | + of_property_read_u32(qe, "fsl,qe-num-riscs", &num_of_risc); |
|---|
| 652 | 627 | |
|---|
| 653 | 628 | of_node_put(qe); |
|---|
| 654 | 629 | |
|---|
| .. | .. |
|---|
| 658 | 633 | |
|---|
| 659 | 634 | unsigned int qe_get_num_of_snums(void) |
|---|
| 660 | 635 | { |
|---|
| 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; |
|---|
| 636 | + return qe_num_of_snum; |
|---|
| 692 | 637 | } |
|---|
| 693 | 638 | EXPORT_SYMBOL(qe_get_num_of_snums); |
|---|
| 694 | 639 | |
|---|