Commit 98658538 authored by Li Yang's avatar Li Yang Committed by Paul Mackerras

[POWERPC] Add QUICC Engine (QE) infrastructure

Add QUICC Engine (QE) configuration, header files, and
QE management and library code that are used by QE devices
drivers.

Includes Leo's modifications up to, and including, the
platform_device to of_device adaptation:

"The series of patches add generic QE infrastructure called
qe_lib, and MPC8360EMDS board support.  Qe_lib is used by
QE device drivers such as ucc_geth driver.

This version updates QE interrupt controller to use new irq
mapping mechanism, addresses all the comments received with
last submission and includes some style fixes.

v2: Change to use device tree for BCSR and MURAM;
Remove I/O port interrupt handling code as it is not generic
enough.

v3: Address comments from Kumar;  Update definition of several
device tree nodes;  Copyright style change."

In addition, the following changes have been made:

o removed typedefs
o uint -> u32 conversions
o removed following defines:
  QE_SIZEOF_BD, BD_BUFFER_ARG, BD_BUFFER_CLEAR, BD_BUFFER,
  BD_STATUS_AND_LENGTH_SET, BD_STATUS_AND_LENGTH, and BD_BUFFER_SET
  because they hid sizeof/in_be32/out_be32 operations from the reader.
o fixed qe_snums_init() serial num assignment to use a const array
o made CONFIG_UCC_FAST select UCC_SLOW
o reduced NR_QE_IC_INTS from 128 to 64
o remove _IO_BASE, etc. defines (not used)
o removed irrelevant comments, added others to resemble removed BD_ defines
o realigned struct definitions in headers
o various other style fixes including things like pinMask -> pin_mask
o fixed a ton of whitespace issues
o marked ioregs as __be32/__be16
o removed platform_device code and redundant get_qe_base()
o removed redundant comments
o added cpu_relax() to qe_reset
o uncasted all get_property() assignments
o eliminated unneeded casts
o eliminated immrbar_phys_to_virt (not used)
Signed-off-by: default avatarLi Yang <leoli@freescale.com>
Signed-off-by: default avatarShlomi Gridish <gridish@freescale.com>
Signed-off-by: default avatarKim Phillips <kim.phillips@freescale.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 9a1ab883
......@@ -351,6 +351,16 @@ config APUS
<http://linux-apus.sourceforge.net/>.
endchoice
config QUICC_ENGINE
bool
depends on PPC_MPC836x || PPC_MPC832x
default y
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 PPC_PSERIES
depends on PPC_MULTIPLATFORM && PPC64
bool "IBM pSeries & new (POWER5-based) iSeries"
......@@ -1059,6 +1069,8 @@ source "fs/Kconfig"
# XXX source "arch/ppc/8260_io/Kconfig"
source "arch/powerpc/sysdev/qe_lib/Kconfig"
source "arch/powerpc/platforms/iseries/Kconfig"
source "lib/Kconfig"
......
......@@ -12,6 +12,7 @@ obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
obj-$(CONFIG_PPC_TODC) += todc.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
ifeq ($(CONFIG_PPC_MERGE),y)
obj-$(CONFIG_PPC_I8259) += i8259.o
......
#
# QE Communication options
#
menu "QE Options"
depends on QUICC_ENGINE
config UCC_SLOW
bool "UCC Slow Protocols Support"
default n
select UCC
help
This option provides qe_lib support to UCC slow
protocols: UART, BISYNC, QMC
config UCC_FAST
bool "UCC Fast Protocols Support"
default n
select UCC
select UCC_SLOW
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
endmenu
#
# Makefile for the linux ppc-specific parts of QE
#
obj-$(CONFIG_QUICC_ENGINE)+= qe.o qe_ic.o qe_io.o
obj-$(CONFIG_UCC) += ucc.o
obj-$(CONFIG_UCC_SLOW) += ucc_slow.o
obj-$(CONFIG_UCC_FAST) += ucc_fast.o
/*
* Copyright (C) 2006 Freescale Semicondutor, 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/mm.h>
#include <linux/interrupt.h>
#include <linux/bootmem.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/ioport.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 void qe_muram_init(void);
static int qe_sdma_init(void);
static DEFINE_SPINLOCK(qe_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 *qe_immr = NULL;
EXPORT_SYMBOL(qe_immr);
static struct qe_snum snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */
static phys_addr_t qebase = -1;
phys_addr_t get_qe_base(void)
{
struct device_node *qe;
if (qebase != -1)
return qebase;
qe = of_find_node_by_type(NULL, "qe");
if (qe) {
unsigned int size;
const void *prop = get_property(qe, "reg", &size);
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;
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,
immrbar_virt_to_phys((void *)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 */
while(in_be32(&qe_immr->cp.cecr) & QE_CR_FLG)
cpu_relax();
spin_unlock_irqrestore(&qe_lock, flags);
return 0;
}
EXPORT_SYMBOL(qe_issue_cmd);
/* Set a baud rate generator. This needs lots of work. There are
* 16 BRGs, which can be connected to the QE channels or output
* as clocks. The BRGs are in two different block of internal
* memory mapped space.
* The baud rate clock is the system clock divided by something.
* 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 get_brg_clk(void)
{
struct device_node *qe;
if (brg_clk)
return brg_clk;
qe = of_find_node_by_type(NULL, "qe");
if (qe) {
unsigned int size;
const u32 *prop = get_property(qe, "brg-frequency", &size);
brg_clk = *prop;
of_node_put(qe);
};
return brg_clk;
}
/* This function is used by UARTS, or anything else that uses a 16x
* oversampled clock.
*/
void qe_setbrg(u32 brg, u32 rate)
{
volatile u32 *bp;
u32 divisor, tempval;
int div16 = 0;
bp = &qe_immr->brg.brgc1;
bp += brg;
divisor = (get_brg_clk() / rate);
if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
div16 = 1;
divisor /= 16;
}
tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE;
if (div16)
tempval |= QE_BRGC_DIV16;
out_be32(bp, tempval);
}
/* 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[] = {
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,
};
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 *sdma = &qe_immr->sdma;
u32 sdma_buf_offset;
if (!sdma)
return -ENODEV;
/* allocate 2 internal temporary buffers (512 bytes size each) for
* the SDMA */
sdma_buf_offset = qe_muram_alloc(512 * 2, 64);
if (IS_MURAM_ERR(sdma_buf_offset))
return -ENOMEM;
out_be32(&sdma->sdebcr, sdma_buf_offset & QE_SDEBCR_BA_MASK);
out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK | (0x1 >>
QE_SDMR_CEN_SHIFT)));
return 0;
}
/*
* muram_alloc / muram_free bits.
*/
static DEFINE_SPINLOCK(qe_muram_lock);
/* 16 blocks should be enough to satisfy all requests
* until the memory subsystem goes up... */
static rh_block_t qe_boot_muram_rh_block[16];
static rh_info_t qe_muram_info;
static void qe_muram_init(void)
{
struct device_node *np;
u32 address;
u64 size;
unsigned int flags;
/* initialize the info header */
rh_init(&qe_muram_info, 1,
sizeof(qe_boot_muram_rh_block) /
sizeof(qe_boot_muram_rh_block[0]), qe_boot_muram_rh_block);
/* Attach the usable muram area */
/* XXX: This is a subset of the available muram. It
* varies with the processor and the microcode patches activated.
*/
if ((np = of_find_node_by_name(NULL, "data-only")) != NULL) {
address = *of_get_address(np, 0, &size, &flags);
of_node_put(np);
rh_attach_region(&qe_muram_info,
(void *)address, (int)size);
}
}
/* This function returns an index into the MURAM area.
*/
u32 qe_muram_alloc(u32 size, u32 align)
{
void *start;
unsigned long flags;
spin_lock_irqsave(&qe_muram_lock, flags);
start = rh_alloc_align(&qe_muram_info, size, align, "QE");
spin_unlock_irqrestore(&qe_muram_lock, flags);
return (u32) start;
}
EXPORT_SYMBOL(qe_muram_alloc);
int qe_muram_free(u32 offset)
{
int ret;
unsigned long flags;
spin_lock_irqsave(&qe_muram_lock, flags);
ret = rh_free(&qe_muram_info, (void *)offset);
spin_unlock_irqrestore(&qe_muram_lock, flags);
return ret;
}
EXPORT_SYMBOL(qe_muram_free);
/* not sure if this is ever needed */
u32 qe_muram_alloc_fixed(u32 offset, u32 size)
{
void *start;
unsigned long flags;
spin_lock_irqsave(&qe_muram_lock, flags);
start = rh_alloc_fixed(&qe_muram_info, (void *)offset, size, "commproc");
spin_unlock_irqrestore(&qe_muram_lock, flags);
return (u32) start;
}
EXPORT_SYMBOL(qe_muram_alloc_fixed);
void qe_muram_dump(void)
{
rh_dump(&qe_muram_info);
}
EXPORT_SYMBOL(qe_muram_dump);
void *qe_muram_addr(u32 offset)
{
return (void *)&qe_immr->muram[offset];
}
EXPORT_SYMBOL(qe_muram_addr);
This diff is collapsed.
/*
* arch/powerpc/sysdev/qe_lib/qe_ic.h
*
* QUICC ENGINE Interrupt Controller Header
*
* Copyright (C) 2006 Freescale Semicondutor, 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_host *irqhost;
/* The "linux" controller struct */
struct irq_chip hc_irq;
/* The device node of the interrupt controller */
struct device_node *of_node;
/* 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 */
/*
* arch/powerpc/sysdev/qe_lib/qe_io.c
*
* QE Parallel I/O ports configuration routines
*
* Copyright (C) Freescale Semicondutor, Inc. 2006. 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/config.h>
#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <sysdev/fsl_soc.h>
#undef DEBUG
#define NUM_OF_PINS 32
struct port_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 */
};
static struct port_regs *par_io = NULL;
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, res.end - res.start + 1);
num_ports = get_property(np, "num-ports", NULL);
if (num_ports)
num_par_io_ports = *num_ports;
return 0;
}
int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
int assignment, int has_irq)
{
u32 pin_mask1bit, pin_mask2bits, new_mask2bits, tmp_val;
if (!par_io)
return -1;
/* calculate pin location for single and 2 bits information */
pin_mask1bit = (u32) (1 << (NUM_OF_PINS - (pin + 1)));
/* Set open drain, if required */
tmp_val = in_be32(&par_io[port].cpodr);
if (open_drain)
out_be32(&par_io[port].cpodr, pin_mask1bit | tmp_val);
else
out_be32(&par_io[port].cpodr, ~pin_mask1bit & tmp_val);
/* define direction */
tmp_val = (pin > (NUM_OF_PINS / 2) - 1) ?
in_be32(&par_io[port].cpdir2) :
in_be32(&par_io[port].cpdir1);
/* get all bits mask for 2 bit per port */
pin_mask2bits = (u32) (0x3 << (NUM_OF_PINS -
(pin % (NUM_OF_PINS / 2) + 1) * 2));
/* Get the final mask we need for the right definition */
new_mask2bits = (u32) (dir << (NUM_OF_PINS -
(pin % (NUM_OF_PINS / 2) + 1) * 2));
/* clear and set 2 bits mask */
if (pin > (NUM_OF_PINS / 2) - 1) {
out_be32(&par_io[port].cpdir2,
~pin_mask2bits & tmp_val);
tmp_val &= ~pin_mask2bits;
out_be32(&par_io[port].cpdir2, new_mask2bits | tmp_val);
} else {
out_be32(&par_io[port].cpdir1,
~pin_mask2bits & tmp_val);
tmp_val &= ~pin_mask2bits;
out_be32(&par_io[port].cpdir1, new_mask2bits | tmp_val);
}
/* define pin assignment */
tmp_val = (pin > (NUM_OF_PINS / 2) - 1) ?
in_be32(&par_io[port].cppar2) :
in_be32(&par_io[port].cppar1);
new_mask2bits = (u32) (assignment << (NUM_OF_PINS -
(pin % (NUM_OF_PINS / 2) + 1) * 2));
/* clear and set 2 bits mask */
if (pin > (NUM_OF_PINS / 2) - 1) {
out_be32(&par_io[port].cppar2,
~pin_mask2bits & tmp_val);
tmp_val &= ~pin_mask2bits;
out_be32(&par_io[port].cppar2, new_mask2bits | tmp_val);
} else {
out_be32(&par_io[port].cppar1,
~pin_mask2bits & tmp_val);
tmp_val &= ~pin_mask2bits;
out_be32(&par_io[port].cppar1, new_mask2bits | tmp_val);
}
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 >= NUM_OF_PINS)
return -EINVAL;
/* calculate pin location */
pin_mask = (u32) (1 << (NUM_OF_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 = get_property(np, "pio-handle", NULL);
if (ph == 0) {
printk(KERN_ERR "pio-handle not available \n");
return -1;
}
pio = of_find_node_by_phandle(*ph);
pio_map = 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);
#ifdef DEBUG
static void dump_par_io(void)
{
int i;
printk(KERN_INFO "PAR IO registars:\n");
printk(KERN_INFO "Base address: 0x%08x\n", (u32) par_io);
for (i = 0; i < num_par_io_ports; i++) {
printk(KERN_INFO "cpodr[%d] : addr - 0x%08x, val - 0x%08x\n",
i, (u32) & par_io[i].cpodr,
in_be32(&par_io[i].cpodr));
printk(KERN_INFO "cpdata[%d]: addr - 0x%08x, val - 0x%08x\n",
i, (u32) & par_io[i].cpdata,
in_be32(&par_io[i].cpdata));
printk(KERN_INFO "cpdir1[%d]: addr - 0x%08x, val - 0x%08x\n",
i, (u32) & par_io[i].cpdir1,
in_be32(&par_io[i].cpdir1));
printk(KERN_INFO "cpdir2[%d]: addr - 0x%08x, val - 0x%08x\n",
i, (u32) & par_io[i].cpdir2,
in_be32(&par_io[i].cpdir2));
printk(KERN_INFO "cppar1[%d]: addr - 0x%08x, val - 0x%08x\n",
i, (u32) & par_io[i].cppar1,
in_be32(&par_io[i].cppar1));
printk(KERN_INFO "cppar2[%d]: addr - 0x%08x, val - 0x%08x\n",
i, (u32) & par_io[i].cppar2,
in_be32(&par_io[i].cppar2));
}
}
EXPORT_SYMBOL(dump_par_io);
#endif /* DEBUG */
/*
* arch/powerpc/sysdev/qe_lib/ucc.c
*
* QE UCC API Set - UCC specific routines implementations.
*
* Copyright (C) 2006 Freescale Semicondutor, 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/init.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/stddef.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/immap_qe.h>
#include <asm/qe.h>
#include <asm/ucc.h>
static DEFINE_SPINLOCK(ucc_lock);
int ucc_set_qe_mux_mii_mng(int ucc_num)
{
unsigned long flags;
spin_lock_irqsave(&ucc_lock, flags);
out_be32(&qe_immr->qmx.cmxgcr,
((in_be32(&qe_immr->qmx.cmxgcr) &
~QE_CMXGCR_MII_ENET_MNG) |
(ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT)));
spin_unlock_irqrestore(&ucc_lock, flags);
return 0;
}
int ucc_set_type(int ucc_num, struct ucc_common *regs,
enum ucc_speed_type speed)
{
u8 guemr = 0;
/* check if the UCC number is in range. */
if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0))
return -EINVAL;
guemr = regs->guemr;
guemr &= ~(UCC_GUEMR_MODE_MASK_RX | UCC_GUEMR_MODE_MASK_TX);
switch (speed) {
case UCC_SPEED_TYPE_SLOW:
guemr |= (UCC_GUEMR_MODE_SLOW_RX | UCC_GUEMR_MODE_SLOW_TX);
break;
case UCC_SPEED_TYPE_FAST:
guemr |= (UCC_GUEMR_MODE_FAST_RX | UCC_GUEMR_MODE_FAST_TX);
break;
default:
return -EINVAL;
}
regs->guemr = guemr;
return 0;
}
int ucc_init_guemr(struct ucc_common *regs)
{
u8 guemr = 0;
if (!regs)
return -EINVAL;
/* Set bit 3 (which is reserved in the GUEMR register) to 1 */
guemr = UCC_GUEMR_SET_RESERVED3;
regs->guemr = guemr;
return 0;
}
static void get_cmxucr_reg(int ucc_num, volatile u32 ** p_cmxucr, u8 * reg_num,
u8 * shift)
{
switch (ucc_num) {
case 0: *p_cmxucr = &(qe_immr->qmx.cmxucr1);
*reg_num = 1;
*shift = 16;
break;
case 2: *p_cmxucr = &(qe_immr->qmx.cmxucr1);
*reg_num = 1;
*shift = 0;
break;
case 4: *p_cmxucr = &(qe_immr->qmx.cmxucr2);
*reg_num = 2;
*shift = 16;
break;
case 6: *p_cmxucr = &(qe_immr->qmx.cmxucr2);
*reg_num = 2;
*shift = 0;
break;
case 1: *p_cmxucr = &(qe_immr->qmx.cmxucr3);
*reg_num = 3;
*shift = 16;
break;
case 3: *p_cmxucr = &(qe_immr->qmx.cmxucr3);
*reg_num = 3;
*shift = 0;
break;
case 5: *p_cmxucr = &(qe_immr->qmx.cmxucr4);
*reg_num = 4;
*shift = 16;
break;
case 7: *p_cmxucr = &(qe_immr->qmx.cmxucr4);
*reg_num = 4;
*shift = 0;
break;
default:
break;
}
}
int ucc_mux_set_grant_tsa_bkpt(int ucc_num, int set, u32 mask)
{
volatile u32 *p_cmxucr;
u8 reg_num;
u8 shift;
/* check if the UCC number is in range. */
if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0))
return -EINVAL;
get_cmxucr_reg(ucc_num, &p_cmxucr, &reg_num, &shift);
if (set)
out_be32(p_cmxucr, in_be32(p_cmxucr) | (mask << shift));
else
out_be32(p_cmxucr, in_be32(p_cmxucr) & ~(mask << shift));
return 0;
}
int ucc_set_qe_mux_rxtx(int ucc_num, enum qe_clock clock, enum comm_dir mode)
{
volatile u32 *p_cmxucr;
u8 reg_num;
u8 shift;
u32 clock_bits;
u32 clock_mask;
int source = -1;
/* check if the UCC number is in range. */
if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0))
return -EINVAL;
if (!((mode == COMM_DIR_RX) || (mode == COMM_DIR_TX))) {
printk(KERN_ERR
"ucc_set_qe_mux_rxtx: bad comm mode type passed.");
return -EINVAL;
}
get_cmxucr_reg(ucc_num, &p_cmxucr, &reg_num, &shift);
switch (reg_num) {
case 1:
switch (clock) {
case QE_BRG1: source = 1; break;
case QE_BRG2: source = 2; break;
case QE_BRG7: source = 3; break;
case QE_BRG8: source = 4; break;
case QE_CLK9: source = 5; break;
case QE_CLK10: source = 6; break;
case QE_CLK11: source = 7; break;
case QE_CLK12: source = 8; break;
case QE_CLK15: source = 9; break;
case QE_CLK16: source = 10; break;
default: source = -1; break;
}
break;
case 2:
switch (clock) {
case QE_BRG5: source = 1; break;
case QE_BRG6: source = 2; break;
case QE_BRG7: source = 3; break;
case QE_BRG8: source = 4; break;
case QE_CLK13: source = 5; break;
case QE_CLK14: source = 6; break;
case QE_CLK19: source = 7; break;
case QE_CLK20: source = 8; break;
case QE_CLK15: source = 9; break;
case QE_CLK16: source = 10; break;
default: source = -1; break;
}
break;
case 3:
switch (clock) {
case QE_BRG9: source = 1; break;
case QE_BRG10: source = 2; break;
case QE_BRG15: source = 3; break;
case QE_BRG16: source = 4; break;
case QE_CLK3: source = 5; break;
case QE_CLK4: source = 6; break;
case QE_CLK17: source = 7; break;
case QE_CLK18: source = 8; break;
case QE_CLK7: source = 9; break;
case QE_CLK8: source = 10; break;
default: source = -1; break;
}
break;
case 4:
switch (clock) {
case QE_BRG13: source = 1; break;
case QE_BRG14: source = 2; break;
case QE_BRG15: source = 3; break;
case QE_BRG16: source = 4; break;
case QE_CLK5: source = 5; break;
case QE_CLK6: source = 6; break;
case QE_CLK21: source = 7; break;
case QE_CLK22: source = 8; break;
case QE_CLK7: source = 9; break;
case QE_CLK8: source = 10; break;
default: source = -1; break;
}
break;
default:
source = -1;
break;
}
if (source == -1) {
printk(KERN_ERR
"ucc_set_qe_mux_rxtx: Bad combination of clock and UCC.");
return -ENOENT;
}
clock_bits = (u32) source;
clock_mask = QE_CMXUCR_TX_CLK_SRC_MASK;
if (mode == COMM_DIR_RX) {
clock_bits <<= 4; /* Rx field is 4 bits to left of Tx field */
clock_mask <<= 4; /* Rx field is 4 bits to left of Tx field */
}
clock_bits <<= shift;
clock_mask <<= shift;
out_be32(p_cmxucr, (in_be32(p_cmxucr) & ~clock_mask) | clock_bits);
return 0;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* include/asm-powerpc/qe_ic.h
*
* Copyright (C) 2006 Freescale Semicondutor, 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>
#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 */
};
void qe_ic_init(struct device_node *node, unsigned int flags);
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);
#endif /* _ASM_POWERPC_QE_IC_H */
/*
* Copyright (C) 2006 Freescale Semicondutor, 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_SPEED_TYPE_SLOW
};
/* Initial UCCs Parameter RAM address relative to: MEM_MAP_BASE (IMMR).
*/
enum ucc_pram_initial_offset {
UCC_PRAM_OFFSET_UCC1 = 0x8400,
UCC_PRAM_OFFSET_UCC2 = 0x8500,
UCC_PRAM_OFFSET_UCC3 = 0x8600,
UCC_PRAM_OFFSET_UCC4 = 0x9000,
UCC_PRAM_OFFSET_UCC5 = 0x8000,
UCC_PRAM_OFFSET_UCC6 = 0x8100,
UCC_PRAM_OFFSET_UCC7 = 0x8200,
UCC_PRAM_OFFSET_UCC8 = 0x8300
};
/* ucc_set_type
* Sets UCC to slow or fast mode.
*
* ucc_num - (In) number of UCC (0-7).
* regs - (In) pointer to registers base for the UCC.
* speed - (In) slow or fast mode for UCC.
*/
int ucc_set_type(int ucc_num, struct ucc_common *regs,
enum ucc_speed_type speed);
/* ucc_init_guemr
* Init the Guemr register.
*
* regs - (In) pointer to registers base for the UCC.
*/
int ucc_init_guemr(struct ucc_common *regs);
int ucc_set_qe_mux_mii_mng(int ucc_num);
int ucc_set_qe_mux_rxtx(int ucc_num, enum qe_clock clock, enum comm_dir mode);
int ucc_mux_set_grant_tsa_bkpt(int ucc_num, int set, u32 mask);
/* QE MUX clock routing for UCC
*/
static inline int ucc_set_qe_mux_grant(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(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(int ucc_num, int set)
{
return ucc_mux_set_grant_tsa_bkpt(ucc_num, set, QE_CMXUCR_BKPT);
}
#endif /* __UCC_H__ */
/*
* include/asm-powerpc/ucc_fast.h
*
* Internal header file for UCC FAST unit routines.
*
* Copyright (C) 2006 Freescale Semicondutor, 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 "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 *uf_regs; /* a pointer to memory map of UCC regs. */
u32 *p_ucce; /* a pointer to the event register in memory. */
u32 *p_uccm; /* a pointer to the mask register in memory. */
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__ */
/*
* Copyright (C) 2006 Freescale Semicondutor, 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 "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;
enum qe_clock rx_clock;
enum qe_clock tx_clock;
struct ucc_slow *us_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 *us_regs; /* a pointer 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) */
u8 *confBd; /* next BD for confirm after Tx */
u8 *tx_bd; /* next BD for new Tx request */
u8 *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_poll_transmitter_now
* 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.
*
* uccs - (In) pointer to the slow UCC structure.
*/
void ucc_slow_poll_transmitter_now(struct ucc_slow_private * uccs);
/* 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_x
* Restarts transmitting on a specified slow UCC.
*
* uccs - (In) pointer to the slow UCC structure.
*/
void ucc_slow_restart_x(struct ucc_slow_private * uccs);
u32 ucc_slow_get_qe_cr_subblock(int uccs_num);
#endif /* __UCC_SLOW_H__ */
......@@ -47,7 +47,6 @@
struct gianfar_platform_data {
/* device specific information */
u32 device_flags;
/* board specific information */
u32 board_flags;
u32 bus_id;
......@@ -83,7 +82,6 @@ struct fsl_i2c_platform_data {
#define FSL_I2C_DEV_SEPARATE_DFSRR 0x00000001
#define FSL_I2C_DEV_CLOCK_5200 0x00000002
enum fsl_usb2_operating_modes {
FSL_USB2_MPH_HOST,
FSL_USB2_DR_HOST,
......@@ -121,5 +119,44 @@ struct fsl_spi_platform_data {
u32 sysclk;
};
/* Ethernet interface (phy management and speed)
*/
enum enet_interface {
ENET_10_MII, /* 10 Base T, MII interface */
ENET_10_RMII, /* 10 Base T, RMII interface */
ENET_10_RGMII, /* 10 Base T, RGMII interface */
ENET_100_MII, /* 100 Base T, MII interface */
ENET_100_RMII, /* 100 Base T, RMII interface */
ENET_100_RGMII, /* 100 Base T, RGMII interface */
ENET_1000_GMII, /* 1000 Base T, GMII interface */
ENET_1000_RGMII, /* 1000 Base T, RGMII interface */
ENET_1000_TBI, /* 1000 Base T, TBI interface */
ENET_1000_RTBI /* 1000 Base T, RTBI interface */
};
struct ucc_geth_platform_data {
/* device specific information */
u32 device_flags;
u32 phy_reg_addr;
/* board specific information */
u32 board_flags;
u8 rx_clock;
u8 tx_clock;
u32 phy_id;
enum enet_interface phy_interface;
u32 phy_interrupt;
u8 mac_addr[6];
};
/* Flags related to UCC Gigabit Ethernet device features */
#define FSL_UGETH_DEV_HAS_GIGABIT 0x00000001
#define FSL_UGETH_DEV_HAS_COALESCE 0x00000002
#define FSL_UGETH_DEV_HAS_RMON 0x00000004
/* Flags in ucc_geth_platform_data */
#define FSL_UGETH_BRD_HAS_PHY_INTR 0x00000001
/* if not set use a timer */
#endif /* _FSL_DEVICE_H_ */
#endif /* __KERNEL__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment