blob: d9c04f588f7f3cb2ab1170712c87b4d160384457 [file] [log] [blame]
Li Yang98658532006-10-03 23:10:46 -05001/*
Yang Li8a56e1e2012-11-01 18:53:42 +00002 * Copyright (C) 2006-2010 Freescale Semiconductor, Inc. All rights reserved.
Li Yang98658532006-10-03 23:10:46 -05003 *
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>
Anton Vorontsov09a3fba2008-11-11 18:31:39 +030022#include <linux/spinlock.h>
Li Yang98658532006-10-03 23:10:46 -050023#include <linux/mm.h>
24#include <linux/interrupt.h>
Li Yang98658532006-10-03 23:10:46 -050025#include <linux/module.h>
26#include <linux/delay.h>
27#include <linux/ioport.h>
Timur Tabibc556ba2008-01-08 10:30:58 -060028#include <linux/crc32.h>
Anton Vorontsovfdfde242009-09-16 01:43:55 +040029#include <linux/mod_devicetable.h>
30#include <linux/of_platform.h>
Li Yang98658532006-10-03 23:10:46 -050031#include <asm/irq.h>
32#include <asm/page.h>
33#include <asm/pgtable.h>
Zhao Qiang7aa1aa62015-11-30 10:48:57 +080034#include <soc/fsl/qe/immap_qe.h>
35#include <soc/fsl/qe/qe.h>
Li Yang98658532006-10-03 23:10:46 -050036#include <asm/prom.h>
37#include <asm/rheap.h>
38
39static void qe_snums_init(void);
Li Yang98658532006-10-03 23:10:46 -050040static int qe_sdma_init(void);
41
42static DEFINE_SPINLOCK(qe_lock);
Anton Vorontsov09a3fba2008-11-11 18:31:39 +030043DEFINE_SPINLOCK(cmxgcr_lock);
44EXPORT_SYMBOL(cmxgcr_lock);
Li Yang98658532006-10-03 23:10:46 -050045
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 */
Anton Vorontsov0b51b022008-03-11 20:24:13 +030061struct qe_immap __iomem *qe_immr;
Li Yang98658532006-10-03 23:10:46 -050062EXPORT_SYMBOL(qe_immr);
63
64static struct qe_snum snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */
Haiying Wang98ca77a2009-05-01 15:40:48 -040065static unsigned int qe_num_of_snum;
Li Yang98658532006-10-03 23:10:46 -050066
67static phys_addr_t qebase = -1;
68
Christophe Leroyb54ea822017-02-07 10:05:11 +010069static phys_addr_t get_qe_base(void)
Li Yang98658532006-10-03 23:10:46 -050070{
71 struct device_node *qe;
Zhao Qiang50669432016-09-23 10:20:31 +080072 int ret;
73 struct resource res;
Li Yang98658532006-10-03 23:10:46 -050074
75 if (qebase != -1)
76 return qebase;
77
Anton Vorontsova2dd70a2008-01-24 18:39:59 +030078 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
Zhao Qiang50669432016-09-23 10:20:31 +080085 ret = of_address_to_resource(qe, 0, &res);
86 if (!ret)
87 qebase = res.start;
Anton Vorontsova2dd70a2008-01-24 18:39:59 +030088 of_node_put(qe);
Li Yang98658532006-10-03 23:10:46 -050089
90 return qebase;
91}
92
Anton Vorontsov0c7b87b2009-09-16 01:43:52 +040093void qe_reset(void)
Li Yang98658532006-10-03 23:10:46 -050094{
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;
Timur Tabif49156ea2009-05-26 10:21:42 -0500114 u32 ret;
Li Yang98658532006-10-03 23:10:46 -0500115
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
Timur Tabi302439d2006-10-31 17:53:42 +0800135 out_be32(&qe_immr->cp.cecdr, cmd_input);
Li Yang98658532006-10-03 23:10:46 -0500136 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 */
Timur Tabif49156ea2009-05-26 10:21:42 -0500142 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). */
Li Yang98658532006-10-03 23:10:46 -0500146 spin_unlock_irqrestore(&qe_lock, flags);
147
Timur Tabif49156ea2009-05-26 10:21:42 -0500148 return ret == 1;
Li Yang98658532006-10-03 23:10:46 -0500149}
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.
Timur Tabi6b0b5942007-10-03 11:34:59 -0500156 * The BRG clock is the QE clock divided by 2.
Li Yang98658532006-10-03 23:10:46 -0500157 * 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
Anton Vorontsov7f0a6fc2008-03-11 20:24:24 +0300164unsigned int qe_get_brg_clk(void)
Li Yang98658532006-10-03 23:10:46 -0500165{
166 struct device_node *qe;
Andy Fleming7e1cc9c2008-05-07 13:19:44 -0500167 int size;
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300168 const u32 *prop;
169
Li Yang98658532006-10-03 23:10:46 -0500170 if (brg_clk)
171 return brg_clk;
172
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300173 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
174 if (!qe) {
175 qe = of_find_node_by_type(NULL, "qe");
176 if (!qe)
177 return brg_clk;
178 }
179
180 prop = of_get_property(qe, "brg-frequency", &size);
Anton Vorontsovd8985fd2008-02-04 16:46:17 +0300181 if (prop && size == sizeof(*prop))
182 brg_clk = *prop;
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300183
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300184 of_node_put(qe);
185
Li Yang98658532006-10-03 23:10:46 -0500186 return brg_clk;
187}
Anton Vorontsov7f0a6fc2008-03-11 20:24:24 +0300188EXPORT_SYMBOL(qe_get_brg_clk);
Li Yang98658532006-10-03 23:10:46 -0500189
Timur Tabi6b0b5942007-10-03 11:34:59 -0500190/* Program the BRG to the given sampling rate and multiplier
191 *
Timur Tabi7264ec42007-11-29 17:26:30 -0600192 * @brg: the BRG, QE_BRG1 - QE_BRG16
Timur Tabi6b0b5942007-10-03 11:34:59 -0500193 * @rate: the desired sampling rate
194 * @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or
195 * GUMR_L[TDCR]. E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01,
196 * then 'multiplier' should be 8.
Li Yang98658532006-10-03 23:10:46 -0500197 */
Timur Tabi7264ec42007-11-29 17:26:30 -0600198int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
Li Yang98658532006-10-03 23:10:46 -0500199{
Li Yang98658532006-10-03 23:10:46 -0500200 u32 divisor, tempval;
Timur Tabi6b0b5942007-10-03 11:34:59 -0500201 u32 div16 = 0;
Li Yang98658532006-10-03 23:10:46 -0500202
Timur Tabi7264ec42007-11-29 17:26:30 -0600203 if ((brg < QE_BRG1) || (brg > QE_BRG16))
204 return -EINVAL;
205
Anton Vorontsov7f0a6fc2008-03-11 20:24:24 +0300206 divisor = qe_get_brg_clk() / (rate * multiplier);
Li Yang98658532006-10-03 23:10:46 -0500207
Li Yang98658532006-10-03 23:10:46 -0500208 if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
Timur Tabi6b0b5942007-10-03 11:34:59 -0500209 div16 = QE_BRGC_DIV16;
Li Yang98658532006-10-03 23:10:46 -0500210 divisor /= 16;
211 }
212
Timur Tabi6b0b5942007-10-03 11:34:59 -0500213 /* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says
214 that the BRG divisor must be even if you're not using divide-by-16
215 mode. */
Joakim Tjernlundae5f8c12011-08-23 14:30:05 +0200216 if (!div16 && (divisor & 1) && (divisor > 3))
Timur Tabi6b0b5942007-10-03 11:34:59 -0500217 divisor++;
Li Yang98658532006-10-03 23:10:46 -0500218
Timur Tabi6b0b5942007-10-03 11:34:59 -0500219 tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
220 QE_BRGC_ENABLE | div16;
221
Timur Tabi7264ec42007-11-29 17:26:30 -0600222 out_be32(&qe_immr->brg.brgc[brg - QE_BRG1], tempval);
223
224 return 0;
Li Yang98658532006-10-03 23:10:46 -0500225}
Timur Tabi7264ec42007-11-29 17:26:30 -0600226EXPORT_SYMBOL(qe_setbrg);
Li Yang98658532006-10-03 23:10:46 -0500227
Timur Tabi174b0da2007-12-03 15:17:58 -0600228/* Convert a string to a QE clock source enum
229 *
230 * This function takes a string, typically from a property in the device
231 * tree, and returns the corresponding "enum qe_clock" value.
232*/
233enum qe_clock qe_clock_source(const char *source)
234{
235 unsigned int i;
236
237 if (strcasecmp(source, "none") == 0)
238 return QE_CLK_NONE;
239
Zhao Qiang68f047e2016-06-06 14:29:58 +0800240 if (strcmp(source, "tsync_pin") == 0)
241 return QE_TSYNC_PIN;
242
243 if (strcmp(source, "rsync_pin") == 0)
244 return QE_RSYNC_PIN;
245
Timur Tabi174b0da2007-12-03 15:17:58 -0600246 if (strncasecmp(source, "brg", 3) == 0) {
247 i = simple_strtoul(source + 3, NULL, 10);
248 if ((i >= 1) && (i <= 16))
249 return (QE_BRG1 - 1) + i;
250 else
251 return QE_CLK_DUMMY;
252 }
253
254 if (strncasecmp(source, "clk", 3) == 0) {
255 i = simple_strtoul(source + 3, NULL, 10);
256 if ((i >= 1) && (i <= 24))
257 return (QE_CLK1 - 1) + i;
258 else
259 return QE_CLK_DUMMY;
260 }
261
262 return QE_CLK_DUMMY;
263}
264EXPORT_SYMBOL(qe_clock_source);
265
Li Yang98658532006-10-03 23:10:46 -0500266/* Initialize SNUMs (thread serial numbers) according to
267 * QE Module Control chapter, SNUM table
268 */
269static void qe_snums_init(void)
270{
271 int i;
Dave Liufa1b42b2010-01-12 00:04:03 +0000272 static const u8 snum_init_76[] = {
273 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
274 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
275 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
276 0xD8, 0xD9, 0xE8, 0xE9, 0x44, 0x45, 0x4C, 0x4D,
277 0x54, 0x55, 0x5C, 0x5D, 0x64, 0x65, 0x6C, 0x6D,
278 0x74, 0x75, 0x7C, 0x7D, 0x84, 0x85, 0x8C, 0x8D,
279 0x94, 0x95, 0x9C, 0x9D, 0xA4, 0xA5, 0xAC, 0xAD,
280 0xB4, 0xB5, 0xBC, 0xBD, 0xC4, 0xC5, 0xCC, 0xCD,
281 0xD4, 0xD5, 0xDC, 0xDD, 0xE4, 0xE5, 0xEC, 0xED,
282 0xF4, 0xF5, 0xFC, 0xFD,
283 };
284 static const u8 snum_init_46[] = {
Li Yang98658532006-10-03 23:10:46 -0500285 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
286 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
287 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
Haiying Wang98ca77a2009-05-01 15:40:48 -0400288 0xD8, 0xD9, 0xE8, 0xE9, 0x08, 0x09, 0x18, 0x19,
289 0x28, 0x29, 0x38, 0x39, 0x48, 0x49, 0x58, 0x59,
290 0x68, 0x69, 0x78, 0x79, 0x80, 0x81,
Li Yang98658532006-10-03 23:10:46 -0500291 };
Dave Liufa1b42b2010-01-12 00:04:03 +0000292 static const u8 *snum_init;
Li Yang98658532006-10-03 23:10:46 -0500293
Haiying Wang98ca77a2009-05-01 15:40:48 -0400294 qe_num_of_snum = qe_get_num_of_snums();
295
Dave Liufa1b42b2010-01-12 00:04:03 +0000296 if (qe_num_of_snum == 76)
297 snum_init = snum_init_76;
298 else
299 snum_init = snum_init_46;
300
Haiying Wang98ca77a2009-05-01 15:40:48 -0400301 for (i = 0; i < qe_num_of_snum; i++) {
Li Yang98658532006-10-03 23:10:46 -0500302 snums[i].num = snum_init[i];
303 snums[i].state = QE_SNUM_STATE_FREE;
304 }
305}
306
307int qe_get_snum(void)
308{
309 unsigned long flags;
310 int snum = -EBUSY;
311 int i;
312
313 spin_lock_irqsave(&qe_lock, flags);
Haiying Wang98ca77a2009-05-01 15:40:48 -0400314 for (i = 0; i < qe_num_of_snum; i++) {
Li Yang98658532006-10-03 23:10:46 -0500315 if (snums[i].state == QE_SNUM_STATE_FREE) {
316 snums[i].state = QE_SNUM_STATE_USED;
317 snum = snums[i].num;
318 break;
319 }
320 }
321 spin_unlock_irqrestore(&qe_lock, flags);
322
323 return snum;
324}
325EXPORT_SYMBOL(qe_get_snum);
326
327void qe_put_snum(u8 snum)
328{
329 int i;
330
Haiying Wang98ca77a2009-05-01 15:40:48 -0400331 for (i = 0; i < qe_num_of_snum; i++) {
Li Yang98658532006-10-03 23:10:46 -0500332 if (snums[i].num == snum) {
333 snums[i].state = QE_SNUM_STATE_FREE;
334 break;
335 }
336 }
337}
338EXPORT_SYMBOL(qe_put_snum);
339
340static int qe_sdma_init(void)
341{
Andy Fleming7e1cc9c2008-05-07 13:19:44 -0500342 struct sdma __iomem *sdma = &qe_immr->sdma;
Anton Vorontsov0c7b87b2009-09-16 01:43:52 +0400343 static unsigned long sdma_buf_offset = (unsigned long)-ENOMEM;
Li Yang98658532006-10-03 23:10:46 -0500344
345 if (!sdma)
346 return -ENODEV;
347
348 /* allocate 2 internal temporary buffers (512 bytes size each) for
349 * the SDMA */
Anton Vorontsov0c7b87b2009-09-16 01:43:52 +0400350 if (IS_ERR_VALUE(sdma_buf_offset)) {
351 sdma_buf_offset = qe_muram_alloc(512 * 2, 4096);
352 if (IS_ERR_VALUE(sdma_buf_offset))
353 return -ENOMEM;
354 }
Li Yang98658532006-10-03 23:10:46 -0500355
Timur Tabi4c356302007-05-08 14:46:36 -0500356 out_be32(&sdma->sdebcr, (u32) sdma_buf_offset & QE_SDEBCR_BA_MASK);
Chuck Meade7f013bc2007-03-27 10:46:10 -0400357 out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK |
358 (0x1 << QE_SDMR_CEN_SHIFT)));
Li Yang98658532006-10-03 23:10:46 -0500359
360 return 0;
361}
362
Timur Tabibc556ba2008-01-08 10:30:58 -0600363/* The maximum number of RISCs we support */
Anton Vorontsov98eaa092009-08-27 21:30:11 +0400364#define MAX_QE_RISC 4
Timur Tabibc556ba2008-01-08 10:30:58 -0600365
366/* Firmware information stored here for qe_get_firmware_info() */
367static struct qe_firmware_info qe_firmware_info;
368
369/*
370 * Set to 1 if QE firmware has been uploaded, and therefore
371 * qe_firmware_info contains valid data.
372 */
373static int qe_firmware_uploaded;
374
375/*
376 * Upload a QE microcode
377 *
378 * This function is a worker function for qe_upload_firmware(). It does
379 * the actual uploading of the microcode.
380 */
381static void qe_upload_microcode(const void *base,
382 const struct qe_microcode *ucode)
383{
384 const __be32 *code = base + be32_to_cpu(ucode->code_offset);
385 unsigned int i;
386
387 if (ucode->major || ucode->minor || ucode->revision)
388 printk(KERN_INFO "qe-firmware: "
389 "uploading microcode '%s' version %u.%u.%u\n",
390 ucode->id, ucode->major, ucode->minor, ucode->revision);
391 else
392 printk(KERN_INFO "qe-firmware: "
393 "uploading microcode '%s'\n", ucode->id);
394
395 /* Use auto-increment */
396 out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
397 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
398
399 for (i = 0; i < be32_to_cpu(ucode->count); i++)
400 out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
Kokoris, Ioannise65650e2011-11-11 17:05:11 +0100401
402 /* Set I-RAM Ready Register */
403 out_be32(&qe_immr->iram.iready, be32_to_cpu(QE_IRAM_READY));
Timur Tabibc556ba2008-01-08 10:30:58 -0600404}
405
406/*
407 * Upload a microcode to the I-RAM at a specific address.
408 *
Paul Bolle395cf962011-08-15 02:02:26 +0200409 * See Documentation/powerpc/qe_firmware.txt for information on QE microcode
Timur Tabibc556ba2008-01-08 10:30:58 -0600410 * uploading.
411 *
412 * Currently, only version 1 is supported, so the 'version' field must be
413 * set to 1.
414 *
415 * The SOC model and revision are not validated, they are only displayed for
416 * informational purposes.
417 *
418 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
419 * all of the microcode structures, minus the CRC.
420 *
421 * 'length' is the size that the structure says it is, including the CRC.
422 */
423int qe_upload_firmware(const struct qe_firmware *firmware)
424{
425 unsigned int i;
426 unsigned int j;
427 u32 crc;
428 size_t calc_size = sizeof(struct qe_firmware);
429 size_t length;
430 const struct qe_header *hdr;
431
432 if (!firmware) {
433 printk(KERN_ERR "qe-firmware: invalid pointer\n");
434 return -EINVAL;
435 }
436
437 hdr = &firmware->header;
438 length = be32_to_cpu(hdr->length);
439
440 /* Check the magic */
441 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
442 (hdr->magic[2] != 'F')) {
443 printk(KERN_ERR "qe-firmware: not a microcode\n");
444 return -EPERM;
445 }
446
447 /* Check the version */
448 if (hdr->version != 1) {
449 printk(KERN_ERR "qe-firmware: unsupported version\n");
450 return -EPERM;
451 }
452
453 /* Validate some of the fields */
Timur Tabi6f913162008-03-03 11:11:30 -0600454 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
Timur Tabibc556ba2008-01-08 10:30:58 -0600455 printk(KERN_ERR "qe-firmware: invalid data\n");
456 return -EINVAL;
457 }
458
459 /* Validate the length and check if there's a CRC */
460 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
461
462 for (i = 0; i < firmware->count; i++)
463 /*
464 * For situations where the second RISC uses the same microcode
465 * as the first, the 'code_offset' and 'count' fields will be
466 * zero, so it's okay to add those.
467 */
468 calc_size += sizeof(__be32) *
469 be32_to_cpu(firmware->microcode[i].count);
470
471 /* Validate the length */
472 if (length != calc_size + sizeof(__be32)) {
473 printk(KERN_ERR "qe-firmware: invalid length\n");
474 return -EPERM;
475 }
476
477 /* Validate the CRC */
478 crc = be32_to_cpu(*(__be32 *)((void *)firmware + calc_size));
479 if (crc != crc32(0, firmware, calc_size)) {
480 printk(KERN_ERR "qe-firmware: firmware CRC is invalid\n");
481 return -EIO;
482 }
483
484 /*
485 * If the microcode calls for it, split the I-RAM.
486 */
487 if (!firmware->split)
488 setbits16(&qe_immr->cp.cercr, QE_CP_CERCR_CIR);
489
490 if (firmware->soc.model)
491 printk(KERN_INFO
492 "qe-firmware: firmware '%s' for %u V%u.%u\n",
493 firmware->id, be16_to_cpu(firmware->soc.model),
494 firmware->soc.major, firmware->soc.minor);
495 else
496 printk(KERN_INFO "qe-firmware: firmware '%s'\n",
497 firmware->id);
498
499 /*
500 * The QE only supports one microcode per RISC, so clear out all the
501 * saved microcode information and put in the new.
502 */
503 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
Rickard Strandqvist5db43122014-07-26 23:26:51 +0200504 strlcpy(qe_firmware_info.id, firmware->id, sizeof(qe_firmware_info.id));
Timur Tabibc556ba2008-01-08 10:30:58 -0600505 qe_firmware_info.extended_modes = firmware->extended_modes;
506 memcpy(qe_firmware_info.vtraps, firmware->vtraps,
507 sizeof(firmware->vtraps));
508
509 /* Loop through each microcode. */
510 for (i = 0; i < firmware->count; i++) {
511 const struct qe_microcode *ucode = &firmware->microcode[i];
512
513 /* Upload a microcode if it's present */
514 if (ucode->code_offset)
515 qe_upload_microcode(firmware, ucode);
516
517 /* Program the traps for this processor */
518 for (j = 0; j < 16; j++) {
519 u32 trap = be32_to_cpu(ucode->traps[j]);
520
521 if (trap)
522 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
523 }
524
525 /* Enable traps */
526 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
527 }
528
529 qe_firmware_uploaded = 1;
530
531 return 0;
532}
533EXPORT_SYMBOL(qe_upload_firmware);
534
535/*
536 * Get info on the currently-loaded firmware
537 *
538 * This function also checks the device tree to see if the boot loader has
539 * uploaded a firmware already.
540 */
541struct qe_firmware_info *qe_get_firmware_info(void)
542{
543 static int initialized;
544 struct property *prop;
545 struct device_node *qe;
546 struct device_node *fw = NULL;
547 const char *sprop;
548 unsigned int i;
549
550 /*
551 * If we haven't checked yet, and a driver hasn't uploaded a firmware
552 * yet, then check the device tree for information.
553 */
Ionut Nicu86f4e5d2008-03-07 19:27:59 +0200554 if (qe_firmware_uploaded)
555 return &qe_firmware_info;
556
557 if (initialized)
Timur Tabibc556ba2008-01-08 10:30:58 -0600558 return NULL;
559
560 initialized = 1;
561
562 /*
563 * Newer device trees have an "fsl,qe" compatible property for the QE
564 * node, but we still need to support older device trees.
565 */
566 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
567 if (!qe) {
568 qe = of_find_node_by_type(NULL, "qe");
569 if (!qe)
570 return NULL;
571 }
572
573 /* Find the 'firmware' child node */
574 for_each_child_of_node(qe, fw) {
575 if (strcmp(fw->name, "firmware") == 0)
576 break;
577 }
578
579 of_node_put(qe);
580
581 /* Did we find the 'firmware' node? */
582 if (!fw)
583 return NULL;
584
585 qe_firmware_uploaded = 1;
586
587 /* Copy the data into qe_firmware_info*/
588 sprop = of_get_property(fw, "id", NULL);
589 if (sprop)
Rickard Strandqvist5db43122014-07-26 23:26:51 +0200590 strlcpy(qe_firmware_info.id, sprop,
591 sizeof(qe_firmware_info.id));
Timur Tabibc556ba2008-01-08 10:30:58 -0600592
593 prop = of_find_property(fw, "extended-modes", NULL);
594 if (prop && (prop->length == sizeof(u64))) {
595 const u64 *iprop = prop->value;
596
597 qe_firmware_info.extended_modes = *iprop;
598 }
599
600 prop = of_find_property(fw, "virtual-traps", NULL);
601 if (prop && (prop->length == 32)) {
602 const u32 *iprop = prop->value;
603
604 for (i = 0; i < ARRAY_SIZE(qe_firmware_info.vtraps); i++)
605 qe_firmware_info.vtraps[i] = iprop[i];
606 }
607
608 of_node_put(fw);
609
610 return &qe_firmware_info;
611}
612EXPORT_SYMBOL(qe_get_firmware_info);
613
Haiying Wang06c44352009-05-01 15:40:47 -0400614unsigned int qe_get_num_of_risc(void)
615{
616 struct device_node *qe;
617 int size;
618 unsigned int num_of_risc = 0;
619 const u32 *prop;
620
621 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
622 if (!qe) {
623 /* Older devices trees did not have an "fsl,qe"
624 * compatible property, so we need to look for
625 * the QE node by name.
626 */
627 qe = of_find_node_by_type(NULL, "qe");
628 if (!qe)
629 return num_of_risc;
630 }
631
632 prop = of_get_property(qe, "fsl,qe-num-riscs", &size);
633 if (prop && size == sizeof(*prop))
634 num_of_risc = *prop;
635
636 of_node_put(qe);
637
638 return num_of_risc;
639}
640EXPORT_SYMBOL(qe_get_num_of_risc);
641
Haiying Wang98ca77a2009-05-01 15:40:48 -0400642unsigned int qe_get_num_of_snums(void)
643{
644 struct device_node *qe;
645 int size;
646 unsigned int num_of_snums;
647 const u32 *prop;
648
649 num_of_snums = 28; /* The default number of snum for threads is 28 */
650 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
651 if (!qe) {
652 /* Older devices trees did not have an "fsl,qe"
653 * compatible property, so we need to look for
654 * the QE node by name.
655 */
656 qe = of_find_node_by_type(NULL, "qe");
657 if (!qe)
658 return num_of_snums;
659 }
660
661 prop = of_get_property(qe, "fsl,qe-num-snums", &size);
662 if (prop && size == sizeof(*prop)) {
663 num_of_snums = *prop;
664 if ((num_of_snums < 28) || (num_of_snums > QE_NUM_OF_SNUM)) {
665 /* No QE ever has fewer than 28 SNUMs */
666 pr_err("QE: number of snum is invalid\n");
Julia Lawall5aac4d72010-08-29 11:52:44 +0200667 of_node_put(qe);
Haiying Wang98ca77a2009-05-01 15:40:48 -0400668 return -EINVAL;
669 }
670 }
671
672 of_node_put(qe);
673
674 return num_of_snums;
675}
676EXPORT_SYMBOL(qe_get_num_of_snums);
Anton Vorontsovfdfde242009-09-16 01:43:55 +0400677
Zhao Qiang302c0592015-11-30 10:48:56 +0800678static int __init qe_init(void)
679{
680 struct device_node *np;
681
682 np = of_find_compatible_node(NULL, NULL, "fsl,qe");
683 if (!np)
684 return -ENODEV;
685 qe_reset();
686 of_node_put(np);
687 return 0;
688}
689subsys_initcall(qe_init);
690
Anton Vorontsovfdfde242009-09-16 01:43:55 +0400691#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx)
Grant Likelya454dc52010-07-22 15:52:34 -0600692static int qe_resume(struct platform_device *ofdev)
Anton Vorontsovfdfde242009-09-16 01:43:55 +0400693{
694 if (!qe_alive_during_sleep())
695 qe_reset();
696 return 0;
697}
698
Grant Likely00006122011-02-22 19:59:54 -0700699static int qe_probe(struct platform_device *ofdev)
Anton Vorontsovfdfde242009-09-16 01:43:55 +0400700{
701 return 0;
702}
703
704static const struct of_device_id qe_ids[] = {
705 { .compatible = "fsl,qe", },
706 { },
707};
708
Grant Likely00006122011-02-22 19:59:54 -0700709static struct platform_driver qe_driver = {
Grant Likely40182942010-04-13 16:13:02 -0700710 .driver = {
711 .name = "fsl-qe",
Grant Likely40182942010-04-13 16:13:02 -0700712 .of_match_table = qe_ids,
713 },
Anton Vorontsovfdfde242009-09-16 01:43:55 +0400714 .probe = qe_probe,
715 .resume = qe_resume,
716};
717
Geliang Tangc9492b42016-11-23 23:04:21 +0800718builtin_platform_driver(qe_driver);
Anton Vorontsovfdfde242009-09-16 01:43:55 +0400719#endif /* defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx) */