/* We allocate this here because it is used almost exclusively for * the communication processor devices.
*/ struct qe_immap __iomem *qe_immr;
EXPORT_SYMBOL(qe_immr);
/* * Newer device trees have an "fsl,qe" compatible property for the QE * node, but we still need to support older device trees.
*/
qe = of_find_compatible_node(NULL, NULL, "fsl,qe"); if (qe) return qe; return of_find_node_by_type(NULL, "qe");
}
/* wait for the QE_CR_FLG to clear */
ret = readx_poll_timeout_atomic(ioread32be, &qe_immr->cp.cecr, val,
(val & QE_CR_FLG) == 0, 0, 100); /* On timeout, ret is -ETIMEDOUT, otherwise it will be 0. */
spin_unlock_irqrestore(&qe_lock, flags);
return ret == 0;
}
EXPORT_SYMBOL(qe_issue_cmd);
/* Set a baud rate generator. This needs lots of work. There are * 16 BRGs, which can be connected to the QE channels or output * as clocks. The BRGs are in two different block of internal * memory mapped space. * The BRG clock is the QE clock divided by 2. * It was set up long ago during the initial boot phase and is * given to us. * Baud rate clocks are zero-based in the driver code (as that maps * to port numbers). Documentation uses 1-based numbering.
*/ staticunsignedint brg_clk = 0;
qe = qe_get_device_node(); if (!qe) return brg_clk;
if (!of_property_read_u32(qe, "brg-frequency", &brg))
brg_clk = brg;
of_node_put(qe);
/* round this if near to a multiple of CLK_GRAN */
mod = brg_clk % CLK_GRAN; if (mod) { if (mod < CLK_GRAN_LIMIT)
brg_clk -= mod; elseif (mod > (CLK_GRAN - CLK_GRAN_LIMIT))
brg_clk += CLK_GRAN - mod;
}
/* Program the BRG to the given sampling rate and multiplier * * @brg: the BRG, QE_BRG1 - QE_BRG16 * @rate: the desired sampling rate * @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or * GUMR_L[TDCR]. E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01, * then 'multiplier' should be 8.
*/ int qe_setbrg(enum qe_clock brg, unsignedint rate, unsignedint multiplier)
{
u32 divisor, tempval;
u32 div16 = 0;
if ((brg < QE_BRG1) || (brg > QE_BRG16)) return -EINVAL;
/* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says that the BRG divisor must be even if you're not using divide-by-16
mode. */ if (qe_general4_errata()) if (!div16 && (divisor & 1) && (divisor > 3))
divisor++;
/* Convert a string to a QE clock source enum * * This function takes a string, typically from a property in the device * tree, and returns the corresponding "enum qe_clock" value.
*/ enum qe_clock qe_clock_source(constchar *source)
{ unsignedint i;
if (strcasecmp(source, "none") == 0) return QE_CLK_NONE;
if (strcmp(source, "tsync_pin") == 0) return QE_TSYNC_PIN;
if (strcmp(source, "rsync_pin") == 0) return QE_RSYNC_PIN;
if (strncasecmp(source, "brg", 3) == 0) {
i = simple_strtoul(source + 3, NULL, 10); if ((i >= 1) && (i <= 16)) return (QE_BRG1 - 1) + i; else return QE_CLK_DUMMY;
}
if (strncasecmp(source, "clk", 3) == 0) {
i = simple_strtoul(source + 3, NULL, 10); if ((i >= 1) && (i <= 24)) return (QE_CLK1 - 1) + i; else return QE_CLK_DUMMY;
}
bitmap_zero(snum_state, QE_NUM_OF_SNUM);
qe_num_of_snum = 28; /* The default number of snum for threads is 28 */
qe = qe_get_device_node(); if (qe) {
i = of_property_read_variable_u8_array(qe, "fsl,qe-snums",
snums, 1, QE_NUM_OF_SNUM); if (i > 0) {
of_node_put(qe);
qe_num_of_snum = i; return;
} /* * Fall back to legacy binding of using the value of * fsl,qe-num-snums to choose one of the static arrays * above.
*/
of_property_read_u32(qe, "fsl,qe-num-snums", &qe_num_of_snum);
of_node_put(qe);
}
/* The maximum number of RISCs we support */ #define MAX_QE_RISC 4
/* Firmware information stored here for qe_get_firmware_info() */ staticstruct qe_firmware_info qe_firmware_info;
/* * Set to 1 if QE firmware has been uploaded, and therefore * qe_firmware_info contains valid data.
*/ staticint qe_firmware_uploaded;
/* * Upload a QE microcode * * This function is a worker function for qe_upload_firmware(). It does * the actual uploading of the microcode.
*/ staticvoid qe_upload_microcode(constvoid *base, conststruct qe_microcode *ucode)
{ const __be32 *code = base + be32_to_cpu(ucode->code_offset); unsignedint i;
/* Use auto-increment */
iowrite32be(be32_to_cpu(ucode->iram_offset) | QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR,
&qe_immr->iram.iadd);
for (i = 0; i < be32_to_cpu(ucode->count); i++)
iowrite32be(be32_to_cpu(code[i]), &qe_immr->iram.idata);
/* Set I-RAM Ready Register */
iowrite32be(QE_IRAM_READY, &qe_immr->iram.iready);
}
/* * Upload a microcode to the I-RAM at a specific address. * * See Documentation/arch/powerpc/qe_firmware.rst for information on QE microcode * uploading. * * Currently, only version 1 is supported, so the 'version' field must be * set to 1. * * The SOC model and revision are not validated, they are only displayed for * informational purposes. * * 'calc_size' is the calculated size, in bytes, of the firmware structure and * all of the microcode structures, minus the CRC. * * 'length' is the size that the structure says it is, including the CRC.
*/ int qe_upload_firmware(conststruct qe_firmware *firmware)
{ unsignedint i; unsignedint j;
u32 crc;
size_t calc_size;
size_t length; conststruct qe_header *hdr;
if (!firmware) {
printk(KERN_ERR "qe-firmware: invalid pointer\n"); return -EINVAL;
}
/* Check the magic */ if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
(hdr->magic[2] != 'F')) {
printk(KERN_ERR "qe-firmware: not a microcode\n"); return -EPERM;
}
/* Check the version */ if (hdr->version != 1) {
printk(KERN_ERR "qe-firmware: unsupported version\n"); return -EPERM;
}
/* Validate some of the fields */ if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
printk(KERN_ERR "qe-firmware: invalid data\n"); return -EINVAL;
}
/* Validate the length and check if there's a CRC */
calc_size = struct_size(firmware, microcode, firmware->count);
for (i = 0; i < firmware->count; i++) /* * For situations where the second RISC uses the same microcode * as the first, the 'code_offset' and 'count' fields will be * zero, so it's okay to add those.
*/
calc_size += sizeof(__be32) *
be32_to_cpu(firmware->microcode[i].count);
/* Validate the length */ if (length != calc_size + sizeof(__be32)) {
printk(KERN_ERR "qe-firmware: invalid length\n"); return -EPERM;
}
/* Validate the CRC */
crc = be32_to_cpu(*(__be32 *)((void *)firmware + calc_size)); if (crc != crc32(0, firmware, calc_size)) {
printk(KERN_ERR "qe-firmware: firmware CRC is invalid\n"); return -EIO;
}
/* * If the microcode calls for it, split the I-RAM.
*/ if (!firmware->split)
qe_setbits_be16(&qe_immr->cp.cercr, QE_CP_CERCR_CIR);
if (firmware->soc.model)
printk(KERN_INFO "qe-firmware: firmware '%s' for %u V%u.%u\n",
firmware->id, be16_to_cpu(firmware->soc.model),
firmware->soc.major, firmware->soc.minor); else
printk(KERN_INFO "qe-firmware: firmware '%s'\n",
firmware->id);
/* * The QE only supports one microcode per RISC, so clear out all the * saved microcode information and put in the new.
*/
memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
strscpy(qe_firmware_info.id, firmware->id, sizeof(qe_firmware_info.id));
qe_firmware_info.extended_modes = be64_to_cpu(firmware->extended_modes);
memcpy(qe_firmware_info.vtraps, firmware->vtraps, sizeof(firmware->vtraps));
/* Loop through each microcode. */ for (i = 0; i < firmware->count; i++) { conststruct qe_microcode *ucode = &firmware->microcode[i];
/* Upload a microcode if it's present */ if (ucode->code_offset)
qe_upload_microcode(firmware, ucode);
/* Program the traps for this processor */ for (j = 0; j < 16; j++) {
u32 trap = be32_to_cpu(ucode->traps[j]);
if (trap)
iowrite32be(trap,
&qe_immr->rsp[i].tibcr[j]);
}
/* * Get info on the currently-loaded firmware * * This function also checks the device tree to see if the boot loader has * uploaded a firmware already.
*/ struct qe_firmware_info *qe_get_firmware_info(void)
{ staticint initialized; struct device_node *qe; struct device_node *fw = NULL; constchar *sprop;
/* * If we haven't checked yet, and a driver hasn't uploaded a firmware * yet, then check the device tree for information.
*/ if (qe_firmware_uploaded) return &qe_firmware_info;
/* Did we find the 'firmware' node? */ if (!fw) return NULL;
qe_firmware_uploaded = 1;
/* Copy the data into qe_firmware_info*/
sprop = of_get_property(fw, "id", NULL); if (sprop)
strscpy(qe_firmware_info.id, sprop, sizeof(qe_firmware_info.id));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.