ls1 has qe and ls1 has arm cpu.
move qe from arch/powerpc to drivers/soc/fsl
to adapt to powerpc and arm
Signed-off-by: Zhao Qiang <qiang.zhao@freescale.com>
Signed-off-by: Scott Wood <scottwood@freescale.com>
FREESCALE QUICC ENGINE LIBRARY
L: linuxppc-dev@lists.ozlabs.org
S: Orphan
-F: arch/powerpc/sysdev/qe_lib/
-F: arch/powerpc/include/asm/*qe.h
+F: drivers/soc/fsl/qe/
+F: include/soc/fsl/*qe*.h
+F: include/soc/fsl/*ucc*.h
FREESCALE USB PERIPHERAL DRIVERS
M: Li Yang <leoli@freescale.com>
source "fs/Kconfig"
-source "arch/powerpc/sysdev/qe_lib/Kconfig"
-
source "lib/Kconfig"
source "arch/powerpc/Kconfig.debug"
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/of.h>
-#include <asm/qe.h>
+#include <soc/fsl/qe/qe.h>
/*
* SPI Parameter RAM common to QE and CPM.
+++ /dev/null
-/*
- * QUICC Engine (QE) Internal Memory Map.
- * The Internal Memory Map for devices with QE on them. This
- * is the superset of all QE devices (8360, etc.).
-
- * Copyright (C) 2006. Freescale Semiconductor, Inc. All rights reserved.
- *
- * Authors: Shlomi Gridish <gridish@freescale.com>
- * Li Yang <leoli@freescale.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#ifndef _ASM_POWERPC_IMMAP_QE_H
-#define _ASM_POWERPC_IMMAP_QE_H
-#ifdef __KERNEL__
-
-#include <linux/kernel.h>
-#include <asm/io.h>
-
-#define QE_IMMAP_SIZE (1024 * 1024) /* 1MB from 1MB+IMMR */
-
-/* QE I-RAM */
-struct qe_iram {
- __be32 iadd; /* I-RAM Address Register */
- __be32 idata; /* I-RAM Data Register */
- u8 res0[0x04];
- __be32 iready; /* I-RAM Ready Register */
- u8 res1[0x70];
-} __attribute__ ((packed));
-
-/* QE Interrupt Controller */
-struct qe_ic_regs {
- __be32 qicr;
- __be32 qivec;
- __be32 qripnr;
- __be32 qipnr;
- __be32 qipxcc;
- __be32 qipycc;
- __be32 qipwcc;
- __be32 qipzcc;
- __be32 qimr;
- __be32 qrimr;
- __be32 qicnr;
- u8 res0[0x4];
- __be32 qiprta;
- __be32 qiprtb;
- u8 res1[0x4];
- __be32 qricr;
- u8 res2[0x20];
- __be32 qhivec;
- u8 res3[0x1C];
-} __attribute__ ((packed));
-
-/* Communications Processor */
-struct cp_qe {
- __be32 cecr; /* QE command register */
- __be32 ceccr; /* QE controller configuration register */
- __be32 cecdr; /* QE command data register */
- u8 res0[0xA];
- __be16 ceter; /* QE timer event register */
- u8 res1[0x2];
- __be16 cetmr; /* QE timers mask register */
- __be32 cetscr; /* QE time-stamp timer control register */
- __be32 cetsr1; /* QE time-stamp register 1 */
- __be32 cetsr2; /* QE time-stamp register 2 */
- u8 res2[0x8];
- __be32 cevter; /* QE virtual tasks event register */
- __be32 cevtmr; /* QE virtual tasks mask register */
- __be16 cercr; /* QE RAM control register */
- u8 res3[0x2];
- u8 res4[0x24];
- __be16 ceexe1; /* QE external request 1 event register */
- u8 res5[0x2];
- __be16 ceexm1; /* QE external request 1 mask register */
- u8 res6[0x2];
- __be16 ceexe2; /* QE external request 2 event register */
- u8 res7[0x2];
- __be16 ceexm2; /* QE external request 2 mask register */
- u8 res8[0x2];
- __be16 ceexe3; /* QE external request 3 event register */
- u8 res9[0x2];
- __be16 ceexm3; /* QE external request 3 mask register */
- u8 res10[0x2];
- __be16 ceexe4; /* QE external request 4 event register */
- u8 res11[0x2];
- __be16 ceexm4; /* QE external request 4 mask register */
- u8 res12[0x3A];
- __be32 ceurnr; /* QE microcode revision number register */
- u8 res13[0x244];
-} __attribute__ ((packed));
-
-/* QE Multiplexer */
-struct qe_mux {
- __be32 cmxgcr; /* CMX general clock route register */
- __be32 cmxsi1cr_l; /* CMX SI1 clock route low register */
- __be32 cmxsi1cr_h; /* CMX SI1 clock route high register */
- __be32 cmxsi1syr; /* CMX SI1 SYNC route register */
- __be32 cmxucr[4]; /* CMX UCCx clock route registers */
- __be32 cmxupcr; /* CMX UPC clock route register */
- u8 res0[0x1C];
-} __attribute__ ((packed));
-
-/* QE Timers */
-struct qe_timers {
- u8 gtcfr1; /* Timer 1 and Timer 2 global config register*/
- u8 res0[0x3];
- u8 gtcfr2; /* Timer 3 and timer 4 global config register*/
- u8 res1[0xB];
- __be16 gtmdr1; /* Timer 1 mode register */
- __be16 gtmdr2; /* Timer 2 mode register */
- __be16 gtrfr1; /* Timer 1 reference register */
- __be16 gtrfr2; /* Timer 2 reference register */
- __be16 gtcpr1; /* Timer 1 capture register */
- __be16 gtcpr2; /* Timer 2 capture register */
- __be16 gtcnr1; /* Timer 1 counter */
- __be16 gtcnr2; /* Timer 2 counter */
- __be16 gtmdr3; /* Timer 3 mode register */
- __be16 gtmdr4; /* Timer 4 mode register */
- __be16 gtrfr3; /* Timer 3 reference register */
- __be16 gtrfr4; /* Timer 4 reference register */
- __be16 gtcpr3; /* Timer 3 capture register */
- __be16 gtcpr4; /* Timer 4 capture register */
- __be16 gtcnr3; /* Timer 3 counter */
- __be16 gtcnr4; /* Timer 4 counter */
- __be16 gtevr1; /* Timer 1 event register */
- __be16 gtevr2; /* Timer 2 event register */
- __be16 gtevr3; /* Timer 3 event register */
- __be16 gtevr4; /* Timer 4 event register */
- __be16 gtps; /* Timer 1 prescale register */
- u8 res2[0x46];
-} __attribute__ ((packed));
-
-/* BRG */
-struct qe_brg {
- __be32 brgc[16]; /* BRG configuration registers */
- u8 res0[0x40];
-} __attribute__ ((packed));
-
-/* SPI */
-struct spi {
- u8 res0[0x20];
- __be32 spmode; /* SPI mode register */
- u8 res1[0x2];
- u8 spie; /* SPI event register */
- u8 res2[0x1];
- u8 res3[0x2];
- u8 spim; /* SPI mask register */
- u8 res4[0x1];
- u8 res5[0x1];
- u8 spcom; /* SPI command register */
- u8 res6[0x2];
- __be32 spitd; /* SPI transmit data register (cpu mode) */
- __be32 spird; /* SPI receive data register (cpu mode) */
- u8 res7[0x8];
-} __attribute__ ((packed));
-
-/* SI */
-struct si1 {
- __be16 siamr1; /* SI1 TDMA mode register */
- __be16 sibmr1; /* SI1 TDMB mode register */
- __be16 sicmr1; /* SI1 TDMC mode register */
- __be16 sidmr1; /* SI1 TDMD mode register */
- u8 siglmr1_h; /* SI1 global mode register high */
- u8 res0[0x1];
- u8 sicmdr1_h; /* SI1 command register high */
- u8 res2[0x1];
- u8 sistr1_h; /* SI1 status register high */
- u8 res3[0x1];
- __be16 sirsr1_h; /* SI1 RAM shadow address register high */
- u8 sitarc1; /* SI1 RAM counter Tx TDMA */
- u8 sitbrc1; /* SI1 RAM counter Tx TDMB */
- u8 sitcrc1; /* SI1 RAM counter Tx TDMC */
- u8 sitdrc1; /* SI1 RAM counter Tx TDMD */
- u8 sirarc1; /* SI1 RAM counter Rx TDMA */
- u8 sirbrc1; /* SI1 RAM counter Rx TDMB */
- u8 sircrc1; /* SI1 RAM counter Rx TDMC */
- u8 sirdrc1; /* SI1 RAM counter Rx TDMD */
- u8 res4[0x8];
- __be16 siemr1; /* SI1 TDME mode register 16 bits */
- __be16 sifmr1; /* SI1 TDMF mode register 16 bits */
- __be16 sigmr1; /* SI1 TDMG mode register 16 bits */
- __be16 sihmr1; /* SI1 TDMH mode register 16 bits */
- u8 siglmg1_l; /* SI1 global mode register low 8 bits */
- u8 res5[0x1];
- u8 sicmdr1_l; /* SI1 command register low 8 bits */
- u8 res6[0x1];
- u8 sistr1_l; /* SI1 status register low 8 bits */
- u8 res7[0x1];
- __be16 sirsr1_l; /* SI1 RAM shadow address register low 16 bits*/
- u8 siterc1; /* SI1 RAM counter Tx TDME 8 bits */
- u8 sitfrc1; /* SI1 RAM counter Tx TDMF 8 bits */
- u8 sitgrc1; /* SI1 RAM counter Tx TDMG 8 bits */
- u8 sithrc1; /* SI1 RAM counter Tx TDMH 8 bits */
- u8 sirerc1; /* SI1 RAM counter Rx TDME 8 bits */
- u8 sirfrc1; /* SI1 RAM counter Rx TDMF 8 bits */
- u8 sirgrc1; /* SI1 RAM counter Rx TDMG 8 bits */
- u8 sirhrc1; /* SI1 RAM counter Rx TDMH 8 bits */
- u8 res8[0x8];
- __be32 siml1; /* SI1 multiframe limit register */
- u8 siedm1; /* SI1 extended diagnostic mode register */
- u8 res9[0xBB];
-} __attribute__ ((packed));
-
-/* SI Routing Tables */
-struct sir {
- u8 tx[0x400];
- u8 rx[0x400];
- u8 res0[0x800];
-} __attribute__ ((packed));
-
-/* USB Controller */
-struct qe_usb_ctlr {
- u8 usb_usmod;
- u8 usb_usadr;
- u8 usb_uscom;
- u8 res1[1];
- __be16 usb_usep[4];
- u8 res2[4];
- __be16 usb_usber;
- u8 res3[2];
- __be16 usb_usbmr;
- u8 res4[1];
- u8 usb_usbs;
- __be16 usb_ussft;
- u8 res5[2];
- __be16 usb_usfrn;
- u8 res6[0x22];
-} __attribute__ ((packed));
-
-/* MCC */
-struct qe_mcc {
- __be32 mcce; /* MCC event register */
- __be32 mccm; /* MCC mask register */
- __be32 mccf; /* MCC configuration register */
- __be32 merl; /* MCC emergency request level register */
- u8 res0[0xF0];
-} __attribute__ ((packed));
-
-/* QE UCC Slow */
-struct ucc_slow {
- __be32 gumr_l; /* UCCx general mode register (low) */
- __be32 gumr_h; /* UCCx general mode register (high) */
- __be16 upsmr; /* UCCx protocol-specific mode register */
- u8 res0[0x2];
- __be16 utodr; /* UCCx transmit on demand register */
- __be16 udsr; /* UCCx data synchronization register */
- __be16 ucce; /* UCCx event register */
- u8 res1[0x2];
- __be16 uccm; /* UCCx mask register */
- u8 res2[0x1];
- u8 uccs; /* UCCx status register */
- u8 res3[0x24];
- __be16 utpt;
- u8 res4[0x52];
- u8 guemr; /* UCC general extended mode register */
-} __attribute__ ((packed));
-
-/* QE UCC Fast */
-struct ucc_fast {
- __be32 gumr; /* UCCx general mode register */
- __be32 upsmr; /* UCCx protocol-specific mode register */
- __be16 utodr; /* UCCx transmit on demand register */
- u8 res0[0x2];
- __be16 udsr; /* UCCx data synchronization register */
- u8 res1[0x2];
- __be32 ucce; /* UCCx event register */
- __be32 uccm; /* UCCx mask register */
- u8 uccs; /* UCCx status register */
- u8 res2[0x7];
- __be32 urfb; /* UCC receive FIFO base */
- __be16 urfs; /* UCC receive FIFO size */
- u8 res3[0x2];
- __be16 urfet; /* UCC receive FIFO emergency threshold */
- __be16 urfset; /* UCC receive FIFO special emergency
- threshold */
- __be32 utfb; /* UCC transmit FIFO base */
- __be16 utfs; /* UCC transmit FIFO size */
- u8 res4[0x2];
- __be16 utfet; /* UCC transmit FIFO emergency threshold */
- u8 res5[0x2];
- __be16 utftt; /* UCC transmit FIFO transmit threshold */
- u8 res6[0x2];
- __be16 utpt; /* UCC transmit polling timer */
- u8 res7[0x2];
- __be32 urtry; /* UCC retry counter register */
- u8 res8[0x4C];
- u8 guemr; /* UCC general extended mode register */
-} __attribute__ ((packed));
-
-struct ucc {
- union {
- struct ucc_slow slow;
- struct ucc_fast fast;
- u8 res[0x200]; /* UCC blocks are 512 bytes each */
- };
-} __attribute__ ((packed));
-
-/* MultiPHY UTOPIA POS Controllers (UPC) */
-struct upc {
- __be32 upgcr; /* UTOPIA/POS general configuration register */
- __be32 uplpa; /* UTOPIA/POS last PHY address */
- __be32 uphec; /* ATM HEC register */
- __be32 upuc; /* UTOPIA/POS UCC configuration */
- __be32 updc1; /* UTOPIA/POS device 1 configuration */
- __be32 updc2; /* UTOPIA/POS device 2 configuration */
- __be32 updc3; /* UTOPIA/POS device 3 configuration */
- __be32 updc4; /* UTOPIA/POS device 4 configuration */
- __be32 upstpa; /* UTOPIA/POS STPA threshold */
- u8 res0[0xC];
- __be32 updrs1_h; /* UTOPIA/POS device 1 rate select */
- __be32 updrs1_l; /* UTOPIA/POS device 1 rate select */
- __be32 updrs2_h; /* UTOPIA/POS device 2 rate select */
- __be32 updrs2_l; /* UTOPIA/POS device 2 rate select */
- __be32 updrs3_h; /* UTOPIA/POS device 3 rate select */
- __be32 updrs3_l; /* UTOPIA/POS device 3 rate select */
- __be32 updrs4_h; /* UTOPIA/POS device 4 rate select */
- __be32 updrs4_l; /* UTOPIA/POS device 4 rate select */
- __be32 updrp1; /* UTOPIA/POS device 1 receive priority low */
- __be32 updrp2; /* UTOPIA/POS device 2 receive priority low */
- __be32 updrp3; /* UTOPIA/POS device 3 receive priority low */
- __be32 updrp4; /* UTOPIA/POS device 4 receive priority low */
- __be32 upde1; /* UTOPIA/POS device 1 event */
- __be32 upde2; /* UTOPIA/POS device 2 event */
- __be32 upde3; /* UTOPIA/POS device 3 event */
- __be32 upde4; /* UTOPIA/POS device 4 event */
- __be16 uprp1;
- __be16 uprp2;
- __be16 uprp3;
- __be16 uprp4;
- u8 res1[0x8];
- __be16 uptirr1_0; /* Device 1 transmit internal rate 0 */
- __be16 uptirr1_1; /* Device 1 transmit internal rate 1 */
- __be16 uptirr1_2; /* Device 1 transmit internal rate 2 */
- __be16 uptirr1_3; /* Device 1 transmit internal rate 3 */
- __be16 uptirr2_0; /* Device 2 transmit internal rate 0 */
- __be16 uptirr2_1; /* Device 2 transmit internal rate 1 */
- __be16 uptirr2_2; /* Device 2 transmit internal rate 2 */
- __be16 uptirr2_3; /* Device 2 transmit internal rate 3 */
- __be16 uptirr3_0; /* Device 3 transmit internal rate 0 */
- __be16 uptirr3_1; /* Device 3 transmit internal rate 1 */
- __be16 uptirr3_2; /* Device 3 transmit internal rate 2 */
- __be16 uptirr3_3; /* Device 3 transmit internal rate 3 */
- __be16 uptirr4_0; /* Device 4 transmit internal rate 0 */
- __be16 uptirr4_1; /* Device 4 transmit internal rate 1 */
- __be16 uptirr4_2; /* Device 4 transmit internal rate 2 */
- __be16 uptirr4_3; /* Device 4 transmit internal rate 3 */
- __be32 uper1; /* Device 1 port enable register */
- __be32 uper2; /* Device 2 port enable register */
- __be32 uper3; /* Device 3 port enable register */
- __be32 uper4; /* Device 4 port enable register */
- u8 res2[0x150];
-} __attribute__ ((packed));
-
-/* SDMA */
-struct sdma {
- __be32 sdsr; /* Serial DMA status register */
- __be32 sdmr; /* Serial DMA mode register */
- __be32 sdtr1; /* SDMA system bus threshold register */
- __be32 sdtr2; /* SDMA secondary bus threshold register */
- __be32 sdhy1; /* SDMA system bus hysteresis register */
- __be32 sdhy2; /* SDMA secondary bus hysteresis register */
- __be32 sdta1; /* SDMA system bus address register */
- __be32 sdta2; /* SDMA secondary bus address register */
- __be32 sdtm1; /* SDMA system bus MSNUM register */
- __be32 sdtm2; /* SDMA secondary bus MSNUM register */
- u8 res0[0x10];
- __be32 sdaqr; /* SDMA address bus qualify register */
- __be32 sdaqmr; /* SDMA address bus qualify mask register */
- u8 res1[0x4];
- __be32 sdebcr; /* SDMA CAM entries base register */
- u8 res2[0x38];
-} __attribute__ ((packed));
-
-/* Debug Space */
-struct dbg {
- __be32 bpdcr; /* Breakpoint debug command register */
- __be32 bpdsr; /* Breakpoint debug status register */
- __be32 bpdmr; /* Breakpoint debug mask register */
- __be32 bprmrr0; /* Breakpoint request mode risc register 0 */
- __be32 bprmrr1; /* Breakpoint request mode risc register 1 */
- u8 res0[0x8];
- __be32 bprmtr0; /* Breakpoint request mode trb register 0 */
- __be32 bprmtr1; /* Breakpoint request mode trb register 1 */
- u8 res1[0x8];
- __be32 bprmir; /* Breakpoint request mode immediate register */
- __be32 bprmsr; /* Breakpoint request mode serial register */
- __be32 bpemr; /* Breakpoint exit mode register */
- u8 res2[0x48];
-} __attribute__ ((packed));
-
-/*
- * RISC Special Registers (Trap and Breakpoint). These are described in
- * the QE Developer's Handbook.
- */
-struct rsp {
- __be32 tibcr[16]; /* Trap/instruction breakpoint control regs */
- u8 res0[64];
- __be32 ibcr0;
- __be32 ibs0;
- __be32 ibcnr0;
- u8 res1[4];
- __be32 ibcr1;
- __be32 ibs1;
- __be32 ibcnr1;
- __be32 npcr;
- __be32 dbcr;
- __be32 dbar;
- __be32 dbamr;
- __be32 dbsr;
- __be32 dbcnr;
- u8 res2[12];
- __be32 dbdr_h;
- __be32 dbdr_l;
- __be32 dbdmr_h;
- __be32 dbdmr_l;
- __be32 bsr;
- __be32 bor;
- __be32 bior;
- u8 res3[4];
- __be32 iatr[4];
- __be32 eccr; /* Exception control configuration register */
- __be32 eicr;
- u8 res4[0x100-0xf8];
-} __attribute__ ((packed));
-
-struct qe_immap {
- struct qe_iram iram; /* I-RAM */
- struct qe_ic_regs ic; /* Interrupt Controller */
- struct cp_qe cp; /* Communications Processor */
- struct qe_mux qmx; /* QE Multiplexer */
- struct qe_timers qet; /* QE Timers */
- struct spi spi[0x2]; /* spi */
- struct qe_mcc mcc; /* mcc */
- struct qe_brg brg; /* brg */
- struct qe_usb_ctlr usb; /* USB */
- struct si1 si1; /* SI */
- u8 res11[0x800];
- struct sir sir; /* SI Routing Tables */
- struct ucc ucc1; /* ucc1 */
- struct ucc ucc3; /* ucc3 */
- struct ucc ucc5; /* ucc5 */
- struct ucc ucc7; /* ucc7 */
- u8 res12[0x600];
- struct upc upc1; /* MultiPHY UTOPIA POS Ctrlr 1*/
- struct ucc ucc2; /* ucc2 */
- struct ucc ucc4; /* ucc4 */
- struct ucc ucc6; /* ucc6 */
- struct ucc ucc8; /* ucc8 */
- u8 res13[0x600];
- struct upc upc2; /* MultiPHY UTOPIA POS Ctrlr 2*/
- struct sdma sdma; /* SDMA */
- struct dbg dbg; /* 0x104080 - 0x1040FF
- Debug Space */
- struct rsp rsp[0x2]; /* 0x104100 - 0x1042FF
- RISC Special Registers
- (Trap and Breakpoint) */
- u8 res14[0x300]; /* 0x104300 - 0x1045FF */
- u8 res15[0x3A00]; /* 0x104600 - 0x107FFF */
- u8 res16[0x8000]; /* 0x108000 - 0x110000 */
- u8 muram[0xC000]; /* 0x110000 - 0x11C000
- Multi-user RAM */
- u8 res17[0x24000]; /* 0x11C000 - 0x140000 */
- u8 res18[0xC0000]; /* 0x140000 - 0x200000 */
-} __attribute__ ((packed));
-
-extern struct qe_immap __iomem *qe_immr;
-extern phys_addr_t get_qe_base(void);
-
-/*
- * Returns the offset within the QE address space of the given pointer.
- *
- * Note that the QE does not support 36-bit physical addresses, so if
- * get_qe_base() returns a number above 4GB, the caller will probably fail.
- */
-static inline phys_addr_t immrbar_virt_to_phys(void *address)
-{
- void *q = (void *)qe_immr;
-
- /* Is it a MURAM address? */
- if ((address >= q) && (address < (q + QE_IMMAP_SIZE)))
- return get_qe_base() + (address - q);
-
- /* It's an address returned by kmalloc */
- return virt_to_phys(address);
-}
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_POWERPC_IMMAP_QE_H */
+++ /dev/null
-/*
- * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Authors: Shlomi Gridish <gridish@freescale.com>
- * Li Yang <leoli@freescale.com>
- *
- * Description:
- * QUICC Engine (QE) external definitions and structure.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#ifndef _ASM_POWERPC_QE_H
-#define _ASM_POWERPC_QE_H
-#ifdef __KERNEL__
-
-#include <linux/compiler.h>
-#include <linux/genalloc.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <asm/cpm.h>
-#include <asm/immap_qe.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/types.h>
-
-#define QE_NUM_OF_SNUM 256 /* There are 256 serial number in QE */
-#define QE_NUM_OF_BRGS 16
-#define QE_NUM_OF_PORTS 1024
-
-/* Memory partitions
-*/
-#define MEM_PART_SYSTEM 0
-#define MEM_PART_SECONDARY 1
-#define MEM_PART_MURAM 2
-
-/* Clocks and BRGs */
-enum qe_clock {
- QE_CLK_NONE = 0,
- QE_BRG1, /* Baud Rate Generator 1 */
- QE_BRG2, /* Baud Rate Generator 2 */
- QE_BRG3, /* Baud Rate Generator 3 */
- QE_BRG4, /* Baud Rate Generator 4 */
- QE_BRG5, /* Baud Rate Generator 5 */
- QE_BRG6, /* Baud Rate Generator 6 */
- QE_BRG7, /* Baud Rate Generator 7 */
- QE_BRG8, /* Baud Rate Generator 8 */
- QE_BRG9, /* Baud Rate Generator 9 */
- QE_BRG10, /* Baud Rate Generator 10 */
- QE_BRG11, /* Baud Rate Generator 11 */
- QE_BRG12, /* Baud Rate Generator 12 */
- QE_BRG13, /* Baud Rate Generator 13 */
- QE_BRG14, /* Baud Rate Generator 14 */
- QE_BRG15, /* Baud Rate Generator 15 */
- QE_BRG16, /* Baud Rate Generator 16 */
- QE_CLK1, /* Clock 1 */
- QE_CLK2, /* Clock 2 */
- QE_CLK3, /* Clock 3 */
- QE_CLK4, /* Clock 4 */
- QE_CLK5, /* Clock 5 */
- QE_CLK6, /* Clock 6 */
- QE_CLK7, /* Clock 7 */
- QE_CLK8, /* Clock 8 */
- QE_CLK9, /* Clock 9 */
- QE_CLK10, /* Clock 10 */
- QE_CLK11, /* Clock 11 */
- QE_CLK12, /* Clock 12 */
- QE_CLK13, /* Clock 13 */
- QE_CLK14, /* Clock 14 */
- QE_CLK15, /* Clock 15 */
- QE_CLK16, /* Clock 16 */
- QE_CLK17, /* Clock 17 */
- QE_CLK18, /* Clock 18 */
- QE_CLK19, /* Clock 19 */
- QE_CLK20, /* Clock 20 */
- QE_CLK21, /* Clock 21 */
- QE_CLK22, /* Clock 22 */
- QE_CLK23, /* Clock 23 */
- QE_CLK24, /* Clock 24 */
- QE_CLK_DUMMY
-};
-
-static inline bool qe_clock_is_brg(enum qe_clock clk)
-{
- return clk >= QE_BRG1 && clk <= QE_BRG16;
-}
-
-extern spinlock_t cmxgcr_lock;
-
-/* Export QE common operations */
-#ifdef CONFIG_QUICC_ENGINE
-extern void qe_reset(void);
-#else
-static inline void qe_reset(void) {}
-#endif
-
-int cpm_muram_init(void);
-
-#if defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE)
-unsigned long cpm_muram_alloc(unsigned long size, unsigned long align);
-int cpm_muram_free(unsigned long offset);
-unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size);
-unsigned long cpm_muram_alloc_common(unsigned long size, genpool_algo_t algo,
- void *data);
-void __iomem *cpm_muram_addr(unsigned long offset);
-unsigned long cpm_muram_offset(void __iomem *addr);
-dma_addr_t cpm_muram_dma(void __iomem *addr);
-#else
-static inline unsigned long cpm_muram_alloc(unsigned long size,
- unsigned long align)
-{
- return -ENOSYS;
-}
-
-static inline int cpm_muram_free(unsigned long offset)
-{
- return -ENOSYS;
-}
-
-static inline unsigned long cpm_muram_alloc_fixed(unsigned long offset,
- unsigned long size)
-{
- return -ENOSYS;
-}
-
-static inline void __iomem *cpm_muram_addr(unsigned long offset)
-{
- return NULL;
-}
-
-static inline unsigned long cpm_muram_offset(void __iomem *addr)
-{
- return -ENOSYS;
-}
-
-static inline dma_addr_t cpm_muram_dma(void __iomem *addr)
-{
- return 0;
-}
-#endif /* defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE) */
-
-/* QE PIO */
-#define QE_PIO_PINS 32
-
-struct qe_pio_regs {
- __be32 cpodr; /* Open drain register */
- __be32 cpdata; /* Data register */
- __be32 cpdir1; /* Direction register */
- __be32 cpdir2; /* Direction register */
- __be32 cppar1; /* Pin assignment register */
- __be32 cppar2; /* Pin assignment register */
-#ifdef CONFIG_PPC_85xx
- u8 pad[8];
-#endif
-};
-
-#define QE_PIO_DIR_IN 2
-#define QE_PIO_DIR_OUT 1
-extern void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin,
- int dir, int open_drain, int assignment,
- int has_irq);
-#ifdef CONFIG_QUICC_ENGINE
-extern int par_io_init(struct device_node *np);
-extern int par_io_of_config(struct device_node *np);
-extern int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
- int assignment, int has_irq);
-extern int par_io_data_set(u8 port, u8 pin, u8 val);
-#else
-static inline int par_io_init(struct device_node *np) { return -ENOSYS; }
-static inline int par_io_of_config(struct device_node *np) { return -ENOSYS; }
-static inline int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
- int assignment, int has_irq) { return -ENOSYS; }
-static inline int par_io_data_set(u8 port, u8 pin, u8 val) { return -ENOSYS; }
-#endif /* CONFIG_QUICC_ENGINE */
-
-/*
- * Pin multiplexing functions.
- */
-struct qe_pin;
-#ifdef CONFIG_QE_GPIO
-extern struct qe_pin *qe_pin_request(struct device_node *np, int index);
-extern void qe_pin_free(struct qe_pin *qe_pin);
-extern void qe_pin_set_gpio(struct qe_pin *qe_pin);
-extern void qe_pin_set_dedicated(struct qe_pin *pin);
-#else
-static inline struct qe_pin *qe_pin_request(struct device_node *np, int index)
-{
- return ERR_PTR(-ENOSYS);
-}
-static inline void qe_pin_free(struct qe_pin *qe_pin) {}
-static inline void qe_pin_set_gpio(struct qe_pin *qe_pin) {}
-static inline void qe_pin_set_dedicated(struct qe_pin *pin) {}
-#endif /* CONFIG_QE_GPIO */
-
-#ifdef CONFIG_QUICC_ENGINE
-int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input);
-#else
-static inline int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol,
- u32 cmd_input)
-{
- return -ENOSYS;
-}
-#endif /* CONFIG_QUICC_ENGINE */
-
-/* QE internal API */
-enum qe_clock qe_clock_source(const char *source);
-unsigned int qe_get_brg_clk(void);
-int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier);
-int qe_get_snum(void);
-void qe_put_snum(u8 snum);
-unsigned int qe_get_num_of_risc(void);
-unsigned int qe_get_num_of_snums(void);
-
-static inline int qe_alive_during_sleep(void)
-{
- /*
- * MPC8568E reference manual says:
- *
- * "...power down sequence waits for all I/O interfaces to become idle.
- * In some applications this may happen eventually without actively
- * shutting down interfaces, but most likely, software will have to
- * take steps to shut down the eTSEC, QUICC Engine Block, and PCI
- * interfaces before issuing the command (either the write to the core
- * MSR[WE] as described above or writing to POWMGTCSR) to put the
- * device into sleep state."
- *
- * MPC8569E reference manual has a similar paragraph.
- */
-#ifdef CONFIG_PPC_85xx
- return 0;
-#else
- return 1;
-#endif
-}
-
-/* we actually use cpm_muram implementation, define this for convenience */
-#define qe_muram_init cpm_muram_init
-#define qe_muram_alloc cpm_muram_alloc
-#define qe_muram_alloc_fixed cpm_muram_alloc_fixed
-#define qe_muram_free cpm_muram_free
-#define qe_muram_addr cpm_muram_addr
-#define qe_muram_offset cpm_muram_offset
-
-/* Structure that defines QE firmware binary files.
- *
- * See Documentation/powerpc/qe_firmware.txt for a description of these
- * fields.
- */
-struct qe_firmware {
- struct qe_header {
- __be32 length; /* Length of the entire structure, in bytes */
- u8 magic[3]; /* Set to { 'Q', 'E', 'F' } */
- u8 version; /* Version of this layout. First ver is '1' */
- } header;
- u8 id[62]; /* Null-terminated identifier string */
- u8 split; /* 0 = shared I-RAM, 1 = split I-RAM */
- u8 count; /* Number of microcode[] structures */
- struct {
- __be16 model; /* The SOC model */
- u8 major; /* The SOC revision major */
- u8 minor; /* The SOC revision minor */
- } __attribute__ ((packed)) soc;
- u8 padding[4]; /* Reserved, for alignment */
- __be64 extended_modes; /* Extended modes */
- __be32 vtraps[8]; /* Virtual trap addresses */
- u8 reserved[4]; /* Reserved, for future expansion */
- struct qe_microcode {
- u8 id[32]; /* Null-terminated identifier */
- __be32 traps[16]; /* Trap addresses, 0 == ignore */
- __be32 eccr; /* The value for the ECCR register */
- __be32 iram_offset; /* Offset into I-RAM for the code */
- __be32 count; /* Number of 32-bit words of the code */
- __be32 code_offset; /* Offset of the actual microcode */
- u8 major; /* The microcode version major */
- u8 minor; /* The microcode version minor */
- u8 revision; /* The microcode version revision */
- u8 padding; /* Reserved, for alignment */
- u8 reserved[4]; /* Reserved, for future expansion */
- } __attribute__ ((packed)) microcode[1];
- /* All microcode binaries should be located here */
- /* CRC32 should be located here, after the microcode binaries */
-} __attribute__ ((packed));
-
-struct qe_firmware_info {
- char id[64]; /* Firmware name */
- u32 vtraps[8]; /* Virtual trap addresses */
- u64 extended_modes; /* Extended modes */
-};
-
-#ifdef CONFIG_QUICC_ENGINE
-/* Upload a firmware to the QE */
-int qe_upload_firmware(const struct qe_firmware *firmware);
-#else
-static inline int qe_upload_firmware(const struct qe_firmware *firmware)
-{
- return -ENOSYS;
-}
-#endif /* CONFIG_QUICC_ENGINE */
-
-/* Obtain information on the uploaded firmware */
-struct qe_firmware_info *qe_get_firmware_info(void);
-
-/* QE USB */
-int qe_usb_clock_set(enum qe_clock clk, int rate);
-
-/* Buffer descriptors */
-struct qe_bd {
- __be16 status;
- __be16 length;
- __be32 buf;
-} __attribute__ ((packed));
-
-#define BD_STATUS_MASK 0xffff0000
-#define BD_LENGTH_MASK 0x0000ffff
-
-/* Alignment */
-#define QE_INTR_TABLE_ALIGN 16 /* ??? */
-#define QE_ALIGNMENT_OF_BD 8
-#define QE_ALIGNMENT_OF_PRAM 64
-
-/* RISC allocation */
-#define QE_RISC_ALLOCATION_RISC1 0x1 /* RISC 1 */
-#define QE_RISC_ALLOCATION_RISC2 0x2 /* RISC 2 */
-#define QE_RISC_ALLOCATION_RISC3 0x4 /* RISC 3 */
-#define QE_RISC_ALLOCATION_RISC4 0x8 /* RISC 4 */
-#define QE_RISC_ALLOCATION_RISC1_AND_RISC2 (QE_RISC_ALLOCATION_RISC1 | \
- QE_RISC_ALLOCATION_RISC2)
-#define QE_RISC_ALLOCATION_FOUR_RISCS (QE_RISC_ALLOCATION_RISC1 | \
- QE_RISC_ALLOCATION_RISC2 | \
- QE_RISC_ALLOCATION_RISC3 | \
- QE_RISC_ALLOCATION_RISC4)
-
-/* QE extended filtering Table Lookup Key Size */
-enum qe_fltr_tbl_lookup_key_size {
- QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES
- = 0x3f, /* LookupKey parsed by the Generate LookupKey
- CMD is truncated to 8 bytes */
- QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES
- = 0x5f, /* LookupKey parsed by the Generate LookupKey
- CMD is truncated to 16 bytes */
-};
-
-/* QE FLTR extended filtering Largest External Table Lookup Key Size */
-enum qe_fltr_largest_external_tbl_lookup_key_size {
- QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE
- = 0x0,/* not used */
- QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES
- = QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES, /* 8 bytes */
- QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES
- = QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES, /* 16 bytes */
-};
-
-/* structure representing QE parameter RAM */
-struct qe_timer_tables {
- u16 tm_base; /* QE timer table base adr */
- u16 tm_ptr; /* QE timer table pointer */
- u16 r_tmr; /* QE timer mode register */
- u16 r_tmv; /* QE timer valid register */
- u32 tm_cmd; /* QE timer cmd register */
- u32 tm_cnt; /* QE timer internal cnt */
-} __attribute__ ((packed));
-
-#define QE_FLTR_TAD_SIZE 8
-
-/* QE extended filtering Termination Action Descriptor (TAD) */
-struct qe_fltr_tad {
- u8 serialized[QE_FLTR_TAD_SIZE];
-} __attribute__ ((packed));
-
-/* Communication Direction */
-enum comm_dir {
- COMM_DIR_NONE = 0,
- COMM_DIR_RX = 1,
- COMM_DIR_TX = 2,
- COMM_DIR_RX_AND_TX = 3
-};
-
-/* QE CMXUCR Registers.
- * There are two UCCs represented in each of the four CMXUCR registers.
- * These values are for the UCC in the LSBs
- */
-#define QE_CMXUCR_MII_ENET_MNG 0x00007000
-#define QE_CMXUCR_MII_ENET_MNG_SHIFT 12
-#define QE_CMXUCR_GRANT 0x00008000
-#define QE_CMXUCR_TSA 0x00004000
-#define QE_CMXUCR_BKPT 0x00000100
-#define QE_CMXUCR_TX_CLK_SRC_MASK 0x0000000F
-
-/* QE CMXGCR Registers.
-*/
-#define QE_CMXGCR_MII_ENET_MNG 0x00007000
-#define QE_CMXGCR_MII_ENET_MNG_SHIFT 12
-#define QE_CMXGCR_USBCS 0x0000000f
-#define QE_CMXGCR_USBCS_CLK3 0x1
-#define QE_CMXGCR_USBCS_CLK5 0x2
-#define QE_CMXGCR_USBCS_CLK7 0x3
-#define QE_CMXGCR_USBCS_CLK9 0x4
-#define QE_CMXGCR_USBCS_CLK13 0x5
-#define QE_CMXGCR_USBCS_CLK17 0x6
-#define QE_CMXGCR_USBCS_CLK19 0x7
-#define QE_CMXGCR_USBCS_CLK21 0x8
-#define QE_CMXGCR_USBCS_BRG9 0x9
-#define QE_CMXGCR_USBCS_BRG10 0xa
-
-/* QE CECR Commands.
-*/
-#define QE_CR_FLG 0x00010000
-#define QE_RESET 0x80000000
-#define QE_INIT_TX_RX 0x00000000
-#define QE_INIT_RX 0x00000001
-#define QE_INIT_TX 0x00000002
-#define QE_ENTER_HUNT_MODE 0x00000003
-#define QE_STOP_TX 0x00000004
-#define QE_GRACEFUL_STOP_TX 0x00000005
-#define QE_RESTART_TX 0x00000006
-#define QE_CLOSE_RX_BD 0x00000007
-#define QE_SWITCH_COMMAND 0x00000007
-#define QE_SET_GROUP_ADDRESS 0x00000008
-#define QE_START_IDMA 0x00000009
-#define QE_MCC_STOP_RX 0x00000009
-#define QE_ATM_TRANSMIT 0x0000000a
-#define QE_HPAC_CLEAR_ALL 0x0000000b
-#define QE_GRACEFUL_STOP_RX 0x0000001a
-#define QE_RESTART_RX 0x0000001b
-#define QE_HPAC_SET_PRIORITY 0x0000010b
-#define QE_HPAC_STOP_TX 0x0000020b
-#define QE_HPAC_STOP_RX 0x0000030b
-#define QE_HPAC_GRACEFUL_STOP_TX 0x0000040b
-#define QE_HPAC_GRACEFUL_STOP_RX 0x0000050b
-#define QE_HPAC_START_TX 0x0000060b
-#define QE_HPAC_START_RX 0x0000070b
-#define QE_USB_STOP_TX 0x0000000a
-#define QE_USB_RESTART_TX 0x0000000c
-#define QE_QMC_STOP_TX 0x0000000c
-#define QE_QMC_STOP_RX 0x0000000d
-#define QE_SS7_SU_FIL_RESET 0x0000000e
-/* jonathbr added from here down for 83xx */
-#define QE_RESET_BCS 0x0000000a
-#define QE_MCC_INIT_TX_RX_16 0x00000003
-#define QE_MCC_STOP_TX 0x00000004
-#define QE_MCC_INIT_TX_1 0x00000005
-#define QE_MCC_INIT_RX_1 0x00000006
-#define QE_MCC_RESET 0x00000007
-#define QE_SET_TIMER 0x00000008
-#define QE_RANDOM_NUMBER 0x0000000c
-#define QE_ATM_MULTI_THREAD_INIT 0x00000011
-#define QE_ASSIGN_PAGE 0x00000012
-#define QE_ADD_REMOVE_HASH_ENTRY 0x00000013
-#define QE_START_FLOW_CONTROL 0x00000014
-#define QE_STOP_FLOW_CONTROL 0x00000015
-#define QE_ASSIGN_PAGE_TO_DEVICE 0x00000016
-
-#define QE_ASSIGN_RISC 0x00000010
-#define QE_CR_MCN_NORMAL_SHIFT 6
-#define QE_CR_MCN_USB_SHIFT 4
-#define QE_CR_MCN_RISC_ASSIGN_SHIFT 8
-#define QE_CR_SNUM_SHIFT 17
-
-/* QE CECR Sub Block - sub block of QE command.
-*/
-#define QE_CR_SUBBLOCK_INVALID 0x00000000
-#define QE_CR_SUBBLOCK_USB 0x03200000
-#define QE_CR_SUBBLOCK_UCCFAST1 0x02000000
-#define QE_CR_SUBBLOCK_UCCFAST2 0x02200000
-#define QE_CR_SUBBLOCK_UCCFAST3 0x02400000
-#define QE_CR_SUBBLOCK_UCCFAST4 0x02600000
-#define QE_CR_SUBBLOCK_UCCFAST5 0x02800000
-#define QE_CR_SUBBLOCK_UCCFAST6 0x02a00000
-#define QE_CR_SUBBLOCK_UCCFAST7 0x02c00000
-#define QE_CR_SUBBLOCK_UCCFAST8 0x02e00000
-#define QE_CR_SUBBLOCK_UCCSLOW1 0x00000000
-#define QE_CR_SUBBLOCK_UCCSLOW2 0x00200000
-#define QE_CR_SUBBLOCK_UCCSLOW3 0x00400000
-#define QE_CR_SUBBLOCK_UCCSLOW4 0x00600000
-#define QE_CR_SUBBLOCK_UCCSLOW5 0x00800000
-#define QE_CR_SUBBLOCK_UCCSLOW6 0x00a00000
-#define QE_CR_SUBBLOCK_UCCSLOW7 0x00c00000
-#define QE_CR_SUBBLOCK_UCCSLOW8 0x00e00000
-#define QE_CR_SUBBLOCK_MCC1 0x03800000
-#define QE_CR_SUBBLOCK_MCC2 0x03a00000
-#define QE_CR_SUBBLOCK_MCC3 0x03000000
-#define QE_CR_SUBBLOCK_IDMA1 0x02800000
-#define QE_CR_SUBBLOCK_IDMA2 0x02a00000
-#define QE_CR_SUBBLOCK_IDMA3 0x02c00000
-#define QE_CR_SUBBLOCK_IDMA4 0x02e00000
-#define QE_CR_SUBBLOCK_HPAC 0x01e00000
-#define QE_CR_SUBBLOCK_SPI1 0x01400000
-#define QE_CR_SUBBLOCK_SPI2 0x01600000
-#define QE_CR_SUBBLOCK_RAND 0x01c00000
-#define QE_CR_SUBBLOCK_TIMER 0x01e00000
-#define QE_CR_SUBBLOCK_GENERAL 0x03c00000
-
-/* QE CECR Protocol - For non-MCC, specifies mode for QE CECR command */
-#define QE_CR_PROTOCOL_UNSPECIFIED 0x00 /* For all other protocols */
-#define QE_CR_PROTOCOL_HDLC_TRANSPARENT 0x00
-#define QE_CR_PROTOCOL_QMC 0x02
-#define QE_CR_PROTOCOL_UART 0x04
-#define QE_CR_PROTOCOL_ATM_POS 0x0A
-#define QE_CR_PROTOCOL_ETHERNET 0x0C
-#define QE_CR_PROTOCOL_L2_SWITCH 0x0D
-
-/* BRG configuration register */
-#define QE_BRGC_ENABLE 0x00010000
-#define QE_BRGC_DIVISOR_SHIFT 1
-#define QE_BRGC_DIVISOR_MAX 0xFFF
-#define QE_BRGC_DIV16 1
-
-/* QE Timers registers */
-#define QE_GTCFR1_PCAS 0x80
-#define QE_GTCFR1_STP2 0x20
-#define QE_GTCFR1_RST2 0x10
-#define QE_GTCFR1_GM2 0x08
-#define QE_GTCFR1_GM1 0x04
-#define QE_GTCFR1_STP1 0x02
-#define QE_GTCFR1_RST1 0x01
-
-/* SDMA registers */
-#define QE_SDSR_BER1 0x02000000
-#define QE_SDSR_BER2 0x01000000
-
-#define QE_SDMR_GLB_1_MSK 0x80000000
-#define QE_SDMR_ADR_SEL 0x20000000
-#define QE_SDMR_BER1_MSK 0x02000000
-#define QE_SDMR_BER2_MSK 0x01000000
-#define QE_SDMR_EB1_MSK 0x00800000
-#define QE_SDMR_ER1_MSK 0x00080000
-#define QE_SDMR_ER2_MSK 0x00040000
-#define QE_SDMR_CEN_MASK 0x0000E000
-#define QE_SDMR_SBER_1 0x00000200
-#define QE_SDMR_SBER_2 0x00000200
-#define QE_SDMR_EB1_PR_MASK 0x000000C0
-#define QE_SDMR_ER1_PR 0x00000008
-
-#define QE_SDMR_CEN_SHIFT 13
-#define QE_SDMR_EB1_PR_SHIFT 6
-
-#define QE_SDTM_MSNUM_SHIFT 24
-
-#define QE_SDEBCR_BA_MASK 0x01FFFFFF
-
-/* Communication Processor */
-#define QE_CP_CERCR_MEE 0x8000 /* Multi-user RAM ECC enable */
-#define QE_CP_CERCR_IEE 0x4000 /* Instruction RAM ECC enable */
-#define QE_CP_CERCR_CIR 0x0800 /* Common instruction RAM */
-
-/* I-RAM */
-#define QE_IRAM_IADD_AIE 0x80000000 /* Auto Increment Enable */
-#define QE_IRAM_IADD_BADDR 0x00080000 /* Base Address */
-#define QE_IRAM_READY 0x80000000 /* Ready */
-
-/* UPC */
-#define UPGCR_PROTOCOL 0x80000000 /* protocol ul2 or pl2 */
-#define UPGCR_TMS 0x40000000 /* Transmit master/slave mode */
-#define UPGCR_RMS 0x20000000 /* Receive master/slave mode */
-#define UPGCR_ADDR 0x10000000 /* Master MPHY Addr multiplexing */
-#define UPGCR_DIAG 0x01000000 /* Diagnostic mode */
-
-/* UCC GUEMR register */
-#define UCC_GUEMR_MODE_MASK_RX 0x02
-#define UCC_GUEMR_MODE_FAST_RX 0x02
-#define UCC_GUEMR_MODE_SLOW_RX 0x00
-#define UCC_GUEMR_MODE_MASK_TX 0x01
-#define UCC_GUEMR_MODE_FAST_TX 0x01
-#define UCC_GUEMR_MODE_SLOW_TX 0x00
-#define UCC_GUEMR_MODE_MASK (UCC_GUEMR_MODE_MASK_RX | UCC_GUEMR_MODE_MASK_TX)
-#define UCC_GUEMR_SET_RESERVED3 0x10 /* Bit 3 in the guemr is reserved but
- must be set 1 */
-
-/* structure representing UCC SLOW parameter RAM */
-struct ucc_slow_pram {
- __be16 rbase; /* RX BD base address */
- __be16 tbase; /* TX BD base address */
- u8 rbmr; /* RX bus mode register (same as CPM's RFCR) */
- u8 tbmr; /* TX bus mode register (same as CPM's TFCR) */
- __be16 mrblr; /* Rx buffer length */
- __be32 rstate; /* Rx internal state */
- __be32 rptr; /* Rx internal data pointer */
- __be16 rbptr; /* rb BD Pointer */
- __be16 rcount; /* Rx internal byte count */
- __be32 rtemp; /* Rx temp */
- __be32 tstate; /* Tx internal state */
- __be32 tptr; /* Tx internal data pointer */
- __be16 tbptr; /* Tx BD pointer */
- __be16 tcount; /* Tx byte count */
- __be32 ttemp; /* Tx temp */
- __be32 rcrc; /* temp receive CRC */
- __be32 tcrc; /* temp transmit CRC */
-} __attribute__ ((packed));
-
-/* General UCC SLOW Mode Register (GUMRH & GUMRL) */
-#define UCC_SLOW_GUMR_H_SAM_QMC 0x00000000
-#define UCC_SLOW_GUMR_H_SAM_SATM 0x00008000
-#define UCC_SLOW_GUMR_H_REVD 0x00002000
-#define UCC_SLOW_GUMR_H_TRX 0x00001000
-#define UCC_SLOW_GUMR_H_TTX 0x00000800
-#define UCC_SLOW_GUMR_H_CDP 0x00000400
-#define UCC_SLOW_GUMR_H_CTSP 0x00000200
-#define UCC_SLOW_GUMR_H_CDS 0x00000100
-#define UCC_SLOW_GUMR_H_CTSS 0x00000080
-#define UCC_SLOW_GUMR_H_TFL 0x00000040
-#define UCC_SLOW_GUMR_H_RFW 0x00000020
-#define UCC_SLOW_GUMR_H_TXSY 0x00000010
-#define UCC_SLOW_GUMR_H_4SYNC 0x00000004
-#define UCC_SLOW_GUMR_H_8SYNC 0x00000008
-#define UCC_SLOW_GUMR_H_16SYNC 0x0000000c
-#define UCC_SLOW_GUMR_H_RTSM 0x00000002
-#define UCC_SLOW_GUMR_H_RSYN 0x00000001
-
-#define UCC_SLOW_GUMR_L_TCI 0x10000000
-#define UCC_SLOW_GUMR_L_RINV 0x02000000
-#define UCC_SLOW_GUMR_L_TINV 0x01000000
-#define UCC_SLOW_GUMR_L_TEND 0x00040000
-#define UCC_SLOW_GUMR_L_TDCR_MASK 0x00030000
-#define UCC_SLOW_GUMR_L_TDCR_32 0x00030000
-#define UCC_SLOW_GUMR_L_TDCR_16 0x00020000
-#define UCC_SLOW_GUMR_L_TDCR_8 0x00010000
-#define UCC_SLOW_GUMR_L_TDCR_1 0x00000000
-#define UCC_SLOW_GUMR_L_RDCR_MASK 0x0000c000
-#define UCC_SLOW_GUMR_L_RDCR_32 0x0000c000
-#define UCC_SLOW_GUMR_L_RDCR_16 0x00008000
-#define UCC_SLOW_GUMR_L_RDCR_8 0x00004000
-#define UCC_SLOW_GUMR_L_RDCR_1 0x00000000
-#define UCC_SLOW_GUMR_L_RENC_NRZI 0x00000800
-#define UCC_SLOW_GUMR_L_RENC_NRZ 0x00000000
-#define UCC_SLOW_GUMR_L_TENC_NRZI 0x00000100
-#define UCC_SLOW_GUMR_L_TENC_NRZ 0x00000000
-#define UCC_SLOW_GUMR_L_DIAG_MASK 0x000000c0
-#define UCC_SLOW_GUMR_L_DIAG_LE 0x000000c0
-#define UCC_SLOW_GUMR_L_DIAG_ECHO 0x00000080
-#define UCC_SLOW_GUMR_L_DIAG_LOOP 0x00000040
-#define UCC_SLOW_GUMR_L_DIAG_NORM 0x00000000
-#define UCC_SLOW_GUMR_L_ENR 0x00000020
-#define UCC_SLOW_GUMR_L_ENT 0x00000010
-#define UCC_SLOW_GUMR_L_MODE_MASK 0x0000000F
-#define UCC_SLOW_GUMR_L_MODE_BISYNC 0x00000008
-#define UCC_SLOW_GUMR_L_MODE_AHDLC 0x00000006
-#define UCC_SLOW_GUMR_L_MODE_UART 0x00000004
-#define UCC_SLOW_GUMR_L_MODE_QMC 0x00000002
-
-/* General UCC FAST Mode Register */
-#define UCC_FAST_GUMR_TCI 0x20000000
-#define UCC_FAST_GUMR_TRX 0x10000000
-#define UCC_FAST_GUMR_TTX 0x08000000
-#define UCC_FAST_GUMR_CDP 0x04000000
-#define UCC_FAST_GUMR_CTSP 0x02000000
-#define UCC_FAST_GUMR_CDS 0x01000000
-#define UCC_FAST_GUMR_CTSS 0x00800000
-#define UCC_FAST_GUMR_TXSY 0x00020000
-#define UCC_FAST_GUMR_RSYN 0x00010000
-#define UCC_FAST_GUMR_RTSM 0x00002000
-#define UCC_FAST_GUMR_REVD 0x00000400
-#define UCC_FAST_GUMR_ENR 0x00000020
-#define UCC_FAST_GUMR_ENT 0x00000010
-
-/* UART Slow UCC Event Register (UCCE) */
-#define UCC_UART_UCCE_AB 0x0200
-#define UCC_UART_UCCE_IDLE 0x0100
-#define UCC_UART_UCCE_GRA 0x0080
-#define UCC_UART_UCCE_BRKE 0x0040
-#define UCC_UART_UCCE_BRKS 0x0020
-#define UCC_UART_UCCE_CCR 0x0008
-#define UCC_UART_UCCE_BSY 0x0004
-#define UCC_UART_UCCE_TX 0x0002
-#define UCC_UART_UCCE_RX 0x0001
-
-/* HDLC Slow UCC Event Register (UCCE) */
-#define UCC_HDLC_UCCE_GLR 0x1000
-#define UCC_HDLC_UCCE_GLT 0x0800
-#define UCC_HDLC_UCCE_IDLE 0x0100
-#define UCC_HDLC_UCCE_BRKE 0x0040
-#define UCC_HDLC_UCCE_BRKS 0x0020
-#define UCC_HDLC_UCCE_TXE 0x0010
-#define UCC_HDLC_UCCE_RXF 0x0008
-#define UCC_HDLC_UCCE_BSY 0x0004
-#define UCC_HDLC_UCCE_TXB 0x0002
-#define UCC_HDLC_UCCE_RXB 0x0001
-
-/* BISYNC Slow UCC Event Register (UCCE) */
-#define UCC_BISYNC_UCCE_GRA 0x0080
-#define UCC_BISYNC_UCCE_TXE 0x0010
-#define UCC_BISYNC_UCCE_RCH 0x0008
-#define UCC_BISYNC_UCCE_BSY 0x0004
-#define UCC_BISYNC_UCCE_TXB 0x0002
-#define UCC_BISYNC_UCCE_RXB 0x0001
-
-/* Gigabit Ethernet Fast UCC Event Register (UCCE) */
-#define UCC_GETH_UCCE_MPD 0x80000000
-#define UCC_GETH_UCCE_SCAR 0x40000000
-#define UCC_GETH_UCCE_GRA 0x20000000
-#define UCC_GETH_UCCE_CBPR 0x10000000
-#define UCC_GETH_UCCE_BSY 0x08000000
-#define UCC_GETH_UCCE_RXC 0x04000000
-#define UCC_GETH_UCCE_TXC 0x02000000
-#define UCC_GETH_UCCE_TXE 0x01000000
-#define UCC_GETH_UCCE_TXB7 0x00800000
-#define UCC_GETH_UCCE_TXB6 0x00400000
-#define UCC_GETH_UCCE_TXB5 0x00200000
-#define UCC_GETH_UCCE_TXB4 0x00100000
-#define UCC_GETH_UCCE_TXB3 0x00080000
-#define UCC_GETH_UCCE_TXB2 0x00040000
-#define UCC_GETH_UCCE_TXB1 0x00020000
-#define UCC_GETH_UCCE_TXB0 0x00010000
-#define UCC_GETH_UCCE_RXB7 0x00008000
-#define UCC_GETH_UCCE_RXB6 0x00004000
-#define UCC_GETH_UCCE_RXB5 0x00002000
-#define UCC_GETH_UCCE_RXB4 0x00001000
-#define UCC_GETH_UCCE_RXB3 0x00000800
-#define UCC_GETH_UCCE_RXB2 0x00000400
-#define UCC_GETH_UCCE_RXB1 0x00000200
-#define UCC_GETH_UCCE_RXB0 0x00000100
-#define UCC_GETH_UCCE_RXF7 0x00000080
-#define UCC_GETH_UCCE_RXF6 0x00000040
-#define UCC_GETH_UCCE_RXF5 0x00000020
-#define UCC_GETH_UCCE_RXF4 0x00000010
-#define UCC_GETH_UCCE_RXF3 0x00000008
-#define UCC_GETH_UCCE_RXF2 0x00000004
-#define UCC_GETH_UCCE_RXF1 0x00000002
-#define UCC_GETH_UCCE_RXF0 0x00000001
-
-/* UCC Protocol Specific Mode Register (UPSMR), when used for UART */
-#define UCC_UART_UPSMR_FLC 0x8000
-#define UCC_UART_UPSMR_SL 0x4000
-#define UCC_UART_UPSMR_CL_MASK 0x3000
-#define UCC_UART_UPSMR_CL_8 0x3000
-#define UCC_UART_UPSMR_CL_7 0x2000
-#define UCC_UART_UPSMR_CL_6 0x1000
-#define UCC_UART_UPSMR_CL_5 0x0000
-#define UCC_UART_UPSMR_UM_MASK 0x0c00
-#define UCC_UART_UPSMR_UM_NORMAL 0x0000
-#define UCC_UART_UPSMR_UM_MAN_MULTI 0x0400
-#define UCC_UART_UPSMR_UM_AUTO_MULTI 0x0c00
-#define UCC_UART_UPSMR_FRZ 0x0200
-#define UCC_UART_UPSMR_RZS 0x0100
-#define UCC_UART_UPSMR_SYN 0x0080
-#define UCC_UART_UPSMR_DRT 0x0040
-#define UCC_UART_UPSMR_PEN 0x0010
-#define UCC_UART_UPSMR_RPM_MASK 0x000c
-#define UCC_UART_UPSMR_RPM_ODD 0x0000
-#define UCC_UART_UPSMR_RPM_LOW 0x0004
-#define UCC_UART_UPSMR_RPM_EVEN 0x0008
-#define UCC_UART_UPSMR_RPM_HIGH 0x000C
-#define UCC_UART_UPSMR_TPM_MASK 0x0003
-#define UCC_UART_UPSMR_TPM_ODD 0x0000
-#define UCC_UART_UPSMR_TPM_LOW 0x0001
-#define UCC_UART_UPSMR_TPM_EVEN 0x0002
-#define UCC_UART_UPSMR_TPM_HIGH 0x0003
-
-/* UCC Protocol Specific Mode Register (UPSMR), when used for Ethernet */
-#define UCC_GETH_UPSMR_FTFE 0x80000000
-#define UCC_GETH_UPSMR_PTPE 0x40000000
-#define UCC_GETH_UPSMR_ECM 0x04000000
-#define UCC_GETH_UPSMR_HSE 0x02000000
-#define UCC_GETH_UPSMR_PRO 0x00400000
-#define UCC_GETH_UPSMR_CAP 0x00200000
-#define UCC_GETH_UPSMR_RSH 0x00100000
-#define UCC_GETH_UPSMR_RPM 0x00080000
-#define UCC_GETH_UPSMR_R10M 0x00040000
-#define UCC_GETH_UPSMR_RLPB 0x00020000
-#define UCC_GETH_UPSMR_TBIM 0x00010000
-#define UCC_GETH_UPSMR_RES1 0x00002000
-#define UCC_GETH_UPSMR_RMM 0x00001000
-#define UCC_GETH_UPSMR_CAM 0x00000400
-#define UCC_GETH_UPSMR_BRO 0x00000200
-#define UCC_GETH_UPSMR_SMM 0x00000080
-#define UCC_GETH_UPSMR_SGMM 0x00000020
-
-/* UCC Transmit On Demand Register (UTODR) */
-#define UCC_SLOW_TOD 0x8000
-#define UCC_FAST_TOD 0x8000
-
-/* UCC Bus Mode Register masks */
-/* Not to be confused with the Bundle Mode Register */
-#define UCC_BMR_GBL 0x20
-#define UCC_BMR_BO_BE 0x10
-#define UCC_BMR_CETM 0x04
-#define UCC_BMR_DTB 0x02
-#define UCC_BMR_BDB 0x01
-
-/* Function code masks */
-#define FC_GBL 0x20
-#define FC_DTB_LCL 0x02
-#define UCC_FAST_FUNCTION_CODE_GBL 0x20
-#define UCC_FAST_FUNCTION_CODE_DTB_LCL 0x02
-#define UCC_FAST_FUNCTION_CODE_BDB_LCL 0x01
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_POWERPC_QE_H */
+++ /dev/null
-/*
- * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Authors: Shlomi Gridish <gridish@freescale.com>
- * Li Yang <leoli@freescale.com>
- *
- * Description:
- * QE IC external definitions and structure.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#ifndef _ASM_POWERPC_QE_IC_H
-#define _ASM_POWERPC_QE_IC_H
-
-#include <linux/irq.h>
-
-struct device_node;
-struct qe_ic;
-
-#define NUM_OF_QE_IC_GROUPS 6
-
-/* Flags when we init the QE IC */
-#define QE_IC_SPREADMODE_GRP_W 0x00000001
-#define QE_IC_SPREADMODE_GRP_X 0x00000002
-#define QE_IC_SPREADMODE_GRP_Y 0x00000004
-#define QE_IC_SPREADMODE_GRP_Z 0x00000008
-#define QE_IC_SPREADMODE_GRP_RISCA 0x00000010
-#define QE_IC_SPREADMODE_GRP_RISCB 0x00000020
-
-#define QE_IC_LOW_SIGNAL 0x00000100
-#define QE_IC_HIGH_SIGNAL 0x00000200
-
-#define QE_IC_GRP_W_PRI0_DEST_SIGNAL_HIGH 0x00001000
-#define QE_IC_GRP_W_PRI1_DEST_SIGNAL_HIGH 0x00002000
-#define QE_IC_GRP_X_PRI0_DEST_SIGNAL_HIGH 0x00004000
-#define QE_IC_GRP_X_PRI1_DEST_SIGNAL_HIGH 0x00008000
-#define QE_IC_GRP_Y_PRI0_DEST_SIGNAL_HIGH 0x00010000
-#define QE_IC_GRP_Y_PRI1_DEST_SIGNAL_HIGH 0x00020000
-#define QE_IC_GRP_Z_PRI0_DEST_SIGNAL_HIGH 0x00040000
-#define QE_IC_GRP_Z_PRI1_DEST_SIGNAL_HIGH 0x00080000
-#define QE_IC_GRP_RISCA_PRI0_DEST_SIGNAL_HIGH 0x00100000
-#define QE_IC_GRP_RISCA_PRI1_DEST_SIGNAL_HIGH 0x00200000
-#define QE_IC_GRP_RISCB_PRI0_DEST_SIGNAL_HIGH 0x00400000
-#define QE_IC_GRP_RISCB_PRI1_DEST_SIGNAL_HIGH 0x00800000
-#define QE_IC_GRP_W_DEST_SIGNAL_SHIFT (12)
-
-/* QE interrupt sources groups */
-enum qe_ic_grp_id {
- QE_IC_GRP_W = 0, /* QE interrupt controller group W */
- QE_IC_GRP_X, /* QE interrupt controller group X */
- QE_IC_GRP_Y, /* QE interrupt controller group Y */
- QE_IC_GRP_Z, /* QE interrupt controller group Z */
- QE_IC_GRP_RISCA, /* QE interrupt controller RISC group A */
- QE_IC_GRP_RISCB /* QE interrupt controller RISC group B */
-};
-
-#ifdef CONFIG_QUICC_ENGINE
-void qe_ic_init(struct device_node *node, unsigned int flags,
- void (*low_handler)(struct irq_desc *desc),
- void (*high_handler)(struct irq_desc *desc));
-unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic);
-unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic);
-#else
-static inline void qe_ic_init(struct device_node *node, unsigned int flags,
- void (*low_handler)(struct irq_desc *desc),
- void (*high_handler)(struct irq_desc *desc))
-{}
-static inline unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic)
-{ return 0; }
-static inline unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic)
-{ return 0; }
-#endif /* CONFIG_QUICC_ENGINE */
-
-void qe_ic_set_highest_priority(unsigned int virq, int high);
-int qe_ic_set_priority(unsigned int virq, unsigned int priority);
-int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high);
-
-static inline void qe_ic_cascade_low_ipic(struct irq_desc *desc)
-{
- struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
- unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
-
- if (cascade_irq != NO_IRQ)
- generic_handle_irq(cascade_irq);
-}
-
-static inline void qe_ic_cascade_high_ipic(struct irq_desc *desc)
-{
- struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
- unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
-
- if (cascade_irq != NO_IRQ)
- generic_handle_irq(cascade_irq);
-}
-
-static inline void qe_ic_cascade_low_mpic(struct irq_desc *desc)
-{
- struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
- unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
- struct irq_chip *chip = irq_desc_get_chip(desc);
-
- if (cascade_irq != NO_IRQ)
- generic_handle_irq(cascade_irq);
-
- chip->irq_eoi(&desc->irq_data);
-}
-
-static inline void qe_ic_cascade_high_mpic(struct irq_desc *desc)
-{
- struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
- unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
- struct irq_chip *chip = irq_desc_get_chip(desc);
-
- if (cascade_irq != NO_IRQ)
- generic_handle_irq(cascade_irq);
-
- chip->irq_eoi(&desc->irq_data);
-}
-
-static inline void qe_ic_cascade_muxed_mpic(struct irq_desc *desc)
-{
- struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
- unsigned int cascade_irq;
- struct irq_chip *chip = irq_desc_get_chip(desc);
-
- cascade_irq = qe_ic_get_high_irq(qe_ic);
- if (cascade_irq == NO_IRQ)
- cascade_irq = qe_ic_get_low_irq(qe_ic);
-
- if (cascade_irq != NO_IRQ)
- generic_handle_irq(cascade_irq);
-
- chip->irq_eoi(&desc->irq_data);
-}
-
-#endif /* _ASM_POWERPC_QE_IC_H */
+++ /dev/null
-/*
- * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Authors: Shlomi Gridish <gridish@freescale.com>
- * Li Yang <leoli@freescale.com>
- *
- * Description:
- * Internal header file for UCC unit routines.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#ifndef __UCC_H__
-#define __UCC_H__
-
-#include <asm/immap_qe.h>
-#include <asm/qe.h>
-
-#define STATISTICS
-
-#define UCC_MAX_NUM 8
-
-/* Slow or fast type for UCCs.
-*/
-enum ucc_speed_type {
- UCC_SPEED_TYPE_FAST = UCC_GUEMR_MODE_FAST_RX | UCC_GUEMR_MODE_FAST_TX,
- UCC_SPEED_TYPE_SLOW = UCC_GUEMR_MODE_SLOW_RX | UCC_GUEMR_MODE_SLOW_TX
-};
-
-/* ucc_set_type
- * Sets UCC to slow or fast mode.
- *
- * ucc_num - (In) number of UCC (0-7).
- * speed - (In) slow or fast mode for UCC.
- */
-int ucc_set_type(unsigned int ucc_num, enum ucc_speed_type speed);
-
-int ucc_set_qe_mux_mii_mng(unsigned int ucc_num);
-
-int ucc_set_qe_mux_rxtx(unsigned int ucc_num, enum qe_clock clock,
- enum comm_dir mode);
-
-int ucc_mux_set_grant_tsa_bkpt(unsigned int ucc_num, int set, u32 mask);
-
-/* QE MUX clock routing for UCC
-*/
-static inline int ucc_set_qe_mux_grant(unsigned int ucc_num, int set)
-{
- return ucc_mux_set_grant_tsa_bkpt(ucc_num, set, QE_CMXUCR_GRANT);
-}
-
-static inline int ucc_set_qe_mux_tsa(unsigned int ucc_num, int set)
-{
- return ucc_mux_set_grant_tsa_bkpt(ucc_num, set, QE_CMXUCR_TSA);
-}
-
-static inline int ucc_set_qe_mux_bkpt(unsigned int ucc_num, int set)
-{
- return ucc_mux_set_grant_tsa_bkpt(ucc_num, set, QE_CMXUCR_BKPT);
-}
-
-#endif /* __UCC_H__ */
+++ /dev/null
-/*
- * Internal header file for UCC FAST unit routines.
- *
- * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Authors: Shlomi Gridish <gridish@freescale.com>
- * Li Yang <leoli@freescale.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#ifndef __UCC_FAST_H__
-#define __UCC_FAST_H__
-
-#include <linux/kernel.h>
-
-#include <asm/immap_qe.h>
-#include <asm/qe.h>
-
-#include <asm/ucc.h>
-
-/* Receive BD's status */
-#define R_E 0x80000000 /* buffer empty */
-#define R_W 0x20000000 /* wrap bit */
-#define R_I 0x10000000 /* interrupt on reception */
-#define R_L 0x08000000 /* last */
-#define R_F 0x04000000 /* first */
-
-/* transmit BD's status */
-#define T_R 0x80000000 /* ready bit */
-#define T_W 0x20000000 /* wrap bit */
-#define T_I 0x10000000 /* interrupt on completion */
-#define T_L 0x08000000 /* last */
-
-/* Rx Data buffer must be 4 bytes aligned in most cases */
-#define UCC_FAST_RX_ALIGN 4
-#define UCC_FAST_MRBLR_ALIGNMENT 4
-#define UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT 8
-
-/* Sizes */
-#define UCC_FAST_URFS_MIN_VAL 0x88
-#define UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR 8
-
-/* ucc_fast_channel_protocol_mode - UCC FAST mode */
-enum ucc_fast_channel_protocol_mode {
- UCC_FAST_PROTOCOL_MODE_HDLC = 0x00000000,
- UCC_FAST_PROTOCOL_MODE_RESERVED01 = 0x00000001,
- UCC_FAST_PROTOCOL_MODE_RESERVED_QMC = 0x00000002,
- UCC_FAST_PROTOCOL_MODE_RESERVED02 = 0x00000003,
- UCC_FAST_PROTOCOL_MODE_RESERVED_UART = 0x00000004,
- UCC_FAST_PROTOCOL_MODE_RESERVED03 = 0x00000005,
- UCC_FAST_PROTOCOL_MODE_RESERVED_EX_MAC_1 = 0x00000006,
- UCC_FAST_PROTOCOL_MODE_RESERVED_EX_MAC_2 = 0x00000007,
- UCC_FAST_PROTOCOL_MODE_RESERVED_BISYNC = 0x00000008,
- UCC_FAST_PROTOCOL_MODE_RESERVED04 = 0x00000009,
- UCC_FAST_PROTOCOL_MODE_ATM = 0x0000000A,
- UCC_FAST_PROTOCOL_MODE_RESERVED05 = 0x0000000B,
- UCC_FAST_PROTOCOL_MODE_ETHERNET = 0x0000000C,
- UCC_FAST_PROTOCOL_MODE_RESERVED06 = 0x0000000D,
- UCC_FAST_PROTOCOL_MODE_POS = 0x0000000E,
- UCC_FAST_PROTOCOL_MODE_RESERVED07 = 0x0000000F
-};
-
-/* ucc_fast_transparent_txrx - UCC Fast Transparent TX & RX */
-enum ucc_fast_transparent_txrx {
- UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL = 0x00000000,
- UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_TRANSPARENT = 0x18000000
-};
-
-/* UCC fast diagnostic mode */
-enum ucc_fast_diag_mode {
- UCC_FAST_DIAGNOSTIC_NORMAL = 0x0,
- UCC_FAST_DIAGNOSTIC_LOCAL_LOOP_BACK = 0x40000000,
- UCC_FAST_DIAGNOSTIC_AUTO_ECHO = 0x80000000,
- UCC_FAST_DIAGNOSTIC_LOOP_BACK_AND_ECHO = 0xC0000000
-};
-
-/* UCC fast Sync length (transparent mode only) */
-enum ucc_fast_sync_len {
- UCC_FAST_SYNC_LEN_NOT_USED = 0x0,
- UCC_FAST_SYNC_LEN_AUTOMATIC = 0x00004000,
- UCC_FAST_SYNC_LEN_8_BIT = 0x00008000,
- UCC_FAST_SYNC_LEN_16_BIT = 0x0000C000
-};
-
-/* UCC fast RTS mode */
-enum ucc_fast_ready_to_send {
- UCC_FAST_SEND_IDLES_BETWEEN_FRAMES = 0x00000000,
- UCC_FAST_SEND_FLAGS_BETWEEN_FRAMES = 0x00002000
-};
-
-/* UCC fast receiver decoding mode */
-enum ucc_fast_rx_decoding_method {
- UCC_FAST_RX_ENCODING_NRZ = 0x00000000,
- UCC_FAST_RX_ENCODING_NRZI = 0x00000800,
- UCC_FAST_RX_ENCODING_RESERVED0 = 0x00001000,
- UCC_FAST_RX_ENCODING_RESERVED1 = 0x00001800
-};
-
-/* UCC fast transmitter encoding mode */
-enum ucc_fast_tx_encoding_method {
- UCC_FAST_TX_ENCODING_NRZ = 0x00000000,
- UCC_FAST_TX_ENCODING_NRZI = 0x00000100,
- UCC_FAST_TX_ENCODING_RESERVED0 = 0x00000200,
- UCC_FAST_TX_ENCODING_RESERVED1 = 0x00000300
-};
-
-/* UCC fast CRC length */
-enum ucc_fast_transparent_tcrc {
- UCC_FAST_16_BIT_CRC = 0x00000000,
- UCC_FAST_CRC_RESERVED0 = 0x00000040,
- UCC_FAST_32_BIT_CRC = 0x00000080,
- UCC_FAST_CRC_RESERVED1 = 0x000000C0
-};
-
-/* Fast UCC initialization structure */
-struct ucc_fast_info {
- int ucc_num;
- enum qe_clock rx_clock;
- enum qe_clock tx_clock;
- u32 regs;
- int irq;
- u32 uccm_mask;
- int bd_mem_part;
- int brkpt_support;
- int grant_support;
- int tsa;
- int cdp;
- int cds;
- int ctsp;
- int ctss;
- int tci;
- int txsy;
- int rtsm;
- int revd;
- int rsyn;
- u16 max_rx_buf_length;
- u16 urfs;
- u16 urfet;
- u16 urfset;
- u16 utfs;
- u16 utfet;
- u16 utftt;
- u16 ufpt;
- enum ucc_fast_channel_protocol_mode mode;
- enum ucc_fast_transparent_txrx ttx_trx;
- enum ucc_fast_tx_encoding_method tenc;
- enum ucc_fast_rx_decoding_method renc;
- enum ucc_fast_transparent_tcrc tcrc;
- enum ucc_fast_sync_len synl;
-};
-
-struct ucc_fast_private {
- struct ucc_fast_info *uf_info;
- struct ucc_fast __iomem *uf_regs; /* a pointer to the UCC regs. */
- u32 __iomem *p_ucce; /* a pointer to the event register in memory. */
- u32 __iomem *p_uccm; /* a pointer to the mask register in memory. */
-#ifdef CONFIG_UGETH_TX_ON_DEMAND
- u16 __iomem *p_utodr; /* pointer to the transmit on demand register */
-#endif
- int enabled_tx; /* Whether channel is enabled for Tx (ENT) */
- int enabled_rx; /* Whether channel is enabled for Rx (ENR) */
- int stopped_tx; /* Whether channel has been stopped for Tx
- (STOP_TX, etc.) */
- int stopped_rx; /* Whether channel has been stopped for Rx */
- u32 ucc_fast_tx_virtual_fifo_base_offset;/* pointer to base of Tx
- virtual fifo */
- u32 ucc_fast_rx_virtual_fifo_base_offset;/* pointer to base of Rx
- virtual fifo */
-#ifdef STATISTICS
- u32 tx_frames; /* Transmitted frames counter. */
- u32 rx_frames; /* Received frames counter (only frames
- passed to application). */
- u32 tx_discarded; /* Discarded tx frames counter (frames that
- were discarded by the driver due to errors).
- */
- u32 rx_discarded; /* Discarded rx frames counter (frames that
- were discarded by the driver due to errors).
- */
-#endif /* STATISTICS */
- u16 mrblr; /* maximum receive buffer length */
-};
-
-/* ucc_fast_init
- * Initializes Fast UCC according to user provided parameters.
- *
- * uf_info - (In) pointer to the fast UCC info structure.
- * uccf_ret - (Out) pointer to the fast UCC structure.
- */
-int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret);
-
-/* ucc_fast_free
- * Frees all resources for fast UCC.
- *
- * uccf - (In) pointer to the fast UCC structure.
- */
-void ucc_fast_free(struct ucc_fast_private * uccf);
-
-/* ucc_fast_enable
- * Enables a fast UCC port.
- * This routine enables Tx and/or Rx through the General UCC Mode Register.
- *
- * uccf - (In) pointer to the fast UCC structure.
- * mode - (In) TX, RX, or both.
- */
-void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode);
-
-/* ucc_fast_disable
- * Disables a fast UCC port.
- * This routine disables Tx and/or Rx through the General UCC Mode Register.
- *
- * uccf - (In) pointer to the fast UCC structure.
- * mode - (In) TX, RX, or both.
- */
-void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode);
-
-/* ucc_fast_irq
- * Handles interrupts on fast UCC.
- * Called from the general interrupt routine to handle interrupts on fast UCC.
- *
- * uccf - (In) pointer to the fast UCC structure.
- */
-void ucc_fast_irq(struct ucc_fast_private * uccf);
-
-/* ucc_fast_transmit_on_demand
- * Immediately forces a poll of the transmitter for data to be sent.
- * Typically, the hardware performs a periodic poll for data that the
- * transmit routine has set up to be transmitted. In cases where
- * this polling cycle is not soon enough, this optional routine can
- * be invoked to force a poll right away, instead. Proper use for
- * each transmission for which this functionality is desired is to
- * call the transmit routine and then this routine right after.
- *
- * uccf - (In) pointer to the fast UCC structure.
- */
-void ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf);
-
-u32 ucc_fast_get_qe_cr_subblock(int uccf_num);
-
-void ucc_fast_dump_regs(struct ucc_fast_private * uccf);
-
-#endif /* __UCC_FAST_H__ */
+++ /dev/null
-/*
- * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Authors: Shlomi Gridish <gridish@freescale.com>
- * Li Yang <leoli@freescale.com>
- *
- * Description:
- * Internal header file for UCC SLOW unit routines.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#ifndef __UCC_SLOW_H__
-#define __UCC_SLOW_H__
-
-#include <linux/kernel.h>
-
-#include <asm/immap_qe.h>
-#include <asm/qe.h>
-
-#include <asm/ucc.h>
-
-/* transmit BD's status */
-#define T_R 0x80000000 /* ready bit */
-#define T_PAD 0x40000000 /* add pads to short frames */
-#define T_W 0x20000000 /* wrap bit */
-#define T_I 0x10000000 /* interrupt on completion */
-#define T_L 0x08000000 /* last */
-
-#define T_A 0x04000000 /* Address - the data transmitted as address
- chars */
-#define T_TC 0x04000000 /* transmit CRC */
-#define T_CM 0x02000000 /* continuous mode */
-#define T_DEF 0x02000000 /* collision on previous attempt to transmit */
-#define T_P 0x01000000 /* Preamble - send Preamble sequence before
- data */
-#define T_HB 0x01000000 /* heartbeat */
-#define T_NS 0x00800000 /* No Stop */
-#define T_LC 0x00800000 /* late collision */
-#define T_RL 0x00400000 /* retransmission limit */
-#define T_UN 0x00020000 /* underrun */
-#define T_CT 0x00010000 /* CTS lost */
-#define T_CSL 0x00010000 /* carrier sense lost */
-#define T_RC 0x003c0000 /* retry count */
-
-/* Receive BD's status */
-#define R_E 0x80000000 /* buffer empty */
-#define R_W 0x20000000 /* wrap bit */
-#define R_I 0x10000000 /* interrupt on reception */
-#define R_L 0x08000000 /* last */
-#define R_C 0x08000000 /* the last byte in this buffer is a cntl
- char */
-#define R_F 0x04000000 /* first */
-#define R_A 0x04000000 /* the first byte in this buffer is address
- byte */
-#define R_CM 0x02000000 /* continuous mode */
-#define R_ID 0x01000000 /* buffer close on reception of idles */
-#define R_M 0x01000000 /* Frame received because of promiscuous
- mode */
-#define R_AM 0x00800000 /* Address match */
-#define R_DE 0x00800000 /* Address match */
-#define R_LG 0x00200000 /* Break received */
-#define R_BR 0x00200000 /* Frame length violation */
-#define R_NO 0x00100000 /* Rx Non Octet Aligned Packet */
-#define R_FR 0x00100000 /* Framing Error (no stop bit) character
- received */
-#define R_PR 0x00080000 /* Parity Error character received */
-#define R_AB 0x00080000 /* Frame Aborted */
-#define R_SH 0x00080000 /* frame is too short */
-#define R_CR 0x00040000 /* CRC Error */
-#define R_OV 0x00020000 /* Overrun */
-#define R_CD 0x00010000 /* CD lost */
-#define R_CL 0x00010000 /* this frame is closed because of a
- collision */
-
-/* Rx Data buffer must be 4 bytes aligned in most cases.*/
-#define UCC_SLOW_RX_ALIGN 4
-#define UCC_SLOW_MRBLR_ALIGNMENT 4
-#define UCC_SLOW_PRAM_SIZE 0x100
-#define ALIGNMENT_OF_UCC_SLOW_PRAM 64
-
-/* UCC Slow Channel Protocol Mode */
-enum ucc_slow_channel_protocol_mode {
- UCC_SLOW_CHANNEL_PROTOCOL_MODE_QMC = 0x00000002,
- UCC_SLOW_CHANNEL_PROTOCOL_MODE_UART = 0x00000004,
- UCC_SLOW_CHANNEL_PROTOCOL_MODE_BISYNC = 0x00000008,
-};
-
-/* UCC Slow Transparent Transmit CRC (TCRC) */
-enum ucc_slow_transparent_tcrc {
- /* 16-bit CCITT CRC (HDLC). (X16 + X12 + X5 + 1) */
- UCC_SLOW_TRANSPARENT_TCRC_CCITT_CRC16 = 0x00000000,
- /* CRC16 (BISYNC). (X16 + X15 + X2 + 1) */
- UCC_SLOW_TRANSPARENT_TCRC_CRC16 = 0x00004000,
- /* 32-bit CCITT CRC (Ethernet and HDLC) */
- UCC_SLOW_TRANSPARENT_TCRC_CCITT_CRC32 = 0x00008000,
-};
-
-/* UCC Slow oversampling rate for transmitter (TDCR) */
-enum ucc_slow_tx_oversampling_rate {
- /* 1x clock mode */
- UCC_SLOW_OVERSAMPLING_RATE_TX_TDCR_1 = 0x00000000,
- /* 8x clock mode */
- UCC_SLOW_OVERSAMPLING_RATE_TX_TDCR_8 = 0x00010000,
- /* 16x clock mode */
- UCC_SLOW_OVERSAMPLING_RATE_TX_TDCR_16 = 0x00020000,
- /* 32x clock mode */
- UCC_SLOW_OVERSAMPLING_RATE_TX_TDCR_32 = 0x00030000,
-};
-
-/* UCC Slow Oversampling rate for receiver (RDCR)
-*/
-enum ucc_slow_rx_oversampling_rate {
- /* 1x clock mode */
- UCC_SLOW_OVERSAMPLING_RATE_RX_RDCR_1 = 0x00000000,
- /* 8x clock mode */
- UCC_SLOW_OVERSAMPLING_RATE_RX_RDCR_8 = 0x00004000,
- /* 16x clock mode */
- UCC_SLOW_OVERSAMPLING_RATE_RX_RDCR_16 = 0x00008000,
- /* 32x clock mode */
- UCC_SLOW_OVERSAMPLING_RATE_RX_RDCR_32 = 0x0000c000,
-};
-
-/* UCC Slow Transmitter encoding method (TENC)
-*/
-enum ucc_slow_tx_encoding_method {
- UCC_SLOW_TRANSMITTER_ENCODING_METHOD_TENC_NRZ = 0x00000000,
- UCC_SLOW_TRANSMITTER_ENCODING_METHOD_TENC_NRZI = 0x00000100
-};
-
-/* UCC Slow Receiver decoding method (RENC)
-*/
-enum ucc_slow_rx_decoding_method {
- UCC_SLOW_RECEIVER_DECODING_METHOD_RENC_NRZ = 0x00000000,
- UCC_SLOW_RECEIVER_DECODING_METHOD_RENC_NRZI = 0x00000800
-};
-
-/* UCC Slow Diagnostic mode (DIAG)
-*/
-enum ucc_slow_diag_mode {
- UCC_SLOW_DIAG_MODE_NORMAL = 0x00000000,
- UCC_SLOW_DIAG_MODE_LOOPBACK = 0x00000040,
- UCC_SLOW_DIAG_MODE_ECHO = 0x00000080,
- UCC_SLOW_DIAG_MODE_LOOPBACK_ECHO = 0x000000c0
-};
-
-struct ucc_slow_info {
- int ucc_num;
- int protocol; /* QE_CR_PROTOCOL_xxx */
- enum qe_clock rx_clock;
- enum qe_clock tx_clock;
- phys_addr_t regs;
- int irq;
- u16 uccm_mask;
- int data_mem_part;
- int init_tx;
- int init_rx;
- u32 tx_bd_ring_len;
- u32 rx_bd_ring_len;
- int rx_interrupts;
- int brkpt_support;
- int grant_support;
- int tsa;
- int cdp;
- int cds;
- int ctsp;
- int ctss;
- int rinv;
- int tinv;
- int rtsm;
- int rfw;
- int tci;
- int tend;
- int tfl;
- int txsy;
- u16 max_rx_buf_length;
- enum ucc_slow_transparent_tcrc tcrc;
- enum ucc_slow_channel_protocol_mode mode;
- enum ucc_slow_diag_mode diag;
- enum ucc_slow_tx_oversampling_rate tdcr;
- enum ucc_slow_rx_oversampling_rate rdcr;
- enum ucc_slow_tx_encoding_method tenc;
- enum ucc_slow_rx_decoding_method renc;
-};
-
-struct ucc_slow_private {
- struct ucc_slow_info *us_info;
- struct ucc_slow __iomem *us_regs; /* Ptr to memory map of UCC regs */
- struct ucc_slow_pram *us_pram; /* a pointer to the parameter RAM */
- u32 us_pram_offset;
- int enabled_tx; /* Whether channel is enabled for Tx (ENT) */
- int enabled_rx; /* Whether channel is enabled for Rx (ENR) */
- int stopped_tx; /* Whether channel has been stopped for Tx
- (STOP_TX, etc.) */
- int stopped_rx; /* Whether channel has been stopped for Rx */
- struct list_head confQ; /* frames passed to chip waiting for tx */
- u32 first_tx_bd_mask; /* mask is used in Tx routine to save status
- and length for first BD in a frame */
- u32 tx_base_offset; /* first BD in Tx BD table offset (In MURAM) */
- u32 rx_base_offset; /* first BD in Rx BD table offset (In MURAM) */
- struct qe_bd *confBd; /* next BD for confirm after Tx */
- struct qe_bd *tx_bd; /* next BD for new Tx request */
- struct qe_bd *rx_bd; /* next BD to collect after Rx */
- void *p_rx_frame; /* accumulating receive frame */
- u16 *p_ucce; /* a pointer to the event register in memory.
- */
- u16 *p_uccm; /* a pointer to the mask register in memory */
- u16 saved_uccm; /* a saved mask for the RX Interrupt bits */
-#ifdef STATISTICS
- u32 tx_frames; /* Transmitted frames counters */
- u32 rx_frames; /* Received frames counters (only frames
- passed to application) */
- u32 rx_discarded; /* Discarded frames counters (frames that
- were discarded by the driver due to
- errors) */
-#endif /* STATISTICS */
-};
-
-/* ucc_slow_init
- * Initializes Slow UCC according to provided parameters.
- *
- * us_info - (In) pointer to the slow UCC info structure.
- * uccs_ret - (Out) pointer to the slow UCC structure.
- */
-int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** uccs_ret);
-
-/* ucc_slow_free
- * Frees all resources for slow UCC.
- *
- * uccs - (In) pointer to the slow UCC structure.
- */
-void ucc_slow_free(struct ucc_slow_private * uccs);
-
-/* ucc_slow_enable
- * Enables a fast UCC port.
- * This routine enables Tx and/or Rx through the General UCC Mode Register.
- *
- * uccs - (In) pointer to the slow UCC structure.
- * mode - (In) TX, RX, or both.
- */
-void ucc_slow_enable(struct ucc_slow_private * uccs, enum comm_dir mode);
-
-/* ucc_slow_disable
- * Disables a fast UCC port.
- * This routine disables Tx and/or Rx through the General UCC Mode Register.
- *
- * uccs - (In) pointer to the slow UCC structure.
- * mode - (In) TX, RX, or both.
- */
-void ucc_slow_disable(struct ucc_slow_private * uccs, enum comm_dir mode);
-
-/* ucc_slow_graceful_stop_tx
- * Smoothly stops transmission on a specified slow UCC.
- *
- * uccs - (In) pointer to the slow UCC structure.
- */
-void ucc_slow_graceful_stop_tx(struct ucc_slow_private * uccs);
-
-/* ucc_slow_stop_tx
- * Stops transmission on a specified slow UCC.
- *
- * uccs - (In) pointer to the slow UCC structure.
- */
-void ucc_slow_stop_tx(struct ucc_slow_private * uccs);
-
-/* ucc_slow_restart_tx
- * Restarts transmitting on a specified slow UCC.
- *
- * uccs - (In) pointer to the slow UCC structure.
- */
-void ucc_slow_restart_tx(struct ucc_slow_private *uccs);
-
-u32 ucc_slow_get_qe_cr_subblock(int uccs_num);
-
-#endif /* __UCC_SLOW_H__ */
#include <asm/udbg.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
-#include <asm/qe.h>
-#include <asm/qe_ic.h>
+#include <soc/fsl/qe/qe.h>
+#include <soc/fsl/qe/qe_ic.h>
#include "mpc83xx.h"
#include <asm/io.h>
#include <asm/hw_irq.h>
#include <asm/ipic.h>
-#include <asm/qe_ic.h>
+#include <soc/fsl/qe/qe_ic.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
#include <asm/udbg.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
-#include <asm/qe.h>
-#include <asm/qe_ic.h>
+#include <soc/fsl/qe/qe.h>
+#include <soc/fsl/qe/qe_ic.h>
#include "mpc83xx.h"
#include <asm/time.h>
#include <asm/ipic.h>
#include <asm/udbg.h>
-#include <asm/qe.h>
-#include <asm/qe_ic.h>
+#include <soc/fsl/qe/qe.h>
+#include <soc/fsl/qe/qe_ic.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
#include <sysdev/simple_gpio.h>
-#include <asm/qe.h>
-#include <asm/qe_ic.h>
+#include <soc/fsl/qe/qe.h>
+#include <soc/fsl/qe/qe_ic.h>
#include "mpc83xx.h"
#include <asm/time.h>
#include <asm/ipic.h>
#include <asm/udbg.h>
-#include <asm/qe.h>
-#include <asm/qe_ic.h>
+#include <soc/fsl/qe/qe.h>
+#include <soc/fsl/qe/qe_ic.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
-#include <asm/qe.h>
+#include <soc/fsl/qe/qe.h>
#include <sysdev/cpm2_pic.h>
#include "mpc85xx.h"
#include <asm/udbg.h>
#include <asm/mpic.h>
#include <asm/ehv_pic.h>
-#include <asm/qe_ic.h>
+#include <soc/fsl/qe/qe_ic.h>
#include <linux/of_platform.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
#include <sysdev/simple_gpio.h>
-#include <asm/qe.h>
-#include <asm/qe_ic.h>
+#include <soc/fsl/qe/qe.h>
+#include <soc/fsl/qe/qe_ic.h>
#include <asm/mpic.h>
#include <asm/swiotlb.h>
#include "smp.h"
#include <asm/prom.h>
#include <asm/udbg.h>
#include <asm/mpic.h>
-#include <asm/qe.h>
-#include <asm/qe_ic.h>
+#include <soc/fsl/qe/qe.h>
+#include <soc/fsl/qe/qe_ic.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
#include <asm/pci-bridge.h>
#include <asm/udbg.h>
#include <asm/mpic.h>
-#include <asm/qe.h>
-#include <asm/qe_ic.h>
+#include <soc/fsl/qe/qe.h>
+#include <soc/fsl/qe/qe_ic.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
If in doubt, say N here.
-config QUICC_ENGINE
- bool "Freescale QUICC Engine (QE) Support"
- depends on FSL_SOC && PPC32
- select GENERIC_ALLOCATOR
- select CRC32
- help
- The QUICC Engine (QE) is a new generation of communications
- coprocessors on Freescale embedded CPUs (akin to CPM in older chips).
- Selecting this option means that you wish to build a kernel
- for a machine with a QE coprocessor.
-
config QE_GPIO
bool "QE GPIO support"
depends on QUICC_ENGINE
obj-$(CONFIG_SIMPLE_GPIO) += simple_gpio.o
obj-$(CONFIG_FSL_RIO) += fsl_rio.o fsl_rmu.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
-obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
-obj-$(CONFIG_CPM) += qe_lib/
mv64x60-$(CONFIG_PCI) += mv64x60_pci.o
obj-$(CONFIG_MV64X60) += $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o \
mv64x60_udbg.o
#include <asm/udbg.h>
#include <asm/io.h>
#include <asm/cpm.h>
-#include <asm/qe.h>
+#include <soc/fsl/qe/qe.h>
#include <mm/mmu_decl.h>
+++ /dev/null
-#
-# QE Communication options
-#
-
-config UCC_SLOW
- bool
- default y if SERIAL_QE
- help
- This option provides qe_lib support to UCC slow
- protocols: UART, BISYNC, QMC
-
-config UCC_FAST
- bool
- default y if UCC_GETH
- help
- This option provides qe_lib support to UCC fast
- protocols: HDLC, Ethernet, ATM, transparent
-
-config UCC
- bool
- default y if UCC_FAST || UCC_SLOW
-
-config QE_USB
- bool
- default y if USB_FSL_QE
- help
- QE USB Controller support
+++ /dev/null
-#
-# Makefile for the linux ppc-specific parts of QE
-#
-obj-$(CONFIG_QUICC_ENGINE)+= qe.o qe_common.o qe_ic.o qe_io.o
-obj-$(CONFIG_CPM) += qe_common.o
-obj-$(CONFIG_UCC) += ucc.o
-obj-$(CONFIG_UCC_SLOW) += ucc_slow.o
-obj-$(CONFIG_UCC_FAST) += ucc_fast.o
-obj-$(CONFIG_QE_USB) += usb.o
-obj-$(CONFIG_QE_GPIO) += gpio.o
+++ /dev/null
-/*
- * QUICC Engine GPIOs
- *
- * Copyright (c) MontaVista Software, Inc. 2008.
- *
- * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <asm/qe.h>
-
-struct qe_gpio_chip {
- struct of_mm_gpio_chip mm_gc;
- spinlock_t lock;
-
- unsigned long pin_flags[QE_PIO_PINS];
-#define QE_PIN_REQUESTED 0
-
- /* shadowed data register to clear/set bits safely */
- u32 cpdata;
-
- /* saved_regs used to restore dedicated functions */
- struct qe_pio_regs saved_regs;
-};
-
-static inline struct qe_gpio_chip *
-to_qe_gpio_chip(struct of_mm_gpio_chip *mm_gc)
-{
- return container_of(mm_gc, struct qe_gpio_chip, mm_gc);
-}
-
-static void qe_gpio_save_regs(struct of_mm_gpio_chip *mm_gc)
-{
- struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
- struct qe_pio_regs __iomem *regs = mm_gc->regs;
-
- qe_gc->cpdata = in_be32(®s->cpdata);
- qe_gc->saved_regs.cpdata = qe_gc->cpdata;
- qe_gc->saved_regs.cpdir1 = in_be32(®s->cpdir1);
- qe_gc->saved_regs.cpdir2 = in_be32(®s->cpdir2);
- qe_gc->saved_regs.cppar1 = in_be32(®s->cppar1);
- qe_gc->saved_regs.cppar2 = in_be32(®s->cppar2);
- qe_gc->saved_regs.cpodr = in_be32(®s->cpodr);
-}
-
-static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio)
-{
- struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
- struct qe_pio_regs __iomem *regs = mm_gc->regs;
- u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio);
-
- return in_be32(®s->cpdata) & pin_mask;
-}
-
-static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
- struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
- struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
- struct qe_pio_regs __iomem *regs = mm_gc->regs;
- unsigned long flags;
- u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio);
-
- spin_lock_irqsave(&qe_gc->lock, flags);
-
- if (val)
- qe_gc->cpdata |= pin_mask;
- else
- qe_gc->cpdata &= ~pin_mask;
-
- out_be32(®s->cpdata, qe_gc->cpdata);
-
- spin_unlock_irqrestore(&qe_gc->lock, flags);
-}
-
-static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
-{
- struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
- struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
- unsigned long flags;
-
- spin_lock_irqsave(&qe_gc->lock, flags);
-
- __par_io_config_pin(mm_gc->regs, gpio, QE_PIO_DIR_IN, 0, 0, 0);
-
- spin_unlock_irqrestore(&qe_gc->lock, flags);
-
- return 0;
-}
-
-static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
-{
- struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
- struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
- unsigned long flags;
-
- qe_gpio_set(gc, gpio, val);
-
- spin_lock_irqsave(&qe_gc->lock, flags);
-
- __par_io_config_pin(mm_gc->regs, gpio, QE_PIO_DIR_OUT, 0, 0, 0);
-
- spin_unlock_irqrestore(&qe_gc->lock, flags);
-
- return 0;
-}
-
-struct qe_pin {
- /*
- * The qe_gpio_chip name is unfortunate, we should change that to
- * something like qe_pio_controller. Someday.
- */
- struct qe_gpio_chip *controller;
- int num;
-};
-
-/**
- * qe_pin_request - Request a QE pin
- * @np: device node to get a pin from
- * @index: index of a pin in the device tree
- * Context: non-atomic
- *
- * This function return qe_pin so that you could use it with the rest of
- * the QE Pin Multiplexing API.
- */
-struct qe_pin *qe_pin_request(struct device_node *np, int index)
-{
- struct qe_pin *qe_pin;
- struct gpio_chip *gc;
- struct of_mm_gpio_chip *mm_gc;
- struct qe_gpio_chip *qe_gc;
- int err;
- unsigned long flags;
-
- qe_pin = kzalloc(sizeof(*qe_pin), GFP_KERNEL);
- if (!qe_pin) {
- pr_debug("%s: can't allocate memory\n", __func__);
- return ERR_PTR(-ENOMEM);
- }
-
- err = of_get_gpio(np, index);
- if (err < 0)
- goto err0;
- gc = gpio_to_chip(err);
- if (WARN_ON(!gc))
- goto err0;
-
- if (!of_device_is_compatible(gc->of_node, "fsl,mpc8323-qe-pario-bank")) {
- pr_debug("%s: tried to get a non-qe pin\n", __func__);
- err = -EINVAL;
- goto err0;
- }
-
- mm_gc = to_of_mm_gpio_chip(gc);
- qe_gc = to_qe_gpio_chip(mm_gc);
-
- spin_lock_irqsave(&qe_gc->lock, flags);
-
- err -= gc->base;
- if (test_and_set_bit(QE_PIN_REQUESTED, &qe_gc->pin_flags[err]) == 0) {
- qe_pin->controller = qe_gc;
- qe_pin->num = err;
- err = 0;
- } else {
- err = -EBUSY;
- }
-
- spin_unlock_irqrestore(&qe_gc->lock, flags);
-
- if (!err)
- return qe_pin;
-err0:
- kfree(qe_pin);
- pr_debug("%s failed with status %d\n", __func__, err);
- return ERR_PTR(err);
-}
-EXPORT_SYMBOL(qe_pin_request);
-
-/**
- * qe_pin_free - Free a pin
- * @qe_pin: pointer to the qe_pin structure
- * Context: any
- *
- * This function frees the qe_pin structure and makes a pin available
- * for further qe_pin_request() calls.
- */
-void qe_pin_free(struct qe_pin *qe_pin)
-{
- struct qe_gpio_chip *qe_gc = qe_pin->controller;
- unsigned long flags;
- const int pin = qe_pin->num;
-
- spin_lock_irqsave(&qe_gc->lock, flags);
- test_and_clear_bit(QE_PIN_REQUESTED, &qe_gc->pin_flags[pin]);
- spin_unlock_irqrestore(&qe_gc->lock, flags);
-
- kfree(qe_pin);
-}
-EXPORT_SYMBOL(qe_pin_free);
-
-/**
- * qe_pin_set_dedicated - Revert a pin to a dedicated peripheral function mode
- * @qe_pin: pointer to the qe_pin structure
- * Context: any
- *
- * This function resets a pin to a dedicated peripheral function that
- * has been set up by the firmware.
- */
-void qe_pin_set_dedicated(struct qe_pin *qe_pin)
-{
- struct qe_gpio_chip *qe_gc = qe_pin->controller;
- struct qe_pio_regs __iomem *regs = qe_gc->mm_gc.regs;
- struct qe_pio_regs *sregs = &qe_gc->saved_regs;
- int pin = qe_pin->num;
- u32 mask1 = 1 << (QE_PIO_PINS - (pin + 1));
- u32 mask2 = 0x3 << (QE_PIO_PINS - (pin % (QE_PIO_PINS / 2) + 1) * 2);
- bool second_reg = pin > (QE_PIO_PINS / 2) - 1;
- unsigned long flags;
-
- spin_lock_irqsave(&qe_gc->lock, flags);
-
- if (second_reg) {
- clrsetbits_be32(®s->cpdir2, mask2, sregs->cpdir2 & mask2);
- clrsetbits_be32(®s->cppar2, mask2, sregs->cppar2 & mask2);
- } else {
- clrsetbits_be32(®s->cpdir1, mask2, sregs->cpdir1 & mask2);
- clrsetbits_be32(®s->cppar1, mask2, sregs->cppar1 & mask2);
- }
-
- if (sregs->cpdata & mask1)
- qe_gc->cpdata |= mask1;
- else
- qe_gc->cpdata &= ~mask1;
-
- out_be32(®s->cpdata, qe_gc->cpdata);
- clrsetbits_be32(®s->cpodr, mask1, sregs->cpodr & mask1);
-
- spin_unlock_irqrestore(&qe_gc->lock, flags);
-}
-EXPORT_SYMBOL(qe_pin_set_dedicated);
-
-/**
- * qe_pin_set_gpio - Set a pin to the GPIO mode
- * @qe_pin: pointer to the qe_pin structure
- * Context: any
- *
- * This function sets a pin to the GPIO mode.
- */
-void qe_pin_set_gpio(struct qe_pin *qe_pin)
-{
- struct qe_gpio_chip *qe_gc = qe_pin->controller;
- struct qe_pio_regs __iomem *regs = qe_gc->mm_gc.regs;
- unsigned long flags;
-
- spin_lock_irqsave(&qe_gc->lock, flags);
-
- /* Let's make it input by default, GPIO API is able to change that. */
- __par_io_config_pin(regs, qe_pin->num, QE_PIO_DIR_IN, 0, 0, 0);
-
- spin_unlock_irqrestore(&qe_gc->lock, flags);
-}
-EXPORT_SYMBOL(qe_pin_set_gpio);
-
-static int __init qe_add_gpiochips(void)
-{
- struct device_node *np;
-
- for_each_compatible_node(np, NULL, "fsl,mpc8323-qe-pario-bank") {
- int ret;
- struct qe_gpio_chip *qe_gc;
- struct of_mm_gpio_chip *mm_gc;
- struct gpio_chip *gc;
-
- qe_gc = kzalloc(sizeof(*qe_gc), GFP_KERNEL);
- if (!qe_gc) {
- ret = -ENOMEM;
- goto err;
- }
-
- spin_lock_init(&qe_gc->lock);
-
- mm_gc = &qe_gc->mm_gc;
- gc = &mm_gc->gc;
-
- mm_gc->save_regs = qe_gpio_save_regs;
- gc->ngpio = QE_PIO_PINS;
- gc->direction_input = qe_gpio_dir_in;
- gc->direction_output = qe_gpio_dir_out;
- gc->get = qe_gpio_get;
- gc->set = qe_gpio_set;
-
- ret = of_mm_gpiochip_add(np, mm_gc);
- if (ret)
- goto err;
- continue;
-err:
- pr_err("%s: registration failed with status %d\n",
- np->full_name, ret);
- kfree(qe_gc);
- /* try others anyway */
- }
- return 0;
-}
-arch_initcall(qe_add_gpiochips);
+++ /dev/null
-/*
- * Copyright (C) 2006-2010 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Authors: Shlomi Gridish <gridish@freescale.com>
- * Li Yang <leoli@freescale.com>
- * Based on cpm2_common.c from Dan Malek (dmalek@jlc.net)
- *
- * Description:
- * General Purpose functions for the global management of the
- * QUICC Engine (QE).
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/crc32.h>
-#include <linux/mod_devicetable.h>
-#include <linux/of_platform.h>
-#include <asm/irq.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/immap_qe.h>
-#include <asm/qe.h>
-#include <asm/prom.h>
-#include <asm/rheap.h>
-
-static void qe_snums_init(void);
-static int qe_sdma_init(void);
-
-static DEFINE_SPINLOCK(qe_lock);
-DEFINE_SPINLOCK(cmxgcr_lock);
-EXPORT_SYMBOL(cmxgcr_lock);
-
-/* QE snum state */
-enum qe_snum_state {
- QE_SNUM_STATE_USED,
- QE_SNUM_STATE_FREE
-};
-
-/* QE snum */
-struct qe_snum {
- u8 num;
- enum qe_snum_state state;
-};
-
-/* We allocate this here because it is used almost exclusively for
- * the communication processor devices.
- */
-struct qe_immap __iomem *qe_immr;
-EXPORT_SYMBOL(qe_immr);
-
-static struct qe_snum snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */
-static unsigned int qe_num_of_snum;
-
-static phys_addr_t qebase = -1;
-
-phys_addr_t get_qe_base(void)
-{
- struct device_node *qe;
- int size;
- const u32 *prop;
-
- if (qebase != -1)
- return qebase;
-
- qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
- if (!qe) {
- qe = of_find_node_by_type(NULL, "qe");
- if (!qe)
- return qebase;
- }
-
- prop = of_get_property(qe, "reg", &size);
- if (prop && size >= sizeof(*prop))
- qebase = of_translate_address(qe, prop);
- of_node_put(qe);
-
- return qebase;
-}
-
-EXPORT_SYMBOL(get_qe_base);
-
-void qe_reset(void)
-{
- if (qe_immr == NULL)
- qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE);
-
- qe_snums_init();
-
- qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
- QE_CR_PROTOCOL_UNSPECIFIED, 0);
-
- /* Reclaim the MURAM memory for our use. */
- qe_muram_init();
-
- if (qe_sdma_init())
- panic("sdma init failed!");
-}
-
-int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input)
-{
- unsigned long flags;
- u8 mcn_shift = 0, dev_shift = 0;
- u32 ret;
-
- spin_lock_irqsave(&qe_lock, flags);
- if (cmd == QE_RESET) {
- out_be32(&qe_immr->cp.cecr, (u32) (cmd | QE_CR_FLG));
- } else {
- if (cmd == QE_ASSIGN_PAGE) {
- /* Here device is the SNUM, not sub-block */
- dev_shift = QE_CR_SNUM_SHIFT;
- } else if (cmd == QE_ASSIGN_RISC) {
- /* Here device is the SNUM, and mcnProtocol is
- * e_QeCmdRiscAssignment value */
- dev_shift = QE_CR_SNUM_SHIFT;
- mcn_shift = QE_CR_MCN_RISC_ASSIGN_SHIFT;
- } else {
- if (device == QE_CR_SUBBLOCK_USB)
- mcn_shift = QE_CR_MCN_USB_SHIFT;
- else
- mcn_shift = QE_CR_MCN_NORMAL_SHIFT;
- }
-
- out_be32(&qe_immr->cp.cecdr, cmd_input);
- out_be32(&qe_immr->cp.cecr,
- (cmd | QE_CR_FLG | ((u32) device << dev_shift) | (u32)
- mcn_protocol << mcn_shift));
- }
-
- /* wait for the QE_CR_FLG to clear */
- ret = spin_event_timeout((in_be32(&qe_immr->cp.cecr) & QE_CR_FLG) == 0,
- 100, 0);
- /* On timeout (e.g. failure), the expression will be false (ret == 0),
- otherwise it will be true (ret == 1). */
- spin_unlock_irqrestore(&qe_lock, flags);
-
- return ret == 1;
-}
-EXPORT_SYMBOL(qe_issue_cmd);
-
-/* Set a baud rate generator. This needs lots of work. There are
- * 16 BRGs, which can be connected to the QE channels or output
- * as clocks. The BRGs are in two different block of internal
- * memory mapped space.
- * The BRG clock is the QE clock divided by 2.
- * It was set up long ago during the initial boot phase and is
- * is given to us.
- * Baud rate clocks are zero-based in the driver code (as that maps
- * to port numbers). Documentation uses 1-based numbering.
- */
-static unsigned int brg_clk = 0;
-
-unsigned int qe_get_brg_clk(void)
-{
- struct device_node *qe;
- int size;
- const u32 *prop;
-
- if (brg_clk)
- return brg_clk;
-
- qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
- if (!qe) {
- qe = of_find_node_by_type(NULL, "qe");
- if (!qe)
- return brg_clk;
- }
-
- prop = of_get_property(qe, "brg-frequency", &size);
- if (prop && size == sizeof(*prop))
- brg_clk = *prop;
-
- of_node_put(qe);
-
- return brg_clk;
-}
-EXPORT_SYMBOL(qe_get_brg_clk);
-
-/* Program the BRG to the given sampling rate and multiplier
- *
- * @brg: the BRG, QE_BRG1 - QE_BRG16
- * @rate: the desired sampling rate
- * @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or
- * GUMR_L[TDCR]. E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01,
- * then 'multiplier' should be 8.
- */
-int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
-{
- u32 divisor, tempval;
- u32 div16 = 0;
-
- if ((brg < QE_BRG1) || (brg > QE_BRG16))
- return -EINVAL;
-
- divisor = qe_get_brg_clk() / (rate * multiplier);
-
- if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
- div16 = QE_BRGC_DIV16;
- divisor /= 16;
- }
-
- /* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says
- that the BRG divisor must be even if you're not using divide-by-16
- mode. */
- if (!div16 && (divisor & 1) && (divisor > 3))
- divisor++;
-
- tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
- QE_BRGC_ENABLE | div16;
-
- out_be32(&qe_immr->brg.brgc[brg - QE_BRG1], tempval);
-
- return 0;
-}
-EXPORT_SYMBOL(qe_setbrg);
-
-/* Convert a string to a QE clock source enum
- *
- * This function takes a string, typically from a property in the device
- * tree, and returns the corresponding "enum qe_clock" value.
-*/
-enum qe_clock qe_clock_source(const char *source)
-{
- unsigned int i;
-
- if (strcasecmp(source, "none") == 0)
- return QE_CLK_NONE;
-
- if (strncasecmp(source, "brg", 3) == 0) {
- i = simple_strtoul(source + 3, NULL, 10);
- if ((i >= 1) && (i <= 16))
- return (QE_BRG1 - 1) + i;
- else
- return QE_CLK_DUMMY;
- }
-
- if (strncasecmp(source, "clk", 3) == 0) {
- i = simple_strtoul(source + 3, NULL, 10);
- if ((i >= 1) && (i <= 24))
- return (QE_CLK1 - 1) + i;
- else
- return QE_CLK_DUMMY;
- }
-
- return QE_CLK_DUMMY;
-}
-EXPORT_SYMBOL(qe_clock_source);
-
-/* Initialize SNUMs (thread serial numbers) according to
- * QE Module Control chapter, SNUM table
- */
-static void qe_snums_init(void)
-{
- int i;
- static const u8 snum_init_76[] = {
- 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
- 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
- 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
- 0xD8, 0xD9, 0xE8, 0xE9, 0x44, 0x45, 0x4C, 0x4D,
- 0x54, 0x55, 0x5C, 0x5D, 0x64, 0x65, 0x6C, 0x6D,
- 0x74, 0x75, 0x7C, 0x7D, 0x84, 0x85, 0x8C, 0x8D,
- 0x94, 0x95, 0x9C, 0x9D, 0xA4, 0xA5, 0xAC, 0xAD,
- 0xB4, 0xB5, 0xBC, 0xBD, 0xC4, 0xC5, 0xCC, 0xCD,
- 0xD4, 0xD5, 0xDC, 0xDD, 0xE4, 0xE5, 0xEC, 0xED,
- 0xF4, 0xF5, 0xFC, 0xFD,
- };
- static const u8 snum_init_46[] = {
- 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
- 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
- 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
- 0xD8, 0xD9, 0xE8, 0xE9, 0x08, 0x09, 0x18, 0x19,
- 0x28, 0x29, 0x38, 0x39, 0x48, 0x49, 0x58, 0x59,
- 0x68, 0x69, 0x78, 0x79, 0x80, 0x81,
- };
- static const u8 *snum_init;
-
- qe_num_of_snum = qe_get_num_of_snums();
-
- if (qe_num_of_snum == 76)
- snum_init = snum_init_76;
- else
- snum_init = snum_init_46;
-
- for (i = 0; i < qe_num_of_snum; i++) {
- snums[i].num = snum_init[i];
- snums[i].state = QE_SNUM_STATE_FREE;
- }
-}
-
-int qe_get_snum(void)
-{
- unsigned long flags;
- int snum = -EBUSY;
- int i;
-
- spin_lock_irqsave(&qe_lock, flags);
- for (i = 0; i < qe_num_of_snum; i++) {
- if (snums[i].state == QE_SNUM_STATE_FREE) {
- snums[i].state = QE_SNUM_STATE_USED;
- snum = snums[i].num;
- break;
- }
- }
- spin_unlock_irqrestore(&qe_lock, flags);
-
- return snum;
-}
-EXPORT_SYMBOL(qe_get_snum);
-
-void qe_put_snum(u8 snum)
-{
- int i;
-
- for (i = 0; i < qe_num_of_snum; i++) {
- if (snums[i].num == snum) {
- snums[i].state = QE_SNUM_STATE_FREE;
- break;
- }
- }
-}
-EXPORT_SYMBOL(qe_put_snum);
-
-static int qe_sdma_init(void)
-{
- struct sdma __iomem *sdma = &qe_immr->sdma;
- static unsigned long sdma_buf_offset = (unsigned long)-ENOMEM;
-
- if (!sdma)
- return -ENODEV;
-
- /* allocate 2 internal temporary buffers (512 bytes size each) for
- * the SDMA */
- if (IS_ERR_VALUE(sdma_buf_offset)) {
- sdma_buf_offset = qe_muram_alloc(512 * 2, 4096);
- if (IS_ERR_VALUE(sdma_buf_offset))
- return -ENOMEM;
- }
-
- out_be32(&sdma->sdebcr, (u32) sdma_buf_offset & QE_SDEBCR_BA_MASK);
- out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK |
- (0x1 << QE_SDMR_CEN_SHIFT)));
-
- return 0;
-}
-
-/* The maximum number of RISCs we support */
-#define MAX_QE_RISC 4
-
-/* Firmware information stored here for qe_get_firmware_info() */
-static struct qe_firmware_info qe_firmware_info;
-
-/*
- * Set to 1 if QE firmware has been uploaded, and therefore
- * qe_firmware_info contains valid data.
- */
-static int qe_firmware_uploaded;
-
-/*
- * Upload a QE microcode
- *
- * This function is a worker function for qe_upload_firmware(). It does
- * the actual uploading of the microcode.
- */
-static void qe_upload_microcode(const void *base,
- const struct qe_microcode *ucode)
-{
- const __be32 *code = base + be32_to_cpu(ucode->code_offset);
- unsigned int i;
-
- if (ucode->major || ucode->minor || ucode->revision)
- printk(KERN_INFO "qe-firmware: "
- "uploading microcode '%s' version %u.%u.%u\n",
- ucode->id, ucode->major, ucode->minor, ucode->revision);
- else
- printk(KERN_INFO "qe-firmware: "
- "uploading microcode '%s'\n", ucode->id);
-
- /* Use auto-increment */
- out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
- QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
-
- for (i = 0; i < be32_to_cpu(ucode->count); i++)
- out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
-
- /* Set I-RAM Ready Register */
- out_be32(&qe_immr->iram.iready, be32_to_cpu(QE_IRAM_READY));
-}
-
-/*
- * Upload a microcode to the I-RAM at a specific address.
- *
- * See Documentation/powerpc/qe_firmware.txt for information on QE microcode
- * uploading.
- *
- * Currently, only version 1 is supported, so the 'version' field must be
- * set to 1.
- *
- * The SOC model and revision are not validated, they are only displayed for
- * informational purposes.
- *
- * 'calc_size' is the calculated size, in bytes, of the firmware structure and
- * all of the microcode structures, minus the CRC.
- *
- * 'length' is the size that the structure says it is, including the CRC.
- */
-int qe_upload_firmware(const struct qe_firmware *firmware)
-{
- unsigned int i;
- unsigned int j;
- u32 crc;
- size_t calc_size = sizeof(struct qe_firmware);
- size_t length;
- const struct qe_header *hdr;
-
- if (!firmware) {
- printk(KERN_ERR "qe-firmware: invalid pointer\n");
- return -EINVAL;
- }
-
- hdr = &firmware->header;
- length = be32_to_cpu(hdr->length);
-
- /* Check the magic */
- if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
- (hdr->magic[2] != 'F')) {
- printk(KERN_ERR "qe-firmware: not a microcode\n");
- return -EPERM;
- }
-
- /* Check the version */
- if (hdr->version != 1) {
- printk(KERN_ERR "qe-firmware: unsupported version\n");
- return -EPERM;
- }
-
- /* Validate some of the fields */
- if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
- printk(KERN_ERR "qe-firmware: invalid data\n");
- return -EINVAL;
- }
-
- /* Validate the length and check if there's a CRC */
- calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
-
- for (i = 0; i < firmware->count; i++)
- /*
- * For situations where the second RISC uses the same microcode
- * as the first, the 'code_offset' and 'count' fields will be
- * zero, so it's okay to add those.
- */
- calc_size += sizeof(__be32) *
- be32_to_cpu(firmware->microcode[i].count);
-
- /* Validate the length */
- if (length != calc_size + sizeof(__be32)) {
- printk(KERN_ERR "qe-firmware: invalid length\n");
- return -EPERM;
- }
-
- /* Validate the CRC */
- crc = be32_to_cpu(*(__be32 *)((void *)firmware + calc_size));
- if (crc != crc32(0, firmware, calc_size)) {
- printk(KERN_ERR "qe-firmware: firmware CRC is invalid\n");
- return -EIO;
- }
-
- /*
- * If the microcode calls for it, split the I-RAM.
- */
- if (!firmware->split)
- setbits16(&qe_immr->cp.cercr, QE_CP_CERCR_CIR);
-
- if (firmware->soc.model)
- printk(KERN_INFO
- "qe-firmware: firmware '%s' for %u V%u.%u\n",
- firmware->id, be16_to_cpu(firmware->soc.model),
- firmware->soc.major, firmware->soc.minor);
- else
- printk(KERN_INFO "qe-firmware: firmware '%s'\n",
- firmware->id);
-
- /*
- * The QE only supports one microcode per RISC, so clear out all the
- * saved microcode information and put in the new.
- */
- memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
- strlcpy(qe_firmware_info.id, firmware->id, sizeof(qe_firmware_info.id));
- qe_firmware_info.extended_modes = firmware->extended_modes;
- memcpy(qe_firmware_info.vtraps, firmware->vtraps,
- sizeof(firmware->vtraps));
-
- /* Loop through each microcode. */
- for (i = 0; i < firmware->count; i++) {
- const struct qe_microcode *ucode = &firmware->microcode[i];
-
- /* Upload a microcode if it's present */
- if (ucode->code_offset)
- qe_upload_microcode(firmware, ucode);
-
- /* Program the traps for this processor */
- for (j = 0; j < 16; j++) {
- u32 trap = be32_to_cpu(ucode->traps[j]);
-
- if (trap)
- out_be32(&qe_immr->rsp[i].tibcr[j], trap);
- }
-
- /* Enable traps */
- out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
- }
-
- qe_firmware_uploaded = 1;
-
- return 0;
-}
-EXPORT_SYMBOL(qe_upload_firmware);
-
-/*
- * Get info on the currently-loaded firmware
- *
- * This function also checks the device tree to see if the boot loader has
- * uploaded a firmware already.
- */
-struct qe_firmware_info *qe_get_firmware_info(void)
-{
- static int initialized;
- struct property *prop;
- struct device_node *qe;
- struct device_node *fw = NULL;
- const char *sprop;
- unsigned int i;
-
- /*
- * If we haven't checked yet, and a driver hasn't uploaded a firmware
- * yet, then check the device tree for information.
- */
- if (qe_firmware_uploaded)
- return &qe_firmware_info;
-
- if (initialized)
- return NULL;
-
- initialized = 1;
-
- /*
- * Newer device trees have an "fsl,qe" compatible property for the QE
- * node, but we still need to support older device trees.
- */
- qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
- if (!qe) {
- qe = of_find_node_by_type(NULL, "qe");
- if (!qe)
- return NULL;
- }
-
- /* Find the 'firmware' child node */
- for_each_child_of_node(qe, fw) {
- if (strcmp(fw->name, "firmware") == 0)
- break;
- }
-
- of_node_put(qe);
-
- /* Did we find the 'firmware' node? */
- if (!fw)
- return NULL;
-
- qe_firmware_uploaded = 1;
-
- /* Copy the data into qe_firmware_info*/
- sprop = of_get_property(fw, "id", NULL);
- if (sprop)
- strlcpy(qe_firmware_info.id, sprop,
- sizeof(qe_firmware_info.id));
-
- prop = of_find_property(fw, "extended-modes", NULL);
- if (prop && (prop->length == sizeof(u64))) {
- const u64 *iprop = prop->value;
-
- qe_firmware_info.extended_modes = *iprop;
- }
-
- prop = of_find_property(fw, "virtual-traps", NULL);
- if (prop && (prop->length == 32)) {
- const u32 *iprop = prop->value;
-
- for (i = 0; i < ARRAY_SIZE(qe_firmware_info.vtraps); i++)
- qe_firmware_info.vtraps[i] = iprop[i];
- }
-
- of_node_put(fw);
-
- return &qe_firmware_info;
-}
-EXPORT_SYMBOL(qe_get_firmware_info);
-
-unsigned int qe_get_num_of_risc(void)
-{
- struct device_node *qe;
- int size;
- unsigned int num_of_risc = 0;
- const u32 *prop;
-
- qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
- if (!qe) {
- /* Older devices trees did not have an "fsl,qe"
- * compatible property, so we need to look for
- * the QE node by name.
- */
- qe = of_find_node_by_type(NULL, "qe");
- if (!qe)
- return num_of_risc;
- }
-
- prop = of_get_property(qe, "fsl,qe-num-riscs", &size);
- if (prop && size == sizeof(*prop))
- num_of_risc = *prop;
-
- of_node_put(qe);
-
- return num_of_risc;
-}
-EXPORT_SYMBOL(qe_get_num_of_risc);
-
-unsigned int qe_get_num_of_snums(void)
-{
- struct device_node *qe;
- int size;
- unsigned int num_of_snums;
- const u32 *prop;
-
- num_of_snums = 28; /* The default number of snum for threads is 28 */
- qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
- if (!qe) {
- /* Older devices trees did not have an "fsl,qe"
- * compatible property, so we need to look for
- * the QE node by name.
- */
- qe = of_find_node_by_type(NULL, "qe");
- if (!qe)
- return num_of_snums;
- }
-
- prop = of_get_property(qe, "fsl,qe-num-snums", &size);
- if (prop && size == sizeof(*prop)) {
- num_of_snums = *prop;
- if ((num_of_snums < 28) || (num_of_snums > QE_NUM_OF_SNUM)) {
- /* No QE ever has fewer than 28 SNUMs */
- pr_err("QE: number of snum is invalid\n");
- of_node_put(qe);
- return -EINVAL;
- }
- }
-
- of_node_put(qe);
-
- return num_of_snums;
-}
-EXPORT_SYMBOL(qe_get_num_of_snums);
-
-static int __init qe_init(void)
-{
- struct device_node *np;
-
- np = of_find_compatible_node(NULL, NULL, "fsl,qe");
- if (!np)
- return -ENODEV;
- qe_reset();
- of_node_put(np);
- return 0;
-}
-subsys_initcall(qe_init);
-
-#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx)
-static int qe_resume(struct platform_device *ofdev)
-{
- if (!qe_alive_during_sleep())
- qe_reset();
- return 0;
-}
-
-static int qe_probe(struct platform_device *ofdev)
-{
- return 0;
-}
-
-static const struct of_device_id qe_ids[] = {
- { .compatible = "fsl,qe", },
- { },
-};
-
-static struct platform_driver qe_driver = {
- .driver = {
- .name = "fsl-qe",
- .of_match_table = qe_ids,
- },
- .probe = qe_probe,
- .resume = qe_resume,
-};
-
-static int __init qe_drv_init(void)
-{
- return platform_driver_register(&qe_driver);
-}
-device_initcall(qe_drv_init);
-#endif /* defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx) */
+++ /dev/null
-/*
- * Common CPM code
- *
- * Author: Scott Wood <scottwood@freescale.com>
- *
- * Copyright 2007-2008,2010 Freescale Semiconductor, Inc.
- *
- * Some parts derived from commproc.c/cpm2_common.c, which is:
- * Copyright (c) 1997 Dan error_act (dmalek@jlc.net)
- * Copyright (c) 1999-2001 Dan Malek <dan@embeddedalley.com>
- * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
- * 2006 (c) MontaVista Software, Inc.
- * Vitaly Bordug <vbordug@ru.mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- */
-#include <linux/genalloc.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/of_device.h>
-#include <linux/spinlock.h>
-#include <linux/export.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <asm/qe.h>
-
-static struct gen_pool *muram_pool;
-static spinlock_t cpm_muram_lock;
-static u8 __iomem *muram_vbase;
-static phys_addr_t muram_pbase;
-
-struct muram_block {
- struct list_head head;
- unsigned long start;
- int size;
-};
-
-static LIST_HEAD(muram_block_list);
-
-/* max address size we deal with */
-#define OF_MAX_ADDR_CELLS 4
-#define GENPOOL_OFFSET (4096 * 8)
-
-int cpm_muram_init(void)
-{
- struct device_node *np;
- struct resource r;
- u32 zero[OF_MAX_ADDR_CELLS] = {};
- resource_size_t max = 0;
- int i = 0;
- int ret = 0;
-
- if (muram_pbase)
- return 0;
-
- spin_lock_init(&cpm_muram_lock);
- np = of_find_compatible_node(NULL, NULL, "fsl,cpm-muram-data");
- if (!np) {
- /* try legacy bindings */
- np = of_find_node_by_name(NULL, "data-only");
- if (!np) {
- pr_err("Cannot find CPM muram data node");
- ret = -ENODEV;
- goto out_muram;
- }
- }
-
- muram_pool = gen_pool_create(0, -1);
- muram_pbase = of_translate_address(np, zero);
- if (muram_pbase == (phys_addr_t)OF_BAD_ADDR) {
- pr_err("Cannot translate zero through CPM muram node");
- ret = -ENODEV;
- goto out_pool;
- }
-
- while (of_address_to_resource(np, i++, &r) == 0) {
- if (r.end > max)
- max = r.end;
- ret = gen_pool_add(muram_pool, r.start - muram_pbase +
- GENPOOL_OFFSET, resource_size(&r), -1);
- if (ret) {
- pr_err("QE: couldn't add muram to pool!\n");
- goto out_pool;
- }
- }
-
- muram_vbase = ioremap(muram_pbase, max - muram_pbase + 1);
- if (!muram_vbase) {
- pr_err("Cannot map QE muram");
- ret = -ENOMEM;
- goto out_pool;
- }
- goto out_muram;
-out_pool:
- gen_pool_destroy(muram_pool);
-out_muram:
- of_node_put(np);
- return ret;
-}
-
-/*
- * cpm_muram_alloc - allocate the requested size worth of multi-user ram
- * @size: number of bytes to allocate
- * @align: requested alignment, in bytes
- *
- * This function returns an offset into the muram area.
- * Use cpm_dpram_addr() to get the virtual address of the area.
- * Use cpm_muram_free() to free the allocation.
- */
-unsigned long cpm_muram_alloc(unsigned long size, unsigned long align)
-{
- unsigned long start;
- unsigned long flags;
- struct genpool_data_align muram_pool_data;
-
- spin_lock_irqsave(&cpm_muram_lock, flags);
- muram_pool_data.align = align;
- start = cpm_muram_alloc_common(size, gen_pool_first_fit_align,
- &muram_pool_data);
- spin_unlock_irqrestore(&cpm_muram_lock, flags);
- return start;
-}
-EXPORT_SYMBOL(cpm_muram_alloc);
-
-/**
- * cpm_muram_free - free a chunk of multi-user ram
- * @offset: The beginning of the chunk as returned by cpm_muram_alloc().
- */
-int cpm_muram_free(unsigned long offset)
-{
- unsigned long flags;
- int size;
- struct muram_block *tmp;
-
- size = 0;
- spin_lock_irqsave(&cpm_muram_lock, flags);
- list_for_each_entry(tmp, &muram_block_list, head) {
- if (tmp->start == offset) {
- size = tmp->size;
- list_del(&tmp->head);
- kfree(tmp);
- break;
- }
- }
- gen_pool_free(muram_pool, offset + GENPOOL_OFFSET, size);
- spin_unlock_irqrestore(&cpm_muram_lock, flags);
- return size;
-}
-EXPORT_SYMBOL(cpm_muram_free);
-
-/*
- * cpm_muram_alloc_fixed - reserve a specific region of multi-user ram
- * @offset: offset of allocation start address
- * @size: number of bytes to allocate
- * This function returns an offset into the muram area
- * Use cpm_dpram_addr() to get the virtual address of the area.
- * Use cpm_muram_free() to free the allocation.
- */
-unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size)
-{
- unsigned long start;
- unsigned long flags;
- struct genpool_data_fixed muram_pool_data_fixed;
-
- spin_lock_irqsave(&cpm_muram_lock, flags);
- muram_pool_data_fixed.offset = offset + GENPOOL_OFFSET;
- start = cpm_muram_alloc_common(size, gen_pool_fixed_alloc,
- &muram_pool_data_fixed);
- spin_unlock_irqrestore(&cpm_muram_lock, flags);
- return start;
-}
-EXPORT_SYMBOL(cpm_muram_alloc_fixed);
-
-/*
- * cpm_muram_alloc_common - cpm_muram_alloc common code
- * @size: number of bytes to allocate
- * @algo: algorithm for alloc.
- * @data: data for genalloc's algorithm.
- *
- * This function returns an offset into the muram area.
- */
-unsigned long cpm_muram_alloc_common(unsigned long size, genpool_algo_t algo,
- void *data)
-{
- struct muram_block *entry;
- unsigned long start;
-
- start = gen_pool_alloc_algo(muram_pool, size, algo, data);
- if (!start)
- goto out2;
- start = start - GENPOOL_OFFSET;
- memset_io(cpm_muram_addr(start), 0, size);
- entry = kmalloc(sizeof(*entry), GFP_KERNEL);
- if (!entry)
- goto out1;
- entry->start = start;
- entry->size = size;
- list_add(&entry->head, &muram_block_list);
-
- return start;
-out1:
- gen_pool_free(muram_pool, start, size);
-out2:
- return (unsigned long)-ENOMEM;
-}
-
-/**
- * cpm_muram_addr - turn a muram offset into a virtual address
- * @offset: muram offset to convert
- */
-void __iomem *cpm_muram_addr(unsigned long offset)
-{
- return muram_vbase + offset;
-}
-EXPORT_SYMBOL(cpm_muram_addr);
-
-unsigned long cpm_muram_offset(void __iomem *addr)
-{
- return addr - (void __iomem *)muram_vbase;
-}
-EXPORT_SYMBOL(cpm_muram_offset);
-
-/**
- * cpm_muram_dma - turn a muram virtual address into a DMA address
- * @offset: virtual address from cpm_muram_addr() to convert
- */
-dma_addr_t cpm_muram_dma(void __iomem *addr)
-{
- return muram_pbase + ((u8 __iomem *)addr - muram_vbase);
-}
-EXPORT_SYMBOL(cpm_muram_dma);
+++ /dev/null
-/*
- * arch/powerpc/sysdev/qe_lib/qe_ic.c
- *
- * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: Li Yang <leoli@freescale.com>
- * Based on code from Shlomi Gridish <gridish@freescale.com>
- *
- * QUICC ENGINE Interrupt Controller
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/slab.h>
-#include <linux/stddef.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/device.h>
-#include <linux/spinlock.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/qe_ic.h>
-
-#include "qe_ic.h"
-
-static DEFINE_RAW_SPINLOCK(qe_ic_lock);
-
-static struct qe_ic_info qe_ic_info[] = {
- [1] = {
- .mask = 0x00008000,
- .mask_reg = QEIC_CIMR,
- .pri_code = 0,
- .pri_reg = QEIC_CIPWCC,
- },
- [2] = {
- .mask = 0x00004000,
- .mask_reg = QEIC_CIMR,
- .pri_code = 1,
- .pri_reg = QEIC_CIPWCC,
- },
- [3] = {
- .mask = 0x00002000,
- .mask_reg = QEIC_CIMR,
- .pri_code = 2,
- .pri_reg = QEIC_CIPWCC,
- },
- [10] = {
- .mask = 0x00000040,
- .mask_reg = QEIC_CIMR,
- .pri_code = 1,
- .pri_reg = QEIC_CIPZCC,
- },
- [11] = {
- .mask = 0x00000020,
- .mask_reg = QEIC_CIMR,
- .pri_code = 2,
- .pri_reg = QEIC_CIPZCC,
- },
- [12] = {
- .mask = 0x00000010,
- .mask_reg = QEIC_CIMR,
- .pri_code = 3,
- .pri_reg = QEIC_CIPZCC,
- },
- [13] = {
- .mask = 0x00000008,
- .mask_reg = QEIC_CIMR,
- .pri_code = 4,
- .pri_reg = QEIC_CIPZCC,
- },
- [14] = {
- .mask = 0x00000004,
- .mask_reg = QEIC_CIMR,
- .pri_code = 5,
- .pri_reg = QEIC_CIPZCC,
- },
- [15] = {
- .mask = 0x00000002,
- .mask_reg = QEIC_CIMR,
- .pri_code = 6,
- .pri_reg = QEIC_CIPZCC,
- },
- [20] = {
- .mask = 0x10000000,
- .mask_reg = QEIC_CRIMR,
- .pri_code = 3,
- .pri_reg = QEIC_CIPRTA,
- },
- [25] = {
- .mask = 0x00800000,
- .mask_reg = QEIC_CRIMR,
- .pri_code = 0,
- .pri_reg = QEIC_CIPRTB,
- },
- [26] = {
- .mask = 0x00400000,
- .mask_reg = QEIC_CRIMR,
- .pri_code = 1,
- .pri_reg = QEIC_CIPRTB,
- },
- [27] = {
- .mask = 0x00200000,
- .mask_reg = QEIC_CRIMR,
- .pri_code = 2,
- .pri_reg = QEIC_CIPRTB,
- },
- [28] = {
- .mask = 0x00100000,
- .mask_reg = QEIC_CRIMR,
- .pri_code = 3,
- .pri_reg = QEIC_CIPRTB,
- },
- [32] = {
- .mask = 0x80000000,
- .mask_reg = QEIC_CIMR,
- .pri_code = 0,
- .pri_reg = QEIC_CIPXCC,
- },
- [33] = {
- .mask = 0x40000000,
- .mask_reg = QEIC_CIMR,
- .pri_code = 1,
- .pri_reg = QEIC_CIPXCC,
- },
- [34] = {
- .mask = 0x20000000,
- .mask_reg = QEIC_CIMR,
- .pri_code = 2,
- .pri_reg = QEIC_CIPXCC,
- },
- [35] = {
- .mask = 0x10000000,
- .mask_reg = QEIC_CIMR,
- .pri_code = 3,
- .pri_reg = QEIC_CIPXCC,
- },
- [36] = {
- .mask = 0x08000000,
- .mask_reg = QEIC_CIMR,
- .pri_code = 4,
- .pri_reg = QEIC_CIPXCC,
- },
- [40] = {
- .mask = 0x00800000,
- .mask_reg = QEIC_CIMR,
- .pri_code = 0,
- .pri_reg = QEIC_CIPYCC,
- },
- [41] = {
- .mask = 0x00400000,
- .mask_reg = QEIC_CIMR,
- .pri_code = 1,
- .pri_reg = QEIC_CIPYCC,
- },
- [42] = {
- .mask = 0x00200000,
- .mask_reg = QEIC_CIMR,
- .pri_code = 2,
- .pri_reg = QEIC_CIPYCC,
- },
- [43] = {
- .mask = 0x00100000,
- .mask_reg = QEIC_CIMR,
- .pri_code = 3,
- .pri_reg = QEIC_CIPYCC,
- },
-};
-
-static inline u32 qe_ic_read(volatile __be32 __iomem * base, unsigned int reg)
-{
- return in_be32(base + (reg >> 2));
-}
-
-static inline void qe_ic_write(volatile __be32 __iomem * base, unsigned int reg,
- u32 value)
-{
- out_be32(base + (reg >> 2), value);
-}
-
-static inline struct qe_ic *qe_ic_from_irq(unsigned int virq)
-{
- return irq_get_chip_data(virq);
-}
-
-static inline struct qe_ic *qe_ic_from_irq_data(struct irq_data *d)
-{
- return irq_data_get_irq_chip_data(d);
-}
-
-static void qe_ic_unmask_irq(struct irq_data *d)
-{
- struct qe_ic *qe_ic = qe_ic_from_irq_data(d);
- unsigned int src = irqd_to_hwirq(d);
- unsigned long flags;
- u32 temp;
-
- raw_spin_lock_irqsave(&qe_ic_lock, flags);
-
- temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg);
- qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,
- temp | qe_ic_info[src].mask);
-
- raw_spin_unlock_irqrestore(&qe_ic_lock, flags);
-}
-
-static void qe_ic_mask_irq(struct irq_data *d)
-{
- struct qe_ic *qe_ic = qe_ic_from_irq_data(d);
- unsigned int src = irqd_to_hwirq(d);
- unsigned long flags;
- u32 temp;
-
- raw_spin_lock_irqsave(&qe_ic_lock, flags);
-
- temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg);
- qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,
- temp & ~qe_ic_info[src].mask);
-
- /* Flush the above write before enabling interrupts; otherwise,
- * spurious interrupts will sometimes happen. To be 100% sure
- * that the write has reached the device before interrupts are
- * enabled, the mask register would have to be read back; however,
- * this is not required for correctness, only to avoid wasting
- * time on a large number of spurious interrupts. In testing,
- * a sync reduced the observed spurious interrupts to zero.
- */
- mb();
-
- raw_spin_unlock_irqrestore(&qe_ic_lock, flags);
-}
-
-static struct irq_chip qe_ic_irq_chip = {
- .name = "QEIC",
- .irq_unmask = qe_ic_unmask_irq,
- .irq_mask = qe_ic_mask_irq,
- .irq_mask_ack = qe_ic_mask_irq,
-};
-
-static int qe_ic_host_match(struct irq_domain *h, struct device_node *node,
- enum irq_domain_bus_token bus_token)
-{
- /* Exact match, unless qe_ic node is NULL */
- struct device_node *of_node = irq_domain_get_of_node(h);
- return of_node == NULL || of_node == node;
-}
-
-static int qe_ic_host_map(struct irq_domain *h, unsigned int virq,
- irq_hw_number_t hw)
-{
- struct qe_ic *qe_ic = h->host_data;
- struct irq_chip *chip;
-
- if (qe_ic_info[hw].mask == 0) {
- printk(KERN_ERR "Can't map reserved IRQ\n");
- return -EINVAL;
- }
- /* Default chip */
- chip = &qe_ic->hc_irq;
-
- irq_set_chip_data(virq, qe_ic);
- irq_set_status_flags(virq, IRQ_LEVEL);
-
- irq_set_chip_and_handler(virq, chip, handle_level_irq);
-
- return 0;
-}
-
-static const struct irq_domain_ops qe_ic_host_ops = {
- .match = qe_ic_host_match,
- .map = qe_ic_host_map,
- .xlate = irq_domain_xlate_onetwocell,
-};
-
-/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
-unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic)
-{
- int irq;
-
- BUG_ON(qe_ic == NULL);
-
- /* get the interrupt source vector. */
- irq = qe_ic_read(qe_ic->regs, QEIC_CIVEC) >> 26;
-
- if (irq == 0)
- return NO_IRQ;
-
- return irq_linear_revmap(qe_ic->irqhost, irq);
-}
-
-/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
-unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic)
-{
- int irq;
-
- BUG_ON(qe_ic == NULL);
-
- /* get the interrupt source vector. */
- irq = qe_ic_read(qe_ic->regs, QEIC_CHIVEC) >> 26;
-
- if (irq == 0)
- return NO_IRQ;
-
- return irq_linear_revmap(qe_ic->irqhost, irq);
-}
-
-void __init qe_ic_init(struct device_node *node, unsigned int flags,
- void (*low_handler)(struct irq_desc *desc),
- void (*high_handler)(struct irq_desc *desc))
-{
- struct qe_ic *qe_ic;
- struct resource res;
- u32 temp = 0, ret, high_active = 0;
-
- ret = of_address_to_resource(node, 0, &res);
- if (ret)
- return;
-
- qe_ic = kzalloc(sizeof(*qe_ic), GFP_KERNEL);
- if (qe_ic == NULL)
- return;
-
- qe_ic->irqhost = irq_domain_add_linear(node, NR_QE_IC_INTS,
- &qe_ic_host_ops, qe_ic);
- if (qe_ic->irqhost == NULL) {
- kfree(qe_ic);
- return;
- }
-
- qe_ic->regs = ioremap(res.start, resource_size(&res));
-
- qe_ic->hc_irq = qe_ic_irq_chip;
-
- qe_ic->virq_high = irq_of_parse_and_map(node, 0);
- qe_ic->virq_low = irq_of_parse_and_map(node, 1);
-
- if (qe_ic->virq_low == NO_IRQ) {
- printk(KERN_ERR "Failed to map QE_IC low IRQ\n");
- kfree(qe_ic);
- return;
- }
-
- /* default priority scheme is grouped. If spread mode is */
- /* required, configure cicr accordingly. */
- if (flags & QE_IC_SPREADMODE_GRP_W)
- temp |= CICR_GWCC;
- if (flags & QE_IC_SPREADMODE_GRP_X)
- temp |= CICR_GXCC;
- if (flags & QE_IC_SPREADMODE_GRP_Y)
- temp |= CICR_GYCC;
- if (flags & QE_IC_SPREADMODE_GRP_Z)
- temp |= CICR_GZCC;
- if (flags & QE_IC_SPREADMODE_GRP_RISCA)
- temp |= CICR_GRTA;
- if (flags & QE_IC_SPREADMODE_GRP_RISCB)
- temp |= CICR_GRTB;
-
- /* choose destination signal for highest priority interrupt */
- if (flags & QE_IC_HIGH_SIGNAL) {
- temp |= (SIGNAL_HIGH << CICR_HPIT_SHIFT);
- high_active = 1;
- }
-
- qe_ic_write(qe_ic->regs, QEIC_CICR, temp);
-
- irq_set_handler_data(qe_ic->virq_low, qe_ic);
- irq_set_chained_handler(qe_ic->virq_low, low_handler);
-
- if (qe_ic->virq_high != NO_IRQ &&
- qe_ic->virq_high != qe_ic->virq_low) {
- irq_set_handler_data(qe_ic->virq_high, qe_ic);
- irq_set_chained_handler(qe_ic->virq_high, high_handler);
- }
-}
-
-void qe_ic_set_highest_priority(unsigned int virq, int high)
-{
- struct qe_ic *qe_ic = qe_ic_from_irq(virq);
- unsigned int src = virq_to_hw(virq);
- u32 temp = 0;
-
- temp = qe_ic_read(qe_ic->regs, QEIC_CICR);
-
- temp &= ~CICR_HP_MASK;
- temp |= src << CICR_HP_SHIFT;
-
- temp &= ~CICR_HPIT_MASK;
- temp |= (high ? SIGNAL_HIGH : SIGNAL_LOW) << CICR_HPIT_SHIFT;
-
- qe_ic_write(qe_ic->regs, QEIC_CICR, temp);
-}
-
-/* Set Priority level within its group, from 1 to 8 */
-int qe_ic_set_priority(unsigned int virq, unsigned int priority)
-{
- struct qe_ic *qe_ic = qe_ic_from_irq(virq);
- unsigned int src = virq_to_hw(virq);
- u32 temp;
-
- if (priority > 8 || priority == 0)
- return -EINVAL;
- if (src > 127)
- return -EINVAL;
- if (qe_ic_info[src].pri_reg == 0)
- return -EINVAL;
-
- temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].pri_reg);
-
- if (priority < 4) {
- temp &= ~(0x7 << (32 - priority * 3));
- temp |= qe_ic_info[src].pri_code << (32 - priority * 3);
- } else {
- temp &= ~(0x7 << (24 - priority * 3));
- temp |= qe_ic_info[src].pri_code << (24 - priority * 3);
- }
-
- qe_ic_write(qe_ic->regs, qe_ic_info[src].pri_reg, temp);
-
- return 0;
-}
-
-/* Set a QE priority to use high irq, only priority 1~2 can use high irq */
-int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high)
-{
- struct qe_ic *qe_ic = qe_ic_from_irq(virq);
- unsigned int src = virq_to_hw(virq);
- u32 temp, control_reg = QEIC_CICNR, shift = 0;
-
- if (priority > 2 || priority == 0)
- return -EINVAL;
-
- switch (qe_ic_info[src].pri_reg) {
- case QEIC_CIPZCC:
- shift = CICNR_ZCC1T_SHIFT;
- break;
- case QEIC_CIPWCC:
- shift = CICNR_WCC1T_SHIFT;
- break;
- case QEIC_CIPYCC:
- shift = CICNR_YCC1T_SHIFT;
- break;
- case QEIC_CIPXCC:
- shift = CICNR_XCC1T_SHIFT;
- break;
- case QEIC_CIPRTA:
- shift = CRICR_RTA1T_SHIFT;
- control_reg = QEIC_CRICR;
- break;
- case QEIC_CIPRTB:
- shift = CRICR_RTB1T_SHIFT;
- control_reg = QEIC_CRICR;
- break;
- default:
- return -EINVAL;
- }
-
- shift += (2 - priority) * 2;
- temp = qe_ic_read(qe_ic->regs, control_reg);
- temp &= ~(SIGNAL_MASK << shift);
- temp |= (high ? SIGNAL_HIGH : SIGNAL_LOW) << shift;
- qe_ic_write(qe_ic->regs, control_reg, temp);
-
- return 0;
-}
-
-static struct bus_type qe_ic_subsys = {
- .name = "qe_ic",
- .dev_name = "qe_ic",
-};
-
-static struct device device_qe_ic = {
- .id = 0,
- .bus = &qe_ic_subsys,
-};
-
-static int __init init_qe_ic_sysfs(void)
-{
- int rc;
-
- printk(KERN_DEBUG "Registering qe_ic with sysfs...\n");
-
- rc = subsys_system_register(&qe_ic_subsys, NULL);
- if (rc) {
- printk(KERN_ERR "Failed registering qe_ic sys class\n");
- return -ENODEV;
- }
- rc = device_register(&device_qe_ic);
- if (rc) {
- printk(KERN_ERR "Failed registering qe_ic sys device\n");
- return -ENODEV;
- }
- return 0;
-}
-
-subsys_initcall(init_qe_ic_sysfs);
+++ /dev/null
-/*
- * arch/powerpc/sysdev/qe_lib/qe_ic.h
- *
- * QUICC ENGINE Interrupt Controller Header
- *
- * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: Li Yang <leoli@freescale.com>
- * Based on code from Shlomi Gridish <gridish@freescale.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#ifndef _POWERPC_SYSDEV_QE_IC_H
-#define _POWERPC_SYSDEV_QE_IC_H
-
-#include <asm/qe_ic.h>
-
-#define NR_QE_IC_INTS 64
-
-/* QE IC registers offset */
-#define QEIC_CICR 0x00
-#define QEIC_CIVEC 0x04
-#define QEIC_CRIPNR 0x08
-#define QEIC_CIPNR 0x0c
-#define QEIC_CIPXCC 0x10
-#define QEIC_CIPYCC 0x14
-#define QEIC_CIPWCC 0x18
-#define QEIC_CIPZCC 0x1c
-#define QEIC_CIMR 0x20
-#define QEIC_CRIMR 0x24
-#define QEIC_CICNR 0x28
-#define QEIC_CIPRTA 0x30
-#define QEIC_CIPRTB 0x34
-#define QEIC_CRICR 0x3c
-#define QEIC_CHIVEC 0x60
-
-/* Interrupt priority registers */
-#define CIPCC_SHIFT_PRI0 29
-#define CIPCC_SHIFT_PRI1 26
-#define CIPCC_SHIFT_PRI2 23
-#define CIPCC_SHIFT_PRI3 20
-#define CIPCC_SHIFT_PRI4 13
-#define CIPCC_SHIFT_PRI5 10
-#define CIPCC_SHIFT_PRI6 7
-#define CIPCC_SHIFT_PRI7 4
-
-/* CICR priority modes */
-#define CICR_GWCC 0x00040000
-#define CICR_GXCC 0x00020000
-#define CICR_GYCC 0x00010000
-#define CICR_GZCC 0x00080000
-#define CICR_GRTA 0x00200000
-#define CICR_GRTB 0x00400000
-#define CICR_HPIT_SHIFT 8
-#define CICR_HPIT_MASK 0x00000300
-#define CICR_HP_SHIFT 24
-#define CICR_HP_MASK 0x3f000000
-
-/* CICNR */
-#define CICNR_WCC1T_SHIFT 20
-#define CICNR_ZCC1T_SHIFT 28
-#define CICNR_YCC1T_SHIFT 12
-#define CICNR_XCC1T_SHIFT 4
-
-/* CRICR */
-#define CRICR_RTA1T_SHIFT 20
-#define CRICR_RTB1T_SHIFT 28
-
-/* Signal indicator */
-#define SIGNAL_MASK 3
-#define SIGNAL_HIGH 2
-#define SIGNAL_LOW 0
-
-struct qe_ic {
- /* Control registers offset */
- volatile u32 __iomem *regs;
-
- /* The remapper for this QEIC */
- struct irq_domain *irqhost;
-
- /* The "linux" controller struct */
- struct irq_chip hc_irq;
-
- /* VIRQ numbers of QE high/low irqs */
- unsigned int virq_high;
- unsigned int virq_low;
-};
-
-/*
- * QE interrupt controller internal structure
- */
-struct qe_ic_info {
- u32 mask; /* location of this source at the QIMR register. */
- u32 mask_reg; /* Mask register offset */
- u8 pri_code; /* for grouped interrupts sources - the interrupt
- code as appears at the group priority register */
- u32 pri_reg; /* Group priority register offset */
-};
-
-#endif /* _POWERPC_SYSDEV_QE_IC_H */
+++ /dev/null
-/*
- * arch/powerpc/sysdev/qe_lib/qe_io.c
- *
- * QE Parallel I/O ports configuration routines
- *
- * Copyright 2006 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: Li Yang <LeoLi@freescale.com>
- * Based on code from Shlomi Gridish <gridish@freescale.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/ioport.h>
-
-#include <asm/io.h>
-#include <asm/qe.h>
-#include <asm/prom.h>
-#include <sysdev/fsl_soc.h>
-
-#undef DEBUG
-
-static struct qe_pio_regs __iomem *par_io;
-static int num_par_io_ports = 0;
-
-int par_io_init(struct device_node *np)
-{
- struct resource res;
- int ret;
- const u32 *num_ports;
-
- /* Map Parallel I/O ports registers */
- ret = of_address_to_resource(np, 0, &res);
- if (ret)
- return ret;
- par_io = ioremap(res.start, resource_size(&res));
-
- num_ports = of_get_property(np, "num-ports", NULL);
- if (num_ports)
- num_par_io_ports = *num_ports;
-
- return 0;
-}
-
-void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin, int dir,
- int open_drain, int assignment, int has_irq)
-{
- u32 pin_mask1bit;
- u32 pin_mask2bits;
- u32 new_mask2bits;
- u32 tmp_val;
-
- /* calculate pin location for single and 2 bits information */
- pin_mask1bit = (u32) (1 << (QE_PIO_PINS - (pin + 1)));
-
- /* Set open drain, if required */
- tmp_val = in_be32(&par_io->cpodr);
- if (open_drain)
- out_be32(&par_io->cpodr, pin_mask1bit | tmp_val);
- else
- out_be32(&par_io->cpodr, ~pin_mask1bit & tmp_val);
-
- /* define direction */
- tmp_val = (pin > (QE_PIO_PINS / 2) - 1) ?
- in_be32(&par_io->cpdir2) :
- in_be32(&par_io->cpdir1);
-
- /* get all bits mask for 2 bit per port */
- pin_mask2bits = (u32) (0x3 << (QE_PIO_PINS -
- (pin % (QE_PIO_PINS / 2) + 1) * 2));
-
- /* Get the final mask we need for the right definition */
- new_mask2bits = (u32) (dir << (QE_PIO_PINS -
- (pin % (QE_PIO_PINS / 2) + 1) * 2));
-
- /* clear and set 2 bits mask */
- if (pin > (QE_PIO_PINS / 2) - 1) {
- out_be32(&par_io->cpdir2,
- ~pin_mask2bits & tmp_val);
- tmp_val &= ~pin_mask2bits;
- out_be32(&par_io->cpdir2, new_mask2bits | tmp_val);
- } else {
- out_be32(&par_io->cpdir1,
- ~pin_mask2bits & tmp_val);
- tmp_val &= ~pin_mask2bits;
- out_be32(&par_io->cpdir1, new_mask2bits | tmp_val);
- }
- /* define pin assignment */
- tmp_val = (pin > (QE_PIO_PINS / 2) - 1) ?
- in_be32(&par_io->cppar2) :
- in_be32(&par_io->cppar1);
-
- new_mask2bits = (u32) (assignment << (QE_PIO_PINS -
- (pin % (QE_PIO_PINS / 2) + 1) * 2));
- /* clear and set 2 bits mask */
- if (pin > (QE_PIO_PINS / 2) - 1) {
- out_be32(&par_io->cppar2,
- ~pin_mask2bits & tmp_val);
- tmp_val &= ~pin_mask2bits;
- out_be32(&par_io->cppar2, new_mask2bits | tmp_val);
- } else {
- out_be32(&par_io->cppar1,
- ~pin_mask2bits & tmp_val);
- tmp_val &= ~pin_mask2bits;
- out_be32(&par_io->cppar1, new_mask2bits | tmp_val);
- }
-}
-EXPORT_SYMBOL(__par_io_config_pin);
-
-int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
- int assignment, int has_irq)
-{
- if (!par_io || port >= num_par_io_ports)
- return -EINVAL;
-
- __par_io_config_pin(&par_io[port], pin, dir, open_drain, assignment,
- has_irq);
- return 0;
-}
-EXPORT_SYMBOL(par_io_config_pin);
-
-int par_io_data_set(u8 port, u8 pin, u8 val)
-{
- u32 pin_mask, tmp_val;
-
- if (port >= num_par_io_ports)
- return -EINVAL;
- if (pin >= QE_PIO_PINS)
- return -EINVAL;
- /* calculate pin location */
- pin_mask = (u32) (1 << (QE_PIO_PINS - 1 - pin));
-
- tmp_val = in_be32(&par_io[port].cpdata);
-
- if (val == 0) /* clear */
- out_be32(&par_io[port].cpdata, ~pin_mask & tmp_val);
- else /* set */
- out_be32(&par_io[port].cpdata, pin_mask | tmp_val);
-
- return 0;
-}
-EXPORT_SYMBOL(par_io_data_set);
-
-int par_io_of_config(struct device_node *np)
-{
- struct device_node *pio;
- const phandle *ph;
- int pio_map_len;
- const unsigned int *pio_map;
-
- if (par_io == NULL) {
- printk(KERN_ERR "par_io not initialized\n");
- return -1;
- }
-
- ph = of_get_property(np, "pio-handle", NULL);
- if (ph == NULL) {
- printk(KERN_ERR "pio-handle not available\n");
- return -1;
- }
-
- pio = of_find_node_by_phandle(*ph);
-
- pio_map = of_get_property(pio, "pio-map", &pio_map_len);
- if (pio_map == NULL) {
- printk(KERN_ERR "pio-map is not set!\n");
- return -1;
- }
- pio_map_len /= sizeof(unsigned int);
- if ((pio_map_len % 6) != 0) {
- printk(KERN_ERR "pio-map format wrong!\n");
- return -1;
- }
-
- while (pio_map_len > 0) {
- par_io_config_pin((u8) pio_map[0], (u8) pio_map[1],
- (int) pio_map[2], (int) pio_map[3],
- (int) pio_map[4], (int) pio_map[5]);
- pio_map += 6;
- pio_map_len -= 6;
- }
- of_node_put(pio);
- return 0;
-}
-EXPORT_SYMBOL(par_io_of_config);
+++ /dev/null
-/*
- * arch/powerpc/sysdev/qe_lib/ucc.c
- *
- * QE UCC API Set - UCC specific routines implementations.
- *
- * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Authors: Shlomi Gridish <gridish@freescale.com>
- * Li Yang <leoli@freescale.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/stddef.h>
-#include <linux/spinlock.h>
-#include <linux/export.h>
-
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/immap_qe.h>
-#include <asm/qe.h>
-#include <asm/ucc.h>
-
-int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
-{
- unsigned long flags;
-
- if (ucc_num > UCC_MAX_NUM - 1)
- return -EINVAL;
-
- spin_lock_irqsave(&cmxgcr_lock, flags);
- clrsetbits_be32(&qe_immr->qmx.cmxgcr, QE_CMXGCR_MII_ENET_MNG,
- ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT);
- spin_unlock_irqrestore(&cmxgcr_lock, flags);
-
- return 0;
-}
-EXPORT_SYMBOL(ucc_set_qe_mux_mii_mng);
-
-/* Configure the UCC to either Slow or Fast.
- *
- * A given UCC can be figured to support either "slow" devices (e.g. UART)
- * or "fast" devices (e.g. Ethernet).
- *
- * 'ucc_num' is the UCC number, from 0 - 7.
- *
- * This function also sets the UCC_GUEMR_SET_RESERVED3 bit because that bit
- * must always be set to 1.
- */
-int ucc_set_type(unsigned int ucc_num, enum ucc_speed_type speed)
-{
- u8 __iomem *guemr;
-
- /* The GUEMR register is at the same location for both slow and fast
- devices, so we just use uccX.slow.guemr. */
- switch (ucc_num) {
- case 0: guemr = &qe_immr->ucc1.slow.guemr;
- break;
- case 1: guemr = &qe_immr->ucc2.slow.guemr;
- break;
- case 2: guemr = &qe_immr->ucc3.slow.guemr;
- break;
- case 3: guemr = &qe_immr->ucc4.slow.guemr;
- break;
- case 4: guemr = &qe_immr->ucc5.slow.guemr;
- break;
- case 5: guemr = &qe_immr->ucc6.slow.guemr;
- break;
- case 6: guemr = &qe_immr->ucc7.slow.guemr;
- break;
- case 7: guemr = &qe_immr->ucc8.slow.guemr;
- break;
- default:
- return -EINVAL;
- }
-
- clrsetbits_8(guemr, UCC_GUEMR_MODE_MASK,
- UCC_GUEMR_SET_RESERVED3 | speed);
-
- return 0;
-}
-
-static void get_cmxucr_reg(unsigned int ucc_num, __be32 __iomem **cmxucr,
- unsigned int *reg_num, unsigned int *shift)
-{
- unsigned int cmx = ((ucc_num & 1) << 1) + (ucc_num > 3);
-
- *reg_num = cmx + 1;
- *cmxucr = &qe_immr->qmx.cmxucr[cmx];
- *shift = 16 - 8 * (ucc_num & 2);
-}
-
-int ucc_mux_set_grant_tsa_bkpt(unsigned int ucc_num, int set, u32 mask)
-{
- __be32 __iomem *cmxucr;
- unsigned int reg_num;
- unsigned int shift;
-
- /* check if the UCC number is in range. */
- if (ucc_num > UCC_MAX_NUM - 1)
- return -EINVAL;
-
- get_cmxucr_reg(ucc_num, &cmxucr, ®_num, &shift);
-
- if (set)
- setbits32(cmxucr, mask << shift);
- else
- clrbits32(cmxucr, mask << shift);
-
- return 0;
-}
-
-int ucc_set_qe_mux_rxtx(unsigned int ucc_num, enum qe_clock clock,
- enum comm_dir mode)
-{
- __be32 __iomem *cmxucr;
- unsigned int reg_num;
- unsigned int shift;
- u32 clock_bits = 0;
-
- /* check if the UCC number is in range. */
- if (ucc_num > UCC_MAX_NUM - 1)
- return -EINVAL;
-
- /* The communications direction must be RX or TX */
- if (!((mode == COMM_DIR_RX) || (mode == COMM_DIR_TX)))
- return -EINVAL;
-
- get_cmxucr_reg(ucc_num, &cmxucr, ®_num, &shift);
-
- switch (reg_num) {
- case 1:
- switch (clock) {
- case QE_BRG1: clock_bits = 1; break;
- case QE_BRG2: clock_bits = 2; break;
- case QE_BRG7: clock_bits = 3; break;
- case QE_BRG8: clock_bits = 4; break;
- case QE_CLK9: clock_bits = 5; break;
- case QE_CLK10: clock_bits = 6; break;
- case QE_CLK11: clock_bits = 7; break;
- case QE_CLK12: clock_bits = 8; break;
- case QE_CLK15: clock_bits = 9; break;
- case QE_CLK16: clock_bits = 10; break;
- default: break;
- }
- break;
- case 2:
- switch (clock) {
- case QE_BRG5: clock_bits = 1; break;
- case QE_BRG6: clock_bits = 2; break;
- case QE_BRG7: clock_bits = 3; break;
- case QE_BRG8: clock_bits = 4; break;
- case QE_CLK13: clock_bits = 5; break;
- case QE_CLK14: clock_bits = 6; break;
- case QE_CLK19: clock_bits = 7; break;
- case QE_CLK20: clock_bits = 8; break;
- case QE_CLK15: clock_bits = 9; break;
- case QE_CLK16: clock_bits = 10; break;
- default: break;
- }
- break;
- case 3:
- switch (clock) {
- case QE_BRG9: clock_bits = 1; break;
- case QE_BRG10: clock_bits = 2; break;
- case QE_BRG15: clock_bits = 3; break;
- case QE_BRG16: clock_bits = 4; break;
- case QE_CLK3: clock_bits = 5; break;
- case QE_CLK4: clock_bits = 6; break;
- case QE_CLK17: clock_bits = 7; break;
- case QE_CLK18: clock_bits = 8; break;
- case QE_CLK7: clock_bits = 9; break;
- case QE_CLK8: clock_bits = 10; break;
- case QE_CLK16: clock_bits = 11; break;
- default: break;
- }
- break;
- case 4:
- switch (clock) {
- case QE_BRG13: clock_bits = 1; break;
- case QE_BRG14: clock_bits = 2; break;
- case QE_BRG15: clock_bits = 3; break;
- case QE_BRG16: clock_bits = 4; break;
- case QE_CLK5: clock_bits = 5; break;
- case QE_CLK6: clock_bits = 6; break;
- case QE_CLK21: clock_bits = 7; break;
- case QE_CLK22: clock_bits = 8; break;
- case QE_CLK7: clock_bits = 9; break;
- case QE_CLK8: clock_bits = 10; break;
- case QE_CLK16: clock_bits = 11; break;
- default: break;
- }
- break;
- default: break;
- }
-
- /* Check for invalid combination of clock and UCC number */
- if (!clock_bits)
- return -ENOENT;
-
- if (mode == COMM_DIR_RX)
- shift += 4;
-
- clrsetbits_be32(cmxucr, QE_CMXUCR_TX_CLK_SRC_MASK << shift,
- clock_bits << shift);
-
- return 0;
-}
+++ /dev/null
-/*
- * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Authors: Shlomi Gridish <gridish@freescale.com>
- * Li Yang <leoli@freescale.com>
- *
- * Description:
- * QE UCC Fast API Set - UCC Fast specific routines implementations.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/stddef.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/export.h>
-
-#include <asm/io.h>
-#include <asm/immap_qe.h>
-#include <asm/qe.h>
-
-#include <asm/ucc.h>
-#include <asm/ucc_fast.h>
-
-void ucc_fast_dump_regs(struct ucc_fast_private * uccf)
-{
- printk(KERN_INFO "UCC%u Fast registers:\n", uccf->uf_info->ucc_num);
- printk(KERN_INFO "Base address: 0x%p\n", uccf->uf_regs);
-
- printk(KERN_INFO "gumr : addr=0x%p, val=0x%08x\n",
- &uccf->uf_regs->gumr, in_be32(&uccf->uf_regs->gumr));
- printk(KERN_INFO "upsmr : addr=0x%p, val=0x%08x\n",
- &uccf->uf_regs->upsmr, in_be32(&uccf->uf_regs->upsmr));
- printk(KERN_INFO "utodr : addr=0x%p, val=0x%04x\n",
- &uccf->uf_regs->utodr, in_be16(&uccf->uf_regs->utodr));
- printk(KERN_INFO "udsr : addr=0x%p, val=0x%04x\n",
- &uccf->uf_regs->udsr, in_be16(&uccf->uf_regs->udsr));
- printk(KERN_INFO "ucce : addr=0x%p, val=0x%08x\n",
- &uccf->uf_regs->ucce, in_be32(&uccf->uf_regs->ucce));
- printk(KERN_INFO "uccm : addr=0x%p, val=0x%08x\n",
- &uccf->uf_regs->uccm, in_be32(&uccf->uf_regs->uccm));
- printk(KERN_INFO "uccs : addr=0x%p, val=0x%02x\n",
- &uccf->uf_regs->uccs, in_8(&uccf->uf_regs->uccs));
- printk(KERN_INFO "urfb : addr=0x%p, val=0x%08x\n",
- &uccf->uf_regs->urfb, in_be32(&uccf->uf_regs->urfb));
- printk(KERN_INFO "urfs : addr=0x%p, val=0x%04x\n",
- &uccf->uf_regs->urfs, in_be16(&uccf->uf_regs->urfs));
- printk(KERN_INFO "urfet : addr=0x%p, val=0x%04x\n",
- &uccf->uf_regs->urfet, in_be16(&uccf->uf_regs->urfet));
- printk(KERN_INFO "urfset: addr=0x%p, val=0x%04x\n",
- &uccf->uf_regs->urfset, in_be16(&uccf->uf_regs->urfset));
- printk(KERN_INFO "utfb : addr=0x%p, val=0x%08x\n",
- &uccf->uf_regs->utfb, in_be32(&uccf->uf_regs->utfb));
- printk(KERN_INFO "utfs : addr=0x%p, val=0x%04x\n",
- &uccf->uf_regs->utfs, in_be16(&uccf->uf_regs->utfs));
- printk(KERN_INFO "utfet : addr=0x%p, val=0x%04x\n",
- &uccf->uf_regs->utfet, in_be16(&uccf->uf_regs->utfet));
- printk(KERN_INFO "utftt : addr=0x%p, val=0x%04x\n",
- &uccf->uf_regs->utftt, in_be16(&uccf->uf_regs->utftt));
- printk(KERN_INFO "utpt : addr=0x%p, val=0x%04x\n",
- &uccf->uf_regs->utpt, in_be16(&uccf->uf_regs->utpt));
- printk(KERN_INFO "urtry : addr=0x%p, val=0x%08x\n",
- &uccf->uf_regs->urtry, in_be32(&uccf->uf_regs->urtry));
- printk(KERN_INFO "guemr : addr=0x%p, val=0x%02x\n",
- &uccf->uf_regs->guemr, in_8(&uccf->uf_regs->guemr));
-}
-EXPORT_SYMBOL(ucc_fast_dump_regs);
-
-u32 ucc_fast_get_qe_cr_subblock(int uccf_num)
-{
- switch (uccf_num) {
- case 0: return QE_CR_SUBBLOCK_UCCFAST1;
- case 1: return QE_CR_SUBBLOCK_UCCFAST2;
- case 2: return QE_CR_SUBBLOCK_UCCFAST3;
- case 3: return QE_CR_SUBBLOCK_UCCFAST4;
- case 4: return QE_CR_SUBBLOCK_UCCFAST5;
- case 5: return QE_CR_SUBBLOCK_UCCFAST6;
- case 6: return QE_CR_SUBBLOCK_UCCFAST7;
- case 7: return QE_CR_SUBBLOCK_UCCFAST8;
- default: return QE_CR_SUBBLOCK_INVALID;
- }
-}
-EXPORT_SYMBOL(ucc_fast_get_qe_cr_subblock);
-
-void ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf)
-{
- out_be16(&uccf->uf_regs->utodr, UCC_FAST_TOD);
-}
-EXPORT_SYMBOL(ucc_fast_transmit_on_demand);
-
-void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode)
-{
- struct ucc_fast __iomem *uf_regs;
- u32 gumr;
-
- uf_regs = uccf->uf_regs;
-
- /* Enable reception and/or transmission on this UCC. */
- gumr = in_be32(&uf_regs->gumr);
- if (mode & COMM_DIR_TX) {
- gumr |= UCC_FAST_GUMR_ENT;
- uccf->enabled_tx = 1;
- }
- if (mode & COMM_DIR_RX) {
- gumr |= UCC_FAST_GUMR_ENR;
- uccf->enabled_rx = 1;
- }
- out_be32(&uf_regs->gumr, gumr);
-}
-EXPORT_SYMBOL(ucc_fast_enable);
-
-void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode)
-{
- struct ucc_fast __iomem *uf_regs;
- u32 gumr;
-
- uf_regs = uccf->uf_regs;
-
- /* Disable reception and/or transmission on this UCC. */
- gumr = in_be32(&uf_regs->gumr);
- if (mode & COMM_DIR_TX) {
- gumr &= ~UCC_FAST_GUMR_ENT;
- uccf->enabled_tx = 0;
- }
- if (mode & COMM_DIR_RX) {
- gumr &= ~UCC_FAST_GUMR_ENR;
- uccf->enabled_rx = 0;
- }
- out_be32(&uf_regs->gumr, gumr);
-}
-EXPORT_SYMBOL(ucc_fast_disable);
-
-int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret)
-{
- struct ucc_fast_private *uccf;
- struct ucc_fast __iomem *uf_regs;
- u32 gumr;
- int ret;
-
- if (!uf_info)
- return -EINVAL;
-
- /* check if the UCC port number is in range. */
- if ((uf_info->ucc_num < 0) || (uf_info->ucc_num > UCC_MAX_NUM - 1)) {
- printk(KERN_ERR "%s: illegal UCC number\n", __func__);
- return -EINVAL;
- }
-
- /* Check that 'max_rx_buf_length' is properly aligned (4). */
- if (uf_info->max_rx_buf_length & (UCC_FAST_MRBLR_ALIGNMENT - 1)) {
- printk(KERN_ERR "%s: max_rx_buf_length not aligned\n",
- __func__);
- return -EINVAL;
- }
-
- /* Validate Virtual Fifo register values */
- if (uf_info->urfs < UCC_FAST_URFS_MIN_VAL) {
- printk(KERN_ERR "%s: urfs is too small\n", __func__);
- return -EINVAL;
- }
-
- if (uf_info->urfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
- printk(KERN_ERR "%s: urfs is not aligned\n", __func__);
- return -EINVAL;
- }
-
- if (uf_info->urfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
- printk(KERN_ERR "%s: urfet is not aligned.\n", __func__);
- return -EINVAL;
- }
-
- if (uf_info->urfset & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
- printk(KERN_ERR "%s: urfset is not aligned\n", __func__);
- return -EINVAL;
- }
-
- if (uf_info->utfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
- printk(KERN_ERR "%s: utfs is not aligned\n", __func__);
- return -EINVAL;
- }
-
- if (uf_info->utfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
- printk(KERN_ERR "%s: utfet is not aligned\n", __func__);
- return -EINVAL;
- }
-
- if (uf_info->utftt & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
- printk(KERN_ERR "%s: utftt is not aligned\n", __func__);
- return -EINVAL;
- }
-
- uccf = kzalloc(sizeof(struct ucc_fast_private), GFP_KERNEL);
- if (!uccf) {
- printk(KERN_ERR "%s: Cannot allocate private data\n",
- __func__);
- return -ENOMEM;
- }
-
- /* Fill fast UCC structure */
- uccf->uf_info = uf_info;
- /* Set the PHY base address */
- uccf->uf_regs = ioremap(uf_info->regs, sizeof(struct ucc_fast));
- if (uccf->uf_regs == NULL) {
- printk(KERN_ERR "%s: Cannot map UCC registers\n", __func__);
- kfree(uccf);
- return -ENOMEM;
- }
-
- uccf->enabled_tx = 0;
- uccf->enabled_rx = 0;
- uccf->stopped_tx = 0;
- uccf->stopped_rx = 0;
- uf_regs = uccf->uf_regs;
- uccf->p_ucce = &uf_regs->ucce;
- uccf->p_uccm = &uf_regs->uccm;
-#ifdef CONFIG_UGETH_TX_ON_DEMAND
- uccf->p_utodr = &uf_regs->utodr;
-#endif
-#ifdef STATISTICS
- uccf->tx_frames = 0;
- uccf->rx_frames = 0;
- uccf->rx_discarded = 0;
-#endif /* STATISTICS */
-
- /* Set UCC to fast type */
- ret = ucc_set_type(uf_info->ucc_num, UCC_SPEED_TYPE_FAST);
- if (ret) {
- printk(KERN_ERR "%s: cannot set UCC type\n", __func__);
- ucc_fast_free(uccf);
- return ret;
- }
-
- uccf->mrblr = uf_info->max_rx_buf_length;
-
- /* Set GUMR */
- /* For more details see the hardware spec. */
- gumr = uf_info->ttx_trx;
- if (uf_info->tci)
- gumr |= UCC_FAST_GUMR_TCI;
- if (uf_info->cdp)
- gumr |= UCC_FAST_GUMR_CDP;
- if (uf_info->ctsp)
- gumr |= UCC_FAST_GUMR_CTSP;
- if (uf_info->cds)
- gumr |= UCC_FAST_GUMR_CDS;
- if (uf_info->ctss)
- gumr |= UCC_FAST_GUMR_CTSS;
- if (uf_info->txsy)
- gumr |= UCC_FAST_GUMR_TXSY;
- if (uf_info->rsyn)
- gumr |= UCC_FAST_GUMR_RSYN;
- gumr |= uf_info->synl;
- if (uf_info->rtsm)
- gumr |= UCC_FAST_GUMR_RTSM;
- gumr |= uf_info->renc;
- if (uf_info->revd)
- gumr |= UCC_FAST_GUMR_REVD;
- gumr |= uf_info->tenc;
- gumr |= uf_info->tcrc;
- gumr |= uf_info->mode;
- out_be32(&uf_regs->gumr, gumr);
-
- /* Allocate memory for Tx Virtual Fifo */
- uccf->ucc_fast_tx_virtual_fifo_base_offset =
- qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
- if (IS_ERR_VALUE(uccf->ucc_fast_tx_virtual_fifo_base_offset)) {
- printk(KERN_ERR "%s: cannot allocate MURAM for TX FIFO\n",
- __func__);
- uccf->ucc_fast_tx_virtual_fifo_base_offset = 0;
- ucc_fast_free(uccf);
- return -ENOMEM;
- }
-
- /* Allocate memory for Rx Virtual Fifo */
- uccf->ucc_fast_rx_virtual_fifo_base_offset =
- qe_muram_alloc(uf_info->urfs +
- UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR,
- UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
- if (IS_ERR_VALUE(uccf->ucc_fast_rx_virtual_fifo_base_offset)) {
- printk(KERN_ERR "%s: cannot allocate MURAM for RX FIFO\n",
- __func__);
- uccf->ucc_fast_rx_virtual_fifo_base_offset = 0;
- ucc_fast_free(uccf);
- return -ENOMEM;
- }
-
- /* Set Virtual Fifo registers */
- out_be16(&uf_regs->urfs, uf_info->urfs);
- out_be16(&uf_regs->urfet, uf_info->urfet);
- out_be16(&uf_regs->urfset, uf_info->urfset);
- out_be16(&uf_regs->utfs, uf_info->utfs);
- out_be16(&uf_regs->utfet, uf_info->utfet);
- out_be16(&uf_regs->utftt, uf_info->utftt);
- /* utfb, urfb are offsets from MURAM base */
- out_be32(&uf_regs->utfb, uccf->ucc_fast_tx_virtual_fifo_base_offset);
- out_be32(&uf_regs->urfb, uccf->ucc_fast_rx_virtual_fifo_base_offset);
-
- /* Mux clocking */
- /* Grant Support */
- ucc_set_qe_mux_grant(uf_info->ucc_num, uf_info->grant_support);
- /* Breakpoint Support */
- ucc_set_qe_mux_bkpt(uf_info->ucc_num, uf_info->brkpt_support);
- /* Set Tsa or NMSI mode. */
- ucc_set_qe_mux_tsa(uf_info->ucc_num, uf_info->tsa);
- /* If NMSI (not Tsa), set Tx and Rx clock. */
- if (!uf_info->tsa) {
- /* Rx clock routing */
- if ((uf_info->rx_clock != QE_CLK_NONE) &&
- ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->rx_clock,
- COMM_DIR_RX)) {
- printk(KERN_ERR "%s: illegal value for RX clock\n",
- __func__);
- ucc_fast_free(uccf);
- return -EINVAL;
- }
- /* Tx clock routing */
- if ((uf_info->tx_clock != QE_CLK_NONE) &&
- ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->tx_clock,
- COMM_DIR_TX)) {
- printk(KERN_ERR "%s: illegal value for TX clock\n",
- __func__);
- ucc_fast_free(uccf);
- return -EINVAL;
- }
- }
-
- /* Set interrupt mask register at UCC level. */
- out_be32(&uf_regs->uccm, uf_info->uccm_mask);
-
- /* First, clear anything pending at UCC level,
- * otherwise, old garbage may come through
- * as soon as the dam is opened. */
-
- /* Writing '1' clears */
- out_be32(&uf_regs->ucce, 0xffffffff);
-
- *uccf_ret = uccf;
- return 0;
-}
-EXPORT_SYMBOL(ucc_fast_init);
-
-void ucc_fast_free(struct ucc_fast_private * uccf)
-{
- if (!uccf)
- return;
-
- if (uccf->ucc_fast_tx_virtual_fifo_base_offset)
- qe_muram_free(uccf->ucc_fast_tx_virtual_fifo_base_offset);
-
- if (uccf->ucc_fast_rx_virtual_fifo_base_offset)
- qe_muram_free(uccf->ucc_fast_rx_virtual_fifo_base_offset);
-
- if (uccf->uf_regs)
- iounmap(uccf->uf_regs);
-
- kfree(uccf);
-}
-EXPORT_SYMBOL(ucc_fast_free);
+++ /dev/null
-/*
- * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Authors: Shlomi Gridish <gridish@freescale.com>
- * Li Yang <leoli@freescale.com>
- *
- * Description:
- * QE UCC Slow API Set - UCC Slow specific routines implementations.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/stddef.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/export.h>
-
-#include <asm/io.h>
-#include <asm/immap_qe.h>
-#include <asm/qe.h>
-
-#include <asm/ucc.h>
-#include <asm/ucc_slow.h>
-
-u32 ucc_slow_get_qe_cr_subblock(int uccs_num)
-{
- switch (uccs_num) {
- case 0: return QE_CR_SUBBLOCK_UCCSLOW1;
- case 1: return QE_CR_SUBBLOCK_UCCSLOW2;
- case 2: return QE_CR_SUBBLOCK_UCCSLOW3;
- case 3: return QE_CR_SUBBLOCK_UCCSLOW4;
- case 4: return QE_CR_SUBBLOCK_UCCSLOW5;
- case 5: return QE_CR_SUBBLOCK_UCCSLOW6;
- case 6: return QE_CR_SUBBLOCK_UCCSLOW7;
- case 7: return QE_CR_SUBBLOCK_UCCSLOW8;
- default: return QE_CR_SUBBLOCK_INVALID;
- }
-}
-EXPORT_SYMBOL(ucc_slow_get_qe_cr_subblock);
-
-void ucc_slow_graceful_stop_tx(struct ucc_slow_private * uccs)
-{
- struct ucc_slow_info *us_info = uccs->us_info;
- u32 id;
-
- id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
- qe_issue_cmd(QE_GRACEFUL_STOP_TX, id,
- QE_CR_PROTOCOL_UNSPECIFIED, 0);
-}
-EXPORT_SYMBOL(ucc_slow_graceful_stop_tx);
-
-void ucc_slow_stop_tx(struct ucc_slow_private * uccs)
-{
- struct ucc_slow_info *us_info = uccs->us_info;
- u32 id;
-
- id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
- qe_issue_cmd(QE_STOP_TX, id, QE_CR_PROTOCOL_UNSPECIFIED, 0);
-}
-EXPORT_SYMBOL(ucc_slow_stop_tx);
-
-void ucc_slow_restart_tx(struct ucc_slow_private * uccs)
-{
- struct ucc_slow_info *us_info = uccs->us_info;
- u32 id;
-
- id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
- qe_issue_cmd(QE_RESTART_TX, id, QE_CR_PROTOCOL_UNSPECIFIED, 0);
-}
-EXPORT_SYMBOL(ucc_slow_restart_tx);
-
-void ucc_slow_enable(struct ucc_slow_private * uccs, enum comm_dir mode)
-{
- struct ucc_slow *us_regs;
- u32 gumr_l;
-
- us_regs = uccs->us_regs;
-
- /* Enable reception and/or transmission on this UCC. */
- gumr_l = in_be32(&us_regs->gumr_l);
- if (mode & COMM_DIR_TX) {
- gumr_l |= UCC_SLOW_GUMR_L_ENT;
- uccs->enabled_tx = 1;
- }
- if (mode & COMM_DIR_RX) {
- gumr_l |= UCC_SLOW_GUMR_L_ENR;
- uccs->enabled_rx = 1;
- }
- out_be32(&us_regs->gumr_l, gumr_l);
-}
-EXPORT_SYMBOL(ucc_slow_enable);
-
-void ucc_slow_disable(struct ucc_slow_private * uccs, enum comm_dir mode)
-{
- struct ucc_slow *us_regs;
- u32 gumr_l;
-
- us_regs = uccs->us_regs;
-
- /* Disable reception and/or transmission on this UCC. */
- gumr_l = in_be32(&us_regs->gumr_l);
- if (mode & COMM_DIR_TX) {
- gumr_l &= ~UCC_SLOW_GUMR_L_ENT;
- uccs->enabled_tx = 0;
- }
- if (mode & COMM_DIR_RX) {
- gumr_l &= ~UCC_SLOW_GUMR_L_ENR;
- uccs->enabled_rx = 0;
- }
- out_be32(&us_regs->gumr_l, gumr_l);
-}
-EXPORT_SYMBOL(ucc_slow_disable);
-
-/* Initialize the UCC for Slow operations
- *
- * The caller should initialize the following us_info
- */
-int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** uccs_ret)
-{
- struct ucc_slow_private *uccs;
- u32 i;
- struct ucc_slow __iomem *us_regs;
- u32 gumr;
- struct qe_bd *bd;
- u32 id;
- u32 command;
- int ret = 0;
-
- if (!us_info)
- return -EINVAL;
-
- /* check if the UCC port number is in range. */
- if ((us_info->ucc_num < 0) || (us_info->ucc_num > UCC_MAX_NUM - 1)) {
- printk(KERN_ERR "%s: illegal UCC number\n", __func__);
- return -EINVAL;
- }
-
- /*
- * Set mrblr
- * Check that 'max_rx_buf_length' is properly aligned (4), unless
- * rfw is 1, meaning that QE accepts one byte at a time, unlike normal
- * case when QE accepts 32 bits at a time.
- */
- if ((!us_info->rfw) &&
- (us_info->max_rx_buf_length & (UCC_SLOW_MRBLR_ALIGNMENT - 1))) {
- printk(KERN_ERR "max_rx_buf_length not aligned.\n");
- return -EINVAL;
- }
-
- uccs = kzalloc(sizeof(struct ucc_slow_private), GFP_KERNEL);
- if (!uccs) {
- printk(KERN_ERR "%s: Cannot allocate private data\n",
- __func__);
- return -ENOMEM;
- }
-
- /* Fill slow UCC structure */
- uccs->us_info = us_info;
- /* Set the PHY base address */
- uccs->us_regs = ioremap(us_info->regs, sizeof(struct ucc_slow));
- if (uccs->us_regs == NULL) {
- printk(KERN_ERR "%s: Cannot map UCC registers\n", __func__);
- kfree(uccs);
- return -ENOMEM;
- }
-
- uccs->saved_uccm = 0;
- uccs->p_rx_frame = 0;
- us_regs = uccs->us_regs;
- uccs->p_ucce = (u16 *) & (us_regs->ucce);
- uccs->p_uccm = (u16 *) & (us_regs->uccm);
-#ifdef STATISTICS
- uccs->rx_frames = 0;
- uccs->tx_frames = 0;
- uccs->rx_discarded = 0;
-#endif /* STATISTICS */
-
- /* Get PRAM base */
- uccs->us_pram_offset =
- qe_muram_alloc(UCC_SLOW_PRAM_SIZE, ALIGNMENT_OF_UCC_SLOW_PRAM);
- if (IS_ERR_VALUE(uccs->us_pram_offset)) {
- printk(KERN_ERR "%s: cannot allocate MURAM for PRAM", __func__);
- ucc_slow_free(uccs);
- return -ENOMEM;
- }
- id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
- qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, id, us_info->protocol,
- uccs->us_pram_offset);
-
- uccs->us_pram = qe_muram_addr(uccs->us_pram_offset);
-
- /* Set UCC to slow type */
- ret = ucc_set_type(us_info->ucc_num, UCC_SPEED_TYPE_SLOW);
- if (ret) {
- printk(KERN_ERR "%s: cannot set UCC type", __func__);
- ucc_slow_free(uccs);
- return ret;
- }
-
- out_be16(&uccs->us_pram->mrblr, us_info->max_rx_buf_length);
-
- INIT_LIST_HEAD(&uccs->confQ);
-
- /* Allocate BDs. */
- uccs->rx_base_offset =
- qe_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd),
- QE_ALIGNMENT_OF_BD);
- if (IS_ERR_VALUE(uccs->rx_base_offset)) {
- printk(KERN_ERR "%s: cannot allocate %u RX BDs\n", __func__,
- us_info->rx_bd_ring_len);
- uccs->rx_base_offset = 0;
- ucc_slow_free(uccs);
- return -ENOMEM;
- }
-
- uccs->tx_base_offset =
- qe_muram_alloc(us_info->tx_bd_ring_len * sizeof(struct qe_bd),
- QE_ALIGNMENT_OF_BD);
- if (IS_ERR_VALUE(uccs->tx_base_offset)) {
- printk(KERN_ERR "%s: cannot allocate TX BDs", __func__);
- uccs->tx_base_offset = 0;
- ucc_slow_free(uccs);
- return -ENOMEM;
- }
-
- /* Init Tx bds */
- bd = uccs->confBd = uccs->tx_bd = qe_muram_addr(uccs->tx_base_offset);
- for (i = 0; i < us_info->tx_bd_ring_len - 1; i++) {
- /* clear bd buffer */
- out_be32(&bd->buf, 0);
- /* set bd status and length */
- out_be32((u32 *) bd, 0);
- bd++;
- }
- /* for last BD set Wrap bit */
- out_be32(&bd->buf, 0);
- out_be32((u32 *) bd, cpu_to_be32(T_W));
-
- /* Init Rx bds */
- bd = uccs->rx_bd = qe_muram_addr(uccs->rx_base_offset);
- for (i = 0; i < us_info->rx_bd_ring_len - 1; i++) {
- /* set bd status and length */
- out_be32((u32*)bd, 0);
- /* clear bd buffer */
- out_be32(&bd->buf, 0);
- bd++;
- }
- /* for last BD set Wrap bit */
- out_be32((u32*)bd, cpu_to_be32(R_W));
- out_be32(&bd->buf, 0);
-
- /* Set GUMR (For more details see the hardware spec.). */
- /* gumr_h */
- gumr = us_info->tcrc;
- if (us_info->cdp)
- gumr |= UCC_SLOW_GUMR_H_CDP;
- if (us_info->ctsp)
- gumr |= UCC_SLOW_GUMR_H_CTSP;
- if (us_info->cds)
- gumr |= UCC_SLOW_GUMR_H_CDS;
- if (us_info->ctss)
- gumr |= UCC_SLOW_GUMR_H_CTSS;
- if (us_info->tfl)
- gumr |= UCC_SLOW_GUMR_H_TFL;
- if (us_info->rfw)
- gumr |= UCC_SLOW_GUMR_H_RFW;
- if (us_info->txsy)
- gumr |= UCC_SLOW_GUMR_H_TXSY;
- if (us_info->rtsm)
- gumr |= UCC_SLOW_GUMR_H_RTSM;
- out_be32(&us_regs->gumr_h, gumr);
-
- /* gumr_l */
- gumr = us_info->tdcr | us_info->rdcr | us_info->tenc | us_info->renc |
- us_info->diag | us_info->mode;
- if (us_info->tci)
- gumr |= UCC_SLOW_GUMR_L_TCI;
- if (us_info->rinv)
- gumr |= UCC_SLOW_GUMR_L_RINV;
- if (us_info->tinv)
- gumr |= UCC_SLOW_GUMR_L_TINV;
- if (us_info->tend)
- gumr |= UCC_SLOW_GUMR_L_TEND;
- out_be32(&us_regs->gumr_l, gumr);
-
- /* Function code registers */
-
- /* if the data is in cachable memory, the 'global' */
- /* in the function code should be set. */
- uccs->us_pram->tbmr = UCC_BMR_BO_BE;
- uccs->us_pram->rbmr = UCC_BMR_BO_BE;
-
- /* rbase, tbase are offsets from MURAM base */
- out_be16(&uccs->us_pram->rbase, uccs->rx_base_offset);
- out_be16(&uccs->us_pram->tbase, uccs->tx_base_offset);
-
- /* Mux clocking */
- /* Grant Support */
- ucc_set_qe_mux_grant(us_info->ucc_num, us_info->grant_support);
- /* Breakpoint Support */
- ucc_set_qe_mux_bkpt(us_info->ucc_num, us_info->brkpt_support);
- /* Set Tsa or NMSI mode. */
- ucc_set_qe_mux_tsa(us_info->ucc_num, us_info->tsa);
- /* If NMSI (not Tsa), set Tx and Rx clock. */
- if (!us_info->tsa) {
- /* Rx clock routing */
- if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->rx_clock,
- COMM_DIR_RX)) {
- printk(KERN_ERR "%s: illegal value for RX clock\n",
- __func__);
- ucc_slow_free(uccs);
- return -EINVAL;
- }
- /* Tx clock routing */
- if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->tx_clock,
- COMM_DIR_TX)) {
- printk(KERN_ERR "%s: illegal value for TX clock\n",
- __func__);
- ucc_slow_free(uccs);
- return -EINVAL;
- }
- }
-
- /* Set interrupt mask register at UCC level. */
- out_be16(&us_regs->uccm, us_info->uccm_mask);
-
- /* First, clear anything pending at UCC level,
- * otherwise, old garbage may come through
- * as soon as the dam is opened. */
-
- /* Writing '1' clears */
- out_be16(&us_regs->ucce, 0xffff);
-
- /* Issue QE Init command */
- if (us_info->init_tx && us_info->init_rx)
- command = QE_INIT_TX_RX;
- else if (us_info->init_tx)
- command = QE_INIT_TX;
- else
- command = QE_INIT_RX; /* We know at least one is TRUE */
-
- qe_issue_cmd(command, id, us_info->protocol, 0);
-
- *uccs_ret = uccs;
- return 0;
-}
-EXPORT_SYMBOL(ucc_slow_init);
-
-void ucc_slow_free(struct ucc_slow_private * uccs)
-{
- if (!uccs)
- return;
-
- if (uccs->rx_base_offset)
- qe_muram_free(uccs->rx_base_offset);
-
- if (uccs->tx_base_offset)
- qe_muram_free(uccs->tx_base_offset);
-
- if (uccs->us_pram)
- qe_muram_free(uccs->us_pram_offset);
-
- if (uccs->us_regs)
- iounmap(uccs->us_regs);
-
- kfree(uccs);
-}
-EXPORT_SYMBOL(ucc_slow_free);
-
+++ /dev/null
-/*
- * QE USB routines
- *
- * Copyright 2006 Freescale Semiconductor, Inc.
- * Shlomi Gridish <gridish@freescale.com>
- * Jerry Huang <Chang-Ming.Huang@freescale.com>
- * Copyright (c) MontaVista Software, Inc. 2008.
- * Anton Vorontsov <avorontsov@ru.mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/export.h>
-#include <linux/io.h>
-#include <asm/immap_qe.h>
-#include <asm/qe.h>
-
-int qe_usb_clock_set(enum qe_clock clk, int rate)
-{
- struct qe_mux __iomem *mux = &qe_immr->qmx;
- unsigned long flags;
- u32 val;
-
- switch (clk) {
- case QE_CLK3: val = QE_CMXGCR_USBCS_CLK3; break;
- case QE_CLK5: val = QE_CMXGCR_USBCS_CLK5; break;
- case QE_CLK7: val = QE_CMXGCR_USBCS_CLK7; break;
- case QE_CLK9: val = QE_CMXGCR_USBCS_CLK9; break;
- case QE_CLK13: val = QE_CMXGCR_USBCS_CLK13; break;
- case QE_CLK17: val = QE_CMXGCR_USBCS_CLK17; break;
- case QE_CLK19: val = QE_CMXGCR_USBCS_CLK19; break;
- case QE_CLK21: val = QE_CMXGCR_USBCS_CLK21; break;
- case QE_BRG9: val = QE_CMXGCR_USBCS_BRG9; break;
- case QE_BRG10: val = QE_CMXGCR_USBCS_BRG10; break;
- default:
- pr_err("%s: requested unknown clock %d\n", __func__, clk);
- return -EINVAL;
- }
-
- if (qe_clock_is_brg(clk))
- qe_setbrg(clk, rate, 1);
-
- spin_lock_irqsave(&cmxgcr_lock, flags);
-
- clrsetbits_be32(&mux->cmxgcr, QE_CMXGCR_USBCS, val);
-
- spin_unlock_irqrestore(&cmxgcr_lock, flags);
-
- return 0;
-}
-EXPORT_SYMBOL(qe_usb_clock_set);
#include <asm/io.h>
#if IS_ENABLED(CONFIG_UCC_GETH)
-#include <asm/ucc.h> /* for ucc_set_qe_mux_mii_mng() */
+#include <soc/fsl/qe/ucc.h>
#endif
#include "gianfar.h"
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/immap_qe.h>
-#include <asm/qe.h>
-#include <asm/ucc.h>
-#include <asm/ucc_fast.h>
+#include <soc/fsl/qe/immap_qe.h>
+#include <soc/fsl/qe/qe.h>
+#include <soc/fsl/qe/ucc.h>
+#include <soc/fsl/qe/ucc_fast.h>
#include <asm/machdep.h>
#include "ucc_geth.h"
#include <linux/list.h>
#include <linux/if_ether.h>
-#include <asm/immap_qe.h>
-#include <asm/qe.h>
+#include <soc/fsl/qe/immap_qe.h>
+#include <soc/fsl/qe/qe.h>
-#include <asm/ucc.h>
-#include <asm/ucc_fast.h>
+#include <soc/fsl/qe/ucc.h>
+#include <soc/fsl/qe/ucc_fast.h>
#define DRV_DESC "QE UCC Gigabit Ethernet Controller"
#define DRV_NAME "ucc_geth"
menu "SOC (System On Chip) specific Drivers"
source "drivers/soc/brcmstb/Kconfig"
+source "drivers/soc/fsl/qe/Kconfig"
source "drivers/soc/mediatek/Kconfig"
source "drivers/soc/qcom/Kconfig"
source "drivers/soc/rockchip/Kconfig"
obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/
obj-$(CONFIG_MACH_DOVE) += dove/
+obj-y += fsl/
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
obj-$(CONFIG_ARCH_QCOM) += qcom/
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
--- /dev/null
+#
+# Makefile for the Linux Kernel SOC fsl specific device drivers
+#
+
+obj-$(CONFIG_QUICC_ENGINE) += qe/
+obj-$(CONFIG_CPM) += qe/
--- /dev/null
+#
+# QE Communication options
+#
+
+config QUICC_ENGINE
+ bool "Freescale QUICC Engine (QE) Support"
+ depends on FSL_SOC && PPC32
+ select GENERIC_ALLOCATOR
+ select CRC32
+ help
+ The QUICC Engine (QE) is a new generation of communications
+ coprocessors on Freescale embedded CPUs (akin to CPM in older chips).
+ Selecting this option means that you wish to build a kernel
+ for a machine with a QE coprocessor.
+
+config UCC_SLOW
+ bool
+ default y if SERIAL_QE
+ help
+ This option provides qe_lib support to UCC slow
+ protocols: UART, BISYNC, QMC
+
+config UCC_FAST
+ bool
+ default y if UCC_GETH
+ help
+ This option provides qe_lib support to UCC fast
+ protocols: HDLC, Ethernet, ATM, transparent
+
+config UCC
+ bool
+ default y if UCC_FAST || UCC_SLOW
+
+config QE_USB
+ bool
+ default y if USB_FSL_QE
+ help
+ QE USB Controller support
--- /dev/null
+#
+# Makefile for the linux ppc-specific parts of QE
+#
+obj-$(CONFIG_QUICC_ENGINE)+= qe.o qe_common.o qe_ic.o qe_io.o
+obj-$(CONFIG_CPM) += qe_common.o
+obj-$(CONFIG_UCC) += ucc.o
+obj-$(CONFIG_UCC_SLOW) += ucc_slow.o
+obj-$(CONFIG_UCC_FAST) += ucc_fast.o
+obj-$(CONFIG_QE_USB) += usb.o
+obj-$(CONFIG_QE_GPIO) += gpio.o
--- /dev/null
+/*
+ * QUICC Engine GPIOs
+ *
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <soc/fsl/qe/qe.h>
+
+struct qe_gpio_chip {
+ struct of_mm_gpio_chip mm_gc;
+ spinlock_t lock;
+
+ unsigned long pin_flags[QE_PIO_PINS];
+#define QE_PIN_REQUESTED 0
+
+ /* shadowed data register to clear/set bits safely */
+ u32 cpdata;
+
+ /* saved_regs used to restore dedicated functions */
+ struct qe_pio_regs saved_regs;
+};
+
+static inline struct qe_gpio_chip *
+to_qe_gpio_chip(struct of_mm_gpio_chip *mm_gc)
+{
+ return container_of(mm_gc, struct qe_gpio_chip, mm_gc);
+}
+
+static void qe_gpio_save_regs(struct of_mm_gpio_chip *mm_gc)
+{
+ struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
+ struct qe_pio_regs __iomem *regs = mm_gc->regs;
+
+ qe_gc->cpdata = in_be32(®s->cpdata);
+ qe_gc->saved_regs.cpdata = qe_gc->cpdata;
+ qe_gc->saved_regs.cpdir1 = in_be32(®s->cpdir1);
+ qe_gc->saved_regs.cpdir2 = in_be32(®s->cpdir2);
+ qe_gc->saved_regs.cppar1 = in_be32(®s->cppar1);
+ qe_gc->saved_regs.cppar2 = in_be32(®s->cppar2);
+ qe_gc->saved_regs.cpodr = in_be32(®s->cpodr);
+}
+
+static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct qe_pio_regs __iomem *regs = mm_gc->regs;
+ u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio);
+
+ return in_be32(®s->cpdata) & pin_mask;
+}
+
+static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
+ struct qe_pio_regs __iomem *regs = mm_gc->regs;
+ unsigned long flags;
+ u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio);
+
+ spin_lock_irqsave(&qe_gc->lock, flags);
+
+ if (val)
+ qe_gc->cpdata |= pin_mask;
+ else
+ qe_gc->cpdata &= ~pin_mask;
+
+ out_be32(®s->cpdata, qe_gc->cpdata);
+
+ spin_unlock_irqrestore(&qe_gc->lock, flags);
+}
+
+static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&qe_gc->lock, flags);
+
+ __par_io_config_pin(mm_gc->regs, gpio, QE_PIO_DIR_IN, 0, 0, 0);
+
+ spin_unlock_irqrestore(&qe_gc->lock, flags);
+
+ return 0;
+}
+
+static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
+ unsigned long flags;
+
+ qe_gpio_set(gc, gpio, val);
+
+ spin_lock_irqsave(&qe_gc->lock, flags);
+
+ __par_io_config_pin(mm_gc->regs, gpio, QE_PIO_DIR_OUT, 0, 0, 0);
+
+ spin_unlock_irqrestore(&qe_gc->lock, flags);
+
+ return 0;
+}
+
+struct qe_pin {
+ /*
+ * The qe_gpio_chip name is unfortunate, we should change that to
+ * something like qe_pio_controller. Someday.
+ */
+ struct qe_gpio_chip *controller;
+ int num;
+};
+
+/**
+ * qe_pin_request - Request a QE pin
+ * @np: device node to get a pin from
+ * @index: index of a pin in the device tree
+ * Context: non-atomic
+ *
+ * This function return qe_pin so that you could use it with the rest of
+ * the QE Pin Multiplexing API.
+ */
+struct qe_pin *qe_pin_request(struct device_node *np, int index)
+{
+ struct qe_pin *qe_pin;
+ struct gpio_chip *gc;
+ struct of_mm_gpio_chip *mm_gc;
+ struct qe_gpio_chip *qe_gc;
+ int err;
+ unsigned long flags;
+
+ qe_pin = kzalloc(sizeof(*qe_pin), GFP_KERNEL);
+ if (!qe_pin) {
+ pr_debug("%s: can't allocate memory\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ err = of_get_gpio(np, index);
+ if (err < 0)
+ goto err0;
+ gc = gpio_to_chip(err);
+ if (WARN_ON(!gc))
+ goto err0;
+
+ if (!of_device_is_compatible(gc->of_node, "fsl,mpc8323-qe-pario-bank")) {
+ pr_debug("%s: tried to get a non-qe pin\n", __func__);
+ err = -EINVAL;
+ goto err0;
+ }
+
+ mm_gc = to_of_mm_gpio_chip(gc);
+ qe_gc = to_qe_gpio_chip(mm_gc);
+
+ spin_lock_irqsave(&qe_gc->lock, flags);
+
+ err -= gc->base;
+ if (test_and_set_bit(QE_PIN_REQUESTED, &qe_gc->pin_flags[err]) == 0) {
+ qe_pin->controller = qe_gc;
+ qe_pin->num = err;
+ err = 0;
+ } else {
+ err = -EBUSY;
+ }
+
+ spin_unlock_irqrestore(&qe_gc->lock, flags);
+
+ if (!err)
+ return qe_pin;
+err0:
+ kfree(qe_pin);
+ pr_debug("%s failed with status %d\n", __func__, err);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL(qe_pin_request);
+
+/**
+ * qe_pin_free - Free a pin
+ * @qe_pin: pointer to the qe_pin structure
+ * Context: any
+ *
+ * This function frees the qe_pin structure and makes a pin available
+ * for further qe_pin_request() calls.
+ */
+void qe_pin_free(struct qe_pin *qe_pin)
+{
+ struct qe_gpio_chip *qe_gc = qe_pin->controller;
+ unsigned long flags;
+ const int pin = qe_pin->num;
+
+ spin_lock_irqsave(&qe_gc->lock, flags);
+ test_and_clear_bit(QE_PIN_REQUESTED, &qe_gc->pin_flags[pin]);
+ spin_unlock_irqrestore(&qe_gc->lock, flags);
+
+ kfree(qe_pin);
+}
+EXPORT_SYMBOL(qe_pin_free);
+
+/**
+ * qe_pin_set_dedicated - Revert a pin to a dedicated peripheral function mode
+ * @qe_pin: pointer to the qe_pin structure
+ * Context: any
+ *
+ * This function resets a pin to a dedicated peripheral function that
+ * has been set up by the firmware.
+ */
+void qe_pin_set_dedicated(struct qe_pin *qe_pin)
+{
+ struct qe_gpio_chip *qe_gc = qe_pin->controller;
+ struct qe_pio_regs __iomem *regs = qe_gc->mm_gc.regs;
+ struct qe_pio_regs *sregs = &qe_gc->saved_regs;
+ int pin = qe_pin->num;
+ u32 mask1 = 1 << (QE_PIO_PINS - (pin + 1));
+ u32 mask2 = 0x3 << (QE_PIO_PINS - (pin % (QE_PIO_PINS / 2) + 1) * 2);
+ bool second_reg = pin > (QE_PIO_PINS / 2) - 1;
+ unsigned long flags;
+
+ spin_lock_irqsave(&qe_gc->lock, flags);
+
+ if (second_reg) {
+ clrsetbits_be32(®s->cpdir2, mask2, sregs->cpdir2 & mask2);
+ clrsetbits_be32(®s->cppar2, mask2, sregs->cppar2 & mask2);
+ } else {
+ clrsetbits_be32(®s->cpdir1, mask2, sregs->cpdir1 & mask2);
+ clrsetbits_be32(®s->cppar1, mask2, sregs->cppar1 & mask2);
+ }
+
+ if (sregs->cpdata & mask1)
+ qe_gc->cpdata |= mask1;
+ else
+ qe_gc->cpdata &= ~mask1;
+
+ out_be32(®s->cpdata, qe_gc->cpdata);
+ clrsetbits_be32(®s->cpodr, mask1, sregs->cpodr & mask1);
+
+ spin_unlock_irqrestore(&qe_gc->lock, flags);
+}
+EXPORT_SYMBOL(qe_pin_set_dedicated);
+
+/**
+ * qe_pin_set_gpio - Set a pin to the GPIO mode
+ * @qe_pin: pointer to the qe_pin structure
+ * Context: any
+ *
+ * This function sets a pin to the GPIO mode.
+ */
+void qe_pin_set_gpio(struct qe_pin *qe_pin)
+{
+ struct qe_gpio_chip *qe_gc = qe_pin->controller;
+ struct qe_pio_regs __iomem *regs = qe_gc->mm_gc.regs;
+ unsigned long flags;
+
+ spin_lock_irqsave(&qe_gc->lock, flags);
+
+ /* Let's make it input by default, GPIO API is able to change that. */
+ __par_io_config_pin(regs, qe_pin->num, QE_PIO_DIR_IN, 0, 0, 0);
+
+ spin_unlock_irqrestore(&qe_gc->lock, flags);
+}
+EXPORT_SYMBOL(qe_pin_set_gpio);
+
+static int __init qe_add_gpiochips(void)
+{
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, "fsl,mpc8323-qe-pario-bank") {
+ int ret;
+ struct qe_gpio_chip *qe_gc;
+ struct of_mm_gpio_chip *mm_gc;
+ struct gpio_chip *gc;
+
+ qe_gc = kzalloc(sizeof(*qe_gc), GFP_KERNEL);
+ if (!qe_gc) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ spin_lock_init(&qe_gc->lock);
+
+ mm_gc = &qe_gc->mm_gc;
+ gc = &mm_gc->gc;
+
+ mm_gc->save_regs = qe_gpio_save_regs;
+ gc->ngpio = QE_PIO_PINS;
+ gc->direction_input = qe_gpio_dir_in;
+ gc->direction_output = qe_gpio_dir_out;
+ gc->get = qe_gpio_get;
+ gc->set = qe_gpio_set;
+
+ ret = of_mm_gpiochip_add(np, mm_gc);
+ if (ret)
+ goto err;
+ continue;
+err:
+ pr_err("%s: registration failed with status %d\n",
+ np->full_name, ret);
+ kfree(qe_gc);
+ /* try others anyway */
+ }
+ return 0;
+}
+arch_initcall(qe_add_gpiochips);
--- /dev/null
+/*
+ * Copyright (C) 2006-2010 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Authors: Shlomi Gridish <gridish@freescale.com>
+ * Li Yang <leoli@freescale.com>
+ * Based on cpm2_common.c from Dan Malek (dmalek@jlc.net)
+ *
+ * Description:
+ * General Purpose functions for the global management of the
+ * QUICC Engine (QE).
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/crc32.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of_platform.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <soc/fsl/qe/immap_qe.h>
+#include <soc/fsl/qe/qe.h>
+#include <asm/prom.h>
+#include <asm/rheap.h>
+
+static void qe_snums_init(void);
+static int qe_sdma_init(void);
+
+static DEFINE_SPINLOCK(qe_lock);
+DEFINE_SPINLOCK(cmxgcr_lock);
+EXPORT_SYMBOL(cmxgcr_lock);
+
+/* QE snum state */
+enum qe_snum_state {
+ QE_SNUM_STATE_USED,
+ QE_SNUM_STATE_FREE
+};
+
+/* QE snum */
+struct qe_snum {
+ u8 num;
+ enum qe_snum_state state;
+};
+
+/* We allocate this here because it is used almost exclusively for
+ * the communication processor devices.
+ */
+struct qe_immap __iomem *qe_immr;
+EXPORT_SYMBOL(qe_immr);
+
+static struct qe_snum snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */
+static unsigned int qe_num_of_snum;
+
+static phys_addr_t qebase = -1;
+
+phys_addr_t get_qe_base(void)
+{
+ struct device_node *qe;
+ int size;
+ const u32 *prop;
+
+ if (qebase != -1)
+ return qebase;
+
+ qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
+ if (!qe) {
+ qe = of_find_node_by_type(NULL, "qe");
+ if (!qe)
+ return qebase;
+ }
+
+ prop = of_get_property(qe, "reg", &size);
+ if (prop && size >= sizeof(*prop))
+ qebase = of_translate_address(qe, prop);
+ of_node_put(qe);
+
+ return qebase;
+}
+
+EXPORT_SYMBOL(get_qe_base);
+
+void qe_reset(void)
+{
+ if (qe_immr == NULL)
+ qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE);
+
+ qe_snums_init();
+
+ qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
+ QE_CR_PROTOCOL_UNSPECIFIED, 0);
+
+ /* Reclaim the MURAM memory for our use. */
+ qe_muram_init();
+
+ if (qe_sdma_init())
+ panic("sdma init failed!");
+}
+
+int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input)
+{
+ unsigned long flags;
+ u8 mcn_shift = 0, dev_shift = 0;
+ u32 ret;
+
+ spin_lock_irqsave(&qe_lock, flags);
+ if (cmd == QE_RESET) {
+ out_be32(&qe_immr->cp.cecr, (u32) (cmd | QE_CR_FLG));
+ } else {
+ if (cmd == QE_ASSIGN_PAGE) {
+ /* Here device is the SNUM, not sub-block */
+ dev_shift = QE_CR_SNUM_SHIFT;
+ } else if (cmd == QE_ASSIGN_RISC) {
+ /* Here device is the SNUM, and mcnProtocol is
+ * e_QeCmdRiscAssignment value */
+ dev_shift = QE_CR_SNUM_SHIFT;
+ mcn_shift = QE_CR_MCN_RISC_ASSIGN_SHIFT;
+ } else {
+ if (device == QE_CR_SUBBLOCK_USB)
+ mcn_shift = QE_CR_MCN_USB_SHIFT;
+ else
+ mcn_shift = QE_CR_MCN_NORMAL_SHIFT;
+ }
+
+ out_be32(&qe_immr->cp.cecdr, cmd_input);
+ out_be32(&qe_immr->cp.cecr,
+ (cmd | QE_CR_FLG | ((u32) device << dev_shift) | (u32)
+ mcn_protocol << mcn_shift));
+ }
+
+ /* wait for the QE_CR_FLG to clear */
+ ret = spin_event_timeout((in_be32(&qe_immr->cp.cecr) & QE_CR_FLG) == 0,
+ 100, 0);
+ /* On timeout (e.g. failure), the expression will be false (ret == 0),
+ otherwise it will be true (ret == 1). */
+ spin_unlock_irqrestore(&qe_lock, flags);
+
+ return ret == 1;
+}
+EXPORT_SYMBOL(qe_issue_cmd);
+
+/* Set a baud rate generator. This needs lots of work. There are
+ * 16 BRGs, which can be connected to the QE channels or output
+ * as clocks. The BRGs are in two different block of internal
+ * memory mapped space.
+ * The BRG clock is the QE clock divided by 2.
+ * It was set up long ago during the initial boot phase and is
+ * is given to us.
+ * Baud rate clocks are zero-based in the driver code (as that maps
+ * to port numbers). Documentation uses 1-based numbering.
+ */
+static unsigned int brg_clk = 0;
+
+unsigned int qe_get_brg_clk(void)
+{
+ struct device_node *qe;
+ int size;
+ const u32 *prop;
+
+ if (brg_clk)
+ return brg_clk;
+
+ qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
+ if (!qe) {
+ qe = of_find_node_by_type(NULL, "qe");
+ if (!qe)
+ return brg_clk;
+ }
+
+ prop = of_get_property(qe, "brg-frequency", &size);
+ if (prop && size == sizeof(*prop))
+ brg_clk = *prop;
+
+ of_node_put(qe);
+
+ return brg_clk;
+}
+EXPORT_SYMBOL(qe_get_brg_clk);
+
+/* Program the BRG to the given sampling rate and multiplier
+ *
+ * @brg: the BRG, QE_BRG1 - QE_BRG16
+ * @rate: the desired sampling rate
+ * @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or
+ * GUMR_L[TDCR]. E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01,
+ * then 'multiplier' should be 8.
+ */
+int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
+{
+ u32 divisor, tempval;
+ u32 div16 = 0;
+
+ if ((brg < QE_BRG1) || (brg > QE_BRG16))
+ return -EINVAL;
+
+ divisor = qe_get_brg_clk() / (rate * multiplier);
+
+ if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
+ div16 = QE_BRGC_DIV16;
+ divisor /= 16;
+ }
+
+ /* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says
+ that the BRG divisor must be even if you're not using divide-by-16
+ mode. */
+ if (!div16 && (divisor & 1) && (divisor > 3))
+ divisor++;
+
+ tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
+ QE_BRGC_ENABLE | div16;
+
+ out_be32(&qe_immr->brg.brgc[brg - QE_BRG1], tempval);
+
+ return 0;
+}
+EXPORT_SYMBOL(qe_setbrg);
+
+/* Convert a string to a QE clock source enum
+ *
+ * This function takes a string, typically from a property in the device
+ * tree, and returns the corresponding "enum qe_clock" value.
+*/
+enum qe_clock qe_clock_source(const char *source)
+{
+ unsigned int i;
+
+ if (strcasecmp(source, "none") == 0)
+ return QE_CLK_NONE;
+
+ if (strncasecmp(source, "brg", 3) == 0) {
+ i = simple_strtoul(source + 3, NULL, 10);
+ if ((i >= 1) && (i <= 16))
+ return (QE_BRG1 - 1) + i;
+ else
+ return QE_CLK_DUMMY;
+ }
+
+ if (strncasecmp(source, "clk", 3) == 0) {
+ i = simple_strtoul(source + 3, NULL, 10);
+ if ((i >= 1) && (i <= 24))
+ return (QE_CLK1 - 1) + i;
+ else
+ return QE_CLK_DUMMY;
+ }
+
+ return QE_CLK_DUMMY;
+}
+EXPORT_SYMBOL(qe_clock_source);
+
+/* Initialize SNUMs (thread serial numbers) according to
+ * QE Module Control chapter, SNUM table
+ */
+static void qe_snums_init(void)
+{
+ int i;
+ static const u8 snum_init_76[] = {
+ 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
+ 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
+ 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
+ 0xD8, 0xD9, 0xE8, 0xE9, 0x44, 0x45, 0x4C, 0x4D,
+ 0x54, 0x55, 0x5C, 0x5D, 0x64, 0x65, 0x6C, 0x6D,
+ 0x74, 0x75, 0x7C, 0x7D, 0x84, 0x85, 0x8C, 0x8D,
+ 0x94, 0x95, 0x9C, 0x9D, 0xA4, 0xA5, 0xAC, 0xAD,
+ 0xB4, 0xB5, 0xBC, 0xBD, 0xC4, 0xC5, 0xCC, 0xCD,
+ 0xD4, 0xD5, 0xDC, 0xDD, 0xE4, 0xE5, 0xEC, 0xED,
+ 0xF4, 0xF5, 0xFC, 0xFD,
+ };
+ static const u8 snum_init_46[] = {
+ 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
+ 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
+ 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
+ 0xD8, 0xD9, 0xE8, 0xE9, 0x08, 0x09, 0x18, 0x19,
+ 0x28, 0x29, 0x38, 0x39, 0x48, 0x49, 0x58, 0x59,
+ 0x68, 0x69, 0x78, 0x79, 0x80, 0x81,
+ };
+ static const u8 *snum_init;
+
+ qe_num_of_snum = qe_get_num_of_snums();
+
+ if (qe_num_of_snum == 76)
+ snum_init = snum_init_76;
+ else
+ snum_init = snum_init_46;
+
+ for (i = 0; i < qe_num_of_snum; i++) {
+ snums[i].num = snum_init[i];
+ snums[i].state = QE_SNUM_STATE_FREE;
+ }
+}
+
+int qe_get_snum(void)
+{
+ unsigned long flags;
+ int snum = -EBUSY;
+ int i;
+
+ spin_lock_irqsave(&qe_lock, flags);
+ for (i = 0; i < qe_num_of_snum; i++) {
+ if (snums[i].state == QE_SNUM_STATE_FREE) {
+ snums[i].state = QE_SNUM_STATE_USED;
+ snum = snums[i].num;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&qe_lock, flags);
+
+ return snum;
+}
+EXPORT_SYMBOL(qe_get_snum);
+
+void qe_put_snum(u8 snum)
+{
+ int i;
+
+ for (i = 0; i < qe_num_of_snum; i++) {
+ if (snums[i].num == snum) {
+ snums[i].state = QE_SNUM_STATE_FREE;
+ break;
+ }
+ }
+}
+EXPORT_SYMBOL(qe_put_snum);
+
+static int qe_sdma_init(void)
+{
+ struct sdma __iomem *sdma = &qe_immr->sdma;
+ static unsigned long sdma_buf_offset = (unsigned long)-ENOMEM;
+
+ if (!sdma)
+ return -ENODEV;
+
+ /* allocate 2 internal temporary buffers (512 bytes size each) for
+ * the SDMA */
+ if (IS_ERR_VALUE(sdma_buf_offset)) {
+ sdma_buf_offset = qe_muram_alloc(512 * 2, 4096);
+ if (IS_ERR_VALUE(sdma_buf_offset))
+ return -ENOMEM;
+ }
+
+ out_be32(&sdma->sdebcr, (u32) sdma_buf_offset & QE_SDEBCR_BA_MASK);
+ out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK |
+ (0x1 << QE_SDMR_CEN_SHIFT)));
+
+ return 0;
+}
+
+/* The maximum number of RISCs we support */
+#define MAX_QE_RISC 4
+
+/* Firmware information stored here for qe_get_firmware_info() */
+static struct qe_firmware_info qe_firmware_info;
+
+/*
+ * Set to 1 if QE firmware has been uploaded, and therefore
+ * qe_firmware_info contains valid data.
+ */
+static int qe_firmware_uploaded;
+
+/*
+ * Upload a QE microcode
+ *
+ * This function is a worker function for qe_upload_firmware(). It does
+ * the actual uploading of the microcode.
+ */
+static void qe_upload_microcode(const void *base,
+ const struct qe_microcode *ucode)
+{
+ const __be32 *code = base + be32_to_cpu(ucode->code_offset);
+ unsigned int i;
+
+ if (ucode->major || ucode->minor || ucode->revision)
+ printk(KERN_INFO "qe-firmware: "
+ "uploading microcode '%s' version %u.%u.%u\n",
+ ucode->id, ucode->major, ucode->minor, ucode->revision);
+ else
+ printk(KERN_INFO "qe-firmware: "
+ "uploading microcode '%s'\n", ucode->id);
+
+ /* Use auto-increment */
+ out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
+ QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
+
+ for (i = 0; i < be32_to_cpu(ucode->count); i++)
+ out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
+
+ /* Set I-RAM Ready Register */
+ out_be32(&qe_immr->iram.iready, be32_to_cpu(QE_IRAM_READY));
+}
+
+/*
+ * Upload a microcode to the I-RAM at a specific address.
+ *
+ * See Documentation/powerpc/qe_firmware.txt for information on QE microcode
+ * uploading.
+ *
+ * Currently, only version 1 is supported, so the 'version' field must be
+ * set to 1.
+ *
+ * The SOC model and revision are not validated, they are only displayed for
+ * informational purposes.
+ *
+ * 'calc_size' is the calculated size, in bytes, of the firmware structure and
+ * all of the microcode structures, minus the CRC.
+ *
+ * 'length' is the size that the structure says it is, including the CRC.
+ */
+int qe_upload_firmware(const struct qe_firmware *firmware)
+{
+ unsigned int i;
+ unsigned int j;
+ u32 crc;
+ size_t calc_size = sizeof(struct qe_firmware);
+ size_t length;
+ const struct qe_header *hdr;
+
+ if (!firmware) {
+ printk(KERN_ERR "qe-firmware: invalid pointer\n");
+ return -EINVAL;
+ }
+
+ hdr = &firmware->header;
+ length = be32_to_cpu(hdr->length);
+
+ /* Check the magic */
+ if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
+ (hdr->magic[2] != 'F')) {
+ printk(KERN_ERR "qe-firmware: not a microcode\n");
+ return -EPERM;
+ }
+
+ /* Check the version */
+ if (hdr->version != 1) {
+ printk(KERN_ERR "qe-firmware: unsupported version\n");
+ return -EPERM;
+ }
+
+ /* Validate some of the fields */
+ if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
+ printk(KERN_ERR "qe-firmware: invalid data\n");
+ return -EINVAL;
+ }
+
+ /* Validate the length and check if there's a CRC */
+ calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
+
+ for (i = 0; i < firmware->count; i++)
+ /*
+ * For situations where the second RISC uses the same microcode
+ * as the first, the 'code_offset' and 'count' fields will be
+ * zero, so it's okay to add those.
+ */
+ calc_size += sizeof(__be32) *
+ be32_to_cpu(firmware->microcode[i].count);
+
+ /* Validate the length */
+ if (length != calc_size + sizeof(__be32)) {
+ printk(KERN_ERR "qe-firmware: invalid length\n");
+ return -EPERM;
+ }
+
+ /* Validate the CRC */
+ crc = be32_to_cpu(*(__be32 *)((void *)firmware + calc_size));
+ if (crc != crc32(0, firmware, calc_size)) {
+ printk(KERN_ERR "qe-firmware: firmware CRC is invalid\n");
+ return -EIO;
+ }
+
+ /*
+ * If the microcode calls for it, split the I-RAM.
+ */
+ if (!firmware->split)
+ setbits16(&qe_immr->cp.cercr, QE_CP_CERCR_CIR);
+
+ if (firmware->soc.model)
+ printk(KERN_INFO
+ "qe-firmware: firmware '%s' for %u V%u.%u\n",
+ firmware->id, be16_to_cpu(firmware->soc.model),
+ firmware->soc.major, firmware->soc.minor);
+ else
+ printk(KERN_INFO "qe-firmware: firmware '%s'\n",
+ firmware->id);
+
+ /*
+ * The QE only supports one microcode per RISC, so clear out all the
+ * saved microcode information and put in the new.
+ */
+ memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
+ strlcpy(qe_firmware_info.id, firmware->id, sizeof(qe_firmware_info.id));
+ qe_firmware_info.extended_modes = firmware->extended_modes;
+ memcpy(qe_firmware_info.vtraps, firmware->vtraps,
+ sizeof(firmware->vtraps));
+
+ /* Loop through each microcode. */
+ for (i = 0; i < firmware->count; i++) {
+ const struct qe_microcode *ucode = &firmware->microcode[i];
+
+ /* Upload a microcode if it's present */
+ if (ucode->code_offset)
+ qe_upload_microcode(firmware, ucode);
+
+ /* Program the traps for this processor */
+ for (j = 0; j < 16; j++) {
+ u32 trap = be32_to_cpu(ucode->traps[j]);
+
+ if (trap)
+ out_be32(&qe_immr->rsp[i].tibcr[j], trap);
+ }
+
+ /* Enable traps */
+ out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
+ }
+
+ qe_firmware_uploaded = 1;
+
+ return 0;
+}
+EXPORT_SYMBOL(qe_upload_firmware);
+
+/*
+ * Get info on the currently-loaded firmware
+ *
+ * This function also checks the device tree to see if the boot loader has
+ * uploaded a firmware already.
+ */
+struct qe_firmware_info *qe_get_firmware_info(void)
+{
+ static int initialized;
+ struct property *prop;
+ struct device_node *qe;
+ struct device_node *fw = NULL;
+ const char *sprop;
+ unsigned int i;
+
+ /*
+ * If we haven't checked yet, and a driver hasn't uploaded a firmware
+ * yet, then check the device tree for information.
+ */
+ if (qe_firmware_uploaded)
+ return &qe_firmware_info;
+
+ if (initialized)
+ return NULL;
+
+ initialized = 1;
+
+ /*
+ * Newer device trees have an "fsl,qe" compatible property for the QE
+ * node, but we still need to support older device trees.
+ */
+ qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
+ if (!qe) {
+ qe = of_find_node_by_type(NULL, "qe");
+ if (!qe)
+ return NULL;
+ }
+
+ /* Find the 'firmware' child node */
+ for_each_child_of_node(qe, fw) {
+ if (strcmp(fw->name, "firmware") == 0)
+ break;
+ }
+
+ of_node_put(qe);
+
+ /* Did we find the 'firmware' node? */
+ if (!fw)
+ return NULL;
+
+ qe_firmware_uploaded = 1;
+
+ /* Copy the data into qe_firmware_info*/
+ sprop = of_get_property(fw, "id", NULL);
+ if (sprop)
+ strlcpy(qe_firmware_info.id, sprop,
+ sizeof(qe_firmware_info.id));
+
+ prop = of_find_property(fw, "extended-modes", NULL);
+ if (prop && (prop->length == sizeof(u64))) {
+ const u64 *iprop = prop->value;
+
+ qe_firmware_info.extended_modes = *iprop;
+ }
+
+ prop = of_find_property(fw, "virtual-traps", NULL);
+ if (prop && (prop->length == 32)) {
+ const u32 *iprop = prop->value;
+
+ for (i = 0; i < ARRAY_SIZE(qe_firmware_info.vtraps); i++)
+ qe_firmware_info.vtraps[i] = iprop[i];
+ }
+
+ of_node_put(fw);
+
+ return &qe_firmware_info;
+}
+EXPORT_SYMBOL(qe_get_firmware_info);
+
+unsigned int qe_get_num_of_risc(void)
+{
+ struct device_node *qe;
+ int size;
+ unsigned int num_of_risc = 0;
+ const u32 *prop;
+
+ qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
+ if (!qe) {
+ /* Older devices trees did not have an "fsl,qe"
+ * compatible property, so we need to look for
+ * the QE node by name.
+ */
+ qe = of_find_node_by_type(NULL, "qe");
+ if (!qe)
+ return num_of_risc;
+ }
+
+ prop = of_get_property(qe, "fsl,qe-num-riscs", &size);
+ if (prop && size == sizeof(*prop))
+ num_of_risc = *prop;
+
+ of_node_put(qe);
+
+ return num_of_risc;
+}
+EXPORT_SYMBOL(qe_get_num_of_risc);
+
+unsigned int qe_get_num_of_snums(void)
+{
+ struct device_node *qe;
+ int size;
+ unsigned int num_of_snums;
+ const u32 *prop;
+
+ num_of_snums = 28; /* The default number of snum for threads is 28 */
+ qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
+ if (!qe) {
+ /* Older devices trees did not have an "fsl,qe"
+ * compatible property, so we need to look for
+ * the QE node by name.
+ */
+ qe = of_find_node_by_type(NULL, "qe");
+ if (!qe)
+ return num_of_snums;
+ }
+
+ prop = of_get_property(qe, "fsl,qe-num-snums", &size);
+ if (prop && size == sizeof(*prop)) {
+ num_of_snums = *prop;
+ if ((num_of_snums < 28) || (num_of_snums > QE_NUM_OF_SNUM)) {
+ /* No QE ever has fewer than 28 SNUMs */
+ pr_err("QE: number of snum is invalid\n");
+ of_node_put(qe);
+ return -EINVAL;
+ }
+ }
+
+ of_node_put(qe);
+
+ return num_of_snums;
+}
+EXPORT_SYMBOL(qe_get_num_of_snums);
+
+static int __init qe_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,qe");
+ if (!np)
+ return -ENODEV;
+ qe_reset();
+ of_node_put(np);
+ return 0;
+}
+subsys_initcall(qe_init);
+
+#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx)
+static int qe_resume(struct platform_device *ofdev)
+{
+ if (!qe_alive_during_sleep())
+ qe_reset();
+ return 0;
+}
+
+static int qe_probe(struct platform_device *ofdev)
+{
+ return 0;
+}
+
+static const struct of_device_id qe_ids[] = {
+ { .compatible = "fsl,qe", },
+ { },
+};
+
+static struct platform_driver qe_driver = {
+ .driver = {
+ .name = "fsl-qe",
+ .of_match_table = qe_ids,
+ },
+ .probe = qe_probe,
+ .resume = qe_resume,
+};
+
+static int __init qe_drv_init(void)
+{
+ return platform_driver_register(&qe_driver);
+}
+device_initcall(qe_drv_init);
+#endif /* defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx) */
--- /dev/null
+/*
+ * Common CPM code
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * Copyright 2007-2008,2010 Freescale Semiconductor, Inc.
+ *
+ * Some parts derived from commproc.c/cpm2_common.c, which is:
+ * Copyright (c) 1997 Dan error_act (dmalek@jlc.net)
+ * Copyright (c) 1999-2001 Dan Malek <dan@embeddedalley.com>
+ * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
+ * 2006 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ */
+#include <linux/genalloc.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/of_device.h>
+#include <linux/spinlock.h>
+#include <linux/export.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <soc/fsl/qe/qe.h>
+
+static struct gen_pool *muram_pool;
+static spinlock_t cpm_muram_lock;
+static u8 __iomem *muram_vbase;
+static phys_addr_t muram_pbase;
+
+struct muram_block {
+ struct list_head head;
+ unsigned long start;
+ int size;
+};
+
+static LIST_HEAD(muram_block_list);
+
+/* max address size we deal with */
+#define OF_MAX_ADDR_CELLS 4
+#define GENPOOL_OFFSET (4096 * 8)
+
+int cpm_muram_init(void)
+{
+ struct device_node *np;
+ struct resource r;
+ u32 zero[OF_MAX_ADDR_CELLS] = {};
+ resource_size_t max = 0;
+ int i = 0;
+ int ret = 0;
+
+ if (muram_pbase)
+ return 0;
+
+ spin_lock_init(&cpm_muram_lock);
+ np = of_find_compatible_node(NULL, NULL, "fsl,cpm-muram-data");
+ if (!np) {
+ /* try legacy bindings */
+ np = of_find_node_by_name(NULL, "data-only");
+ if (!np) {
+ pr_err("Cannot find CPM muram data node");
+ ret = -ENODEV;
+ goto out_muram;
+ }
+ }
+
+ muram_pool = gen_pool_create(0, -1);
+ muram_pbase = of_translate_address(np, zero);
+ if (muram_pbase == (phys_addr_t)OF_BAD_ADDR) {
+ pr_err("Cannot translate zero through CPM muram node");
+ ret = -ENODEV;
+ goto out_pool;
+ }
+
+ while (of_address_to_resource(np, i++, &r) == 0) {
+ if (r.end > max)
+ max = r.end;
+ ret = gen_pool_add(muram_pool, r.start - muram_pbase +
+ GENPOOL_OFFSET, resource_size(&r), -1);
+ if (ret) {
+ pr_err("QE: couldn't add muram to pool!\n");
+ goto out_pool;
+ }
+ }
+
+ muram_vbase = ioremap(muram_pbase, max - muram_pbase + 1);
+ if (!muram_vbase) {
+ pr_err("Cannot map QE muram");
+ ret = -ENOMEM;
+ goto out_pool;
+ }
+ goto out_muram;
+out_pool:
+ gen_pool_destroy(muram_pool);
+out_muram:
+ of_node_put(np);
+ return ret;
+}
+
+/*
+ * cpm_muram_alloc - allocate the requested size worth of multi-user ram
+ * @size: number of bytes to allocate
+ * @align: requested alignment, in bytes
+ *
+ * This function returns an offset into the muram area.
+ * Use cpm_dpram_addr() to get the virtual address of the area.
+ * Use cpm_muram_free() to free the allocation.
+ */
+unsigned long cpm_muram_alloc(unsigned long size, unsigned long align)
+{
+ unsigned long start;
+ unsigned long flags;
+ struct genpool_data_align muram_pool_data;
+
+ spin_lock_irqsave(&cpm_muram_lock, flags);
+ muram_pool_data.align = align;
+ start = cpm_muram_alloc_common(size, gen_pool_first_fit_align,
+ &muram_pool_data);
+ spin_unlock_irqrestore(&cpm_muram_lock, flags);
+ return start;
+}
+EXPORT_SYMBOL(cpm_muram_alloc);
+
+/**
+ * cpm_muram_free - free a chunk of multi-user ram
+ * @offset: The beginning of the chunk as returned by cpm_muram_alloc().
+ */
+int cpm_muram_free(unsigned long offset)
+{
+ unsigned long flags;
+ int size;
+ struct muram_block *tmp;
+
+ size = 0;
+ spin_lock_irqsave(&cpm_muram_lock, flags);
+ list_for_each_entry(tmp, &muram_block_list, head) {
+ if (tmp->start == offset) {
+ size = tmp->size;
+ list_del(&tmp->head);
+ kfree(tmp);
+ break;
+ }
+ }
+ gen_pool_free(muram_pool, offset + GENPOOL_OFFSET, size);
+ spin_unlock_irqrestore(&cpm_muram_lock, flags);
+ return size;
+}
+EXPORT_SYMBOL(cpm_muram_free);
+
+/*
+ * cpm_muram_alloc_fixed - reserve a specific region of multi-user ram
+ * @offset: offset of allocation start address
+ * @size: number of bytes to allocate
+ * This function returns an offset into the muram area
+ * Use cpm_dpram_addr() to get the virtual address of the area.
+ * Use cpm_muram_free() to free the allocation.
+ */
+unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size)
+{
+ unsigned long start;
+ unsigned long flags;
+ struct genpool_data_fixed muram_pool_data_fixed;
+
+ spin_lock_irqsave(&cpm_muram_lock, flags);
+ muram_pool_data_fixed.offset = offset + GENPOOL_OFFSET;
+ start = cpm_muram_alloc_common(size, gen_pool_fixed_alloc,
+ &muram_pool_data_fixed);
+ spin_unlock_irqrestore(&cpm_muram_lock, flags);
+ return start;
+}
+EXPORT_SYMBOL(cpm_muram_alloc_fixed);
+
+/*
+ * cpm_muram_alloc_common - cpm_muram_alloc common code
+ * @size: number of bytes to allocate
+ * @algo: algorithm for alloc.
+ * @data: data for genalloc's algorithm.
+ *
+ * This function returns an offset into the muram area.
+ */
+unsigned long cpm_muram_alloc_common(unsigned long size, genpool_algo_t algo,
+ void *data)
+{
+ struct muram_block *entry;
+ unsigned long start;
+
+ start = gen_pool_alloc_algo(muram_pool, size, algo, data);
+ if (!start)
+ goto out2;
+ start = start - GENPOOL_OFFSET;
+ memset_io(cpm_muram_addr(start), 0, size);
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ goto out1;
+ entry->start = start;
+ entry->size = size;
+ list_add(&entry->head, &muram_block_list);
+
+ return start;
+out1:
+ gen_pool_free(muram_pool, start, size);
+out2:
+ return (unsigned long)-ENOMEM;
+}
+
+/**
+ * cpm_muram_addr - turn a muram offset into a virtual address
+ * @offset: muram offset to convert
+ */
+void __iomem *cpm_muram_addr(unsigned long offset)
+{
+ return muram_vbase + offset;
+}
+EXPORT_SYMBOL(cpm_muram_addr);
+
+unsigned long cpm_muram_offset(void __iomem *addr)
+{
+ return addr - (void __iomem *)muram_vbase;
+}
+EXPORT_SYMBOL(cpm_muram_offset);
+
+/**
+ * cpm_muram_dma - turn a muram virtual address into a DMA address
+ * @offset: virtual address from cpm_muram_addr() to convert
+ */
+dma_addr_t cpm_muram_dma(void __iomem *addr)
+{
+ return muram_pbase + ((u8 __iomem *)addr - muram_vbase);
+}
+EXPORT_SYMBOL(cpm_muram_dma);
--- /dev/null
+/*
+ * arch/powerpc/sysdev/qe_lib/qe_ic.c
+ *
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Li Yang <leoli@freescale.com>
+ * Based on code from Shlomi Gridish <gridish@freescale.com>
+ *
+ * QUICC ENGINE Interrupt Controller
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <soc/fsl/qe/qe_ic.h>
+
+#include "qe_ic.h"
+
+static DEFINE_RAW_SPINLOCK(qe_ic_lock);
+
+static struct qe_ic_info qe_ic_info[] = {
+ [1] = {
+ .mask = 0x00008000,
+ .mask_reg = QEIC_CIMR,
+ .pri_code = 0,
+ .pri_reg = QEIC_CIPWCC,
+ },
+ [2] = {
+ .mask = 0x00004000,
+ .mask_reg = QEIC_CIMR,
+ .pri_code = 1,
+ .pri_reg = QEIC_CIPWCC,
+ },
+ [3] = {
+ .mask = 0x00002000,
+ .mask_reg = QEIC_CIMR,
+ .pri_code = 2,
+ .pri_reg = QEIC_CIPWCC,
+ },
+ [10] = {
+ .mask = 0x00000040,
+ .mask_reg = QEIC_CIMR,
+ .pri_code = 1,
+ .pri_reg = QEIC_CIPZCC,
+ },
+ [11] = {
+ .mask = 0x00000020,
+ .mask_reg = QEIC_CIMR,
+ .pri_code = 2,
+ .pri_reg = QEIC_CIPZCC,
+ },
+ [12] = {
+ .mask = 0x00000010,
+ .mask_reg = QEIC_CIMR,
+ .pri_code = 3,
+ .pri_reg = QEIC_CIPZCC,
+ },
+ [13] = {
+ .mask = 0x00000008,
+ .mask_reg = QEIC_CIMR,
+ .pri_code = 4,
+ .pri_reg = QEIC_CIPZCC,
+ },
+ [14] = {
+ .mask = 0x00000004,
+ .mask_reg = QEIC_CIMR,
+ .pri_code = 5,
+ .pri_reg = QEIC_CIPZCC,
+ },
+ [15] = {
+ .mask = 0x00000002,
+ .mask_reg = QEIC_CIMR,
+ .pri_code = 6,
+ .pri_reg = QEIC_CIPZCC,
+ },
+ [20] = {
+ .mask = 0x10000000,
+ .mask_reg = QEIC_CRIMR,
+ .pri_code = 3,
+ .pri_reg = QEIC_CIPRTA,
+ },
+ [25] = {
+ .mask = 0x00800000,
+ .mask_reg = QEIC_CRIMR,
+ .pri_code = 0,
+ .pri_reg = QEIC_CIPRTB,
+ },
+ [26] = {
+ .mask = 0x00400000,
+ .mask_reg = QEIC_CRIMR,
+ .pri_code = 1,
+ .pri_reg = QEIC_CIPRTB,
+ },
+ [27] = {
+ .mask = 0x00200000,
+ .mask_reg = QEIC_CRIMR,
+ .pri_code = 2,
+ .pri_reg = QEIC_CIPRTB,
+ },
+ [28] = {
+ .mask = 0x00100000,
+ .mask_reg = QEIC_CRIMR,
+ .pri_code = 3,
+ .pri_reg = QEIC_CIPRTB,
+ },
+ [32] = {
+ .mask = 0x80000000,
+ .mask_reg = QEIC_CIMR,
+ .pri_code = 0,
+ .pri_reg = QEIC_CIPXCC,
+ },
+ [33] = {
+ .mask = 0x40000000,
+ .mask_reg = QEIC_CIMR,
+ .pri_code = 1,
+ .pri_reg = QEIC_CIPXCC,
+ },
+ [34] = {
+ .mask = 0x20000000,
+ .mask_reg = QEIC_CIMR,
+ .pri_code = 2,
+ .pri_reg = QEIC_CIPXCC,
+ },
+ [35] = {
+ .mask = 0x10000000,
+ .mask_reg = QEIC_CIMR,
+ .pri_code = 3,
+ .pri_reg = QEIC_CIPXCC,
+ },
+ [36] = {
+ .mask = 0x08000000,
+ .mask_reg = QEIC_CIMR,
+ .pri_code = 4,
+ .pri_reg = QEIC_CIPXCC,
+ },
+ [40] = {
+ .mask = 0x00800000,
+ .mask_reg = QEIC_CIMR,
+ .pri_code = 0,
+ .pri_reg = QEIC_CIPYCC,
+ },
+ [41] = {
+ .mask = 0x00400000,
+ .mask_reg = QEIC_CIMR,
+ .pri_code = 1,
+ .pri_reg = QEIC_CIPYCC,
+ },
+ [42] = {
+ .mask = 0x00200000,
+ .mask_reg = QEIC_CIMR,
+ .pri_code = 2,
+ .pri_reg = QEIC_CIPYCC,
+ },
+ [43] = {
+ .mask = 0x00100000,
+ .mask_reg = QEIC_CIMR,
+ .pri_code = 3,
+ .pri_reg = QEIC_CIPYCC,
+ },
+};
+
+static inline u32 qe_ic_read(volatile __be32 __iomem * base, unsigned int reg)
+{
+ return in_be32(base + (reg >> 2));
+}
+
+static inline void qe_ic_write(volatile __be32 __iomem * base, unsigned int reg,
+ u32 value)
+{
+ out_be32(base + (reg >> 2), value);
+}
+
+static inline struct qe_ic *qe_ic_from_irq(unsigned int virq)
+{
+ return irq_get_chip_data(virq);
+}
+
+static inline struct qe_ic *qe_ic_from_irq_data(struct irq_data *d)
+{
+ return irq_data_get_irq_chip_data(d);
+}
+
+static void qe_ic_unmask_irq(struct irq_data *d)
+{
+ struct qe_ic *qe_ic = qe_ic_from_irq_data(d);
+ unsigned int src = irqd_to_hwirq(d);
+ unsigned long flags;
+ u32 temp;
+
+ raw_spin_lock_irqsave(&qe_ic_lock, flags);
+
+ temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg);
+ qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,
+ temp | qe_ic_info[src].mask);
+
+ raw_spin_unlock_irqrestore(&qe_ic_lock, flags);
+}
+
+static void qe_ic_mask_irq(struct irq_data *d)
+{
+ struct qe_ic *qe_ic = qe_ic_from_irq_data(d);
+ unsigned int src = irqd_to_hwirq(d);
+ unsigned long flags;
+ u32 temp;
+
+ raw_spin_lock_irqsave(&qe_ic_lock, flags);
+
+ temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg);
+ qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,
+ temp & ~qe_ic_info[src].mask);
+
+ /* Flush the above write before enabling interrupts; otherwise,
+ * spurious interrupts will sometimes happen. To be 100% sure
+ * that the write has reached the device before interrupts are
+ * enabled, the mask register would have to be read back; however,
+ * this is not required for correctness, only to avoid wasting
+ * time on a large number of spurious interrupts. In testing,
+ * a sync reduced the observed spurious interrupts to zero.
+ */
+ mb();
+
+ raw_spin_unlock_irqrestore(&qe_ic_lock, flags);
+}
+
+static struct irq_chip qe_ic_irq_chip = {
+ .name = "QEIC",
+ .irq_unmask = qe_ic_unmask_irq,
+ .irq_mask = qe_ic_mask_irq,
+ .irq_mask_ack = qe_ic_mask_irq,
+};
+
+static int qe_ic_host_match(struct irq_domain *h, struct device_node *node,
+ enum irq_domain_bus_token bus_token)
+{
+ /* Exact match, unless qe_ic node is NULL */
+ struct device_node *of_node = irq_domain_get_of_node(h);
+ return of_node == NULL || of_node == node;
+}
+
+static int qe_ic_host_map(struct irq_domain *h, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ struct qe_ic *qe_ic = h->host_data;
+ struct irq_chip *chip;
+
+ if (qe_ic_info[hw].mask == 0) {
+ printk(KERN_ERR "Can't map reserved IRQ\n");
+ return -EINVAL;
+ }
+ /* Default chip */
+ chip = &qe_ic->hc_irq;
+
+ irq_set_chip_data(virq, qe_ic);
+ irq_set_status_flags(virq, IRQ_LEVEL);
+
+ irq_set_chip_and_handler(virq, chip, handle_level_irq);
+
+ return 0;
+}
+
+static const struct irq_domain_ops qe_ic_host_ops = {
+ .match = qe_ic_host_match,
+ .map = qe_ic_host_map,
+ .xlate = irq_domain_xlate_onetwocell,
+};
+
+/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
+unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic)
+{
+ int irq;
+
+ BUG_ON(qe_ic == NULL);
+
+ /* get the interrupt source vector. */
+ irq = qe_ic_read(qe_ic->regs, QEIC_CIVEC) >> 26;
+
+ if (irq == 0)
+ return NO_IRQ;
+
+ return irq_linear_revmap(qe_ic->irqhost, irq);
+}
+
+/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
+unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic)
+{
+ int irq;
+
+ BUG_ON(qe_ic == NULL);
+
+ /* get the interrupt source vector. */
+ irq = qe_ic_read(qe_ic->regs, QEIC_CHIVEC) >> 26;
+
+ if (irq == 0)
+ return NO_IRQ;
+
+ return irq_linear_revmap(qe_ic->irqhost, irq);
+}
+
+void __init qe_ic_init(struct device_node *node, unsigned int flags,
+ void (*low_handler)(struct irq_desc *desc),
+ void (*high_handler)(struct irq_desc *desc))
+{
+ struct qe_ic *qe_ic;
+ struct resource res;
+ u32 temp = 0, ret, high_active = 0;
+
+ ret = of_address_to_resource(node, 0, &res);
+ if (ret)
+ return;
+
+ qe_ic = kzalloc(sizeof(*qe_ic), GFP_KERNEL);
+ if (qe_ic == NULL)
+ return;
+
+ qe_ic->irqhost = irq_domain_add_linear(node, NR_QE_IC_INTS,
+ &qe_ic_host_ops, qe_ic);
+ if (qe_ic->irqhost == NULL) {
+ kfree(qe_ic);
+ return;
+ }
+
+ qe_ic->regs = ioremap(res.start, resource_size(&res));
+
+ qe_ic->hc_irq = qe_ic_irq_chip;
+
+ qe_ic->virq_high = irq_of_parse_and_map(node, 0);
+ qe_ic->virq_low = irq_of_parse_and_map(node, 1);
+
+ if (qe_ic->virq_low == NO_IRQ) {
+ printk(KERN_ERR "Failed to map QE_IC low IRQ\n");
+ kfree(qe_ic);
+ return;
+ }
+
+ /* default priority scheme is grouped. If spread mode is */
+ /* required, configure cicr accordingly. */
+ if (flags & QE_IC_SPREADMODE_GRP_W)
+ temp |= CICR_GWCC;
+ if (flags & QE_IC_SPREADMODE_GRP_X)
+ temp |= CICR_GXCC;
+ if (flags & QE_IC_SPREADMODE_GRP_Y)
+ temp |= CICR_GYCC;
+ if (flags & QE_IC_SPREADMODE_GRP_Z)
+ temp |= CICR_GZCC;
+ if (flags & QE_IC_SPREADMODE_GRP_RISCA)
+ temp |= CICR_GRTA;
+ if (flags & QE_IC_SPREADMODE_GRP_RISCB)
+ temp |= CICR_GRTB;
+
+ /* choose destination signal for highest priority interrupt */
+ if (flags & QE_IC_HIGH_SIGNAL) {
+ temp |= (SIGNAL_HIGH << CICR_HPIT_SHIFT);
+ high_active = 1;
+ }
+
+ qe_ic_write(qe_ic->regs, QEIC_CICR, temp);
+
+ irq_set_handler_data(qe_ic->virq_low, qe_ic);
+ irq_set_chained_handler(qe_ic->virq_low, low_handler);
+
+ if (qe_ic->virq_high != NO_IRQ &&
+ qe_ic->virq_high != qe_ic->virq_low) {
+ irq_set_handler_data(qe_ic->virq_high, qe_ic);
+ irq_set_chained_handler(qe_ic->virq_high, high_handler);
+ }
+}
+
+void qe_ic_set_highest_priority(unsigned int virq, int high)
+{
+ struct qe_ic *qe_ic = qe_ic_from_irq(virq);
+ unsigned int src = virq_to_hw(virq);
+ u32 temp = 0;
+
+ temp = qe_ic_read(qe_ic->regs, QEIC_CICR);
+
+ temp &= ~CICR_HP_MASK;
+ temp |= src << CICR_HP_SHIFT;
+
+ temp &= ~CICR_HPIT_MASK;
+ temp |= (high ? SIGNAL_HIGH : SIGNAL_LOW) << CICR_HPIT_SHIFT;
+
+ qe_ic_write(qe_ic->regs, QEIC_CICR, temp);
+}
+
+/* Set Priority level within its group, from 1 to 8 */
+int qe_ic_set_priority(unsigned int virq, unsigned int priority)
+{
+ struct qe_ic *qe_ic = qe_ic_from_irq(virq);
+ unsigned int src = virq_to_hw(virq);
+ u32 temp;
+
+ if (priority > 8 || priority == 0)
+ return -EINVAL;
+ if (src > 127)
+ return -EINVAL;
+ if (qe_ic_info[src].pri_reg == 0)
+ return -EINVAL;
+
+ temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].pri_reg);
+
+ if (priority < 4) {
+ temp &= ~(0x7 << (32 - priority * 3));
+ temp |= qe_ic_info[src].pri_code << (32 - priority * 3);
+ } else {
+ temp &= ~(0x7 << (24 - priority * 3));
+ temp |= qe_ic_info[src].pri_code << (24 - priority * 3);
+ }
+
+ qe_ic_write(qe_ic->regs, qe_ic_info[src].pri_reg, temp);
+
+ return 0;
+}
+
+/* Set a QE priority to use high irq, only priority 1~2 can use high irq */
+int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high)
+{
+ struct qe_ic *qe_ic = qe_ic_from_irq(virq);
+ unsigned int src = virq_to_hw(virq);
+ u32 temp, control_reg = QEIC_CICNR, shift = 0;
+
+ if (priority > 2 || priority == 0)
+ return -EINVAL;
+
+ switch (qe_ic_info[src].pri_reg) {
+ case QEIC_CIPZCC:
+ shift = CICNR_ZCC1T_SHIFT;
+ break;
+ case QEIC_CIPWCC:
+ shift = CICNR_WCC1T_SHIFT;
+ break;
+ case QEIC_CIPYCC:
+ shift = CICNR_YCC1T_SHIFT;
+ break;
+ case QEIC_CIPXCC:
+ shift = CICNR_XCC1T_SHIFT;
+ break;
+ case QEIC_CIPRTA:
+ shift = CRICR_RTA1T_SHIFT;
+ control_reg = QEIC_CRICR;
+ break;
+ case QEIC_CIPRTB:
+ shift = CRICR_RTB1T_SHIFT;
+ control_reg = QEIC_CRICR;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ shift += (2 - priority) * 2;
+ temp = qe_ic_read(qe_ic->regs, control_reg);
+ temp &= ~(SIGNAL_MASK << shift);
+ temp |= (high ? SIGNAL_HIGH : SIGNAL_LOW) << shift;
+ qe_ic_write(qe_ic->regs, control_reg, temp);
+
+ return 0;
+}
+
+static struct bus_type qe_ic_subsys = {
+ .name = "qe_ic",
+ .dev_name = "qe_ic",
+};
+
+static struct device device_qe_ic = {
+ .id = 0,
+ .bus = &qe_ic_subsys,
+};
+
+static int __init init_qe_ic_sysfs(void)
+{
+ int rc;
+
+ printk(KERN_DEBUG "Registering qe_ic with sysfs...\n");
+
+ rc = subsys_system_register(&qe_ic_subsys, NULL);
+ if (rc) {
+ printk(KERN_ERR "Failed registering qe_ic sys class\n");
+ return -ENODEV;
+ }
+ rc = device_register(&device_qe_ic);
+ if (rc) {
+ printk(KERN_ERR "Failed registering qe_ic sys device\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+subsys_initcall(init_qe_ic_sysfs);
--- /dev/null
+/*
+ * drivers/soc/fsl/qe/qe_ic.h
+ *
+ * QUICC ENGINE Interrupt Controller Header
+ *
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Li Yang <leoli@freescale.com>
+ * Based on code from Shlomi Gridish <gridish@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#ifndef _POWERPC_SYSDEV_QE_IC_H
+#define _POWERPC_SYSDEV_QE_IC_H
+
+#include <soc/fsl/qe/qe_ic.h>
+
+#define NR_QE_IC_INTS 64
+
+/* QE IC registers offset */
+#define QEIC_CICR 0x00
+#define QEIC_CIVEC 0x04
+#define QEIC_CRIPNR 0x08
+#define QEIC_CIPNR 0x0c
+#define QEIC_CIPXCC 0x10
+#define QEIC_CIPYCC 0x14
+#define QEIC_CIPWCC 0x18
+#define QEIC_CIPZCC 0x1c
+#define QEIC_CIMR 0x20
+#define QEIC_CRIMR 0x24
+#define QEIC_CICNR 0x28
+#define QEIC_CIPRTA 0x30
+#define QEIC_CIPRTB 0x34
+#define QEIC_CRICR 0x3c
+#define QEIC_CHIVEC 0x60
+
+/* Interrupt priority registers */
+#define CIPCC_SHIFT_PRI0 29
+#define CIPCC_SHIFT_PRI1 26
+#define CIPCC_SHIFT_PRI2 23
+#define CIPCC_SHIFT_PRI3 20
+#define CIPCC_SHIFT_PRI4 13
+#define CIPCC_SHIFT_PRI5 10
+#define CIPCC_SHIFT_PRI6 7
+#define CIPCC_SHIFT_PRI7 4
+
+/* CICR priority modes */
+#define CICR_GWCC 0x00040000
+#define CICR_GXCC 0x00020000
+#define CICR_GYCC 0x00010000
+#define CICR_GZCC 0x00080000
+#define CICR_GRTA 0x00200000
+#define CICR_GRTB 0x00400000
+#define CICR_HPIT_SHIFT 8
+#define CICR_HPIT_MASK 0x00000300
+#define CICR_HP_SHIFT 24
+#define CICR_HP_MASK 0x3f000000
+
+/* CICNR */
+#define CICNR_WCC1T_SHIFT 20
+#define CICNR_ZCC1T_SHIFT 28
+#define CICNR_YCC1T_SHIFT 12
+#define CICNR_XCC1T_SHIFT 4
+
+/* CRICR */
+#define CRICR_RTA1T_SHIFT 20
+#define CRICR_RTB1T_SHIFT 28
+
+/* Signal indicator */
+#define SIGNAL_MASK 3
+#define SIGNAL_HIGH 2
+#define SIGNAL_LOW 0
+
+struct qe_ic {
+ /* Control registers offset */
+ volatile u32 __iomem *regs;
+
+ /* The remapper for this QEIC */
+ struct irq_domain *irqhost;
+
+ /* The "linux" controller struct */
+ struct irq_chip hc_irq;
+
+ /* VIRQ numbers of QE high/low irqs */
+ unsigned int virq_high;
+ unsigned int virq_low;
+};
+
+/*
+ * QE interrupt controller internal structure
+ */
+struct qe_ic_info {
+ u32 mask; /* location of this source at the QIMR register. */
+ u32 mask_reg; /* Mask register offset */
+ u8 pri_code; /* for grouped interrupts sources - the interrupt
+ code as appears at the group priority register */
+ u32 pri_reg; /* Group priority register offset */
+};
+
+#endif /* _POWERPC_SYSDEV_QE_IC_H */
--- /dev/null
+/*
+ * arch/powerpc/sysdev/qe_lib/qe_io.c
+ *
+ * QE Parallel I/O ports configuration routines
+ *
+ * Copyright 2006 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Li Yang <LeoLi@freescale.com>
+ * Based on code from Shlomi Gridish <gridish@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include <soc/fsl/qe/qe.h>
+#include <asm/prom.h>
+#include <sysdev/fsl_soc.h>
+
+#undef DEBUG
+
+static struct qe_pio_regs __iomem *par_io;
+static int num_par_io_ports = 0;
+
+int par_io_init(struct device_node *np)
+{
+ struct resource res;
+ int ret;
+ const u32 *num_ports;
+
+ /* Map Parallel I/O ports registers */
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret)
+ return ret;
+ par_io = ioremap(res.start, resource_size(&res));
+
+ num_ports = of_get_property(np, "num-ports", NULL);
+ if (num_ports)
+ num_par_io_ports = *num_ports;
+
+ return 0;
+}
+
+void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin, int dir,
+ int open_drain, int assignment, int has_irq)
+{
+ u32 pin_mask1bit;
+ u32 pin_mask2bits;
+ u32 new_mask2bits;
+ u32 tmp_val;
+
+ /* calculate pin location for single and 2 bits information */
+ pin_mask1bit = (u32) (1 << (QE_PIO_PINS - (pin + 1)));
+
+ /* Set open drain, if required */
+ tmp_val = in_be32(&par_io->cpodr);
+ if (open_drain)
+ out_be32(&par_io->cpodr, pin_mask1bit | tmp_val);
+ else
+ out_be32(&par_io->cpodr, ~pin_mask1bit & tmp_val);
+
+ /* define direction */
+ tmp_val = (pin > (QE_PIO_PINS / 2) - 1) ?
+ in_be32(&par_io->cpdir2) :
+ in_be32(&par_io->cpdir1);
+
+ /* get all bits mask for 2 bit per port */
+ pin_mask2bits = (u32) (0x3 << (QE_PIO_PINS -
+ (pin % (QE_PIO_PINS / 2) + 1) * 2));
+
+ /* Get the final mask we need for the right definition */
+ new_mask2bits = (u32) (dir << (QE_PIO_PINS -
+ (pin % (QE_PIO_PINS / 2) + 1) * 2));
+
+ /* clear and set 2 bits mask */
+ if (pin > (QE_PIO_PINS / 2) - 1) {
+ out_be32(&par_io->cpdir2,
+ ~pin_mask2bits & tmp_val);
+ tmp_val &= ~pin_mask2bits;
+ out_be32(&par_io->cpdir2, new_mask2bits | tmp_val);
+ } else {
+ out_be32(&par_io->cpdir1,
+ ~pin_mask2bits & tmp_val);
+ tmp_val &= ~pin_mask2bits;
+ out_be32(&par_io->cpdir1, new_mask2bits | tmp_val);
+ }
+ /* define pin assignment */
+ tmp_val = (pin > (QE_PIO_PINS / 2) - 1) ?
+ in_be32(&par_io->cppar2) :
+ in_be32(&par_io->cppar1);
+
+ new_mask2bits = (u32) (assignment << (QE_PIO_PINS -
+ (pin % (QE_PIO_PINS / 2) + 1) * 2));
+ /* clear and set 2 bits mask */
+ if (pin > (QE_PIO_PINS / 2) - 1) {
+ out_be32(&par_io->cppar2,
+ ~pin_mask2bits & tmp_val);
+ tmp_val &= ~pin_mask2bits;
+ out_be32(&par_io->cppar2, new_mask2bits | tmp_val);
+ } else {
+ out_be32(&par_io->cppar1,
+ ~pin_mask2bits & tmp_val);
+ tmp_val &= ~pin_mask2bits;
+ out_be32(&par_io->cppar1, new_mask2bits | tmp_val);
+ }
+}
+EXPORT_SYMBOL(__par_io_config_pin);
+
+int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
+ int assignment, int has_irq)
+{
+ if (!par_io || port >= num_par_io_ports)
+ return -EINVAL;
+
+ __par_io_config_pin(&par_io[port], pin, dir, open_drain, assignment,
+ has_irq);
+ return 0;
+}
+EXPORT_SYMBOL(par_io_config_pin);
+
+int par_io_data_set(u8 port, u8 pin, u8 val)
+{
+ u32 pin_mask, tmp_val;
+
+ if (port >= num_par_io_ports)
+ return -EINVAL;
+ if (pin >= QE_PIO_PINS)
+ return -EINVAL;
+ /* calculate pin location */
+ pin_mask = (u32) (1 << (QE_PIO_PINS - 1 - pin));
+
+ tmp_val = in_be32(&par_io[port].cpdata);
+
+ if (val == 0) /* clear */
+ out_be32(&par_io[port].cpdata, ~pin_mask & tmp_val);
+ else /* set */
+ out_be32(&par_io[port].cpdata, pin_mask | tmp_val);
+
+ return 0;
+}
+EXPORT_SYMBOL(par_io_data_set);
+
+int par_io_of_config(struct device_node *np)
+{
+ struct device_node *pio;
+ const phandle *ph;
+ int pio_map_len;
+ const unsigned int *pio_map;
+
+ if (par_io == NULL) {
+ printk(KERN_ERR "par_io not initialized\n");
+ return -1;
+ }
+
+ ph = of_get_property(np, "pio-handle", NULL);
+ if (ph == NULL) {
+ printk(KERN_ERR "pio-handle not available\n");
+ return -1;
+ }
+
+ pio = of_find_node_by_phandle(*ph);
+
+ pio_map = of_get_property(pio, "pio-map", &pio_map_len);
+ if (pio_map == NULL) {
+ printk(KERN_ERR "pio-map is not set!\n");
+ return -1;
+ }
+ pio_map_len /= sizeof(unsigned int);
+ if ((pio_map_len % 6) != 0) {
+ printk(KERN_ERR "pio-map format wrong!\n");
+ return -1;
+ }
+
+ while (pio_map_len > 0) {
+ par_io_config_pin((u8) pio_map[0], (u8) pio_map[1],
+ (int) pio_map[2], (int) pio_map[3],
+ (int) pio_map[4], (int) pio_map[5]);
+ pio_map += 6;
+ pio_map_len -= 6;
+ }
+ of_node_put(pio);
+ return 0;
+}
+EXPORT_SYMBOL(par_io_of_config);
--- /dev/null
+/*
+ * arch/powerpc/sysdev/qe_lib/ucc.c
+ *
+ * QE UCC API Set - UCC specific routines implementations.
+ *
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Authors: Shlomi Gridish <gridish@freescale.com>
+ * Li Yang <leoli@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/stddef.h>
+#include <linux/spinlock.h>
+#include <linux/export.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <soc/fsl/qe/immap_qe.h>
+#include <soc/fsl/qe/qe.h>
+#include <soc/fsl/qe/ucc.h>
+
+int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
+{
+ unsigned long flags;
+
+ if (ucc_num > UCC_MAX_NUM - 1)
+ return -EINVAL;
+
+ spin_lock_irqsave(&cmxgcr_lock, flags);
+ clrsetbits_be32(&qe_immr->qmx.cmxgcr, QE_CMXGCR_MII_ENET_MNG,
+ ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT);
+ spin_unlock_irqrestore(&cmxgcr_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(ucc_set_qe_mux_mii_mng);
+
+/* Configure the UCC to either Slow or Fast.
+ *
+ * A given UCC can be figured to support either "slow" devices (e.g. UART)
+ * or "fast" devices (e.g. Ethernet).
+ *
+ * 'ucc_num' is the UCC number, from 0 - 7.
+ *
+ * This function also sets the UCC_GUEMR_SET_RESERVED3 bit because that bit
+ * must always be set to 1.
+ */
+int ucc_set_type(unsigned int ucc_num, enum ucc_speed_type speed)
+{
+ u8 __iomem *guemr;
+
+ /* The GUEMR register is at the same location for both slow and fast
+ devices, so we just use uccX.slow.guemr. */
+ switch (ucc_num) {
+ case 0: guemr = &qe_immr->ucc1.slow.guemr;
+ break;
+ case 1: guemr = &qe_immr->ucc2.slow.guemr;
+ break;
+ case 2: guemr = &qe_immr->ucc3.slow.guemr;
+ break;
+ case 3: guemr = &qe_immr->ucc4.slow.guemr;
+ break;
+ case 4: guemr = &qe_immr->ucc5.slow.guemr;
+ break;
+ case 5: guemr = &qe_immr->ucc6.slow.guemr;
+ break;
+ case 6: guemr = &qe_immr->ucc7.slow.guemr;
+ break;
+ case 7: guemr = &qe_immr->ucc8.slow.guemr;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ clrsetbits_8(guemr, UCC_GUEMR_MODE_MASK,
+ UCC_GUEMR_SET_RESERVED3 | speed);
+
+ return 0;
+}
+
+static void get_cmxucr_reg(unsigned int ucc_num, __be32 __iomem **cmxucr,
+ unsigned int *reg_num, unsigned int *shift)
+{
+ unsigned int cmx = ((ucc_num & 1) << 1) + (ucc_num > 3);
+
+ *reg_num = cmx + 1;
+ *cmxucr = &qe_immr->qmx.cmxucr[cmx];
+ *shift = 16 - 8 * (ucc_num & 2);
+}
+
+int ucc_mux_set_grant_tsa_bkpt(unsigned int ucc_num, int set, u32 mask)
+{
+ __be32 __iomem *cmxucr;
+ unsigned int reg_num;
+ unsigned int shift;
+
+ /* check if the UCC number is in range. */
+ if (ucc_num > UCC_MAX_NUM - 1)
+ return -EINVAL;
+
+ get_cmxucr_reg(ucc_num, &cmxucr, ®_num, &shift);
+
+ if (set)
+ setbits32(cmxucr, mask << shift);
+ else
+ clrbits32(cmxucr, mask << shift);
+
+ return 0;
+}
+
+int ucc_set_qe_mux_rxtx(unsigned int ucc_num, enum qe_clock clock,
+ enum comm_dir mode)
+{
+ __be32 __iomem *cmxucr;
+ unsigned int reg_num;
+ unsigned int shift;
+ u32 clock_bits = 0;
+
+ /* check if the UCC number is in range. */
+ if (ucc_num > UCC_MAX_NUM - 1)
+ return -EINVAL;
+
+ /* The communications direction must be RX or TX */
+ if (!((mode == COMM_DIR_RX) || (mode == COMM_DIR_TX)))
+ return -EINVAL;
+
+ get_cmxucr_reg(ucc_num, &cmxucr, ®_num, &shift);
+
+ switch (reg_num) {
+ case 1:
+ switch (clock) {
+ case QE_BRG1: clock_bits = 1; break;
+ case QE_BRG2: clock_bits = 2; break;
+ case QE_BRG7: clock_bits = 3; break;
+ case QE_BRG8: clock_bits = 4; break;
+ case QE_CLK9: clock_bits = 5; break;
+ case QE_CLK10: clock_bits = 6; break;
+ case QE_CLK11: clock_bits = 7; break;
+ case QE_CLK12: clock_bits = 8; break;
+ case QE_CLK15: clock_bits = 9; break;
+ case QE_CLK16: clock_bits = 10; break;
+ default: break;
+ }
+ break;
+ case 2:
+ switch (clock) {
+ case QE_BRG5: clock_bits = 1; break;
+ case QE_BRG6: clock_bits = 2; break;
+ case QE_BRG7: clock_bits = 3; break;
+ case QE_BRG8: clock_bits = 4; break;
+ case QE_CLK13: clock_bits = 5; break;
+ case QE_CLK14: clock_bits = 6; break;
+ case QE_CLK19: clock_bits = 7; break;
+ case QE_CLK20: clock_bits = 8; break;
+ case QE_CLK15: clock_bits = 9; break;
+ case QE_CLK16: clock_bits = 10; break;
+ default: break;
+ }
+ break;
+ case 3:
+ switch (clock) {
+ case QE_BRG9: clock_bits = 1; break;
+ case QE_BRG10: clock_bits = 2; break;
+ case QE_BRG15: clock_bits = 3; break;
+ case QE_BRG16: clock_bits = 4; break;
+ case QE_CLK3: clock_bits = 5; break;
+ case QE_CLK4: clock_bits = 6; break;
+ case QE_CLK17: clock_bits = 7; break;
+ case QE_CLK18: clock_bits = 8; break;
+ case QE_CLK7: clock_bits = 9; break;
+ case QE_CLK8: clock_bits = 10; break;
+ case QE_CLK16: clock_bits = 11; break;
+ default: break;
+ }
+ break;
+ case 4:
+ switch (clock) {
+ case QE_BRG13: clock_bits = 1; break;
+ case QE_BRG14: clock_bits = 2; break;
+ case QE_BRG15: clock_bits = 3; break;
+ case QE_BRG16: clock_bits = 4; break;
+ case QE_CLK5: clock_bits = 5; break;
+ case QE_CLK6: clock_bits = 6; break;
+ case QE_CLK21: clock_bits = 7; break;
+ case QE_CLK22: clock_bits = 8; break;
+ case QE_CLK7: clock_bits = 9; break;
+ case QE_CLK8: clock_bits = 10; break;
+ case QE_CLK16: clock_bits = 11; break;
+ default: break;
+ }
+ break;
+ default: break;
+ }
+
+ /* Check for invalid combination of clock and UCC number */
+ if (!clock_bits)
+ return -ENOENT;
+
+ if (mode == COMM_DIR_RX)
+ shift += 4;
+
+ clrsetbits_be32(cmxucr, QE_CMXUCR_TX_CLK_SRC_MASK << shift,
+ clock_bits << shift);
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Authors: Shlomi Gridish <gridish@freescale.com>
+ * Li Yang <leoli@freescale.com>
+ *
+ * Description:
+ * QE UCC Fast API Set - UCC Fast specific routines implementations.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/export.h>
+
+#include <asm/io.h>
+#include <soc/fsl/qe/immap_qe.h>
+#include <soc/fsl/qe/qe.h>
+
+#include <soc/fsl/qe/ucc.h>
+#include <soc/fsl/qe/ucc_fast.h>
+
+void ucc_fast_dump_regs(struct ucc_fast_private * uccf)
+{
+ printk(KERN_INFO "UCC%u Fast registers:\n", uccf->uf_info->ucc_num);
+ printk(KERN_INFO "Base address: 0x%p\n", uccf->uf_regs);
+
+ printk(KERN_INFO "gumr : addr=0x%p, val=0x%08x\n",
+ &uccf->uf_regs->gumr, in_be32(&uccf->uf_regs->gumr));
+ printk(KERN_INFO "upsmr : addr=0x%p, val=0x%08x\n",
+ &uccf->uf_regs->upsmr, in_be32(&uccf->uf_regs->upsmr));
+ printk(KERN_INFO "utodr : addr=0x%p, val=0x%04x\n",
+ &uccf->uf_regs->utodr, in_be16(&uccf->uf_regs->utodr));
+ printk(KERN_INFO "udsr : addr=0x%p, val=0x%04x\n",
+ &uccf->uf_regs->udsr, in_be16(&uccf->uf_regs->udsr));
+ printk(KERN_INFO "ucce : addr=0x%p, val=0x%08x\n",
+ &uccf->uf_regs->ucce, in_be32(&uccf->uf_regs->ucce));
+ printk(KERN_INFO "uccm : addr=0x%p, val=0x%08x\n",
+ &uccf->uf_regs->uccm, in_be32(&uccf->uf_regs->uccm));
+ printk(KERN_INFO "uccs : addr=0x%p, val=0x%02x\n",
+ &uccf->uf_regs->uccs, in_8(&uccf->uf_regs->uccs));
+ printk(KERN_INFO "urfb : addr=0x%p, val=0x%08x\n",
+ &uccf->uf_regs->urfb, in_be32(&uccf->uf_regs->urfb));
+ printk(KERN_INFO "urfs : addr=0x%p, val=0x%04x\n",
+ &uccf->uf_regs->urfs, in_be16(&uccf->uf_regs->urfs));
+ printk(KERN_INFO "urfet : addr=0x%p, val=0x%04x\n",
+ &uccf->uf_regs->urfet, in_be16(&uccf->uf_regs->urfet));
+ printk(KERN_INFO "urfset: addr=0x%p, val=0x%04x\n",
+ &uccf->uf_regs->urfset, in_be16(&uccf->uf_regs->urfset));
+ printk(KERN_INFO "utfb : addr=0x%p, val=0x%08x\n",
+ &uccf->uf_regs->utfb, in_be32(&uccf->uf_regs->utfb));
+ printk(KERN_INFO "utfs : addr=0x%p, val=0x%04x\n",
+ &uccf->uf_regs->utfs, in_be16(&uccf->uf_regs->utfs));
+ printk(KERN_INFO "utfet : addr=0x%p, val=0x%04x\n",
+ &uccf->uf_regs->utfet, in_be16(&uccf->uf_regs->utfet));
+ printk(KERN_INFO "utftt : addr=0x%p, val=0x%04x\n",
+ &uccf->uf_regs->utftt, in_be16(&uccf->uf_regs->utftt));
+ printk(KERN_INFO "utpt : addr=0x%p, val=0x%04x\n",
+ &uccf->uf_regs->utpt, in_be16(&uccf->uf_regs->utpt));
+ printk(KERN_INFO "urtry : addr=0x%p, val=0x%08x\n",
+ &uccf->uf_regs->urtry, in_be32(&uccf->uf_regs->urtry));
+ printk(KERN_INFO "guemr : addr=0x%p, val=0x%02x\n",
+ &uccf->uf_regs->guemr, in_8(&uccf->uf_regs->guemr));
+}
+EXPORT_SYMBOL(ucc_fast_dump_regs);
+
+u32 ucc_fast_get_qe_cr_subblock(int uccf_num)
+{
+ switch (uccf_num) {
+ case 0: return QE_CR_SUBBLOCK_UCCFAST1;
+ case 1: return QE_CR_SUBBLOCK_UCCFAST2;
+ case 2: return QE_CR_SUBBLOCK_UCCFAST3;
+ case 3: return QE_CR_SUBBLOCK_UCCFAST4;
+ case 4: return QE_CR_SUBBLOCK_UCCFAST5;
+ case 5: return QE_CR_SUBBLOCK_UCCFAST6;
+ case 6: return QE_CR_SUBBLOCK_UCCFAST7;
+ case 7: return QE_CR_SUBBLOCK_UCCFAST8;
+ default: return QE_CR_SUBBLOCK_INVALID;
+ }
+}
+EXPORT_SYMBOL(ucc_fast_get_qe_cr_subblock);
+
+void ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf)
+{
+ out_be16(&uccf->uf_regs->utodr, UCC_FAST_TOD);
+}
+EXPORT_SYMBOL(ucc_fast_transmit_on_demand);
+
+void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode)
+{
+ struct ucc_fast __iomem *uf_regs;
+ u32 gumr;
+
+ uf_regs = uccf->uf_regs;
+
+ /* Enable reception and/or transmission on this UCC. */
+ gumr = in_be32(&uf_regs->gumr);
+ if (mode & COMM_DIR_TX) {
+ gumr |= UCC_FAST_GUMR_ENT;
+ uccf->enabled_tx = 1;
+ }
+ if (mode & COMM_DIR_RX) {
+ gumr |= UCC_FAST_GUMR_ENR;
+ uccf->enabled_rx = 1;
+ }
+ out_be32(&uf_regs->gumr, gumr);
+}
+EXPORT_SYMBOL(ucc_fast_enable);
+
+void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode)
+{
+ struct ucc_fast __iomem *uf_regs;
+ u32 gumr;
+
+ uf_regs = uccf->uf_regs;
+
+ /* Disable reception and/or transmission on this UCC. */
+ gumr = in_be32(&uf_regs->gumr);
+ if (mode & COMM_DIR_TX) {
+ gumr &= ~UCC_FAST_GUMR_ENT;
+ uccf->enabled_tx = 0;
+ }
+ if (mode & COMM_DIR_RX) {
+ gumr &= ~UCC_FAST_GUMR_ENR;
+ uccf->enabled_rx = 0;
+ }
+ out_be32(&uf_regs->gumr, gumr);
+}
+EXPORT_SYMBOL(ucc_fast_disable);
+
+int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret)
+{
+ struct ucc_fast_private *uccf;
+ struct ucc_fast __iomem *uf_regs;
+ u32 gumr;
+ int ret;
+
+ if (!uf_info)
+ return -EINVAL;
+
+ /* check if the UCC port number is in range. */
+ if ((uf_info->ucc_num < 0) || (uf_info->ucc_num > UCC_MAX_NUM - 1)) {
+ printk(KERN_ERR "%s: illegal UCC number\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Check that 'max_rx_buf_length' is properly aligned (4). */
+ if (uf_info->max_rx_buf_length & (UCC_FAST_MRBLR_ALIGNMENT - 1)) {
+ printk(KERN_ERR "%s: max_rx_buf_length not aligned\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ /* Validate Virtual Fifo register values */
+ if (uf_info->urfs < UCC_FAST_URFS_MIN_VAL) {
+ printk(KERN_ERR "%s: urfs is too small\n", __func__);
+ return -EINVAL;
+ }
+
+ if (uf_info->urfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
+ printk(KERN_ERR "%s: urfs is not aligned\n", __func__);
+ return -EINVAL;
+ }
+
+ if (uf_info->urfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
+ printk(KERN_ERR "%s: urfet is not aligned.\n", __func__);
+ return -EINVAL;
+ }
+
+ if (uf_info->urfset & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
+ printk(KERN_ERR "%s: urfset is not aligned\n", __func__);
+ return -EINVAL;
+ }
+
+ if (uf_info->utfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
+ printk(KERN_ERR "%s: utfs is not aligned\n", __func__);
+ return -EINVAL;
+ }
+
+ if (uf_info->utfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
+ printk(KERN_ERR "%s: utfet is not aligned\n", __func__);
+ return -EINVAL;
+ }
+
+ if (uf_info->utftt & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
+ printk(KERN_ERR "%s: utftt is not aligned\n", __func__);
+ return -EINVAL;
+ }
+
+ uccf = kzalloc(sizeof(struct ucc_fast_private), GFP_KERNEL);
+ if (!uccf) {
+ printk(KERN_ERR "%s: Cannot allocate private data\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ /* Fill fast UCC structure */
+ uccf->uf_info = uf_info;
+ /* Set the PHY base address */
+ uccf->uf_regs = ioremap(uf_info->regs, sizeof(struct ucc_fast));
+ if (uccf->uf_regs == NULL) {
+ printk(KERN_ERR "%s: Cannot map UCC registers\n", __func__);
+ kfree(uccf);
+ return -ENOMEM;
+ }
+
+ uccf->enabled_tx = 0;
+ uccf->enabled_rx = 0;
+ uccf->stopped_tx = 0;
+ uccf->stopped_rx = 0;
+ uf_regs = uccf->uf_regs;
+ uccf->p_ucce = &uf_regs->ucce;
+ uccf->p_uccm = &uf_regs->uccm;
+#ifdef CONFIG_UGETH_TX_ON_DEMAND
+ uccf->p_utodr = &uf_regs->utodr;
+#endif
+#ifdef STATISTICS
+ uccf->tx_frames = 0;
+ uccf->rx_frames = 0;
+ uccf->rx_discarded = 0;
+#endif /* STATISTICS */
+
+ /* Set UCC to fast type */
+ ret = ucc_set_type(uf_info->ucc_num, UCC_SPEED_TYPE_FAST);
+ if (ret) {
+ printk(KERN_ERR "%s: cannot set UCC type\n", __func__);
+ ucc_fast_free(uccf);
+ return ret;
+ }
+
+ uccf->mrblr = uf_info->max_rx_buf_length;
+
+ /* Set GUMR */
+ /* For more details see the hardware spec. */
+ gumr = uf_info->ttx_trx;
+ if (uf_info->tci)
+ gumr |= UCC_FAST_GUMR_TCI;
+ if (uf_info->cdp)
+ gumr |= UCC_FAST_GUMR_CDP;
+ if (uf_info->ctsp)
+ gumr |= UCC_FAST_GUMR_CTSP;
+ if (uf_info->cds)
+ gumr |= UCC_FAST_GUMR_CDS;
+ if (uf_info->ctss)
+ gumr |= UCC_FAST_GUMR_CTSS;
+ if (uf_info->txsy)
+ gumr |= UCC_FAST_GUMR_TXSY;
+ if (uf_info->rsyn)
+ gumr |= UCC_FAST_GUMR_RSYN;
+ gumr |= uf_info->synl;
+ if (uf_info->rtsm)
+ gumr |= UCC_FAST_GUMR_RTSM;
+ gumr |= uf_info->renc;
+ if (uf_info->revd)
+ gumr |= UCC_FAST_GUMR_REVD;
+ gumr |= uf_info->tenc;
+ gumr |= uf_info->tcrc;
+ gumr |= uf_info->mode;
+ out_be32(&uf_regs->gumr, gumr);
+
+ /* Allocate memory for Tx Virtual Fifo */
+ uccf->ucc_fast_tx_virtual_fifo_base_offset =
+ qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
+ if (IS_ERR_VALUE(uccf->ucc_fast_tx_virtual_fifo_base_offset)) {
+ printk(KERN_ERR "%s: cannot allocate MURAM for TX FIFO\n",
+ __func__);
+ uccf->ucc_fast_tx_virtual_fifo_base_offset = 0;
+ ucc_fast_free(uccf);
+ return -ENOMEM;
+ }
+
+ /* Allocate memory for Rx Virtual Fifo */
+ uccf->ucc_fast_rx_virtual_fifo_base_offset =
+ qe_muram_alloc(uf_info->urfs +
+ UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR,
+ UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
+ if (IS_ERR_VALUE(uccf->ucc_fast_rx_virtual_fifo_base_offset)) {
+ printk(KERN_ERR "%s: cannot allocate MURAM for RX FIFO\n",
+ __func__);
+ uccf->ucc_fast_rx_virtual_fifo_base_offset = 0;
+ ucc_fast_free(uccf);
+ return -ENOMEM;
+ }
+
+ /* Set Virtual Fifo registers */
+ out_be16(&uf_regs->urfs, uf_info->urfs);
+ out_be16(&uf_regs->urfet, uf_info->urfet);
+ out_be16(&uf_regs->urfset, uf_info->urfset);
+ out_be16(&uf_regs->utfs, uf_info->utfs);
+ out_be16(&uf_regs->utfet, uf_info->utfet);
+ out_be16(&uf_regs->utftt, uf_info->utftt);
+ /* utfb, urfb are offsets from MURAM base */
+ out_be32(&uf_regs->utfb, uccf->ucc_fast_tx_virtual_fifo_base_offset);
+ out_be32(&uf_regs->urfb, uccf->ucc_fast_rx_virtual_fifo_base_offset);
+
+ /* Mux clocking */
+ /* Grant Support */
+ ucc_set_qe_mux_grant(uf_info->ucc_num, uf_info->grant_support);
+ /* Breakpoint Support */
+ ucc_set_qe_mux_bkpt(uf_info->ucc_num, uf_info->brkpt_support);
+ /* Set Tsa or NMSI mode. */
+ ucc_set_qe_mux_tsa(uf_info->ucc_num, uf_info->tsa);
+ /* If NMSI (not Tsa), set Tx and Rx clock. */
+ if (!uf_info->tsa) {
+ /* Rx clock routing */
+ if ((uf_info->rx_clock != QE_CLK_NONE) &&
+ ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->rx_clock,
+ COMM_DIR_RX)) {
+ printk(KERN_ERR "%s: illegal value for RX clock\n",
+ __func__);
+ ucc_fast_free(uccf);
+ return -EINVAL;
+ }
+ /* Tx clock routing */
+ if ((uf_info->tx_clock != QE_CLK_NONE) &&
+ ucc_set_qe_mux_rxtx(uf_info->ucc_num, uf_info->tx_clock,
+ COMM_DIR_TX)) {
+ printk(KERN_ERR "%s: illegal value for TX clock\n",
+ __func__);
+ ucc_fast_free(uccf);
+ return -EINVAL;
+ }
+ }
+
+ /* Set interrupt mask register at UCC level. */
+ out_be32(&uf_regs->uccm, uf_info->uccm_mask);
+
+ /* First, clear anything pending at UCC level,
+ * otherwise, old garbage may come through
+ * as soon as the dam is opened. */
+
+ /* Writing '1' clears */
+ out_be32(&uf_regs->ucce, 0xffffffff);
+
+ *uccf_ret = uccf;
+ return 0;
+}
+EXPORT_SYMBOL(ucc_fast_init);
+
+void ucc_fast_free(struct ucc_fast_private * uccf)
+{
+ if (!uccf)
+ return;
+
+ if (uccf->ucc_fast_tx_virtual_fifo_base_offset)
+ qe_muram_free(uccf->ucc_fast_tx_virtual_fifo_base_offset);
+
+ if (uccf->ucc_fast_rx_virtual_fifo_base_offset)
+ qe_muram_free(uccf->ucc_fast_rx_virtual_fifo_base_offset);
+
+ if (uccf->uf_regs)
+ iounmap(uccf->uf_regs);
+
+ kfree(uccf);
+}
+EXPORT_SYMBOL(ucc_fast_free);
--- /dev/null
+/*
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Authors: Shlomi Gridish <gridish@freescale.com>
+ * Li Yang <leoli@freescale.com>
+ *
+ * Description:
+ * QE UCC Slow API Set - UCC Slow specific routines implementations.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/export.h>
+
+#include <asm/io.h>
+#include <soc/fsl/qe/immap_qe.h>
+#include <soc/fsl/qe/qe.h>
+
+#include <soc/fsl/qe/ucc.h>
+#include <soc/fsl/qe/ucc_slow.h>
+
+u32 ucc_slow_get_qe_cr_subblock(int uccs_num)
+{
+ switch (uccs_num) {
+ case 0: return QE_CR_SUBBLOCK_UCCSLOW1;
+ case 1: return QE_CR_SUBBLOCK_UCCSLOW2;
+ case 2: return QE_CR_SUBBLOCK_UCCSLOW3;
+ case 3: return QE_CR_SUBBLOCK_UCCSLOW4;
+ case 4: return QE_CR_SUBBLOCK_UCCSLOW5;
+ case 5: return QE_CR_SUBBLOCK_UCCSLOW6;
+ case 6: return QE_CR_SUBBLOCK_UCCSLOW7;
+ case 7: return QE_CR_SUBBLOCK_UCCSLOW8;
+ default: return QE_CR_SUBBLOCK_INVALID;
+ }
+}
+EXPORT_SYMBOL(ucc_slow_get_qe_cr_subblock);
+
+void ucc_slow_graceful_stop_tx(struct ucc_slow_private * uccs)
+{
+ struct ucc_slow_info *us_info = uccs->us_info;
+ u32 id;
+
+ id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
+ qe_issue_cmd(QE_GRACEFUL_STOP_TX, id,
+ QE_CR_PROTOCOL_UNSPECIFIED, 0);
+}
+EXPORT_SYMBOL(ucc_slow_graceful_stop_tx);
+
+void ucc_slow_stop_tx(struct ucc_slow_private * uccs)
+{
+ struct ucc_slow_info *us_info = uccs->us_info;
+ u32 id;
+
+ id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
+ qe_issue_cmd(QE_STOP_TX, id, QE_CR_PROTOCOL_UNSPECIFIED, 0);
+}
+EXPORT_SYMBOL(ucc_slow_stop_tx);
+
+void ucc_slow_restart_tx(struct ucc_slow_private * uccs)
+{
+ struct ucc_slow_info *us_info = uccs->us_info;
+ u32 id;
+
+ id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
+ qe_issue_cmd(QE_RESTART_TX, id, QE_CR_PROTOCOL_UNSPECIFIED, 0);
+}
+EXPORT_SYMBOL(ucc_slow_restart_tx);
+
+void ucc_slow_enable(struct ucc_slow_private * uccs, enum comm_dir mode)
+{
+ struct ucc_slow *us_regs;
+ u32 gumr_l;
+
+ us_regs = uccs->us_regs;
+
+ /* Enable reception and/or transmission on this UCC. */
+ gumr_l = in_be32(&us_regs->gumr_l);
+ if (mode & COMM_DIR_TX) {
+ gumr_l |= UCC_SLOW_GUMR_L_ENT;
+ uccs->enabled_tx = 1;
+ }
+ if (mode & COMM_DIR_RX) {
+ gumr_l |= UCC_SLOW_GUMR_L_ENR;
+ uccs->enabled_rx = 1;
+ }
+ out_be32(&us_regs->gumr_l, gumr_l);
+}
+EXPORT_SYMBOL(ucc_slow_enable);
+
+void ucc_slow_disable(struct ucc_slow_private * uccs, enum comm_dir mode)
+{
+ struct ucc_slow *us_regs;
+ u32 gumr_l;
+
+ us_regs = uccs->us_regs;
+
+ /* Disable reception and/or transmission on this UCC. */
+ gumr_l = in_be32(&us_regs->gumr_l);
+ if (mode & COMM_DIR_TX) {
+ gumr_l &= ~UCC_SLOW_GUMR_L_ENT;
+ uccs->enabled_tx = 0;
+ }
+ if (mode & COMM_DIR_RX) {
+ gumr_l &= ~UCC_SLOW_GUMR_L_ENR;
+ uccs->enabled_rx = 0;
+ }
+ out_be32(&us_regs->gumr_l, gumr_l);
+}
+EXPORT_SYMBOL(ucc_slow_disable);
+
+/* Initialize the UCC for Slow operations
+ *
+ * The caller should initialize the following us_info
+ */
+int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** uccs_ret)
+{
+ struct ucc_slow_private *uccs;
+ u32 i;
+ struct ucc_slow __iomem *us_regs;
+ u32 gumr;
+ struct qe_bd *bd;
+ u32 id;
+ u32 command;
+ int ret = 0;
+
+ if (!us_info)
+ return -EINVAL;
+
+ /* check if the UCC port number is in range. */
+ if ((us_info->ucc_num < 0) || (us_info->ucc_num > UCC_MAX_NUM - 1)) {
+ printk(KERN_ERR "%s: illegal UCC number\n", __func__);
+ return -EINVAL;
+ }
+
+ /*
+ * Set mrblr
+ * Check that 'max_rx_buf_length' is properly aligned (4), unless
+ * rfw is 1, meaning that QE accepts one byte at a time, unlike normal
+ * case when QE accepts 32 bits at a time.
+ */
+ if ((!us_info->rfw) &&
+ (us_info->max_rx_buf_length & (UCC_SLOW_MRBLR_ALIGNMENT - 1))) {
+ printk(KERN_ERR "max_rx_buf_length not aligned.\n");
+ return -EINVAL;
+ }
+
+ uccs = kzalloc(sizeof(struct ucc_slow_private), GFP_KERNEL);
+ if (!uccs) {
+ printk(KERN_ERR "%s: Cannot allocate private data\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ /* Fill slow UCC structure */
+ uccs->us_info = us_info;
+ /* Set the PHY base address */
+ uccs->us_regs = ioremap(us_info->regs, sizeof(struct ucc_slow));
+ if (uccs->us_regs == NULL) {
+ printk(KERN_ERR "%s: Cannot map UCC registers\n", __func__);
+ kfree(uccs);
+ return -ENOMEM;
+ }
+
+ uccs->saved_uccm = 0;
+ uccs->p_rx_frame = 0;
+ us_regs = uccs->us_regs;
+ uccs->p_ucce = (u16 *) & (us_regs->ucce);
+ uccs->p_uccm = (u16 *) & (us_regs->uccm);
+#ifdef STATISTICS
+ uccs->rx_frames = 0;
+ uccs->tx_frames = 0;
+ uccs->rx_discarded = 0;
+#endif /* STATISTICS */
+
+ /* Get PRAM base */
+ uccs->us_pram_offset =
+ qe_muram_alloc(UCC_SLOW_PRAM_SIZE, ALIGNMENT_OF_UCC_SLOW_PRAM);
+ if (IS_ERR_VALUE(uccs->us_pram_offset)) {
+ printk(KERN_ERR "%s: cannot allocate MURAM for PRAM", __func__);
+ ucc_slow_free(uccs);
+ return -ENOMEM;
+ }
+ id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
+ qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, id, us_info->protocol,
+ uccs->us_pram_offset);
+
+ uccs->us_pram = qe_muram_addr(uccs->us_pram_offset);
+
+ /* Set UCC to slow type */
+ ret = ucc_set_type(us_info->ucc_num, UCC_SPEED_TYPE_SLOW);
+ if (ret) {
+ printk(KERN_ERR "%s: cannot set UCC type", __func__);
+ ucc_slow_free(uccs);
+ return ret;
+ }
+
+ out_be16(&uccs->us_pram->mrblr, us_info->max_rx_buf_length);
+
+ INIT_LIST_HEAD(&uccs->confQ);
+
+ /* Allocate BDs. */
+ uccs->rx_base_offset =
+ qe_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd),
+ QE_ALIGNMENT_OF_BD);
+ if (IS_ERR_VALUE(uccs->rx_base_offset)) {
+ printk(KERN_ERR "%s: cannot allocate %u RX BDs\n", __func__,
+ us_info->rx_bd_ring_len);
+ uccs->rx_base_offset = 0;
+ ucc_slow_free(uccs);
+ return -ENOMEM;
+ }
+
+ uccs->tx_base_offset =
+ qe_muram_alloc(us_info->tx_bd_ring_len * sizeof(struct qe_bd),
+ QE_ALIGNMENT_OF_BD);
+ if (IS_ERR_VALUE(uccs->tx_base_offset)) {
+ printk(KERN_ERR "%s: cannot allocate TX BDs", __func__);
+ uccs->tx_base_offset = 0;
+ ucc_slow_free(uccs);
+ return -ENOMEM;
+ }
+
+ /* Init Tx bds */
+ bd = uccs->confBd = uccs->tx_bd = qe_muram_addr(uccs->tx_base_offset);
+ for (i = 0; i < us_info->tx_bd_ring_len - 1; i++) {
+ /* clear bd buffer */
+ out_be32(&bd->buf, 0);
+ /* set bd status and length */
+ out_be32((u32 *) bd, 0);
+ bd++;
+ }
+ /* for last BD set Wrap bit */
+ out_be32(&bd->buf, 0);
+ out_be32((u32 *) bd, cpu_to_be32(T_W));
+
+ /* Init Rx bds */
+ bd = uccs->rx_bd = qe_muram_addr(uccs->rx_base_offset);
+ for (i = 0; i < us_info->rx_bd_ring_len - 1; i++) {
+ /* set bd status and length */
+ out_be32((u32*)bd, 0);
+ /* clear bd buffer */
+ out_be32(&bd->buf, 0);
+ bd++;
+ }
+ /* for last BD set Wrap bit */
+ out_be32((u32*)bd, cpu_to_be32(R_W));
+ out_be32(&bd->buf, 0);
+
+ /* Set GUMR (For more details see the hardware spec.). */
+ /* gumr_h */
+ gumr = us_info->tcrc;
+ if (us_info->cdp)
+ gumr |= UCC_SLOW_GUMR_H_CDP;
+ if (us_info->ctsp)
+ gumr |= UCC_SLOW_GUMR_H_CTSP;
+ if (us_info->cds)
+ gumr |= UCC_SLOW_GUMR_H_CDS;
+ if (us_info->ctss)
+ gumr |= UCC_SLOW_GUMR_H_CTSS;
+ if (us_info->tfl)
+ gumr |= UCC_SLOW_GUMR_H_TFL;
+ if (us_info->rfw)
+ gumr |= UCC_SLOW_GUMR_H_RFW;
+ if (us_info->txsy)
+ gumr |= UCC_SLOW_GUMR_H_TXSY;
+ if (us_info->rtsm)
+ gumr |= UCC_SLOW_GUMR_H_RTSM;
+ out_be32(&us_regs->gumr_h, gumr);
+
+ /* gumr_l */
+ gumr = us_info->tdcr | us_info->rdcr | us_info->tenc | us_info->renc |
+ us_info->diag | us_info->mode;
+ if (us_info->tci)
+ gumr |= UCC_SLOW_GUMR_L_TCI;
+ if (us_info->rinv)
+ gumr |= UCC_SLOW_GUMR_L_RINV;
+ if (us_info->tinv)
+ gumr |= UCC_SLOW_GUMR_L_TINV;
+ if (us_info->tend)
+ gumr |= UCC_SLOW_GUMR_L_TEND;
+ out_be32(&us_regs->gumr_l, gumr);
+
+ /* Function code registers */
+
+ /* if the data is in cachable memory, the 'global' */
+ /* in the function code should be set. */
+ uccs->us_pram->tbmr = UCC_BMR_BO_BE;
+ uccs->us_pram->rbmr = UCC_BMR_BO_BE;
+
+ /* rbase, tbase are offsets from MURAM base */
+ out_be16(&uccs->us_pram->rbase, uccs->rx_base_offset);
+ out_be16(&uccs->us_pram->tbase, uccs->tx_base_offset);
+
+ /* Mux clocking */
+ /* Grant Support */
+ ucc_set_qe_mux_grant(us_info->ucc_num, us_info->grant_support);
+ /* Breakpoint Support */
+ ucc_set_qe_mux_bkpt(us_info->ucc_num, us_info->brkpt_support);
+ /* Set Tsa or NMSI mode. */
+ ucc_set_qe_mux_tsa(us_info->ucc_num, us_info->tsa);
+ /* If NMSI (not Tsa), set Tx and Rx clock. */
+ if (!us_info->tsa) {
+ /* Rx clock routing */
+ if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->rx_clock,
+ COMM_DIR_RX)) {
+ printk(KERN_ERR "%s: illegal value for RX clock\n",
+ __func__);
+ ucc_slow_free(uccs);
+ return -EINVAL;
+ }
+ /* Tx clock routing */
+ if (ucc_set_qe_mux_rxtx(us_info->ucc_num, us_info->tx_clock,
+ COMM_DIR_TX)) {
+ printk(KERN_ERR "%s: illegal value for TX clock\n",
+ __func__);
+ ucc_slow_free(uccs);
+ return -EINVAL;
+ }
+ }
+
+ /* Set interrupt mask register at UCC level. */
+ out_be16(&us_regs->uccm, us_info->uccm_mask);
+
+ /* First, clear anything pending at UCC level,
+ * otherwise, old garbage may come through
+ * as soon as the dam is opened. */
+
+ /* Writing '1' clears */
+ out_be16(&us_regs->ucce, 0xffff);
+
+ /* Issue QE Init command */
+ if (us_info->init_tx && us_info->init_rx)
+ command = QE_INIT_TX_RX;
+ else if (us_info->init_tx)
+ command = QE_INIT_TX;
+ else
+ command = QE_INIT_RX; /* We know at least one is TRUE */
+
+ qe_issue_cmd(command, id, us_info->protocol, 0);
+
+ *uccs_ret = uccs;
+ return 0;
+}
+EXPORT_SYMBOL(ucc_slow_init);
+
+void ucc_slow_free(struct ucc_slow_private * uccs)
+{
+ if (!uccs)
+ return;
+
+ if (uccs->rx_base_offset)
+ qe_muram_free(uccs->rx_base_offset);
+
+ if (uccs->tx_base_offset)
+ qe_muram_free(uccs->tx_base_offset);
+
+ if (uccs->us_pram)
+ qe_muram_free(uccs->us_pram_offset);
+
+ if (uccs->us_regs)
+ iounmap(uccs->us_regs);
+
+ kfree(uccs);
+}
+EXPORT_SYMBOL(ucc_slow_free);
+
--- /dev/null
+/*
+ * QE USB routines
+ *
+ * Copyright 2006 Freescale Semiconductor, Inc.
+ * Shlomi Gridish <gridish@freescale.com>
+ * Jerry Huang <Chang-Ming.Huang@freescale.com>
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ * Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <soc/fsl/qe/immap_qe.h>
+#include <soc/fsl/qe/qe.h>
+
+int qe_usb_clock_set(enum qe_clock clk, int rate)
+{
+ struct qe_mux __iomem *mux = &qe_immr->qmx;
+ unsigned long flags;
+ u32 val;
+
+ switch (clk) {
+ case QE_CLK3: val = QE_CMXGCR_USBCS_CLK3; break;
+ case QE_CLK5: val = QE_CMXGCR_USBCS_CLK5; break;
+ case QE_CLK7: val = QE_CMXGCR_USBCS_CLK7; break;
+ case QE_CLK9: val = QE_CMXGCR_USBCS_CLK9; break;
+ case QE_CLK13: val = QE_CMXGCR_USBCS_CLK13; break;
+ case QE_CLK17: val = QE_CMXGCR_USBCS_CLK17; break;
+ case QE_CLK19: val = QE_CMXGCR_USBCS_CLK19; break;
+ case QE_CLK21: val = QE_CMXGCR_USBCS_CLK21; break;
+ case QE_BRG9: val = QE_CMXGCR_USBCS_BRG9; break;
+ case QE_BRG10: val = QE_CMXGCR_USBCS_BRG10; break;
+ default:
+ pr_err("%s: requested unknown clock %d\n", __func__, clk);
+ return -EINVAL;
+ }
+
+ if (qe_clock_is_brg(clk))
+ qe_setbrg(clk, rate, 1);
+
+ spin_lock_irqsave(&cmxgcr_lock, flags);
+
+ clrsetbits_be32(&mux->cmxgcr, QE_CMXGCR_USBCS, val);
+
+ spin_unlock_irqrestore(&cmxgcr_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(qe_usb_clock_set);
* option) any later version.
*/
#include <asm/cpm.h>
-#include <asm/qe.h>
+#include <soc/fsl/qe/qe.h>
#include <linux/dma-mapping.h>
#include <linux/fsl_devices.h>
#include <linux/kernel.h>
#include <linux/dma-mapping.h>
#include <linux/fs_uart_pd.h>
-#include <asm/ucc_slow.h>
+#include <soc/fsl/qe/ucc_slow.h>
#include <linux/firmware.h>
#include <asm/reg.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
-#include <asm/qe.h>
+#include <soc/fsl/qe/qe.h>
#include <asm/cpm.h>
#include <asm/dma.h>
#include <asm/reg.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
-#include <asm/qe.h>
+#include <soc/fsl/qe/qe.h>
#include <asm/fsl_gtm.h>
#include "fhci.h"
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/gpio.h>
-#include <asm/qe.h>
+#include <soc/fsl/qe/qe.h>
#include "fhci.h"
/* virtual root hub specific descriptor */
#include <linux/io.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
-#include <asm/qe.h>
+#include <soc/fsl/qe/qe.h>
#include <asm/fsl_gtm.h>
#include "fhci.h"
#include <linux/io.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
-#include <asm/qe.h>
-#include <asm/immap_qe.h>
+#include <soc/fsl/qe/qe.h>
+#include <soc/fsl/qe/immap_qe.h>
#define USB_CLOCK 48000000
--- /dev/null
+/*
+ * QUICC Engine (QE) Internal Memory Map.
+ * The Internal Memory Map for devices with QE on them. This
+ * is the superset of all QE devices (8360, etc.).
+
+ * Copyright (C) 2006. Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Authors: Shlomi Gridish <gridish@freescale.com>
+ * Li Yang <leoli@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#ifndef _ASM_POWERPC_IMMAP_QE_H
+#define _ASM_POWERPC_IMMAP_QE_H
+#ifdef __KERNEL__
+
+#include <linux/kernel.h>
+#include <asm/io.h>
+
+#define QE_IMMAP_SIZE (1024 * 1024) /* 1MB from 1MB+IMMR */
+
+/* QE I-RAM */
+struct qe_iram {
+ __be32 iadd; /* I-RAM Address Register */
+ __be32 idata; /* I-RAM Data Register */
+ u8 res0[0x04];
+ __be32 iready; /* I-RAM Ready Register */
+ u8 res1[0x70];
+} __attribute__ ((packed));
+
+/* QE Interrupt Controller */
+struct qe_ic_regs {
+ __be32 qicr;
+ __be32 qivec;
+ __be32 qripnr;
+ __be32 qipnr;
+ __be32 qipxcc;
+ __be32 qipycc;
+ __be32 qipwcc;
+ __be32 qipzcc;
+ __be32 qimr;
+ __be32 qrimr;
+ __be32 qicnr;
+ u8 res0[0x4];
+ __be32 qiprta;
+ __be32 qiprtb;
+ u8 res1[0x4];
+ __be32 qricr;
+ u8 res2[0x20];
+ __be32 qhivec;
+ u8 res3[0x1C];
+} __attribute__ ((packed));
+
+/* Communications Processor */
+struct cp_qe {
+ __be32 cecr; /* QE command register */
+ __be32 ceccr; /* QE controller configuration register */
+ __be32 cecdr; /* QE command data register */
+ u8 res0[0xA];
+ __be16 ceter; /* QE timer event register */
+ u8 res1[0x2];
+ __be16 cetmr; /* QE timers mask register */
+ __be32 cetscr; /* QE time-stamp timer control register */
+ __be32 cetsr1; /* QE time-stamp register 1 */
+ __be32 cetsr2; /* QE time-stamp register 2 */
+ u8 res2[0x8];
+ __be32 cevter; /* QE virtual tasks event register */
+ __be32 cevtmr; /* QE virtual tasks mask register */
+ __be16 cercr; /* QE RAM control register */
+ u8 res3[0x2];
+ u8 res4[0x24];
+ __be16 ceexe1; /* QE external request 1 event register */
+ u8 res5[0x2];
+ __be16 ceexm1; /* QE external request 1 mask register */
+ u8 res6[0x2];
+ __be16 ceexe2; /* QE external request 2 event register */
+ u8 res7[0x2];
+ __be16 ceexm2; /* QE external request 2 mask register */
+ u8 res8[0x2];
+ __be16 ceexe3; /* QE external request 3 event register */
+ u8 res9[0x2];
+ __be16 ceexm3; /* QE external request 3 mask register */
+ u8 res10[0x2];
+ __be16 ceexe4; /* QE external request 4 event register */
+ u8 res11[0x2];
+ __be16 ceexm4; /* QE external request 4 mask register */
+ u8 res12[0x3A];
+ __be32 ceurnr; /* QE microcode revision number register */
+ u8 res13[0x244];
+} __attribute__ ((packed));
+
+/* QE Multiplexer */
+struct qe_mux {
+ __be32 cmxgcr; /* CMX general clock route register */
+ __be32 cmxsi1cr_l; /* CMX SI1 clock route low register */
+ __be32 cmxsi1cr_h; /* CMX SI1 clock route high register */
+ __be32 cmxsi1syr; /* CMX SI1 SYNC route register */
+ __be32 cmxucr[4]; /* CMX UCCx clock route registers */
+ __be32 cmxupcr; /* CMX UPC clock route register */
+ u8 res0[0x1C];
+} __attribute__ ((packed));
+
+/* QE Timers */
+struct qe_timers {
+ u8 gtcfr1; /* Timer 1 and Timer 2 global config register*/
+ u8 res0[0x3];
+ u8 gtcfr2; /* Timer 3 and timer 4 global config register*/
+ u8 res1[0xB];
+ __be16 gtmdr1; /* Timer 1 mode register */
+ __be16 gtmdr2; /* Timer 2 mode register */
+ __be16 gtrfr1; /* Timer 1 reference register */
+ __be16 gtrfr2; /* Timer 2 reference register */
+ __be16 gtcpr1; /* Timer 1 capture register */
+ __be16 gtcpr2; /* Timer 2 capture register */
+ __be16 gtcnr1; /* Timer 1 counter */
+ __be16 gtcnr2; /* Timer 2 counter */
+ __be16 gtmdr3; /* Timer 3 mode register */
+ __be16 gtmdr4; /* Timer 4 mode register */
+ __be16 gtrfr3; /* Timer 3 reference register */
+ __be16 gtrfr4; /* Timer 4 reference register */
+ __be16 gtcpr3; /* Timer 3 capture register */
+ __be16 gtcpr4; /* Timer 4 capture register */
+ __be16 gtcnr3; /* Timer 3 counter */
+ __be16 gtcnr4; /* Timer 4 counter */
+ __be16 gtevr1; /* Timer 1 event register */
+ __be16 gtevr2; /* Timer 2 event register */
+ __be16 gtevr3; /* Timer 3 event register */
+ __be16 gtevr4; /* Timer 4 event register */
+ __be16 gtps; /* Timer 1 prescale register */
+ u8 res2[0x46];
+} __attribute__ ((packed));
+
+/* BRG */
+struct qe_brg {
+ __be32 brgc[16]; /* BRG configuration registers */
+ u8 res0[0x40];
+} __attribute__ ((packed));
+
+/* SPI */
+struct spi {
+ u8 res0[0x20];
+ __be32 spmode; /* SPI mode register */
+ u8 res1[0x2];
+ u8 spie; /* SPI event register */
+ u8 res2[0x1];
+ u8 res3[0x2];
+ u8 spim; /* SPI mask register */
+ u8 res4[0x1];
+ u8 res5[0x1];
+ u8 spcom; /* SPI command register */
+ u8 res6[0x2];
+ __be32 spitd; /* SPI transmit data register (cpu mode) */
+ __be32 spird; /* SPI receive data register (cpu mode) */
+ u8 res7[0x8];
+} __attribute__ ((packed));
+
+/* SI */
+struct si1 {
+ __be16 siamr1; /* SI1 TDMA mode register */
+ __be16 sibmr1; /* SI1 TDMB mode register */
+ __be16 sicmr1; /* SI1 TDMC mode register */
+ __be16 sidmr1; /* SI1 TDMD mode register */
+ u8 siglmr1_h; /* SI1 global mode register high */
+ u8 res0[0x1];
+ u8 sicmdr1_h; /* SI1 command register high */
+ u8 res2[0x1];
+ u8 sistr1_h; /* SI1 status register high */
+ u8 res3[0x1];
+ __be16 sirsr1_h; /* SI1 RAM shadow address register high */
+ u8 sitarc1; /* SI1 RAM counter Tx TDMA */
+ u8 sitbrc1; /* SI1 RAM counter Tx TDMB */
+ u8 sitcrc1; /* SI1 RAM counter Tx TDMC */
+ u8 sitdrc1; /* SI1 RAM counter Tx TDMD */
+ u8 sirarc1; /* SI1 RAM counter Rx TDMA */
+ u8 sirbrc1; /* SI1 RAM counter Rx TDMB */
+ u8 sircrc1; /* SI1 RAM counter Rx TDMC */
+ u8 sirdrc1; /* SI1 RAM counter Rx TDMD */
+ u8 res4[0x8];
+ __be16 siemr1; /* SI1 TDME mode register 16 bits */
+ __be16 sifmr1; /* SI1 TDMF mode register 16 bits */
+ __be16 sigmr1; /* SI1 TDMG mode register 16 bits */
+ __be16 sihmr1; /* SI1 TDMH mode register 16 bits */
+ u8 siglmg1_l; /* SI1 global mode register low 8 bits */
+ u8 res5[0x1];
+ u8 sicmdr1_l; /* SI1 command register low 8 bits */
+ u8 res6[0x1];
+ u8 sistr1_l; /* SI1 status register low 8 bits */
+ u8 res7[0x1];
+ __be16 sirsr1_l; /* SI1 RAM shadow address register low 16 bits*/
+ u8 siterc1; /* SI1 RAM counter Tx TDME 8 bits */
+ u8 sitfrc1; /* SI1 RAM counter Tx TDMF 8 bits */
+ u8 sitgrc1; /* SI1 RAM counter Tx TDMG 8 bits */
+ u8 sithrc1; /* SI1 RAM counter Tx TDMH 8 bits */
+ u8 sirerc1; /* SI1 RAM counter Rx TDME 8 bits */
+ u8 sirfrc1; /* SI1 RAM counter Rx TDMF 8 bits */
+ u8 sirgrc1; /* SI1 RAM counter Rx TDMG 8 bits */
+ u8 sirhrc1; /* SI1 RAM counter Rx TDMH 8 bits */
+ u8 res8[0x8];
+ __be32 siml1; /* SI1 multiframe limit register */
+ u8 siedm1; /* SI1 extended diagnostic mode register */
+ u8 res9[0xBB];
+} __attribute__ ((packed));
+
+/* SI Routing Tables */
+struct sir {
+ u8 tx[0x400];
+ u8 rx[0x400];
+ u8 res0[0x800];
+} __attribute__ ((packed));
+
+/* USB Controller */
+struct qe_usb_ctlr {
+ u8 usb_usmod;
+ u8 usb_usadr;
+ u8 usb_uscom;
+ u8 res1[1];
+ __be16 usb_usep[4];
+ u8 res2[4];
+ __be16 usb_usber;
+ u8 res3[2];
+ __be16 usb_usbmr;
+ u8 res4[1];
+ u8 usb_usbs;
+ __be16 usb_ussft;
+ u8 res5[2];
+ __be16 usb_usfrn;
+ u8 res6[0x22];
+} __attribute__ ((packed));
+
+/* MCC */
+struct qe_mcc {
+ __be32 mcce; /* MCC event register */
+ __be32 mccm; /* MCC mask register */
+ __be32 mccf; /* MCC configuration register */
+ __be32 merl; /* MCC emergency request level register */
+ u8 res0[0xF0];
+} __attribute__ ((packed));
+
+/* QE UCC Slow */
+struct ucc_slow {
+ __be32 gumr_l; /* UCCx general mode register (low) */
+ __be32 gumr_h; /* UCCx general mode register (high) */
+ __be16 upsmr; /* UCCx protocol-specific mode register */
+ u8 res0[0x2];
+ __be16 utodr; /* UCCx transmit on demand register */
+ __be16 udsr; /* UCCx data synchronization register */
+ __be16 ucce; /* UCCx event register */
+ u8 res1[0x2];
+ __be16 uccm; /* UCCx mask register */
+ u8 res2[0x1];
+ u8 uccs; /* UCCx status register */
+ u8 res3[0x24];
+ __be16 utpt;
+ u8 res4[0x52];
+ u8 guemr; /* UCC general extended mode register */
+} __attribute__ ((packed));
+
+/* QE UCC Fast */
+struct ucc_fast {
+ __be32 gumr; /* UCCx general mode register */
+ __be32 upsmr; /* UCCx protocol-specific mode register */
+ __be16 utodr; /* UCCx transmit on demand register */
+ u8 res0[0x2];
+ __be16 udsr; /* UCCx data synchronization register */
+ u8 res1[0x2];
+ __be32 ucce; /* UCCx event register */
+ __be32 uccm; /* UCCx mask register */
+ u8 uccs; /* UCCx status register */
+ u8 res2[0x7];
+ __be32 urfb; /* UCC receive FIFO base */
+ __be16 urfs; /* UCC receive FIFO size */
+ u8 res3[0x2];
+ __be16 urfet; /* UCC receive FIFO emergency threshold */
+ __be16 urfset; /* UCC receive FIFO special emergency
+ threshold */
+ __be32 utfb; /* UCC transmit FIFO base */
+ __be16 utfs; /* UCC transmit FIFO size */
+ u8 res4[0x2];
+ __be16 utfet; /* UCC transmit FIFO emergency threshold */
+ u8 res5[0x2];
+ __be16 utftt; /* UCC transmit FIFO transmit threshold */
+ u8 res6[0x2];
+ __be16 utpt; /* UCC transmit polling timer */
+ u8 res7[0x2];
+ __be32 urtry; /* UCC retry counter register */
+ u8 res8[0x4C];
+ u8 guemr; /* UCC general extended mode register */
+} __attribute__ ((packed));
+
+struct ucc {
+ union {
+ struct ucc_slow slow;
+ struct ucc_fast fast;
+ u8 res[0x200]; /* UCC blocks are 512 bytes each */
+ };
+} __attribute__ ((packed));
+
+/* MultiPHY UTOPIA POS Controllers (UPC) */
+struct upc {
+ __be32 upgcr; /* UTOPIA/POS general configuration register */
+ __be32 uplpa; /* UTOPIA/POS last PHY address */
+ __be32 uphec; /* ATM HEC register */
+ __be32 upuc; /* UTOPIA/POS UCC configuration */
+ __be32 updc1; /* UTOPIA/POS device 1 configuration */
+ __be32 updc2; /* UTOPIA/POS device 2 configuration */
+ __be32 updc3; /* UTOPIA/POS device 3 configuration */
+ __be32 updc4; /* UTOPIA/POS device 4 configuration */
+ __be32 upstpa; /* UTOPIA/POS STPA threshold */
+ u8 res0[0xC];
+ __be32 updrs1_h; /* UTOPIA/POS device 1 rate select */
+ __be32 updrs1_l; /* UTOPIA/POS device 1 rate select */
+ __be32 updrs2_h; /* UTOPIA/POS device 2 rate select */
+ __be32 updrs2_l; /* UTOPIA/POS device 2 rate select */
+ __be32 updrs3_h; /* UTOPIA/POS device 3 rate select */
+ __be32 updrs3_l; /* UTOPIA/POS device 3 rate select */
+ __be32 updrs4_h; /* UTOPIA/POS device 4 rate select */
+ __be32 updrs4_l; /* UTOPIA/POS device 4 rate select */
+ __be32 updrp1; /* UTOPIA/POS device 1 receive priority low */
+ __be32 updrp2; /* UTOPIA/POS device 2 receive priority low */
+ __be32 updrp3; /* UTOPIA/POS device 3 receive priority low */
+ __be32 updrp4; /* UTOPIA/POS device 4 receive priority low */
+ __be32 upde1; /* UTOPIA/POS device 1 event */
+ __be32 upde2; /* UTOPIA/POS device 2 event */
+ __be32 upde3; /* UTOPIA/POS device 3 event */
+ __be32 upde4; /* UTOPIA/POS device 4 event */
+ __be16 uprp1;
+ __be16 uprp2;
+ __be16 uprp3;
+ __be16 uprp4;
+ u8 res1[0x8];
+ __be16 uptirr1_0; /* Device 1 transmit internal rate 0 */
+ __be16 uptirr1_1; /* Device 1 transmit internal rate 1 */
+ __be16 uptirr1_2; /* Device 1 transmit internal rate 2 */
+ __be16 uptirr1_3; /* Device 1 transmit internal rate 3 */
+ __be16 uptirr2_0; /* Device 2 transmit internal rate 0 */
+ __be16 uptirr2_1; /* Device 2 transmit internal rate 1 */
+ __be16 uptirr2_2; /* Device 2 transmit internal rate 2 */
+ __be16 uptirr2_3; /* Device 2 transmit internal rate 3 */
+ __be16 uptirr3_0; /* Device 3 transmit internal rate 0 */
+ __be16 uptirr3_1; /* Device 3 transmit internal rate 1 */
+ __be16 uptirr3_2; /* Device 3 transmit internal rate 2 */
+ __be16 uptirr3_3; /* Device 3 transmit internal rate 3 */
+ __be16 uptirr4_0; /* Device 4 transmit internal rate 0 */
+ __be16 uptirr4_1; /* Device 4 transmit internal rate 1 */
+ __be16 uptirr4_2; /* Device 4 transmit internal rate 2 */
+ __be16 uptirr4_3; /* Device 4 transmit internal rate 3 */
+ __be32 uper1; /* Device 1 port enable register */
+ __be32 uper2; /* Device 2 port enable register */
+ __be32 uper3; /* Device 3 port enable register */
+ __be32 uper4; /* Device 4 port enable register */
+ u8 res2[0x150];
+} __attribute__ ((packed));
+
+/* SDMA */
+struct sdma {
+ __be32 sdsr; /* Serial DMA status register */
+ __be32 sdmr; /* Serial DMA mode register */
+ __be32 sdtr1; /* SDMA system bus threshold register */
+ __be32 sdtr2; /* SDMA secondary bus threshold register */
+ __be32 sdhy1; /* SDMA system bus hysteresis register */
+ __be32 sdhy2; /* SDMA secondary bus hysteresis register */
+ __be32 sdta1; /* SDMA system bus address register */
+ __be32 sdta2; /* SDMA secondary bus address register */
+ __be32 sdtm1; /* SDMA system bus MSNUM register */
+ __be32 sdtm2; /* SDMA secondary bus MSNUM register */
+ u8 res0[0x10];
+ __be32 sdaqr; /* SDMA address bus qualify register */
+ __be32 sdaqmr; /* SDMA address bus qualify mask register */
+ u8 res1[0x4];
+ __be32 sdebcr; /* SDMA CAM entries base register */
+ u8 res2[0x38];
+} __attribute__ ((packed));
+
+/* Debug Space */
+struct dbg {
+ __be32 bpdcr; /* Breakpoint debug command register */
+ __be32 bpdsr; /* Breakpoint debug status register */
+ __be32 bpdmr; /* Breakpoint debug mask register */
+ __be32 bprmrr0; /* Breakpoint request mode risc register 0 */
+ __be32 bprmrr1; /* Breakpoint request mode risc register 1 */
+ u8 res0[0x8];
+ __be32 bprmtr0; /* Breakpoint request mode trb register 0 */
+ __be32 bprmtr1; /* Breakpoint request mode trb register 1 */
+ u8 res1[0x8];
+ __be32 bprmir; /* Breakpoint request mode immediate register */
+ __be32 bprmsr; /* Breakpoint request mode serial register */
+ __be32 bpemr; /* Breakpoint exit mode register */
+ u8 res2[0x48];
+} __attribute__ ((packed));
+
+/*
+ * RISC Special Registers (Trap and Breakpoint). These are described in
+ * the QE Developer's Handbook.
+ */
+struct rsp {
+ __be32 tibcr[16]; /* Trap/instruction breakpoint control regs */
+ u8 res0[64];
+ __be32 ibcr0;
+ __be32 ibs0;
+ __be32 ibcnr0;
+ u8 res1[4];
+ __be32 ibcr1;
+ __be32 ibs1;
+ __be32 ibcnr1;
+ __be32 npcr;
+ __be32 dbcr;
+ __be32 dbar;
+ __be32 dbamr;
+ __be32 dbsr;
+ __be32 dbcnr;
+ u8 res2[12];
+ __be32 dbdr_h;
+ __be32 dbdr_l;
+ __be32 dbdmr_h;
+ __be32 dbdmr_l;
+ __be32 bsr;
+ __be32 bor;
+ __be32 bior;
+ u8 res3[4];
+ __be32 iatr[4];
+ __be32 eccr; /* Exception control configuration register */
+ __be32 eicr;
+ u8 res4[0x100-0xf8];
+} __attribute__ ((packed));
+
+struct qe_immap {
+ struct qe_iram iram; /* I-RAM */
+ struct qe_ic_regs ic; /* Interrupt Controller */
+ struct cp_qe cp; /* Communications Processor */
+ struct qe_mux qmx; /* QE Multiplexer */
+ struct qe_timers qet; /* QE Timers */
+ struct spi spi[0x2]; /* spi */
+ struct qe_mcc mcc; /* mcc */
+ struct qe_brg brg; /* brg */
+ struct qe_usb_ctlr usb; /* USB */
+ struct si1 si1; /* SI */
+ u8 res11[0x800];
+ struct sir sir; /* SI Routing Tables */
+ struct ucc ucc1; /* ucc1 */
+ struct ucc ucc3; /* ucc3 */
+ struct ucc ucc5; /* ucc5 */
+ struct ucc ucc7; /* ucc7 */
+ u8 res12[0x600];
+ struct upc upc1; /* MultiPHY UTOPIA POS Ctrlr 1*/
+ struct ucc ucc2; /* ucc2 */
+ struct ucc ucc4; /* ucc4 */
+ struct ucc ucc6; /* ucc6 */
+ struct ucc ucc8; /* ucc8 */
+ u8 res13[0x600];
+ struct upc upc2; /* MultiPHY UTOPIA POS Ctrlr 2*/
+ struct sdma sdma; /* SDMA */
+ struct dbg dbg; /* 0x104080 - 0x1040FF
+ Debug Space */
+ struct rsp rsp[0x2]; /* 0x104100 - 0x1042FF
+ RISC Special Registers
+ (Trap and Breakpoint) */
+ u8 res14[0x300]; /* 0x104300 - 0x1045FF */
+ u8 res15[0x3A00]; /* 0x104600 - 0x107FFF */
+ u8 res16[0x8000]; /* 0x108000 - 0x110000 */
+ u8 muram[0xC000]; /* 0x110000 - 0x11C000
+ Multi-user RAM */
+ u8 res17[0x24000]; /* 0x11C000 - 0x140000 */
+ u8 res18[0xC0000]; /* 0x140000 - 0x200000 */
+} __attribute__ ((packed));
+
+extern struct qe_immap __iomem *qe_immr;
+extern phys_addr_t get_qe_base(void);
+
+/*
+ * Returns the offset within the QE address space of the given pointer.
+ *
+ * Note that the QE does not support 36-bit physical addresses, so if
+ * get_qe_base() returns a number above 4GB, the caller will probably fail.
+ */
+static inline phys_addr_t immrbar_virt_to_phys(void *address)
+{
+ void *q = (void *)qe_immr;
+
+ /* Is it a MURAM address? */
+ if ((address >= q) && (address < (q + QE_IMMAP_SIZE)))
+ return get_qe_base() + (address - q);
+
+ /* It's an address returned by kmalloc */
+ return virt_to_phys(address);
+}
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_IMMAP_QE_H */
--- /dev/null
+/*
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Authors: Shlomi Gridish <gridish@freescale.com>
+ * Li Yang <leoli@freescale.com>
+ *
+ * Description:
+ * QUICC Engine (QE) external definitions and structure.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#ifndef _ASM_POWERPC_QE_H
+#define _ASM_POWERPC_QE_H
+#ifdef __KERNEL__
+
+#include <linux/compiler.h>
+#include <linux/genalloc.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <asm/cpm.h>
+#include <soc/fsl/qe/immap_qe.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/types.h>
+
+#define QE_NUM_OF_SNUM 256 /* There are 256 serial number in QE */
+#define QE_NUM_OF_BRGS 16
+#define QE_NUM_OF_PORTS 1024
+
+/* Memory partitions
+*/
+#define MEM_PART_SYSTEM 0
+#define MEM_PART_SECONDARY 1
+#define MEM_PART_MURAM 2
+
+/* Clocks and BRGs */
+enum qe_clock {
+ QE_CLK_NONE = 0,
+ QE_BRG1, /* Baud Rate Generator 1 */
+ QE_BRG2, /* Baud Rate Generator 2 */
+ QE_BRG3, /* Baud Rate Generator 3 */
+ QE_BRG4, /* Baud Rate Generator 4 */
+ QE_BRG5, /* Baud Rate Generator 5 */
+ QE_BRG6, /* Baud Rate Generator 6 */
+ QE_BRG7, /* Baud Rate Generator 7 */
+ QE_BRG8, /* Baud Rate Generator 8 */
+ QE_BRG9, /* Baud Rate Generator 9 */
+ QE_BRG10, /* Baud Rate Generator 10 */
+ QE_BRG11, /* Baud Rate Generator 11 */
+ QE_BRG12, /* Baud Rate Generator 12 */
+ QE_BRG13, /* Baud Rate Generator 13 */
+ QE_BRG14, /* Baud Rate Generator 14 */
+ QE_BRG15, /* Baud Rate Generator 15 */
+ QE_BRG16, /* Baud Rate Generator 16 */
+ QE_CLK1, /* Clock 1 */
+ QE_CLK2, /* Clock 2 */
+ QE_CLK3, /* Clock 3 */
+ QE_CLK4, /* Clock 4 */
+ QE_CLK5, /* Clock 5 */
+ QE_CLK6, /* Clock 6 */
+ QE_CLK7, /* Clock 7 */
+ QE_CLK8, /* Clock 8 */
+ QE_CLK9, /* Clock 9 */
+ QE_CLK10, /* Clock 10 */
+ QE_CLK11, /* Clock 11 */
+ QE_CLK12, /* Clock 12 */
+ QE_CLK13, /* Clock 13 */
+ QE_CLK14, /* Clock 14 */
+ QE_CLK15, /* Clock 15 */
+ QE_CLK16, /* Clock 16 */
+ QE_CLK17, /* Clock 17 */
+ QE_CLK18, /* Clock 18 */
+ QE_CLK19, /* Clock 19 */
+ QE_CLK20, /* Clock 20 */
+ QE_CLK21, /* Clock 21 */
+ QE_CLK22, /* Clock 22 */
+ QE_CLK23, /* Clock 23 */
+ QE_CLK24, /* Clock 24 */
+ QE_CLK_DUMMY
+};
+
+static inline bool qe_clock_is_brg(enum qe_clock clk)
+{
+ return clk >= QE_BRG1 && clk <= QE_BRG16;
+}
+
+extern spinlock_t cmxgcr_lock;
+
+/* Export QE common operations */
+#ifdef CONFIG_QUICC_ENGINE
+extern void qe_reset(void);
+#else
+static inline void qe_reset(void) {}
+#endif
+
+int cpm_muram_init(void);
+
+#if defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE)
+unsigned long cpm_muram_alloc(unsigned long size, unsigned long align);
+int cpm_muram_free(unsigned long offset);
+unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size);
+unsigned long cpm_muram_alloc_common(unsigned long size, genpool_algo_t algo,
+ void *data);
+void __iomem *cpm_muram_addr(unsigned long offset);
+unsigned long cpm_muram_offset(void __iomem *addr);
+dma_addr_t cpm_muram_dma(void __iomem *addr);
+#else
+static inline unsigned long cpm_muram_alloc(unsigned long size,
+ unsigned long align)
+{
+ return -ENOSYS;
+}
+
+static inline int cpm_muram_free(unsigned long offset)
+{
+ return -ENOSYS;
+}
+
+static inline unsigned long cpm_muram_alloc_fixed(unsigned long offset,
+ unsigned long size)
+{
+ return -ENOSYS;
+}
+
+static inline void __iomem *cpm_muram_addr(unsigned long offset)
+{
+ return NULL;
+}
+
+static inline unsigned long cpm_muram_offset(void __iomem *addr)
+{
+ return -ENOSYS;
+}
+
+static inline dma_addr_t cpm_muram_dma(void __iomem *addr)
+{
+ return 0;
+}
+#endif /* defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE) */
+
+/* QE PIO */
+#define QE_PIO_PINS 32
+
+struct qe_pio_regs {
+ __be32 cpodr; /* Open drain register */
+ __be32 cpdata; /* Data register */
+ __be32 cpdir1; /* Direction register */
+ __be32 cpdir2; /* Direction register */
+ __be32 cppar1; /* Pin assignment register */
+ __be32 cppar2; /* Pin assignment register */
+#ifdef CONFIG_PPC_85xx
+ u8 pad[8];
+#endif
+};
+
+#define QE_PIO_DIR_IN 2
+#define QE_PIO_DIR_OUT 1
+extern void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin,
+ int dir, int open_drain, int assignment,
+ int has_irq);
+#ifdef CONFIG_QUICC_ENGINE
+extern int par_io_init(struct device_node *np);
+extern int par_io_of_config(struct device_node *np);
+extern int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
+ int assignment, int has_irq);
+extern int par_io_data_set(u8 port, u8 pin, u8 val);
+#else
+static inline int par_io_init(struct device_node *np) { return -ENOSYS; }
+static inline int par_io_of_config(struct device_node *np) { return -ENOSYS; }
+static inline int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
+ int assignment, int has_irq) { return -ENOSYS; }
+static inline int par_io_data_set(u8 port, u8 pin, u8 val) { return -ENOSYS; }
+#endif /* CONFIG_QUICC_ENGINE */
+
+/*
+ * Pin multiplexing functions.
+ */
+struct qe_pin;
+#ifdef CONFIG_QE_GPIO
+extern struct qe_pin *qe_pin_request(struct device_node *np, int index);
+extern void qe_pin_free(struct qe_pin *qe_pin);
+extern void qe_pin_set_gpio(struct qe_pin *qe_pin);
+extern void qe_pin_set_dedicated(struct qe_pin *pin);
+#else
+static inline struct qe_pin *qe_pin_request(struct device_node *np, int index)
+{
+ return ERR_PTR(-ENOSYS);
+}
+static inline void qe_pin_free(struct qe_pin *qe_pin) {}
+static inline void qe_pin_set_gpio(struct qe_pin *qe_pin) {}
+static inline void qe_pin_set_dedicated(struct qe_pin *pin) {}
+#endif /* CONFIG_QE_GPIO */
+
+#ifdef CONFIG_QUICC_ENGINE
+int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input);
+#else
+static inline int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol,
+ u32 cmd_input)
+{
+ return -ENOSYS;
+}
+#endif /* CONFIG_QUICC_ENGINE */
+
+/* QE internal API */
+enum qe_clock qe_clock_source(const char *source);
+unsigned int qe_get_brg_clk(void);
+int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier);
+int qe_get_snum(void);
+void qe_put_snum(u8 snum);
+unsigned int qe_get_num_of_risc(void);
+unsigned int qe_get_num_of_snums(void);
+
+static inline int qe_alive_during_sleep(void)
+{
+ /*
+ * MPC8568E reference manual says:
+ *
+ * "...power down sequence waits for all I/O interfaces to become idle.
+ * In some applications this may happen eventually without actively
+ * shutting down interfaces, but most likely, software will have to
+ * take steps to shut down the eTSEC, QUICC Engine Block, and PCI
+ * interfaces before issuing the command (either the write to the core
+ * MSR[WE] as described above or writing to POWMGTCSR) to put the
+ * device into sleep state."
+ *
+ * MPC8569E reference manual has a similar paragraph.
+ */
+#ifdef CONFIG_PPC_85xx
+ return 0;
+#else
+ return 1;
+#endif
+}
+
+/* we actually use cpm_muram implementation, define this for convenience */
+#define qe_muram_init cpm_muram_init
+#define qe_muram_alloc cpm_muram_alloc
+#define qe_muram_alloc_fixed cpm_muram_alloc_fixed
+#define qe_muram_free cpm_muram_free
+#define qe_muram_addr cpm_muram_addr
+#define qe_muram_offset cpm_muram_offset
+
+/* Structure that defines QE firmware binary files.
+ *
+ * See Documentation/powerpc/qe_firmware.txt for a description of these
+ * fields.
+ */
+struct qe_firmware {
+ struct qe_header {
+ __be32 length; /* Length of the entire structure, in bytes */
+ u8 magic[3]; /* Set to { 'Q', 'E', 'F' } */
+ u8 version; /* Version of this layout. First ver is '1' */
+ } header;
+ u8 id[62]; /* Null-terminated identifier string */
+ u8 split; /* 0 = shared I-RAM, 1 = split I-RAM */
+ u8 count; /* Number of microcode[] structures */
+ struct {
+ __be16 model; /* The SOC model */
+ u8 major; /* The SOC revision major */
+ u8 minor; /* The SOC revision minor */
+ } __attribute__ ((packed)) soc;
+ u8 padding[4]; /* Reserved, for alignment */
+ __be64 extended_modes; /* Extended modes */
+ __be32 vtraps[8]; /* Virtual trap addresses */
+ u8 reserved[4]; /* Reserved, for future expansion */
+ struct qe_microcode {
+ u8 id[32]; /* Null-terminated identifier */
+ __be32 traps[16]; /* Trap addresses, 0 == ignore */
+ __be32 eccr; /* The value for the ECCR register */
+ __be32 iram_offset; /* Offset into I-RAM for the code */
+ __be32 count; /* Number of 32-bit words of the code */
+ __be32 code_offset; /* Offset of the actual microcode */
+ u8 major; /* The microcode version major */
+ u8 minor; /* The microcode version minor */
+ u8 revision; /* The microcode version revision */
+ u8 padding; /* Reserved, for alignment */
+ u8 reserved[4]; /* Reserved, for future expansion */
+ } __attribute__ ((packed)) microcode[1];
+ /* All microcode binaries should be located here */
+ /* CRC32 should be located here, after the microcode binaries */
+} __attribute__ ((packed));
+
+struct qe_firmware_info {
+ char id[64]; /* Firmware name */
+ u32 vtraps[8]; /* Virtual trap addresses */
+ u64 extended_modes; /* Extended modes */
+};
+
+#ifdef CONFIG_QUICC_ENGINE
+/* Upload a firmware to the QE */
+int qe_upload_firmware(const struct qe_firmware *firmware);
+#else
+static inline int qe_upload_firmware(const struct qe_firmware *firmware)
+{
+ return -ENOSYS;
+}
+#endif /* CONFIG_QUICC_ENGINE */
+
+/* Obtain information on the uploaded firmware */
+struct qe_firmware_info *qe_get_firmware_info(void);
+
+/* QE USB */
+int qe_usb_clock_set(enum qe_clock clk, int rate);
+
+/* Buffer descriptors */
+struct qe_bd {
+ __be16 status;
+ __be16 length;
+ __be32 buf;
+} __attribute__ ((packed));
+
+#define BD_STATUS_MASK 0xffff0000
+#define BD_LENGTH_MASK 0x0000ffff
+
+/* Alignment */
+#define QE_INTR_TABLE_ALIGN 16 /* ??? */
+#define QE_ALIGNMENT_OF_BD 8
+#define QE_ALIGNMENT_OF_PRAM 64
+
+/* RISC allocation */
+#define QE_RISC_ALLOCATION_RISC1 0x1 /* RISC 1 */
+#define QE_RISC_ALLOCATION_RISC2 0x2 /* RISC 2 */
+#define QE_RISC_ALLOCATION_RISC3 0x4 /* RISC 3 */
+#define QE_RISC_ALLOCATION_RISC4 0x8 /* RISC 4 */
+#define QE_RISC_ALLOCATION_RISC1_AND_RISC2 (QE_RISC_ALLOCATION_RISC1 | \
+ QE_RISC_ALLOCATION_RISC2)
+#define QE_RISC_ALLOCATION_FOUR_RISCS (QE_RISC_ALLOCATION_RISC1 | \
+ QE_RISC_ALLOCATION_RISC2 | \
+ QE_RISC_ALLOCATION_RISC3 | \
+ QE_RISC_ALLOCATION_RISC4)
+
+/* QE extended filtering Table Lookup Key Size */
+enum qe_fltr_tbl_lookup_key_size {
+ QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES
+ = 0x3f, /* LookupKey parsed by the Generate LookupKey
+ CMD is truncated to 8 bytes */
+ QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES
+ = 0x5f, /* LookupKey parsed by the Generate LookupKey
+ CMD is truncated to 16 bytes */
+};
+
+/* QE FLTR extended filtering Largest External Table Lookup Key Size */
+enum qe_fltr_largest_external_tbl_lookup_key_size {
+ QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE
+ = 0x0,/* not used */
+ QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES
+ = QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES, /* 8 bytes */
+ QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES
+ = QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES, /* 16 bytes */
+};
+
+/* structure representing QE parameter RAM */
+struct qe_timer_tables {
+ u16 tm_base; /* QE timer table base adr */
+ u16 tm_ptr; /* QE timer table pointer */
+ u16 r_tmr; /* QE timer mode register */
+ u16 r_tmv; /* QE timer valid register */
+ u32 tm_cmd; /* QE timer cmd register */
+ u32 tm_cnt; /* QE timer internal cnt */
+} __attribute__ ((packed));
+
+#define QE_FLTR_TAD_SIZE 8
+
+/* QE extended filtering Termination Action Descriptor (TAD) */
+struct qe_fltr_tad {
+ u8 serialized[QE_FLTR_TAD_SIZE];
+} __attribute__ ((packed));
+
+/* Communication Direction */
+enum comm_dir {
+ COMM_DIR_NONE = 0,
+ COMM_DIR_RX = 1,
+ COMM_DIR_TX = 2,
+ COMM_DIR_RX_AND_TX = 3
+};
+
+/* QE CMXUCR Registers.
+ * There are two UCCs represented in each of the four CMXUCR registers.
+ * These values are for the UCC in the LSBs
+ */
+#define QE_CMXUCR_MII_ENET_MNG 0x00007000
+#define QE_CMXUCR_MII_ENET_MNG_SHIFT 12
+#define QE_CMXUCR_GRANT 0x00008000
+#define QE_CMXUCR_TSA 0x00004000
+#define QE_CMXUCR_BKPT 0x00000100
+#define QE_CMXUCR_TX_CLK_SRC_MASK 0x0000000F
+
+/* QE CMXGCR Registers.
+*/
+#define QE_CMXGCR_MII_ENET_MNG 0x00007000
+#define QE_CMXGCR_MII_ENET_MNG_SHIFT 12
+#define QE_CMXGCR_USBCS 0x0000000f
+#define QE_CMXGCR_USBCS_CLK3 0x1
+#define QE_CMXGCR_USBCS_CLK5 0x2
+#define QE_CMXGCR_USBCS_CLK7 0x3
+#define QE_CMXGCR_USBCS_CLK9 0x4
+#define QE_CMXGCR_USBCS_CLK13 0x5
+#define QE_CMXGCR_USBCS_CLK17 0x6
+#define QE_CMXGCR_USBCS_CLK19 0x7
+#define QE_CMXGCR_USBCS_CLK21 0x8
+#define QE_CMXGCR_USBCS_BRG9 0x9
+#define QE_CMXGCR_USBCS_BRG10 0xa
+
+/* QE CECR Commands.
+*/
+#define QE_CR_FLG 0x00010000
+#define QE_RESET 0x80000000
+#define QE_INIT_TX_RX 0x00000000
+#define QE_INIT_RX 0x00000001
+#define QE_INIT_TX 0x00000002
+#define QE_ENTER_HUNT_MODE 0x00000003
+#define QE_STOP_TX 0x00000004
+#define QE_GRACEFUL_STOP_TX 0x00000005
+#define QE_RESTART_TX 0x00000006
+#define QE_CLOSE_RX_BD 0x00000007
+#define QE_SWITCH_COMMAND 0x00000007
+#define QE_SET_GROUP_ADDRESS 0x00000008
+#define QE_START_IDMA 0x00000009
+#define QE_MCC_STOP_RX 0x00000009
+#define QE_ATM_TRANSMIT 0x0000000a
+#define QE_HPAC_CLEAR_ALL 0x0000000b
+#define QE_GRACEFUL_STOP_RX 0x0000001a
+#define QE_RESTART_RX 0x0000001b
+#define QE_HPAC_SET_PRIORITY 0x0000010b
+#define QE_HPAC_STOP_TX 0x0000020b
+#define QE_HPAC_STOP_RX 0x0000030b
+#define QE_HPAC_GRACEFUL_STOP_TX 0x0000040b
+#define QE_HPAC_GRACEFUL_STOP_RX 0x0000050b
+#define QE_HPAC_START_TX 0x0000060b
+#define QE_HPAC_START_RX 0x0000070b
+#define QE_USB_STOP_TX 0x0000000a
+#define QE_USB_RESTART_TX 0x0000000c
+#define QE_QMC_STOP_TX 0x0000000c
+#define QE_QMC_STOP_RX 0x0000000d
+#define QE_SS7_SU_FIL_RESET 0x0000000e
+/* jonathbr added from here down for 83xx */
+#define QE_RESET_BCS 0x0000000a
+#define QE_MCC_INIT_TX_RX_16 0x00000003
+#define QE_MCC_STOP_TX 0x00000004
+#define QE_MCC_INIT_TX_1 0x00000005
+#define QE_MCC_INIT_RX_1 0x00000006
+#define QE_MCC_RESET 0x00000007
+#define QE_SET_TIMER 0x00000008
+#define QE_RANDOM_NUMBER 0x0000000c
+#define QE_ATM_MULTI_THREAD_INIT 0x00000011
+#define QE_ASSIGN_PAGE 0x00000012
+#define QE_ADD_REMOVE_HASH_ENTRY 0x00000013
+#define QE_START_FLOW_CONTROL 0x00000014
+#define QE_STOP_FLOW_CONTROL 0x00000015
+#define QE_ASSIGN_PAGE_TO_DEVICE 0x00000016
+
+#define QE_ASSIGN_RISC 0x00000010
+#define QE_CR_MCN_NORMAL_SHIFT 6
+#define QE_CR_MCN_USB_SHIFT 4
+#define QE_CR_MCN_RISC_ASSIGN_SHIFT 8
+#define QE_CR_SNUM_SHIFT 17
+
+/* QE CECR Sub Block - sub block of QE command.
+*/
+#define QE_CR_SUBBLOCK_INVALID 0x00000000
+#define QE_CR_SUBBLOCK_USB 0x03200000
+#define QE_CR_SUBBLOCK_UCCFAST1 0x02000000
+#define QE_CR_SUBBLOCK_UCCFAST2 0x02200000
+#define QE_CR_SUBBLOCK_UCCFAST3 0x02400000
+#define QE_CR_SUBBLOCK_UCCFAST4 0x02600000
+#define QE_CR_SUBBLOCK_UCCFAST5 0x02800000
+#define QE_CR_SUBBLOCK_UCCFAST6 0x02a00000
+#define QE_CR_SUBBLOCK_UCCFAST7 0x02c00000
+#define QE_CR_SUBBLOCK_UCCFAST8 0x02e00000
+#define QE_CR_SUBBLOCK_UCCSLOW1 0x00000000
+#define QE_CR_SUBBLOCK_UCCSLOW2 0x00200000
+#define QE_CR_SUBBLOCK_UCCSLOW3 0x00400000
+#define QE_CR_SUBBLOCK_UCCSLOW4 0x00600000
+#define QE_CR_SUBBLOCK_UCCSLOW5 0x00800000
+#define QE_CR_SUBBLOCK_UCCSLOW6 0x00a00000
+#define QE_CR_SUBBLOCK_UCCSLOW7 0x00c00000
+#define QE_CR_SUBBLOCK_UCCSLOW8 0x00e00000
+#define QE_CR_SUBBLOCK_MCC1 0x03800000
+#define QE_CR_SUBBLOCK_MCC2 0x03a00000
+#define QE_CR_SUBBLOCK_MCC3 0x03000000
+#define QE_CR_SUBBLOCK_IDMA1 0x02800000
+#define QE_CR_SUBBLOCK_IDMA2 0x02a00000
+#define QE_CR_SUBBLOCK_IDMA3 0x02c00000
+#define QE_CR_SUBBLOCK_IDMA4 0x02e00000
+#define QE_CR_SUBBLOCK_HPAC 0x01e00000
+#define QE_CR_SUBBLOCK_SPI1 0x01400000
+#define QE_CR_SUBBLOCK_SPI2 0x01600000
+#define QE_CR_SUBBLOCK_RAND 0x01c00000
+#define QE_CR_SUBBLOCK_TIMER 0x01e00000
+#define QE_CR_SUBBLOCK_GENERAL 0x03c00000
+
+/* QE CECR Protocol - For non-MCC, specifies mode for QE CECR command */
+#define QE_CR_PROTOCOL_UNSPECIFIED 0x00 /* For all other protocols */
+#define QE_CR_PROTOCOL_HDLC_TRANSPARENT 0x00
+#define QE_CR_PROTOCOL_QMC 0x02
+#define QE_CR_PROTOCOL_UART 0x04
+#define QE_CR_PROTOCOL_ATM_POS 0x0A
+#define QE_CR_PROTOCOL_ETHERNET 0x0C
+#define QE_CR_PROTOCOL_L2_SWITCH 0x0D
+
+/* BRG configuration register */
+#define QE_BRGC_ENABLE 0x00010000
+#define QE_BRGC_DIVISOR_SHIFT 1
+#define QE_BRGC_DIVISOR_MAX 0xFFF
+#define QE_BRGC_DIV16 1
+
+/* QE Timers registers */
+#define QE_GTCFR1_PCAS 0x80
+#define QE_GTCFR1_STP2 0x20
+#define QE_GTCFR1_RST2 0x10
+#define QE_GTCFR1_GM2 0x08
+#define QE_GTCFR1_GM1 0x04
+#define QE_GTCFR1_STP1 0x02
+#define QE_GTCFR1_RST1 0x01
+
+/* SDMA registers */
+#define QE_SDSR_BER1 0x02000000
+#define QE_SDSR_BER2 0x01000000
+
+#define QE_SDMR_GLB_1_MSK 0x80000000
+#define QE_SDMR_ADR_SEL 0x20000000
+#define QE_SDMR_BER1_MSK 0x02000000
+#define QE_SDMR_BER2_MSK 0x01000000
+#define QE_SDMR_EB1_MSK 0x00800000
+#define QE_SDMR_ER1_MSK 0x00080000
+#define QE_SDMR_ER2_MSK 0x00040000
+#define QE_SDMR_CEN_MASK 0x0000E000
+#define QE_SDMR_SBER_1 0x00000200
+#define QE_SDMR_SBER_2 0x00000200
+#define QE_SDMR_EB1_PR_MASK 0x000000C0
+#define QE_SDMR_ER1_PR 0x00000008
+
+#define QE_SDMR_CEN_SHIFT 13
+#define QE_SDMR_EB1_PR_SHIFT 6
+
+#define QE_SDTM_MSNUM_SHIFT 24
+
+#define QE_SDEBCR_BA_MASK 0x01FFFFFF
+
+/* Communication Processor */
+#define QE_CP_CERCR_MEE 0x8000 /* Multi-user RAM ECC enable */
+#define QE_CP_CERCR_IEE 0x4000 /* Instruction RAM ECC enable */
+#define QE_CP_CERCR_CIR 0x0800 /* Common instruction RAM */
+
+/* I-RAM */
+#define QE_IRAM_IADD_AIE 0x80000000 /* Auto Increment Enable */
+#define QE_IRAM_IADD_BADDR 0x00080000 /* Base Address */
+#define QE_IRAM_READY 0x80000000 /* Ready */
+
+/* UPC */
+#define UPGCR_PROTOCOL 0x80000000 /* protocol ul2 or pl2 */
+#define UPGCR_TMS 0x40000000 /* Transmit master/slave mode */
+#define UPGCR_RMS 0x20000000 /* Receive master/slave mode */
+#define UPGCR_ADDR 0x10000000 /* Master MPHY Addr multiplexing */
+#define UPGCR_DIAG 0x01000000 /* Diagnostic mode */
+
+/* UCC GUEMR register */
+#define UCC_GUEMR_MODE_MASK_RX 0x02
+#define UCC_GUEMR_MODE_FAST_RX 0x02
+#define UCC_GUEMR_MODE_SLOW_RX 0x00
+#define UCC_GUEMR_MODE_MASK_TX 0x01
+#define UCC_GUEMR_MODE_FAST_TX 0x01
+#define UCC_GUEMR_MODE_SLOW_TX 0x00
+#define UCC_GUEMR_MODE_MASK (UCC_GUEMR_MODE_MASK_RX | UCC_GUEMR_MODE_MASK_TX)
+#define UCC_GUEMR_SET_RESERVED3 0x10 /* Bit 3 in the guemr is reserved but
+ must be set 1 */
+
+/* structure representing UCC SLOW parameter RAM */
+struct ucc_slow_pram {
+ __be16 rbase; /* RX BD base address */
+ __be16 tbase; /* TX BD base address */
+ u8 rbmr; /* RX bus mode register (same as CPM's RFCR) */
+ u8 tbmr; /* TX bus mode register (same as CPM's TFCR) */
+ __be16 mrblr; /* Rx buffer length */
+ __be32 rstate; /* Rx internal state */
+ __be32 rptr; /* Rx internal data pointer */
+ __be16 rbptr; /* rb BD Pointer */
+ __be16 rcount; /* Rx internal byte count */
+ __be32 rtemp; /* Rx temp */
+ __be32 tstate; /* Tx internal state */
+ __be32 tptr; /* Tx internal data pointer */
+ __be16 tbptr; /* Tx BD pointer */
+ __be16 tcount; /* Tx byte count */
+ __be32 ttemp; /* Tx temp */
+ __be32 rcrc; /* temp receive CRC */
+ __be32 tcrc; /* temp transmit CRC */
+} __attribute__ ((packed));
+
+/* General UCC SLOW Mode Register (GUMRH & GUMRL) */
+#define UCC_SLOW_GUMR_H_SAM_QMC 0x00000000
+#define UCC_SLOW_GUMR_H_SAM_SATM 0x00008000
+#define UCC_SLOW_GUMR_H_REVD 0x00002000
+#define UCC_SLOW_GUMR_H_TRX 0x00001000
+#define UCC_SLOW_GUMR_H_TTX 0x00000800
+#define UCC_SLOW_GUMR_H_CDP 0x00000400
+#define UCC_SLOW_GUMR_H_CTSP 0x00000200
+#define UCC_SLOW_GUMR_H_CDS 0x00000100
+#define UCC_SLOW_GUMR_H_CTSS 0x00000080
+#define UCC_SLOW_GUMR_H_TFL 0x00000040
+#define UCC_SLOW_GUMR_H_RFW 0x00000020
+#define UCC_SLOW_GUMR_H_TXSY 0x00000010
+#define UCC_SLOW_GUMR_H_4SYNC 0x00000004
+#define UCC_SLOW_GUMR_H_8SYNC 0x00000008
+#define UCC_SLOW_GUMR_H_16SYNC 0x0000000c
+#define UCC_SLOW_GUMR_H_RTSM 0x00000002
+#define UCC_SLOW_GUMR_H_RSYN 0x00000001
+
+#define UCC_SLOW_GUMR_L_TCI 0x10000000
+#define UCC_SLOW_GUMR_L_RINV 0x02000000
+#define UCC_SLOW_GUMR_L_TINV 0x01000000
+#define UCC_SLOW_GUMR_L_TEND 0x00040000
+#define UCC_SLOW_GUMR_L_TDCR_MASK 0x00030000
+#define UCC_SLOW_GUMR_L_TDCR_32 0x00030000
+#define UCC_SLOW_GUMR_L_TDCR_16 0x00020000
+#define UCC_SLOW_GUMR_L_TDCR_8 0x00010000
+#define UCC_SLOW_GUMR_L_TDCR_1 0x00000000
+#define UCC_SLOW_GUMR_L_RDCR_MASK 0x0000c000
+#define UCC_SLOW_GUMR_L_RDCR_32 0x0000c000
+#define UCC_SLOW_GUMR_L_RDCR_16 0x00008000
+#define UCC_SLOW_GUMR_L_RDCR_8 0x00004000
+#define UCC_SLOW_GUMR_L_RDCR_1 0x00000000
+#define UCC_SLOW_GUMR_L_RENC_NRZI 0x00000800
+#define UCC_SLOW_GUMR_L_RENC_NRZ 0x00000000
+#define UCC_SLOW_GUMR_L_TENC_NRZI 0x00000100
+#define UCC_SLOW_GUMR_L_TENC_NRZ 0x00000000
+#define UCC_SLOW_GUMR_L_DIAG_MASK 0x000000c0
+#define UCC_SLOW_GUMR_L_DIAG_LE 0x000000c0
+#define UCC_SLOW_GUMR_L_DIAG_ECHO 0x00000080
+#define UCC_SLOW_GUMR_L_DIAG_LOOP 0x00000040
+#define UCC_SLOW_GUMR_L_DIAG_NORM 0x00000000
+#define UCC_SLOW_GUMR_L_ENR 0x00000020
+#define UCC_SLOW_GUMR_L_ENT 0x00000010
+#define UCC_SLOW_GUMR_L_MODE_MASK 0x0000000F
+#define UCC_SLOW_GUMR_L_MODE_BISYNC 0x00000008
+#define UCC_SLOW_GUMR_L_MODE_AHDLC 0x00000006
+#define UCC_SLOW_GUMR_L_MODE_UART 0x00000004
+#define UCC_SLOW_GUMR_L_MODE_QMC 0x00000002
+
+/* General UCC FAST Mode Register */
+#define UCC_FAST_GUMR_TCI 0x20000000
+#define UCC_FAST_GUMR_TRX 0x10000000
+#define UCC_FAST_GUMR_TTX 0x08000000
+#define UCC_FAST_GUMR_CDP 0x04000000
+#define UCC_FAST_GUMR_CTSP 0x02000000
+#define UCC_FAST_GUMR_CDS 0x01000000
+#define UCC_FAST_GUMR_CTSS 0x00800000
+#define UCC_FAST_GUMR_TXSY 0x00020000
+#define UCC_FAST_GUMR_RSYN 0x00010000
+#define UCC_FAST_GUMR_RTSM 0x00002000
+#define UCC_FAST_GUMR_REVD 0x00000400
+#define UCC_FAST_GUMR_ENR 0x00000020
+#define UCC_FAST_GUMR_ENT 0x00000010
+
+/* UART Slow UCC Event Register (UCCE) */
+#define UCC_UART_UCCE_AB 0x0200
+#define UCC_UART_UCCE_IDLE 0x0100
+#define UCC_UART_UCCE_GRA 0x0080
+#define UCC_UART_UCCE_BRKE 0x0040
+#define UCC_UART_UCCE_BRKS 0x0020
+#define UCC_UART_UCCE_CCR 0x0008
+#define UCC_UART_UCCE_BSY 0x0004
+#define UCC_UART_UCCE_TX 0x0002
+#define UCC_UART_UCCE_RX 0x0001
+
+/* HDLC Slow UCC Event Register (UCCE) */
+#define UCC_HDLC_UCCE_GLR 0x1000
+#define UCC_HDLC_UCCE_GLT 0x0800
+#define UCC_HDLC_UCCE_IDLE 0x0100
+#define UCC_HDLC_UCCE_BRKE 0x0040
+#define UCC_HDLC_UCCE_BRKS 0x0020
+#define UCC_HDLC_UCCE_TXE 0x0010
+#define UCC_HDLC_UCCE_RXF 0x0008
+#define UCC_HDLC_UCCE_BSY 0x0004
+#define UCC_HDLC_UCCE_TXB 0x0002
+#define UCC_HDLC_UCCE_RXB 0x0001
+
+/* BISYNC Slow UCC Event Register (UCCE) */
+#define UCC_BISYNC_UCCE_GRA 0x0080
+#define UCC_BISYNC_UCCE_TXE 0x0010
+#define UCC_BISYNC_UCCE_RCH 0x0008
+#define UCC_BISYNC_UCCE_BSY 0x0004
+#define UCC_BISYNC_UCCE_TXB 0x0002
+#define UCC_BISYNC_UCCE_RXB 0x0001
+
+/* Gigabit Ethernet Fast UCC Event Register (UCCE) */
+#define UCC_GETH_UCCE_MPD 0x80000000
+#define UCC_GETH_UCCE_SCAR 0x40000000
+#define UCC_GETH_UCCE_GRA 0x20000000
+#define UCC_GETH_UCCE_CBPR 0x10000000
+#define UCC_GETH_UCCE_BSY 0x08000000
+#define UCC_GETH_UCCE_RXC 0x04000000
+#define UCC_GETH_UCCE_TXC 0x02000000
+#define UCC_GETH_UCCE_TXE 0x01000000
+#define UCC_GETH_UCCE_TXB7 0x00800000
+#define UCC_GETH_UCCE_TXB6 0x00400000
+#define UCC_GETH_UCCE_TXB5 0x00200000
+#define UCC_GETH_UCCE_TXB4 0x00100000
+#define UCC_GETH_UCCE_TXB3 0x00080000
+#define UCC_GETH_UCCE_TXB2 0x00040000
+#define UCC_GETH_UCCE_TXB1 0x00020000
+#define UCC_GETH_UCCE_TXB0 0x00010000
+#define UCC_GETH_UCCE_RXB7 0x00008000
+#define UCC_GETH_UCCE_RXB6 0x00004000
+#define UCC_GETH_UCCE_RXB5 0x00002000
+#define UCC_GETH_UCCE_RXB4 0x00001000
+#define UCC_GETH_UCCE_RXB3 0x00000800
+#define UCC_GETH_UCCE_RXB2 0x00000400
+#define UCC_GETH_UCCE_RXB1 0x00000200
+#define UCC_GETH_UCCE_RXB0 0x00000100
+#define UCC_GETH_UCCE_RXF7 0x00000080
+#define UCC_GETH_UCCE_RXF6 0x00000040
+#define UCC_GETH_UCCE_RXF5 0x00000020
+#define UCC_GETH_UCCE_RXF4 0x00000010
+#define UCC_GETH_UCCE_RXF3 0x00000008
+#define UCC_GETH_UCCE_RXF2 0x00000004
+#define UCC_GETH_UCCE_RXF1 0x00000002
+#define UCC_GETH_UCCE_RXF0 0x00000001
+
+/* UCC Protocol Specific Mode Register (UPSMR), when used for UART */
+#define UCC_UART_UPSMR_FLC 0x8000
+#define UCC_UART_UPSMR_SL 0x4000
+#define UCC_UART_UPSMR_CL_MASK 0x3000
+#define UCC_UART_UPSMR_CL_8 0x3000
+#define UCC_UART_UPSMR_CL_7 0x2000
+#define UCC_UART_UPSMR_CL_6 0x1000
+#define UCC_UART_UPSMR_CL_5 0x0000
+#define UCC_UART_UPSMR_UM_MASK 0x0c00
+#define UCC_UART_UPSMR_UM_NORMAL 0x0000
+#define UCC_UART_UPSMR_UM_MAN_MULTI 0x0400
+#define UCC_UART_UPSMR_UM_AUTO_MULTI 0x0c00
+#define UCC_UART_UPSMR_FRZ 0x0200
+#define UCC_UART_UPSMR_RZS 0x0100
+#define UCC_UART_UPSMR_SYN 0x0080
+#define UCC_UART_UPSMR_DRT 0x0040
+#define UCC_UART_UPSMR_PEN 0x0010
+#define UCC_UART_UPSMR_RPM_MASK 0x000c
+#define UCC_UART_UPSMR_RPM_ODD 0x0000
+#define UCC_UART_UPSMR_RPM_LOW 0x0004
+#define UCC_UART_UPSMR_RPM_EVEN 0x0008
+#define UCC_UART_UPSMR_RPM_HIGH 0x000C
+#define UCC_UART_UPSMR_TPM_MASK 0x0003
+#define UCC_UART_UPSMR_TPM_ODD 0x0000
+#define UCC_UART_UPSMR_TPM_LOW 0x0001
+#define UCC_UART_UPSMR_TPM_EVEN 0x0002
+#define UCC_UART_UPSMR_TPM_HIGH 0x0003
+
+/* UCC Protocol Specific Mode Register (UPSMR), when used for Ethernet */
+#define UCC_GETH_UPSMR_FTFE 0x80000000
+#define UCC_GETH_UPSMR_PTPE 0x40000000
+#define UCC_GETH_UPSMR_ECM 0x04000000
+#define UCC_GETH_UPSMR_HSE 0x02000000
+#define UCC_GETH_UPSMR_PRO 0x00400000
+#define UCC_GETH_UPSMR_CAP 0x00200000
+#define UCC_GETH_UPSMR_RSH 0x00100000
+#define UCC_GETH_UPSMR_RPM 0x00080000
+#define UCC_GETH_UPSMR_R10M 0x00040000
+#define UCC_GETH_UPSMR_RLPB 0x00020000
+#define UCC_GETH_UPSMR_TBIM 0x00010000
+#define UCC_GETH_UPSMR_RES1 0x00002000
+#define UCC_GETH_UPSMR_RMM 0x00001000
+#define UCC_GETH_UPSMR_CAM 0x00000400
+#define UCC_GETH_UPSMR_BRO 0x00000200
+#define UCC_GETH_UPSMR_SMM 0x00000080
+#define UCC_GETH_UPSMR_SGMM 0x00000020
+
+/* UCC Transmit On Demand Register (UTODR) */
+#define UCC_SLOW_TOD 0x8000
+#define UCC_FAST_TOD 0x8000
+
+/* UCC Bus Mode Register masks */
+/* Not to be confused with the Bundle Mode Register */
+#define UCC_BMR_GBL 0x20
+#define UCC_BMR_BO_BE 0x10
+#define UCC_BMR_CETM 0x04
+#define UCC_BMR_DTB 0x02
+#define UCC_BMR_BDB 0x01
+
+/* Function code masks */
+#define FC_GBL 0x20
+#define FC_DTB_LCL 0x02
+#define UCC_FAST_FUNCTION_CODE_GBL 0x20
+#define UCC_FAST_FUNCTION_CODE_DTB_LCL 0x02
+#define UCC_FAST_FUNCTION_CODE_BDB_LCL 0x01
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_QE_H */
--- /dev/null
+/*
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Authors: Shlomi Gridish <gridish@freescale.com>
+ * Li Yang <leoli@freescale.com>
+ *
+ * Description:
+ * QE IC external definitions and structure.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#ifndef _ASM_POWERPC_QE_IC_H
+#define _ASM_POWERPC_QE_IC_H
+
+#include <linux/irq.h>
+
+struct device_node;
+struct qe_ic;
+
+#define NUM_OF_QE_IC_GROUPS 6
+
+/* Flags when we init the QE IC */
+#define QE_IC_SPREADMODE_GRP_W 0x00000001
+#define QE_IC_SPREADMODE_GRP_X 0x00000002
+#define QE_IC_SPREADMODE_GRP_Y 0x00000004
+#define QE_IC_SPREADMODE_GRP_Z 0x00000008
+#define QE_IC_SPREADMODE_GRP_RISCA 0x00000010
+#define QE_IC_SPREADMODE_GRP_RISCB 0x00000020
+
+#define QE_IC_LOW_SIGNAL 0x00000100
+#define QE_IC_HIGH_SIGNAL 0x00000200
+
+#define QE_IC_GRP_W_PRI0_DEST_SIGNAL_HIGH 0x00001000
+#define QE_IC_GRP_W_PRI1_DEST_SIGNAL_HIGH 0x00002000
+#define QE_IC_GRP_X_PRI0_DEST_SIGNAL_HIGH 0x00004000
+#define QE_IC_GRP_X_PRI1_DEST_SIGNAL_HIGH 0x00008000
+#define QE_IC_GRP_Y_PRI0_DEST_SIGNAL_HIGH 0x00010000
+#define QE_IC_GRP_Y_PRI1_DEST_SIGNAL_HIGH 0x00020000
+#define QE_IC_GRP_Z_PRI0_DEST_SIGNAL_HIGH 0x00040000
+#define QE_IC_GRP_Z_PRI1_DEST_SIGNAL_HIGH 0x00080000
+#define QE_IC_GRP_RISCA_PRI0_DEST_SIGNAL_HIGH 0x00100000
+#define QE_IC_GRP_RISCA_PRI1_DEST_SIGNAL_HIGH 0x00200000
+#define QE_IC_GRP_RISCB_PRI0_DEST_SIGNAL_HIGH 0x00400000
+#define QE_IC_GRP_RISCB_PRI1_DEST_SIGNAL_HIGH 0x00800000
+#define QE_IC_GRP_W_DEST_SIGNAL_SHIFT (12)
+
+/* QE interrupt sources groups */
+enum qe_ic_grp_id {
+ QE_IC_GRP_W = 0, /* QE interrupt controller group W */
+ QE_IC_GRP_X, /* QE interrupt controller group X */
+ QE_IC_GRP_Y, /* QE interrupt controller group Y */
+ QE_IC_GRP_Z, /* QE interrupt controller group Z */
+ QE_IC_GRP_RISCA, /* QE interrupt controller RISC group A */
+ QE_IC_GRP_RISCB /* QE interrupt controller RISC group B */
+};
+
+#ifdef CONFIG_QUICC_ENGINE
+void qe_ic_init(struct device_node *node, unsigned int flags,
+ void (*low_handler)(struct irq_desc *desc),
+ void (*high_handler)(struct irq_desc *desc));
+unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic);
+unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic);
+#else
+static inline void qe_ic_init(struct device_node *node, unsigned int flags,
+ void (*low_handler)(struct irq_desc *desc),
+ void (*high_handler)(struct irq_desc *desc))
+{}
+static inline unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic)
+{ return 0; }
+static inline unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic)
+{ return 0; }
+#endif /* CONFIG_QUICC_ENGINE */
+
+void qe_ic_set_highest_priority(unsigned int virq, int high);
+int qe_ic_set_priority(unsigned int virq, unsigned int priority);
+int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high);
+
+static inline void qe_ic_cascade_low_ipic(struct irq_desc *desc)
+{
+ struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
+ unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
+
+ if (cascade_irq != NO_IRQ)
+ generic_handle_irq(cascade_irq);
+}
+
+static inline void qe_ic_cascade_high_ipic(struct irq_desc *desc)
+{
+ struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
+ unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
+
+ if (cascade_irq != NO_IRQ)
+ generic_handle_irq(cascade_irq);
+}
+
+static inline void qe_ic_cascade_low_mpic(struct irq_desc *desc)
+{
+ struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
+ unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+
+ if (cascade_irq != NO_IRQ)
+ generic_handle_irq(cascade_irq);
+
+ chip->irq_eoi(&desc->irq_data);
+}
+
+static inline void qe_ic_cascade_high_mpic(struct irq_desc *desc)
+{
+ struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
+ unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+
+ if (cascade_irq != NO_IRQ)
+ generic_handle_irq(cascade_irq);
+
+ chip->irq_eoi(&desc->irq_data);
+}
+
+static inline void qe_ic_cascade_muxed_mpic(struct irq_desc *desc)
+{
+ struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
+ unsigned int cascade_irq;
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+
+ cascade_irq = qe_ic_get_high_irq(qe_ic);
+ if (cascade_irq == NO_IRQ)
+ cascade_irq = qe_ic_get_low_irq(qe_ic);
+
+ if (cascade_irq != NO_IRQ)
+ generic_handle_irq(cascade_irq);
+
+ chip->irq_eoi(&desc->irq_data);
+}
+
+#endif /* _ASM_POWERPC_QE_IC_H */
--- /dev/null
+/*
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Authors: Shlomi Gridish <gridish@freescale.com>
+ * Li Yang <leoli@freescale.com>
+ *
+ * Description:
+ * Internal header file for UCC unit routines.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#ifndef __UCC_H__
+#define __UCC_H__
+
+#include <soc/fsl/qe/immap_qe.h>
+#include <soc/fsl/qe/qe.h>
+
+#define STATISTICS
+
+#define UCC_MAX_NUM 8
+
+/* Slow or fast type for UCCs.
+*/
+enum ucc_speed_type {
+ UCC_SPEED_TYPE_FAST = UCC_GUEMR_MODE_FAST_RX | UCC_GUEMR_MODE_FAST_TX,
+ UCC_SPEED_TYPE_SLOW = UCC_GUEMR_MODE_SLOW_RX | UCC_GUEMR_MODE_SLOW_TX
+};
+
+/* ucc_set_type
+ * Sets UCC to slow or fast mode.
+ *
+ * ucc_num - (In) number of UCC (0-7).
+ * speed - (In) slow or fast mode for UCC.
+ */
+int ucc_set_type(unsigned int ucc_num, enum ucc_speed_type speed);
+
+int ucc_set_qe_mux_mii_mng(unsigned int ucc_num);
+
+int ucc_set_qe_mux_rxtx(unsigned int ucc_num, enum qe_clock clock,
+ enum comm_dir mode);
+
+int ucc_mux_set_grant_tsa_bkpt(unsigned int ucc_num, int set, u32 mask);
+
+/* QE MUX clock routing for UCC
+*/
+static inline int ucc_set_qe_mux_grant(unsigned int ucc_num, int set)
+{
+ return ucc_mux_set_grant_tsa_bkpt(ucc_num, set, QE_CMXUCR_GRANT);
+}
+
+static inline int ucc_set_qe_mux_tsa(unsigned int ucc_num, int set)
+{
+ return ucc_mux_set_grant_tsa_bkpt(ucc_num, set, QE_CMXUCR_TSA);
+}
+
+static inline int ucc_set_qe_mux_bkpt(unsigned int ucc_num, int set)
+{
+ return ucc_mux_set_grant_tsa_bkpt(ucc_num, set, QE_CMXUCR_BKPT);
+}
+
+#endif /* __UCC_H__ */
--- /dev/null
+/*
+ * Internal header file for UCC FAST unit routines.
+ *
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Authors: Shlomi Gridish <gridish@freescale.com>
+ * Li Yang <leoli@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#ifndef __UCC_FAST_H__
+#define __UCC_FAST_H__
+
+#include <linux/kernel.h>
+
+#include <soc/fsl/qe/immap_qe.h>
+#include <soc/fsl/qe/qe.h>
+
+#include <soc/fsl/qe/ucc.h>
+
+/* Receive BD's status */
+#define R_E 0x80000000 /* buffer empty */
+#define R_W 0x20000000 /* wrap bit */
+#define R_I 0x10000000 /* interrupt on reception */
+#define R_L 0x08000000 /* last */
+#define R_F 0x04000000 /* first */
+
+/* transmit BD's status */
+#define T_R 0x80000000 /* ready bit */
+#define T_W 0x20000000 /* wrap bit */
+#define T_I 0x10000000 /* interrupt on completion */
+#define T_L 0x08000000 /* last */
+
+/* Rx Data buffer must be 4 bytes aligned in most cases */
+#define UCC_FAST_RX_ALIGN 4
+#define UCC_FAST_MRBLR_ALIGNMENT 4
+#define UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT 8
+
+/* Sizes */
+#define UCC_FAST_URFS_MIN_VAL 0x88
+#define UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR 8
+
+/* ucc_fast_channel_protocol_mode - UCC FAST mode */
+enum ucc_fast_channel_protocol_mode {
+ UCC_FAST_PROTOCOL_MODE_HDLC = 0x00000000,
+ UCC_FAST_PROTOCOL_MODE_RESERVED01 = 0x00000001,
+ UCC_FAST_PROTOCOL_MODE_RESERVED_QMC = 0x00000002,
+ UCC_FAST_PROTOCOL_MODE_RESERVED02 = 0x00000003,
+ UCC_FAST_PROTOCOL_MODE_RESERVED_UART = 0x00000004,
+ UCC_FAST_PROTOCOL_MODE_RESERVED03 = 0x00000005,
+ UCC_FAST_PROTOCOL_MODE_RESERVED_EX_MAC_1 = 0x00000006,
+ UCC_FAST_PROTOCOL_MODE_RESERVED_EX_MAC_2 = 0x00000007,
+ UCC_FAST_PROTOCOL_MODE_RESERVED_BISYNC = 0x00000008,
+ UCC_FAST_PROTOCOL_MODE_RESERVED04 = 0x00000009,
+ UCC_FAST_PROTOCOL_MODE_ATM = 0x0000000A,
+ UCC_FAST_PROTOCOL_MODE_RESERVED05 = 0x0000000B,
+ UCC_FAST_PROTOCOL_MODE_ETHERNET = 0x0000000C,
+ UCC_FAST_PROTOCOL_MODE_RESERVED06 = 0x0000000D,
+ UCC_FAST_PROTOCOL_MODE_POS = 0x0000000E,
+ UCC_FAST_PROTOCOL_MODE_RESERVED07 = 0x0000000F
+};
+
+/* ucc_fast_transparent_txrx - UCC Fast Transparent TX & RX */
+enum ucc_fast_transparent_txrx {
+ UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL = 0x00000000,
+ UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_TRANSPARENT = 0x18000000
+};
+
+/* UCC fast diagnostic mode */
+enum ucc_fast_diag_mode {
+ UCC_FAST_DIAGNOSTIC_NORMAL = 0x0,
+ UCC_FAST_DIAGNOSTIC_LOCAL_LOOP_BACK = 0x40000000,
+ UCC_FAST_DIAGNOSTIC_AUTO_ECHO = 0x80000000,
+ UCC_FAST_DIAGNOSTIC_LOOP_BACK_AND_ECHO = 0xC0000000
+};
+
+/* UCC fast Sync length (transparent mode only) */
+enum ucc_fast_sync_len {
+ UCC_FAST_SYNC_LEN_NOT_USED = 0x0,
+ UCC_FAST_SYNC_LEN_AUTOMATIC = 0x00004000,
+ UCC_FAST_SYNC_LEN_8_BIT = 0x00008000,
+ UCC_FAST_SYNC_LEN_16_BIT = 0x0000C000
+};
+
+/* UCC fast RTS mode */
+enum ucc_fast_ready_to_send {
+ UCC_FAST_SEND_IDLES_BETWEEN_FRAMES = 0x00000000,
+ UCC_FAST_SEND_FLAGS_BETWEEN_FRAMES = 0x00002000
+};
+
+/* UCC fast receiver decoding mode */
+enum ucc_fast_rx_decoding_method {
+ UCC_FAST_RX_ENCODING_NRZ = 0x00000000,
+ UCC_FAST_RX_ENCODING_NRZI = 0x00000800,
+ UCC_FAST_RX_ENCODING_RESERVED0 = 0x00001000,
+ UCC_FAST_RX_ENCODING_RESERVED1 = 0x00001800
+};
+
+/* UCC fast transmitter encoding mode */
+enum ucc_fast_tx_encoding_method {
+ UCC_FAST_TX_ENCODING_NRZ = 0x00000000,
+ UCC_FAST_TX_ENCODING_NRZI = 0x00000100,
+ UCC_FAST_TX_ENCODING_RESERVED0 = 0x00000200,
+ UCC_FAST_TX_ENCODING_RESERVED1 = 0x00000300
+};
+
+/* UCC fast CRC length */
+enum ucc_fast_transparent_tcrc {
+ UCC_FAST_16_BIT_CRC = 0x00000000,
+ UCC_FAST_CRC_RESERVED0 = 0x00000040,
+ UCC_FAST_32_BIT_CRC = 0x00000080,
+ UCC_FAST_CRC_RESERVED1 = 0x000000C0
+};
+
+/* Fast UCC initialization structure */
+struct ucc_fast_info {
+ int ucc_num;
+ enum qe_clock rx_clock;
+ enum qe_clock tx_clock;
+ u32 regs;
+ int irq;
+ u32 uccm_mask;
+ int bd_mem_part;
+ int brkpt_support;
+ int grant_support;
+ int tsa;
+ int cdp;
+ int cds;
+ int ctsp;
+ int ctss;
+ int tci;
+ int txsy;
+ int rtsm;
+ int revd;
+ int rsyn;
+ u16 max_rx_buf_length;
+ u16 urfs;
+ u16 urfet;
+ u16 urfset;
+ u16 utfs;
+ u16 utfet;
+ u16 utftt;
+ u16 ufpt;
+ enum ucc_fast_channel_protocol_mode mode;
+ enum ucc_fast_transparent_txrx ttx_trx;
+ enum ucc_fast_tx_encoding_method tenc;
+ enum ucc_fast_rx_decoding_method renc;
+ enum ucc_fast_transparent_tcrc tcrc;
+ enum ucc_fast_sync_len synl;
+};
+
+struct ucc_fast_private {
+ struct ucc_fast_info *uf_info;
+ struct ucc_fast __iomem *uf_regs; /* a pointer to the UCC regs. */
+ u32 __iomem *p_ucce; /* a pointer to the event register in memory. */
+ u32 __iomem *p_uccm; /* a pointer to the mask register in memory. */
+#ifdef CONFIG_UGETH_TX_ON_DEMAND
+ u16 __iomem *p_utodr; /* pointer to the transmit on demand register */
+#endif
+ int enabled_tx; /* Whether channel is enabled for Tx (ENT) */
+ int enabled_rx; /* Whether channel is enabled for Rx (ENR) */
+ int stopped_tx; /* Whether channel has been stopped for Tx
+ (STOP_TX, etc.) */
+ int stopped_rx; /* Whether channel has been stopped for Rx */
+ u32 ucc_fast_tx_virtual_fifo_base_offset;/* pointer to base of Tx
+ virtual fifo */
+ u32 ucc_fast_rx_virtual_fifo_base_offset;/* pointer to base of Rx
+ virtual fifo */
+#ifdef STATISTICS
+ u32 tx_frames; /* Transmitted frames counter. */
+ u32 rx_frames; /* Received frames counter (only frames
+ passed to application). */
+ u32 tx_discarded; /* Discarded tx frames counter (frames that
+ were discarded by the driver due to errors).
+ */
+ u32 rx_discarded; /* Discarded rx frames counter (frames that
+ were discarded by the driver due to errors).
+ */
+#endif /* STATISTICS */
+ u16 mrblr; /* maximum receive buffer length */
+};
+
+/* ucc_fast_init
+ * Initializes Fast UCC according to user provided parameters.
+ *
+ * uf_info - (In) pointer to the fast UCC info structure.
+ * uccf_ret - (Out) pointer to the fast UCC structure.
+ */
+int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret);
+
+/* ucc_fast_free
+ * Frees all resources for fast UCC.
+ *
+ * uccf - (In) pointer to the fast UCC structure.
+ */
+void ucc_fast_free(struct ucc_fast_private * uccf);
+
+/* ucc_fast_enable
+ * Enables a fast UCC port.
+ * This routine enables Tx and/or Rx through the General UCC Mode Register.
+ *
+ * uccf - (In) pointer to the fast UCC structure.
+ * mode - (In) TX, RX, or both.
+ */
+void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode);
+
+/* ucc_fast_disable
+ * Disables a fast UCC port.
+ * This routine disables Tx and/or Rx through the General UCC Mode Register.
+ *
+ * uccf - (In) pointer to the fast UCC structure.
+ * mode - (In) TX, RX, or both.
+ */
+void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode);
+
+/* ucc_fast_irq
+ * Handles interrupts on fast UCC.
+ * Called from the general interrupt routine to handle interrupts on fast UCC.
+ *
+ * uccf - (In) pointer to the fast UCC structure.
+ */
+void ucc_fast_irq(struct ucc_fast_private * uccf);
+
+/* ucc_fast_transmit_on_demand
+ * Immediately forces a poll of the transmitter for data to be sent.
+ * Typically, the hardware performs a periodic poll for data that the
+ * transmit routine has set up to be transmitted. In cases where
+ * this polling cycle is not soon enough, this optional routine can
+ * be invoked to force a poll right away, instead. Proper use for
+ * each transmission for which this functionality is desired is to
+ * call the transmit routine and then this routine right after.
+ *
+ * uccf - (In) pointer to the fast UCC structure.
+ */
+void ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf);
+
+u32 ucc_fast_get_qe_cr_subblock(int uccf_num);
+
+void ucc_fast_dump_regs(struct ucc_fast_private * uccf);
+
+#endif /* __UCC_FAST_H__ */
--- /dev/null
+/*
+ * Copyright (C) 2006 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Authors: Shlomi Gridish <gridish@freescale.com>
+ * Li Yang <leoli@freescale.com>
+ *
+ * Description:
+ * Internal header file for UCC SLOW unit routines.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#ifndef __UCC_SLOW_H__
+#define __UCC_SLOW_H__
+
+#include <linux/kernel.h>
+
+#include <soc/fsl/qe/immap_qe.h>
+#include <soc/fsl/qe/qe.h>
+
+#include <soc/fsl/qe/ucc.h>
+
+/* transmit BD's status */
+#define T_R 0x80000000 /* ready bit */
+#define T_PAD 0x40000000 /* add pads to short frames */
+#define T_W 0x20000000 /* wrap bit */
+#define T_I 0x10000000 /* interrupt on completion */
+#define T_L 0x08000000 /* last */
+
+#define T_A 0x04000000 /* Address - the data transmitted as address
+ chars */
+#define T_TC 0x04000000 /* transmit CRC */
+#define T_CM 0x02000000 /* continuous mode */
+#define T_DEF 0x02000000 /* collision on previous attempt to transmit */
+#define T_P 0x01000000 /* Preamble - send Preamble sequence before
+ data */
+#define T_HB 0x01000000 /* heartbeat */
+#define T_NS 0x00800000 /* No Stop */
+#define T_LC 0x00800000 /* late collision */
+#define T_RL 0x00400000 /* retransmission limit */
+#define T_UN 0x00020000 /* underrun */
+#define T_CT 0x00010000 /* CTS lost */
+#define T_CSL 0x00010000 /* carrier sense lost */
+#define T_RC 0x003c0000 /* retry count */
+
+/* Receive BD's status */
+#define R_E 0x80000000 /* buffer empty */
+#define R_W 0x20000000 /* wrap bit */
+#define R_I 0x10000000 /* interrupt on reception */
+#define R_L 0x08000000 /* last */
+#define R_C 0x08000000 /* the last byte in this buffer is a cntl
+ char */
+#define R_F 0x04000000 /* first */
+#define R_A 0x04000000 /* the first byte in this buffer is address
+ byte */
+#define R_CM 0x02000000 /* continuous mode */
+#define R_ID 0x01000000 /* buffer close on reception of idles */
+#define R_M 0x01000000 /* Frame received because of promiscuous
+ mode */
+#define R_AM 0x00800000 /* Address match */
+#define R_DE 0x00800000 /* Address match */
+#define R_LG 0x00200000 /* Break received */
+#define R_BR 0x00200000 /* Frame length violation */
+#define R_NO 0x00100000 /* Rx Non Octet Aligned Packet */
+#define R_FR 0x00100000 /* Framing Error (no stop bit) character
+ received */
+#define R_PR 0x00080000 /* Parity Error character received */
+#define R_AB 0x00080000 /* Frame Aborted */
+#define R_SH 0x00080000 /* frame is too short */
+#define R_CR 0x00040000 /* CRC Error */
+#define R_OV 0x00020000 /* Overrun */
+#define R_CD 0x00010000 /* CD lost */
+#define R_CL 0x00010000 /* this frame is closed because of a
+ collision */
+
+/* Rx Data buffer must be 4 bytes aligned in most cases.*/
+#define UCC_SLOW_RX_ALIGN 4
+#define UCC_SLOW_MRBLR_ALIGNMENT 4
+#define UCC_SLOW_PRAM_SIZE 0x100
+#define ALIGNMENT_OF_UCC_SLOW_PRAM 64
+
+/* UCC Slow Channel Protocol Mode */
+enum ucc_slow_channel_protocol_mode {
+ UCC_SLOW_CHANNEL_PROTOCOL_MODE_QMC = 0x00000002,
+ UCC_SLOW_CHANNEL_PROTOCOL_MODE_UART = 0x00000004,
+ UCC_SLOW_CHANNEL_PROTOCOL_MODE_BISYNC = 0x00000008,
+};
+
+/* UCC Slow Transparent Transmit CRC (TCRC) */
+enum ucc_slow_transparent_tcrc {
+ /* 16-bit CCITT CRC (HDLC). (X16 + X12 + X5 + 1) */
+ UCC_SLOW_TRANSPARENT_TCRC_CCITT_CRC16 = 0x00000000,
+ /* CRC16 (BISYNC). (X16 + X15 + X2 + 1) */
+ UCC_SLOW_TRANSPARENT_TCRC_CRC16 = 0x00004000,
+ /* 32-bit CCITT CRC (Ethernet and HDLC) */
+ UCC_SLOW_TRANSPARENT_TCRC_CCITT_CRC32 = 0x00008000,
+};
+
+/* UCC Slow oversampling rate for transmitter (TDCR) */
+enum ucc_slow_tx_oversampling_rate {
+ /* 1x clock mode */
+ UCC_SLOW_OVERSAMPLING_RATE_TX_TDCR_1 = 0x00000000,
+ /* 8x clock mode */
+ UCC_SLOW_OVERSAMPLING_RATE_TX_TDCR_8 = 0x00010000,
+ /* 16x clock mode */
+ UCC_SLOW_OVERSAMPLING_RATE_TX_TDCR_16 = 0x00020000,
+ /* 32x clock mode */
+ UCC_SLOW_OVERSAMPLING_RATE_TX_TDCR_32 = 0x00030000,
+};
+
+/* UCC Slow Oversampling rate for receiver (RDCR)
+*/
+enum ucc_slow_rx_oversampling_rate {
+ /* 1x clock mode */
+ UCC_SLOW_OVERSAMPLING_RATE_RX_RDCR_1 = 0x00000000,
+ /* 8x clock mode */
+ UCC_SLOW_OVERSAMPLING_RATE_RX_RDCR_8 = 0x00004000,
+ /* 16x clock mode */
+ UCC_SLOW_OVERSAMPLING_RATE_RX_RDCR_16 = 0x00008000,
+ /* 32x clock mode */
+ UCC_SLOW_OVERSAMPLING_RATE_RX_RDCR_32 = 0x0000c000,
+};
+
+/* UCC Slow Transmitter encoding method (TENC)
+*/
+enum ucc_slow_tx_encoding_method {
+ UCC_SLOW_TRANSMITTER_ENCODING_METHOD_TENC_NRZ = 0x00000000,
+ UCC_SLOW_TRANSMITTER_ENCODING_METHOD_TENC_NRZI = 0x00000100
+};
+
+/* UCC Slow Receiver decoding method (RENC)
+*/
+enum ucc_slow_rx_decoding_method {
+ UCC_SLOW_RECEIVER_DECODING_METHOD_RENC_NRZ = 0x00000000,
+ UCC_SLOW_RECEIVER_DECODING_METHOD_RENC_NRZI = 0x00000800
+};
+
+/* UCC Slow Diagnostic mode (DIAG)
+*/
+enum ucc_slow_diag_mode {
+ UCC_SLOW_DIAG_MODE_NORMAL = 0x00000000,
+ UCC_SLOW_DIAG_MODE_LOOPBACK = 0x00000040,
+ UCC_SLOW_DIAG_MODE_ECHO = 0x00000080,
+ UCC_SLOW_DIAG_MODE_LOOPBACK_ECHO = 0x000000c0
+};
+
+struct ucc_slow_info {
+ int ucc_num;
+ int protocol; /* QE_CR_PROTOCOL_xxx */
+ enum qe_clock rx_clock;
+ enum qe_clock tx_clock;
+ phys_addr_t regs;
+ int irq;
+ u16 uccm_mask;
+ int data_mem_part;
+ int init_tx;
+ int init_rx;
+ u32 tx_bd_ring_len;
+ u32 rx_bd_ring_len;
+ int rx_interrupts;
+ int brkpt_support;
+ int grant_support;
+ int tsa;
+ int cdp;
+ int cds;
+ int ctsp;
+ int ctss;
+ int rinv;
+ int tinv;
+ int rtsm;
+ int rfw;
+ int tci;
+ int tend;
+ int tfl;
+ int txsy;
+ u16 max_rx_buf_length;
+ enum ucc_slow_transparent_tcrc tcrc;
+ enum ucc_slow_channel_protocol_mode mode;
+ enum ucc_slow_diag_mode diag;
+ enum ucc_slow_tx_oversampling_rate tdcr;
+ enum ucc_slow_rx_oversampling_rate rdcr;
+ enum ucc_slow_tx_encoding_method tenc;
+ enum ucc_slow_rx_decoding_method renc;
+};
+
+struct ucc_slow_private {
+ struct ucc_slow_info *us_info;
+ struct ucc_slow __iomem *us_regs; /* Ptr to memory map of UCC regs */
+ struct ucc_slow_pram *us_pram; /* a pointer to the parameter RAM */
+ u32 us_pram_offset;
+ int enabled_tx; /* Whether channel is enabled for Tx (ENT) */
+ int enabled_rx; /* Whether channel is enabled for Rx (ENR) */
+ int stopped_tx; /* Whether channel has been stopped for Tx
+ (STOP_TX, etc.) */
+ int stopped_rx; /* Whether channel has been stopped for Rx */
+ struct list_head confQ; /* frames passed to chip waiting for tx */
+ u32 first_tx_bd_mask; /* mask is used in Tx routine to save status
+ and length for first BD in a frame */
+ u32 tx_base_offset; /* first BD in Tx BD table offset (In MURAM) */
+ u32 rx_base_offset; /* first BD in Rx BD table offset (In MURAM) */
+ struct qe_bd *confBd; /* next BD for confirm after Tx */
+ struct qe_bd *tx_bd; /* next BD for new Tx request */
+ struct qe_bd *rx_bd; /* next BD to collect after Rx */
+ void *p_rx_frame; /* accumulating receive frame */
+ u16 *p_ucce; /* a pointer to the event register in memory.
+ */
+ u16 *p_uccm; /* a pointer to the mask register in memory */
+ u16 saved_uccm; /* a saved mask for the RX Interrupt bits */
+#ifdef STATISTICS
+ u32 tx_frames; /* Transmitted frames counters */
+ u32 rx_frames; /* Received frames counters (only frames
+ passed to application) */
+ u32 rx_discarded; /* Discarded frames counters (frames that
+ were discarded by the driver due to
+ errors) */
+#endif /* STATISTICS */
+};
+
+/* ucc_slow_init
+ * Initializes Slow UCC according to provided parameters.
+ *
+ * us_info - (In) pointer to the slow UCC info structure.
+ * uccs_ret - (Out) pointer to the slow UCC structure.
+ */
+int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** uccs_ret);
+
+/* ucc_slow_free
+ * Frees all resources for slow UCC.
+ *
+ * uccs - (In) pointer to the slow UCC structure.
+ */
+void ucc_slow_free(struct ucc_slow_private * uccs);
+
+/* ucc_slow_enable
+ * Enables a fast UCC port.
+ * This routine enables Tx and/or Rx through the General UCC Mode Register.
+ *
+ * uccs - (In) pointer to the slow UCC structure.
+ * mode - (In) TX, RX, or both.
+ */
+void ucc_slow_enable(struct ucc_slow_private * uccs, enum comm_dir mode);
+
+/* ucc_slow_disable
+ * Disables a fast UCC port.
+ * This routine disables Tx and/or Rx through the General UCC Mode Register.
+ *
+ * uccs - (In) pointer to the slow UCC structure.
+ * mode - (In) TX, RX, or both.
+ */
+void ucc_slow_disable(struct ucc_slow_private * uccs, enum comm_dir mode);
+
+/* ucc_slow_graceful_stop_tx
+ * Smoothly stops transmission on a specified slow UCC.
+ *
+ * uccs - (In) pointer to the slow UCC structure.
+ */
+void ucc_slow_graceful_stop_tx(struct ucc_slow_private * uccs);
+
+/* ucc_slow_stop_tx
+ * Stops transmission on a specified slow UCC.
+ *
+ * uccs - (In) pointer to the slow UCC structure.
+ */
+void ucc_slow_stop_tx(struct ucc_slow_private * uccs);
+
+/* ucc_slow_restart_tx
+ * Restarts transmitting on a specified slow UCC.
+ *
+ * uccs - (In) pointer to the slow UCC structure.
+ */
+void ucc_slow_restart_tx(struct ucc_slow_private *uccs);
+
+u32 ucc_slow_get_qe_cr_subblock(int uccs_num);
+
+#endif /* __UCC_SLOW_H__ */