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