blob: 818e763f826509b78efdcd2ca216e395b8a52c43 [file] [log] [blame]
Li Yang98658532006-10-03 23:10:46 -05001/*
Dave Liufa1b42b2010-01-12 00:04:03 +00002 * Copyright (C) 2006-2010 Freescale Semicondutor, 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>
25#include <linux/bootmem.h>
26#include <linux/module.h>
27#include <linux/delay.h>
28#include <linux/ioport.h>
Timur Tabibc556ba2008-01-08 10:30:58 -060029#include <linux/crc32.h>
Anton Vorontsovfdfde242009-09-16 01:43:55 +040030#include <linux/mod_devicetable.h>
31#include <linux/of_platform.h>
Li Yang98658532006-10-03 23:10:46 -050032#include <asm/irq.h>
33#include <asm/page.h>
34#include <asm/pgtable.h>
35#include <asm/immap_qe.h>
36#include <asm/qe.h>
37#include <asm/prom.h>
38#include <asm/rheap.h>
39
40static void qe_snums_init(void);
Li Yang98658532006-10-03 23:10:46 -050041static int qe_sdma_init(void);
42
43static DEFINE_SPINLOCK(qe_lock);
Anton Vorontsov09a3fba2008-11-11 18:31:39 +030044DEFINE_SPINLOCK(cmxgcr_lock);
45EXPORT_SYMBOL(cmxgcr_lock);
Li Yang98658532006-10-03 23:10:46 -050046
47/* QE snum state */
48enum qe_snum_state {
49 QE_SNUM_STATE_USED,
50 QE_SNUM_STATE_FREE
51};
52
53/* QE snum */
54struct qe_snum {
55 u8 num;
56 enum qe_snum_state state;
57};
58
59/* We allocate this here because it is used almost exclusively for
60 * the communication processor devices.
61 */
Anton Vorontsov0b51b022008-03-11 20:24:13 +030062struct qe_immap __iomem *qe_immr;
Li Yang98658532006-10-03 23:10:46 -050063EXPORT_SYMBOL(qe_immr);
64
65static struct qe_snum snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */
Haiying Wang98ca77a2009-05-01 15:40:48 -040066static unsigned int qe_num_of_snum;
Li Yang98658532006-10-03 23:10:46 -050067
68static phys_addr_t qebase = -1;
69
70phys_addr_t get_qe_base(void)
71{
72 struct device_node *qe;
Andy Fleming7e1cc9c2008-05-07 13:19:44 -050073 int size;
Anton Vorontsovd8985fd2008-02-04 16:46:17 +030074 const u32 *prop;
Li Yang98658532006-10-03 23:10:46 -050075
76 if (qebase != -1)
77 return qebase;
78
Anton Vorontsova2dd70a2008-01-24 18:39:59 +030079 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
80 if (!qe) {
81 qe = of_find_node_by_type(NULL, "qe");
82 if (!qe)
83 return qebase;
84 }
85
86 prop = of_get_property(qe, "reg", &size);
Anton Vorontsovd8985fd2008-02-04 16:46:17 +030087 if (prop && size >= sizeof(*prop))
88 qebase = of_translate_address(qe, prop);
Anton Vorontsova2dd70a2008-01-24 18:39:59 +030089 of_node_put(qe);
Li Yang98658532006-10-03 23:10:46 -050090
91 return qebase;
92}
93
94EXPORT_SYMBOL(get_qe_base);
95
Anton Vorontsov0c7b87b2009-09-16 01:43:52 +040096void qe_reset(void)
Li Yang98658532006-10-03 23:10:46 -050097{
98 if (qe_immr == NULL)
99 qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE);
100
101 qe_snums_init();
102
103 qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
104 QE_CR_PROTOCOL_UNSPECIFIED, 0);
105
106 /* Reclaim the MURAM memory for our use. */
107 qe_muram_init();
108
109 if (qe_sdma_init())
110 panic("sdma init failed!");
111}
112
113int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input)
114{
115 unsigned long flags;
116 u8 mcn_shift = 0, dev_shift = 0;
Timur Tabif49156ea2009-05-26 10:21:42 -0500117 u32 ret;
Li Yang98658532006-10-03 23:10:46 -0500118
119 spin_lock_irqsave(&qe_lock, flags);
120 if (cmd == QE_RESET) {
121 out_be32(&qe_immr->cp.cecr, (u32) (cmd | QE_CR_FLG));
122 } else {
123 if (cmd == QE_ASSIGN_PAGE) {
124 /* Here device is the SNUM, not sub-block */
125 dev_shift = QE_CR_SNUM_SHIFT;
126 } else if (cmd == QE_ASSIGN_RISC) {
127 /* Here device is the SNUM, and mcnProtocol is
128 * e_QeCmdRiscAssignment value */
129 dev_shift = QE_CR_SNUM_SHIFT;
130 mcn_shift = QE_CR_MCN_RISC_ASSIGN_SHIFT;
131 } else {
132 if (device == QE_CR_SUBBLOCK_USB)
133 mcn_shift = QE_CR_MCN_USB_SHIFT;
134 else
135 mcn_shift = QE_CR_MCN_NORMAL_SHIFT;
136 }
137
Timur Tabi302439d2006-10-31 17:53:42 +0800138 out_be32(&qe_immr->cp.cecdr, cmd_input);
Li Yang98658532006-10-03 23:10:46 -0500139 out_be32(&qe_immr->cp.cecr,
140 (cmd | QE_CR_FLG | ((u32) device << dev_shift) | (u32)
141 mcn_protocol << mcn_shift));
142 }
143
144 /* wait for the QE_CR_FLG to clear */
Timur Tabif49156ea2009-05-26 10:21:42 -0500145 ret = spin_event_timeout((in_be32(&qe_immr->cp.cecr) & QE_CR_FLG) == 0,
146 100, 0);
147 /* On timeout (e.g. failure), the expression will be false (ret == 0),
148 otherwise it will be true (ret == 1). */
Li Yang98658532006-10-03 23:10:46 -0500149 spin_unlock_irqrestore(&qe_lock, flags);
150
Timur Tabif49156ea2009-05-26 10:21:42 -0500151 return ret == 1;
Li Yang98658532006-10-03 23:10:46 -0500152}
153EXPORT_SYMBOL(qe_issue_cmd);
154
155/* Set a baud rate generator. This needs lots of work. There are
156 * 16 BRGs, which can be connected to the QE channels or output
157 * as clocks. The BRGs are in two different block of internal
158 * memory mapped space.
Timur Tabi6b0b5942007-10-03 11:34:59 -0500159 * The BRG clock is the QE clock divided by 2.
Li Yang98658532006-10-03 23:10:46 -0500160 * It was set up long ago during the initial boot phase and is
161 * is given to us.
162 * Baud rate clocks are zero-based in the driver code (as that maps
163 * to port numbers). Documentation uses 1-based numbering.
164 */
165static unsigned int brg_clk = 0;
166
Anton Vorontsov7f0a6fc2008-03-11 20:24:24 +0300167unsigned int qe_get_brg_clk(void)
Li Yang98658532006-10-03 23:10:46 -0500168{
169 struct device_node *qe;
Andy Fleming7e1cc9c2008-05-07 13:19:44 -0500170 int size;
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300171 const u32 *prop;
172
Li Yang98658532006-10-03 23:10:46 -0500173 if (brg_clk)
174 return brg_clk;
175
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300176 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
177 if (!qe) {
178 qe = of_find_node_by_type(NULL, "qe");
179 if (!qe)
180 return brg_clk;
181 }
182
183 prop = of_get_property(qe, "brg-frequency", &size);
Anton Vorontsovd8985fd2008-02-04 16:46:17 +0300184 if (prop && size == sizeof(*prop))
185 brg_clk = *prop;
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300186
Anton Vorontsova2dd70a2008-01-24 18:39:59 +0300187 of_node_put(qe);
188
Li Yang98658532006-10-03 23:10:46 -0500189 return brg_clk;
190}
Anton Vorontsov7f0a6fc2008-03-11 20:24:24 +0300191EXPORT_SYMBOL(qe_get_brg_clk);
Li Yang98658532006-10-03 23:10:46 -0500192
Timur Tabi6b0b5942007-10-03 11:34:59 -0500193/* Program the BRG to the given sampling rate and multiplier
194 *
Timur Tabi7264ec42007-11-29 17:26:30 -0600195 * @brg: the BRG, QE_BRG1 - QE_BRG16
Timur Tabi6b0b5942007-10-03 11:34:59 -0500196 * @rate: the desired sampling rate
197 * @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or
198 * GUMR_L[TDCR]. E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01,
199 * then 'multiplier' should be 8.
Li Yang98658532006-10-03 23:10:46 -0500200 */
Timur Tabi7264ec42007-11-29 17:26:30 -0600201int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
Li Yang98658532006-10-03 23:10:46 -0500202{
Li Yang98658532006-10-03 23:10:46 -0500203 u32 divisor, tempval;
Timur Tabi6b0b5942007-10-03 11:34:59 -0500204 u32 div16 = 0;
Li Yang98658532006-10-03 23:10:46 -0500205
Timur Tabi7264ec42007-11-29 17:26:30 -0600206 if ((brg < QE_BRG1) || (brg > QE_BRG16))
207 return -EINVAL;
208
Anton Vorontsov7f0a6fc2008-03-11 20:24:24 +0300209 divisor = qe_get_brg_clk() / (rate * multiplier);
Li Yang98658532006-10-03 23:10:46 -0500210
Li Yang98658532006-10-03 23:10:46 -0500211 if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
Timur Tabi6b0b5942007-10-03 11:34:59 -0500212 div16 = QE_BRGC_DIV16;
Li Yang98658532006-10-03 23:10:46 -0500213 divisor /= 16;
214 }
215
Timur Tabi6b0b5942007-10-03 11:34:59 -0500216 /* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says
217 that the BRG divisor must be even if you're not using divide-by-16
218 mode. */
Joakim Tjernlundae5f8c12011-08-23 14:30:05 +0200219 if (!div16 && (divisor & 1) && (divisor > 3))
Timur Tabi6b0b5942007-10-03 11:34:59 -0500220 divisor++;
Li Yang98658532006-10-03 23:10:46 -0500221
Timur Tabi6b0b5942007-10-03 11:34:59 -0500222 tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
223 QE_BRGC_ENABLE | div16;
224
Timur Tabi7264ec42007-11-29 17:26:30 -0600225 out_be32(&qe_immr->brg.brgc[brg - QE_BRG1], tempval);
226
227 return 0;
Li Yang98658532006-10-03 23:10:46 -0500228}
Timur Tabi7264ec42007-11-29 17:26:30 -0600229EXPORT_SYMBOL(qe_setbrg);
Li Yang98658532006-10-03 23:10:46 -0500230
Timur Tabi174b0da2007-12-03 15:17:58 -0600231/* Convert a string to a QE clock source enum
232 *
233 * This function takes a string, typically from a property in the device
234 * tree, and returns the corresponding "enum qe_clock" value.
235*/
236enum qe_clock qe_clock_source(const char *source)
237{
238 unsigned int i;
239
240 if (strcasecmp(source, "none") == 0)
241 return QE_CLK_NONE;
242
243 if (strncasecmp(source, "brg", 3) == 0) {
244 i = simple_strtoul(source + 3, NULL, 10);
245 if ((i >= 1) && (i <= 16))
246 return (QE_BRG1 - 1) + i;
247 else
248 return QE_CLK_DUMMY;
249 }
250
251 if (strncasecmp(source, "clk", 3) == 0) {
252 i = simple_strtoul(source + 3, NULL, 10);
253 if ((i >= 1) && (i <= 24))
254 return (QE_CLK1 - 1) + i;
255 else
256 return QE_CLK_DUMMY;
257 }
258
259 return QE_CLK_DUMMY;
260}
261EXPORT_SYMBOL(qe_clock_source);
262
Li Yang98658532006-10-03 23:10:46 -0500263/* Initialize SNUMs (thread serial numbers) according to
264 * QE Module Control chapter, SNUM table
265 */
266static void qe_snums_init(void)
267{
268 int i;
Dave Liufa1b42b2010-01-12 00:04:03 +0000269 static const u8 snum_init_76[] = {
270 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
271 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
272 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
273 0xD8, 0xD9, 0xE8, 0xE9, 0x44, 0x45, 0x4C, 0x4D,
274 0x54, 0x55, 0x5C, 0x5D, 0x64, 0x65, 0x6C, 0x6D,
275 0x74, 0x75, 0x7C, 0x7D, 0x84, 0x85, 0x8C, 0x8D,
276 0x94, 0x95, 0x9C, 0x9D, 0xA4, 0xA5, 0xAC, 0xAD,
277 0xB4, 0xB5, 0xBC, 0xBD, 0xC4, 0xC5, 0xCC, 0xCD,
278 0xD4, 0xD5, 0xDC, 0xDD, 0xE4, 0xE5, 0xEC, 0xED,
279 0xF4, 0xF5, 0xFC, 0xFD,
280 };
281 static const u8 snum_init_46[] = {
Li Yang98658532006-10-03 23:10:46 -0500282 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
283 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
284 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
Haiying Wang98ca77a2009-05-01 15:40:48 -0400285 0xD8, 0xD9, 0xE8, 0xE9, 0x08, 0x09, 0x18, 0x19,
286 0x28, 0x29, 0x38, 0x39, 0x48, 0x49, 0x58, 0x59,
287 0x68, 0x69, 0x78, 0x79, 0x80, 0x81,
Li Yang98658532006-10-03 23:10:46 -0500288 };
Dave Liufa1b42b2010-01-12 00:04:03 +0000289 static const u8 *snum_init;
Li Yang98658532006-10-03 23:10:46 -0500290
Haiying Wang98ca77a2009-05-01 15:40:48 -0400291 qe_num_of_snum = qe_get_num_of_snums();
292
Dave Liufa1b42b2010-01-12 00:04:03 +0000293 if (qe_num_of_snum == 76)
294 snum_init = snum_init_76;
295 else
296 snum_init = snum_init_46;
297
Haiying Wang98ca77a2009-05-01 15:40:48 -0400298 for (i = 0; i < qe_num_of_snum; i++) {
Li Yang98658532006-10-03 23:10:46 -0500299 snums[i].num = snum_init[i];
300 snums[i].state = QE_SNUM_STATE_FREE;
301 }
302}
303
304int qe_get_snum(void)
305{
306 unsigned long flags;
307 int snum = -EBUSY;
308 int i;
309
310 spin_lock_irqsave(&qe_lock, flags);
Haiying Wang98ca77a2009-05-01 15:40:48 -0400311 for (i = 0; i < qe_num_of_snum; i++) {
Li Yang98658532006-10-03 23:10:46 -0500312 if (snums[i].state == QE_SNUM_STATE_FREE) {
313 snums[i].state = QE_SNUM_STATE_USED;
314 snum = snums[i].num;
315 break;
316 }
317 }
318 spin_unlock_irqrestore(&qe_lock, flags);
319
320 return snum;
321}
322EXPORT_SYMBOL(qe_get_snum);
323
324void qe_put_snum(u8 snum)
325{
326 int i;
327
Haiying Wang98ca77a2009-05-01 15:40:48 -0400328 for (i = 0; i < qe_num_of_snum; i++) {
Li Yang98658532006-10-03 23:10:46 -0500329 if (snums[i].num == snum) {
330 snums[i].state = QE_SNUM_STATE_FREE;
331 break;
332 }
333 }
334}
335EXPORT_SYMBOL(qe_put_snum);
336
337static int qe_sdma_init(void)
338{
Andy Fleming7e1cc9c2008-05-07 13:19:44 -0500339 struct sdma __iomem *sdma = &qe_immr->sdma;
Anton Vorontsov0c7b87b2009-09-16 01:43:52 +0400340 static unsigned long sdma_buf_offset = (unsigned long)-ENOMEM;
Li Yang98658532006-10-03 23:10:46 -0500341
342 if (!sdma)
343 return -ENODEV;
344
345 /* allocate 2 internal temporary buffers (512 bytes size each) for
346 * the SDMA */
Anton Vorontsov0c7b87b2009-09-16 01:43:52 +0400347 if (IS_ERR_VALUE(sdma_buf_offset)) {
348 sdma_buf_offset = qe_muram_alloc(512 * 2, 4096);
349 if (IS_ERR_VALUE(sdma_buf_offset))
350 return -ENOMEM;
351 }
Li Yang98658532006-10-03 23:10:46 -0500352
Timur Tabi4c356302007-05-08 14:46:36 -0500353 out_be32(&sdma->sdebcr, (u32) sdma_buf_offset & QE_SDEBCR_BA_MASK);
Chuck Meade7f013bc2007-03-27 10:46:10 -0400354 out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK |
355 (0x1 << QE_SDMR_CEN_SHIFT)));
Li Yang98658532006-10-03 23:10:46 -0500356
357 return 0;
358}
359
Timur Tabibc556ba2008-01-08 10:30:58 -0600360/* The maximum number of RISCs we support */
Anton Vorontsov98eaa092009-08-27 21:30:11 +0400361#define MAX_QE_RISC 4
Timur Tabibc556ba2008-01-08 10:30:58 -0600362
363/* Firmware information stored here for qe_get_firmware_info() */
364static struct qe_firmware_info qe_firmware_info;
365
366/*
367 * Set to 1 if QE firmware has been uploaded, and therefore
368 * qe_firmware_info contains valid data.
369 */
370static int qe_firmware_uploaded;
371
372/*
373 * Upload a QE microcode
374 *
375 * This function is a worker function for qe_upload_firmware(). It does
376 * the actual uploading of the microcode.
377 */
378static void qe_upload_microcode(const void *base,
379 const struct qe_microcode *ucode)
380{
381 const __be32 *code = base + be32_to_cpu(ucode->code_offset);
382 unsigned int i;
383
384 if (ucode->major || ucode->minor || ucode->revision)
385 printk(KERN_INFO "qe-firmware: "
386 "uploading microcode '%s' version %u.%u.%u\n",
387 ucode->id, ucode->major, ucode->minor, ucode->revision);
388 else
389 printk(KERN_INFO "qe-firmware: "
390 "uploading microcode '%s'\n", ucode->id);
391
392 /* Use auto-increment */
393 out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
394 QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
395
396 for (i = 0; i < be32_to_cpu(ucode->count); i++)
397 out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
398}
399
400/*
401 * Upload a microcode to the I-RAM at a specific address.
402 *
Paul Bolle395cf962011-08-15 02:02:26 +0200403 * See Documentation/powerpc/qe_firmware.txt for information on QE microcode
Timur Tabibc556ba2008-01-08 10:30:58 -0600404 * uploading.
405 *
406 * Currently, only version 1 is supported, so the 'version' field must be
407 * set to 1.
408 *
409 * The SOC model and revision are not validated, they are only displayed for
410 * informational purposes.
411 *
412 * 'calc_size' is the calculated size, in bytes, of the firmware structure and
413 * all of the microcode structures, minus the CRC.
414 *
415 * 'length' is the size that the structure says it is, including the CRC.
416 */
417int qe_upload_firmware(const struct qe_firmware *firmware)
418{
419 unsigned int i;
420 unsigned int j;
421 u32 crc;
422 size_t calc_size = sizeof(struct qe_firmware);
423 size_t length;
424 const struct qe_header *hdr;
425
426 if (!firmware) {
427 printk(KERN_ERR "qe-firmware: invalid pointer\n");
428 return -EINVAL;
429 }
430
431 hdr = &firmware->header;
432 length = be32_to_cpu(hdr->length);
433
434 /* Check the magic */
435 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
436 (hdr->magic[2] != 'F')) {
437 printk(KERN_ERR "qe-firmware: not a microcode\n");
438 return -EPERM;
439 }
440
441 /* Check the version */
442 if (hdr->version != 1) {
443 printk(KERN_ERR "qe-firmware: unsupported version\n");
444 return -EPERM;
445 }
446
447 /* Validate some of the fields */
Timur Tabi6f913162008-03-03 11:11:30 -0600448 if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
Timur Tabibc556ba2008-01-08 10:30:58 -0600449 printk(KERN_ERR "qe-firmware: invalid data\n");
450 return -EINVAL;
451 }
452
453 /* Validate the length and check if there's a CRC */
454 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
455
456 for (i = 0; i < firmware->count; i++)
457 /*
458 * For situations where the second RISC uses the same microcode
459 * as the first, the 'code_offset' and 'count' fields will be
460 * zero, so it's okay to add those.
461 */
462 calc_size += sizeof(__be32) *
463 be32_to_cpu(firmware->microcode[i].count);
464
465 /* Validate the length */
466 if (length != calc_size + sizeof(__be32)) {
467 printk(KERN_ERR "qe-firmware: invalid length\n");
468 return -EPERM;
469 }
470
471 /* Validate the CRC */
472 crc = be32_to_cpu(*(__be32 *)((void *)firmware + calc_size));
473 if (crc != crc32(0, firmware, calc_size)) {
474 printk(KERN_ERR "qe-firmware: firmware CRC is invalid\n");
475 return -EIO;
476 }
477
478 /*
479 * If the microcode calls for it, split the I-RAM.
480 */
481 if (!firmware->split)
482 setbits16(&qe_immr->cp.cercr, QE_CP_CERCR_CIR);
483
484 if (firmware->soc.model)
485 printk(KERN_INFO
486 "qe-firmware: firmware '%s' for %u V%u.%u\n",
487 firmware->id, be16_to_cpu(firmware->soc.model),
488 firmware->soc.major, firmware->soc.minor);
489 else
490 printk(KERN_INFO "qe-firmware: firmware '%s'\n",
491 firmware->id);
492
493 /*
494 * The QE only supports one microcode per RISC, so clear out all the
495 * saved microcode information and put in the new.
496 */
497 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
498 strcpy(qe_firmware_info.id, firmware->id);
499 qe_firmware_info.extended_modes = firmware->extended_modes;
500 memcpy(qe_firmware_info.vtraps, firmware->vtraps,
501 sizeof(firmware->vtraps));
502
503 /* Loop through each microcode. */
504 for (i = 0; i < firmware->count; i++) {
505 const struct qe_microcode *ucode = &firmware->microcode[i];
506
507 /* Upload a microcode if it's present */
508 if (ucode->code_offset)
509 qe_upload_microcode(firmware, ucode);
510
511 /* Program the traps for this processor */
512 for (j = 0; j < 16; j++) {
513 u32 trap = be32_to_cpu(ucode->traps[j]);
514
515 if (trap)
516 out_be32(&qe_immr->rsp[i].tibcr[j], trap);
517 }
518
519 /* Enable traps */
520 out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
521 }
522
523 qe_firmware_uploaded = 1;
524
525 return 0;
526}
527EXPORT_SYMBOL(qe_upload_firmware);
528
529/*
530 * Get info on the currently-loaded firmware
531 *
532 * This function also checks the device tree to see if the boot loader has
533 * uploaded a firmware already.
534 */
535struct qe_firmware_info *qe_get_firmware_info(void)
536{
537 static int initialized;
538 struct property *prop;
539 struct device_node *qe;
540 struct device_node *fw = NULL;
541 const char *sprop;
542 unsigned int i;
543
544 /*
545 * If we haven't checked yet, and a driver hasn't uploaded a firmware
546 * yet, then check the device tree for information.
547 */
Ionut Nicu86f4e5d2008-03-07 19:27:59 +0200548 if (qe_firmware_uploaded)
549 return &qe_firmware_info;
550
551 if (initialized)
Timur Tabibc556ba2008-01-08 10:30:58 -0600552 return NULL;
553
554 initialized = 1;
555
556 /*
557 * Newer device trees have an "fsl,qe" compatible property for the QE
558 * node, but we still need to support older device trees.
559 */
560 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
561 if (!qe) {
562 qe = of_find_node_by_type(NULL, "qe");
563 if (!qe)
564 return NULL;
565 }
566
567 /* Find the 'firmware' child node */
568 for_each_child_of_node(qe, fw) {
569 if (strcmp(fw->name, "firmware") == 0)
570 break;
571 }
572
573 of_node_put(qe);
574
575 /* Did we find the 'firmware' node? */
576 if (!fw)
577 return NULL;
578
579 qe_firmware_uploaded = 1;
580
581 /* Copy the data into qe_firmware_info*/
582 sprop = of_get_property(fw, "id", NULL);
583 if (sprop)
584 strncpy(qe_firmware_info.id, sprop,
585 sizeof(qe_firmware_info.id) - 1);
586
587 prop = of_find_property(fw, "extended-modes", NULL);
588 if (prop && (prop->length == sizeof(u64))) {
589 const u64 *iprop = prop->value;
590
591 qe_firmware_info.extended_modes = *iprop;
592 }
593
594 prop = of_find_property(fw, "virtual-traps", NULL);
595 if (prop && (prop->length == 32)) {
596 const u32 *iprop = prop->value;
597
598 for (i = 0; i < ARRAY_SIZE(qe_firmware_info.vtraps); i++)
599 qe_firmware_info.vtraps[i] = iprop[i];
600 }
601
602 of_node_put(fw);
603
604 return &qe_firmware_info;
605}
606EXPORT_SYMBOL(qe_get_firmware_info);
607
Haiying Wang06c44352009-05-01 15:40:47 -0400608unsigned int qe_get_num_of_risc(void)
609{
610 struct device_node *qe;
611 int size;
612 unsigned int num_of_risc = 0;
613 const u32 *prop;
614
615 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
616 if (!qe) {
617 /* Older devices trees did not have an "fsl,qe"
618 * compatible property, so we need to look for
619 * the QE node by name.
620 */
621 qe = of_find_node_by_type(NULL, "qe");
622 if (!qe)
623 return num_of_risc;
624 }
625
626 prop = of_get_property(qe, "fsl,qe-num-riscs", &size);
627 if (prop && size == sizeof(*prop))
628 num_of_risc = *prop;
629
630 of_node_put(qe);
631
632 return num_of_risc;
633}
634EXPORT_SYMBOL(qe_get_num_of_risc);
635
Haiying Wang98ca77a2009-05-01 15:40:48 -0400636unsigned int qe_get_num_of_snums(void)
637{
638 struct device_node *qe;
639 int size;
640 unsigned int num_of_snums;
641 const u32 *prop;
642
643 num_of_snums = 28; /* The default number of snum for threads is 28 */
644 qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
645 if (!qe) {
646 /* Older devices trees did not have an "fsl,qe"
647 * compatible property, so we need to look for
648 * the QE node by name.
649 */
650 qe = of_find_node_by_type(NULL, "qe");
651 if (!qe)
652 return num_of_snums;
653 }
654
655 prop = of_get_property(qe, "fsl,qe-num-snums", &size);
656 if (prop && size == sizeof(*prop)) {
657 num_of_snums = *prop;
658 if ((num_of_snums < 28) || (num_of_snums > QE_NUM_OF_SNUM)) {
659 /* No QE ever has fewer than 28 SNUMs */
660 pr_err("QE: number of snum is invalid\n");
Julia Lawall5aac4d72010-08-29 11:52:44 +0200661 of_node_put(qe);
Haiying Wang98ca77a2009-05-01 15:40:48 -0400662 return -EINVAL;
663 }
664 }
665
666 of_node_put(qe);
667
668 return num_of_snums;
669}
670EXPORT_SYMBOL(qe_get_num_of_snums);
Anton Vorontsovfdfde242009-09-16 01:43:55 +0400671
672#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx)
Grant Likelya454dc52010-07-22 15:52:34 -0600673static int qe_resume(struct platform_device *ofdev)
Anton Vorontsovfdfde242009-09-16 01:43:55 +0400674{
675 if (!qe_alive_during_sleep())
676 qe_reset();
677 return 0;
678}
679
Grant Likely00006122011-02-22 19:59:54 -0700680static int qe_probe(struct platform_device *ofdev)
Anton Vorontsovfdfde242009-09-16 01:43:55 +0400681{
682 return 0;
683}
684
685static const struct of_device_id qe_ids[] = {
686 { .compatible = "fsl,qe", },
687 { },
688};
689
Grant Likely00006122011-02-22 19:59:54 -0700690static struct platform_driver qe_driver = {
Grant Likely40182942010-04-13 16:13:02 -0700691 .driver = {
692 .name = "fsl-qe",
693 .owner = THIS_MODULE,
694 .of_match_table = qe_ids,
695 },
Anton Vorontsovfdfde242009-09-16 01:43:55 +0400696 .probe = qe_probe,
697 .resume = qe_resume,
698};
699
700static int __init qe_drv_init(void)
701{
Grant Likely00006122011-02-22 19:59:54 -0700702 return platform_driver_register(&qe_driver);
Anton Vorontsovfdfde242009-09-16 01:43:55 +0400703}
704device_initcall(qe_drv_init);
705#endif /* defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx) */