Commit 4e6d816e authored by Paul Mackerras's avatar Paul Mackerras
parents d86d9b8c 611a15af
/*
* MPC8560 ADS Device Tree Source
*
* Copyright 2006 Freescale Semiconductor Inc.
*
* 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.
*/
/ {
model = "MPC8560ADS";
compatible = "MPC85xxADS";
#address-cells = <1>;
#size-cells = <1>;
linux,phandle = <100>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
linux,phandle = <200>;
PowerPC,8560@0 {
device_type = "cpu";
reg = <0>;
d-cache-line-size = <20>; // 32 bytes
i-cache-line-size = <20>; // 32 bytes
d-cache-size = <8000>; // L1, 32K
i-cache-size = <8000>; // L1, 32K
timebase-frequency = <04ead9a0>;
bus-frequency = <13ab6680>;
clock-frequency = <312c8040>;
32-bit;
linux,phandle = <201>;
linux,boot-cpu;
};
};
memory {
device_type = "memory";
linux,phandle = <300>;
reg = <00000000 10000000>;
};
soc8560@e0000000 {
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
device_type = "soc";
ranges = <0 e0000000 00100000>;
reg = <e0000000 00000200>;
bus-frequency = <13ab6680>;
mdio@24520 {
device_type = "mdio";
compatible = "gianfar";
reg = <24520 20>;
linux,phandle = <24520>;
#address-cells = <1>;
#size-cells = <0>;
ethernet-phy@0 {
linux,phandle = <2452000>;
interrupt-parent = <40000>;
interrupts = <35 1>;
reg = <0>;
device_type = "ethernet-phy";
};
ethernet-phy@1 {
linux,phandle = <2452001>;
interrupt-parent = <40000>;
interrupts = <35 1>;
reg = <1>;
device_type = "ethernet-phy";
};
ethernet-phy@2 {
linux,phandle = <2452002>;
interrupt-parent = <40000>;
interrupts = <37 1>;
reg = <2>;
device_type = "ethernet-phy";
};
ethernet-phy@3 {
linux,phandle = <2452003>;
interrupt-parent = <40000>;
interrupts = <37 1>;
reg = <3>;
device_type = "ethernet-phy";
};
};
ethernet@24000 {
device_type = "network";
model = "TSEC";
compatible = "gianfar";
reg = <24000 1000>;
address = [ 00 00 0C 00 00 FD ];
interrupts = <d 2 e 2 12 2>;
interrupt-parent = <40000>;
phy-handle = <2452000>;
};
ethernet@25000 {
#address-cells = <1>;
#size-cells = <0>;
device_type = "network";
model = "TSEC";
compatible = "gianfar";
reg = <25000 1000>;
address = [ 00 00 0C 00 01 FD ];
interrupts = <13 2 14 2 18 2>;
interrupt-parent = <40000>;
phy-handle = <2452001>;
};
pci@8000 {
linux,phandle = <8000>;
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
compatible = "85xx";
device_type = "pci";
reg = <8000 400>;
clock-frequency = <3f940aa>;
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x2 */
1000 0 0 1 40000 31 1
1000 0 0 2 40000 32 1
1000 0 0 3 40000 33 1
1000 0 0 4 40000 34 1
/* IDSEL 0x3 */
1800 0 0 1 40000 34 1
1800 0 0 2 40000 31 1
1800 0 0 3 40000 32 1
1800 0 0 4 40000 33 1
/* IDSEL 0x4 */
2000 0 0 1 40000 33 1
2000 0 0 2 40000 34 1
2000 0 0 3 40000 31 1
2000 0 0 4 40000 32 1
/* IDSEL 0x5 */
2800 0 0 1 40000 32 1
2800 0 0 2 40000 33 1
2800 0 0 3 40000 34 1
2800 0 0 4 40000 31 1
/* IDSEL 12 */
6000 0 0 1 40000 31 1
6000 0 0 2 40000 32 1
6000 0 0 3 40000 33 1
6000 0 0 4 40000 34 1
/* IDSEL 13 */
6800 0 0 1 40000 34 1
6800 0 0 2 40000 31 1
6800 0 0 3 40000 32 1
6800 0 0 4 40000 33 1
/* IDSEL 14*/
7000 0 0 1 40000 33 1
7000 0 0 2 40000 34 1
7000 0 0 3 40000 31 1
7000 0 0 4 40000 32 1
/* IDSEL 15 */
7800 0 0 1 40000 32 1
7800 0 0 2 40000 33 1
7800 0 0 3 40000 34 1
7800 0 0 4 40000 31 1
/* IDSEL 18 */
9000 0 0 1 40000 31 1
9000 0 0 2 40000 32 1
9000 0 0 3 40000 33 1
9000 0 0 4 40000 34 1
/* IDSEL 19 */
9800 0 0 1 40000 34 1
9800 0 0 2 40000 31 1
9800 0 0 3 40000 32 1
9800 0 0 4 40000 33 1
/* IDSEL 20 */
a000 0 0 1 40000 33 1
a000 0 0 2 40000 34 1
a000 0 0 3 40000 31 1
a000 0 0 4 40000 32 1
/* IDSEL 21 */
a800 0 0 1 40000 32 1
a800 0 0 2 40000 33 1
a800 0 0 3 40000 34 1
a800 0 0 4 40000 31 1>;
interrupt-parent = <40000>;
interrupts = <42 0>;
bus-range = <0 0>;
ranges = <02000000 0 80000000 80000000 0 20000000
01000000 0 00000000 e2000000 0 01000000>;
};
pic@40000 {
linux,phandle = <40000>;
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
reg = <40000 20100>;
built-in;
device_type = "open-pic";
};
cpm@e0000000 {
linux,phandle = <e0000000>;
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
device_type = "cpm";
model = "CPM2";
ranges = <0 0 c0000>;
reg = <80000 40000>;
command-proc = <919c0>;
brg-frequency = <9d5b340>;
pic@90c00 {
linux,phandle = <90c00>;
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
interrupts = <1e 0>;
interrupt-parent = <40000>;
reg = <90c00 80>;
built-in;
device_type = "cpm-pic";
};
scc@91a00 {
device_type = "serial";
compatible = "cpm_uart";
model = "SCC";
device-id = <1>;
reg = <91a00 20 88000 100>;
clock-setup = <00ffffff 0>;
rx-clock = <1>;
tx-clock = <1>;
current-speed = <1c200>;
interrupts = <64 1>;
interrupt-parent = <90c00>;
};
scc@91a20 {
device_type = "serial";
compatible = "cpm_uart";
model = "SCC";
device-id = <2>;
reg = <91a20 20 88100 100>;
clock-setup = <ff00ffff 90000>;
rx-clock = <2>;
tx-clock = <2>;
current-speed = <1c200>;
interrupts = <65 1>;
interrupt-parent = <90c00>;
};
fcc@91320 {
device_type = "network";
compatible = "fs_enet";
model = "FCC";
device-id = <2>;
reg = <91320 20 88500 100 913a0 30>;
mac-address = [ 00 00 0C 00 02 FD ];
clock-setup = <ff00ffff 250000>;
rx-clock = <15>;
tx-clock = <16>;
interrupts = <5d 1>;
interrupt-parent = <90c00>;
phy-handle = <2452002>;
};
fcc@91340 {
device_type = "network";
compatible = "fs_enet";
model = "FCC";
device-id = <3>;
reg = <91340 20 88600 100 913d0 30>;
mac-address = [ 00 00 0C 00 03 FD ];
clock-setup = <ffff00ff 3700>;
rx-clock = <17>;
tx-clock = <18>;
interrupts = <5e 1>;
interrupt-parent = <90c00>;
phy-handle = <2452003>;
};
};
};
};
This diff is collapsed.
......@@ -20,3 +20,8 @@ ifeq ($(CONFIG_PPC64),y)
obj-$(CONFIG_SMP) += locks.o
obj-$(CONFIG_DEBUG_KERNEL) += sstep.o
endif
# Temporary hack until we have migrated to asm-powerpc
ifeq ($(CONFIG_PPC_MERGE),y)
obj-$(CONFIG_CPM2) += rheap.o
endif
......@@ -11,6 +11,12 @@ config MPC8540_ADS
help
This option enables support for the MPC 8540 ADS board
config MPC8560_ADS
bool "Freescale MPC8560 ADS"
select DEFAULT_UIMAGE
help
This option enables support for the MPC 8560 ADS board
config MPC85xx_CDS
bool "Freescale MPC85xx CDS"
select DEFAULT_UIMAGE
......@@ -25,6 +31,11 @@ config MPC8540
select PPC_INDIRECT_PCI
default y if MPC8540_ADS || MPC85xx_CDS
config MPC8560
bool
select PPC_INDIRECT_PCI
default y if MPC8560_ADS
config PPC_INDIRECT_PCI_BE
bool
depends on PPC_85xx
......@@ -34,4 +45,14 @@ config MPIC
bool
default y
config CPM2
bool
depends on MPC8560
default y
help
The CPM2 (Communications Processor Module) is a coprocessor on
embedded CPUs made by Motorola. Selecting this option means that
you wish to build a kernel for a machine with a CPM2 coprocessor
on it.
endmenu
......@@ -3,4 +3,5 @@
#
obj-$(CONFIG_PPC_85xx) += misc.o pci.o
obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o
obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o
......@@ -32,6 +32,13 @@
#include <sysdev/fsl_soc.h>
#include "mpc85xx.h"
#ifdef CONFIG_CPM2
#include <linux/fs_enet_pd.h>
#include <asm/cpm2.h>
#include <sysdev/cpm2_pic.h>
#include <asm/fs_pd.h>
#endif
#ifndef CONFIG_PCI
unsigned long isa_io_base = 0;
unsigned long isa_mem_base = 0;
......@@ -57,12 +64,29 @@ mpc85xx_pcibios_fixup(void)
}
#endif /* CONFIG_PCI */
#ifdef CONFIG_CPM2
static void cpm2_cascade(unsigned int irq, struct irq_desc *desc,
struct pt_regs *regs)
{
int cascade_irq;
while ((cascade_irq = cpm2_get_irq(regs)) >= 0) {
generic_handle_irq(cascade_irq, regs);
}
desc->chip->eoi(irq);
}
#endif /* CONFIG_CPM2 */
void __init mpc85xx_ads_pic_init(void)
{
struct mpic *mpic;
struct resource r;
struct device_node *np = NULL;
#ifdef CONFIG_CPM2
int irq;
#endif
np = of_find_node_by_type(np, "open-pic");
......@@ -104,11 +128,103 @@ void __init mpc85xx_ads_pic_init(void)
mpic_assign_isu(mpic, 14, r.start + 0x10100);
mpic_init(mpic);
#ifdef CONFIG_CPM2
/* Setup CPM2 PIC */
np = of_find_node_by_type(NULL, "cpm-pic");
if (np == NULL) {
printk(KERN_ERR "PIC init: can not find cpm-pic node\n");
return;
}
irq = irq_of_parse_and_map(np, 0);
cpm2_pic_init(np);
set_irq_chained_handler(irq, cpm2_cascade);
#endif
}
/*
* Setup the architecture
*/
#ifdef CONFIG_CPM2
void init_fcc_ioports(struct fs_platform_info *fpi)
{
struct io_port *io = cpm2_map(im_ioport);
int fcc_no = fs_get_fcc_index(fpi->fs_no);
int target;
u32 tempval;
switch(fcc_no) {
case 1:
tempval = in_be32(&io->iop_pdirb);
tempval &= ~PB2_DIRB0;
tempval |= PB2_DIRB1;
out_be32(&io->iop_pdirb, tempval);
tempval = in_be32(&io->iop_psorb);
tempval &= ~PB2_PSORB0;
tempval |= PB2_PSORB1;
out_be32(&io->iop_psorb, tempval);
tempval = in_be32(&io->iop_pparb);
tempval |= (PB2_DIRB0 | PB2_DIRB1);
out_be32(&io->iop_pparb, tempval);
target = CPM_CLK_FCC2;
break;
case 2:
tempval = in_be32(&io->iop_pdirb);
tempval &= ~PB3_DIRB0;
tempval |= PB3_DIRB1;
out_be32(&io->iop_pdirb, tempval);
tempval = in_be32(&io->iop_psorb);
tempval &= ~PB3_PSORB0;
tempval |= PB3_PSORB1;
out_be32(&io->iop_psorb, tempval);
tempval = in_be32(&io->iop_pparb);
tempval |= (PB3_DIRB0 | PB3_DIRB1);
out_be32(&io->iop_pparb, tempval);
tempval = in_be32(&io->iop_pdirc);
tempval |= PC3_DIRC1;
out_be32(&io->iop_pdirc, tempval);
tempval = in_be32(&io->iop_pparc);
tempval |= PC3_DIRC1;
out_be32(&io->iop_pparc, tempval);
target = CPM_CLK_FCC3;
break;
default:
printk(KERN_ERR "init_fcc_ioports: invalid FCC number\n");
return;
}
/* Port C has clocks...... */
tempval = in_be32(&io->iop_psorc);
tempval &= ~(PC_CLK(fpi->clk_rx - 8) | PC_CLK(fpi->clk_tx - 8));
out_be32(&io->iop_psorc, tempval);
tempval = in_be32(&io->iop_pdirc);
tempval &= ~(PC_CLK(fpi->clk_rx - 8) | PC_CLK(fpi->clk_tx - 8));
out_be32(&io->iop_pdirc, tempval);
tempval = in_be32(&io->iop_pparc);
tempval |= (PC_CLK(fpi->clk_rx - 8) | PC_CLK(fpi->clk_tx - 8));
out_be32(&io->iop_pparc, tempval);
cpm2_unmap(io);
/* Configure Serial Interface clock routing.
* First, clear FCC bits to zero,
* then set the ones we want.
*/
cpm2_clk_setup(target, fpi->clk_rx, CPM_CLK_RX);
cpm2_clk_setup(target, fpi->clk_tx, CPM_CLK_TX);
}
#endif
static void __init mpc85xx_ads_setup_arch(void)
{
struct device_node *cpu;
......@@ -131,6 +247,10 @@ static void __init mpc85xx_ads_setup_arch(void)
of_node_put(cpu);
}
#ifdef CONFIG_CPM2
cpm2_reset();
#endif
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
add_bridge(np);
......
/*
* MPC85xx ADS board definitions
*
* Maintainer: Kumar Gala <galak@kernel.crashing.org>
*
* Copyright 2004 Freescale Semiconductor Inc.
*
* 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 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 __MACH_MPC85XXADS_H
#define __MACH_MPC85XXADS_H
#include <linux/config.h>
#include <linux/initrd.h>
#include <sysdev/fsl_soc.h>
#define BCSR_ADDR ((uint)0xf8000000)
#define BCSR_SIZE ((uint)(32 * 1024))
#ifdef CONFIG_CPM2
#define MPC85xx_CPM_OFFSET (0x80000)
#define CPM_MAP_ADDR (get_immrbase() + MPC85xx_CPM_OFFSET)
#define CPM_IRQ_OFFSET 60
#define SIU_INT_SMC1 ((uint)0x04+CPM_IRQ_OFFSET)
#define SIU_INT_SMC2 ((uint)0x05+CPM_IRQ_OFFSET)
#define SIU_INT_SCC1 ((uint)0x28+CPM_IRQ_OFFSET)
#define SIU_INT_SCC2 ((uint)0x29+CPM_IRQ_OFFSET)
#define SIU_INT_SCC3 ((uint)0x2a+CPM_IRQ_OFFSET)
#define SIU_INT_SCC4 ((uint)0x2b+CPM_IRQ_OFFSET)
/* FCC1 Clock Source Configuration. These can be
* redefined in the board specific file.
* Can only choose from CLK9-12 */
#define F1_RXCLK 12
#define F1_TXCLK 11
/* FCC2 Clock Source Configuration. These can be
* redefined in the board specific file.
* Can only choose from CLK13-16 */
#define F2_RXCLK 13
#define F2_TXCLK 14
/* FCC3 Clock Source Configuration. These can be
* redefined in the board specific file.
* Can only choose from CLK13-16 */
#define F3_RXCLK 15
#define F3_TXCLK 16
#endif /* CONFIG_CPM2 */
#endif /* __MACH_MPC85XXADS_H */
......@@ -17,3 +17,8 @@ ifeq ($(CONFIG_PPC_MERGE),y)
obj-$(CONFIG_PPC_I8259) += i8259.o
obj-$(CONFIG_PPC_83xx) += ipic.o
endif
# Temporary hack until we have migrated to asm-powerpc
ifeq ($(ARCH),powerpc)
obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o
endif
/*
* General Purpose functions for the global management of the
* 8260 Communication Processor Module.
* Copyright (c) 1999-2001 Dan Malek <dan@embeddedalley.com>
* Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
* 2.3.99 Updates
*
* 2006 (c) MontaVista Software, Inc.
* Vitaly Bordug <vbordug@ru.mvista.com>
* Merged to arch/powerpc from arch/ppc/syslib/cpm2_common.c
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
/*
*
* In addition to the individual control of the communication
* channels, there are a few functions that globally affect the
* communication processor.
*
* Buffer descriptors must be allocated from the dual ported memory
* space. The allocator for that is here. When the communication
* process is reset, we reclaim the memory available. There is
* currently no deallocator for this memory.
*/
#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/module.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mpc8260.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/cpm2.h>
#include <asm/rheap.h>
#include <asm/fs_pd.h>
#include <sysdev/fsl_soc.h>
static void cpm2_dpinit(void);
cpm_cpm2_t *cpmp; /* Pointer to comm processor space */
/* We allocate this here because it is used almost exclusively for
* the communication processor devices.
*/
cpm2_map_t *cpm2_immr;
intctl_cpm2_t *cpm2_intctl;
#define CPM_MAP_SIZE (0x40000) /* 256k - the PQ3 reserve this amount
of space for CPM as it is larger
than on PQ2 */
void
cpm2_reset(void)
{
cpm2_immr = (cpm2_map_t *)ioremap(CPM_MAP_ADDR, CPM_MAP_SIZE);
cpm2_intctl = cpm2_map(im_intctl);
/* Reclaim the DP memory for our use.
*/
cpm2_dpinit();
/* Tell everyone where the comm processor resides.
*/
cpmp = &cpm2_immr->im_cpm;
}
/* Set a baud rate generator. This needs lots of work. There are
* eight BRGs, which can be connected to the CPM 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.
*/
#define BRG_INT_CLK (get_brgfreq())
#define BRG_UART_CLK (BRG_INT_CLK/16)
/* This function is used by UARTS, or anything else that uses a 16x
* oversampled clock.
*/
void
cpm_setbrg(uint brg, uint rate)
{
volatile uint *bp;
/* This is good enough to get SMCs running.....
*/
if (brg < 4) {
bp = cpm2_map_size(im_brgc1, 16);
} else {
bp = cpm2_map_size(im_brgc5, 16);
brg -= 4;
}
bp += brg;
*bp = ((BRG_UART_CLK / rate) << 1) | CPM_BRG_EN;
cpm2_unmap(bp);
}
/* This function is used to set high speed synchronous baud rate
* clocks.
*/
void
cpm2_fastbrg(uint brg, uint rate, int div16)
{
volatile uint *bp;
if (brg < 4) {
bp = cpm2_map_size(im_brgc1, 16);
}
else {
bp = cpm2_map_size(im_brgc5, 16);
brg -= 4;
}
bp += brg;
*bp = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
if (div16)
*bp |= CPM_BRG_DIV16;
cpm2_unmap(bp);
}
int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode)
{
int ret = 0;
int shift;
int i, bits = 0;
cpmux_t *im_cpmux;
u32 *reg;
u32 mask = 7;
u8 clk_map [24][3] = {
{CPM_CLK_FCC1, CPM_BRG5, 0},
{CPM_CLK_FCC1, CPM_BRG6, 1},
{CPM_CLK_FCC1, CPM_BRG7, 2},
{CPM_CLK_FCC1, CPM_BRG8, 3},
{CPM_CLK_FCC1, CPM_CLK9, 4},
{CPM_CLK_FCC1, CPM_CLK10, 5},
{CPM_CLK_FCC1, CPM_CLK11, 6},
{CPM_CLK_FCC1, CPM_CLK12, 7},
{CPM_CLK_FCC2, CPM_BRG5, 0},
{CPM_CLK_FCC2, CPM_BRG6, 1},
{CPM_CLK_FCC2, CPM_BRG7, 2},
{CPM_CLK_FCC2, CPM_BRG8, 3},
{CPM_CLK_FCC2, CPM_CLK13, 4},
{CPM_CLK_FCC2, CPM_CLK14, 5},
{CPM_CLK_FCC2, CPM_CLK15, 6},
{CPM_CLK_FCC2, CPM_CLK16, 7},
{CPM_CLK_FCC3, CPM_BRG5, 0},
{CPM_CLK_FCC3, CPM_BRG6, 1},
{CPM_CLK_FCC3, CPM_BRG7, 2},
{CPM_CLK_FCC3, CPM_BRG8, 3},
{CPM_CLK_FCC3, CPM_CLK13, 4},
{CPM_CLK_FCC3, CPM_CLK14, 5},
{CPM_CLK_FCC3, CPM_CLK15, 6},
{CPM_CLK_FCC3, CPM_CLK16, 7}
};
im_cpmux = cpm2_map(im_cpmux);
switch (target) {
case CPM_CLK_SCC1:
reg = &im_cpmux->cmx_scr;
shift = 24;
case CPM_CLK_SCC2:
reg = &im_cpmux->cmx_scr;
shift = 16;
break;
case CPM_CLK_SCC3:
reg = &im_cpmux->cmx_scr;
shift = 8;
break;
case CPM_CLK_SCC4:
reg = &im_cpmux->cmx_scr;
shift = 0;
break;
case CPM_CLK_FCC1:
reg = &im_cpmux->cmx_fcr;
shift = 24;
break;
case CPM_CLK_FCC2:
reg = &im_cpmux->cmx_fcr;
shift = 16;
break;
case CPM_CLK_FCC3:
reg = &im_cpmux->cmx_fcr;
shift = 8;
break;
default:
printk(KERN_ERR "cpm2_clock_setup: invalid clock target\n");
return -EINVAL;
}
if (mode == CPM_CLK_RX)
shift +=3;
for (i=0; i<24; i++) {
if (clk_map[i][0] == target && clk_map[i][1] == clock) {
bits = clk_map[i][2];
break;
}
}
if (i == sizeof(clk_map)/3)
ret = -EINVAL;
bits <<= shift;
mask <<= shift;
out_be32(reg, (in_be32(reg) & ~mask) | bits);
cpm2_unmap(im_cpmux);
return ret;
}
/*
* dpalloc / dpfree bits.
*/
static spinlock_t cpm_dpmem_lock;
/* 16 blocks should be enough to satisfy all requests
* until the memory subsystem goes up... */
static rh_block_t cpm_boot_dpmem_rh_block[16];
static rh_info_t cpm_dpmem_info;
static u8* im_dprambase;
static void cpm2_dpinit(void)
{
spin_lock_init(&cpm_dpmem_lock);
im_dprambase = ioremap(CPM_MAP_ADDR, CPM_DATAONLY_BASE + CPM_DATAONLY_SIZE);
/* initialize the info header */
rh_init(&cpm_dpmem_info, 1,
sizeof(cpm_boot_dpmem_rh_block) /
sizeof(cpm_boot_dpmem_rh_block[0]),
cpm_boot_dpmem_rh_block);
/* Attach the usable dpmem area */
/* XXX: This is actually crap. CPM_DATAONLY_BASE and
* CPM_DATAONLY_SIZE is only a subset of the available dpram. It
* varies with the processor and the microcode patches activated.
* But the following should be at least safe.
*/
rh_attach_region(&cpm_dpmem_info, (void *)CPM_DATAONLY_BASE,
CPM_DATAONLY_SIZE);
}
/* This function returns an index into the DPRAM area.
*/
uint cpm_dpalloc(uint size, uint align)
{
void *start;
unsigned long flags;
spin_lock_irqsave(&cpm_dpmem_lock, flags);
cpm_dpmem_info.alignment = align;
start = rh_alloc(&cpm_dpmem_info, size, "commproc");
spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
return (uint)start;
}
EXPORT_SYMBOL(cpm_dpalloc);
int cpm_dpfree(uint offset)
{
int ret;
unsigned long flags;
spin_lock_irqsave(&cpm_dpmem_lock, flags);
ret = rh_free(&cpm_dpmem_info, (void *)offset);
spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
return ret;
}
EXPORT_SYMBOL(cpm_dpfree);
/* not sure if this is ever needed */
uint cpm_dpalloc_fixed(uint offset, uint size, uint align)
{
void *start;
unsigned long flags;
spin_lock_irqsave(&cpm_dpmem_lock, flags);
cpm_dpmem_info.alignment = align;
start = rh_alloc_fixed(&cpm_dpmem_info, (void *)offset, size, "commproc");
spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
return (uint)start;
}
EXPORT_SYMBOL(cpm_dpalloc_fixed);
void cpm_dpdump(void)
{
rh_dump(&cpm_dpmem_info);
}
EXPORT_SYMBOL(cpm_dpdump);
void *cpm_dpram_addr(uint offset)
{
return (void *)(im_dprambase + offset);
}
EXPORT_SYMBOL(cpm_dpram_addr);
/*
* Platform information definitions.
*
* Copied from arch/ppc/syslib/cpm2_pic.c with minor subsequent updates
* to make in work in arch/powerpc/. Original (c) belongs to Dan Malek.
*
* Author: Vitaly Bordug <vbordug@ru.mvista.com>
*
* 1999-2001 (c) Dan Malek <dan@embeddedalley.com>
* 2006 (c) MontaVista Software, Inc.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
/* The CPM2 internal interrupt controller. It is usually
* the only interrupt controller.
* There are two 32-bit registers (high/low) for up to 64
* possible interrupts.
*
* Now, the fun starts.....Interrupt Numbers DO NOT MAP
* in a simple arithmetic fashion to mask or pending registers.
* That is, interrupt 4 does not map to bit position 4.
* We create two tables, indexed by vector number, to indicate
* which register to use and which bit in the register to use.
*/
#include <linux/stddef.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/irq.h>
#include <asm/immap_cpm2.h>
#include <asm/mpc8260.h>
#include <asm/io.h>
#include <asm/prom.h>
#include "cpm2_pic.h"
static struct device_node *cpm2_pic_node;
static struct irq_host *cpm2_pic_host;
#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
static const u_char irq_to_siureg[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
/* bit numbers do not match the docs, these are precomputed so the bit for
* a given irq is (1 << irq_to_siubit[irq]) */
static const u_char irq_to_siubit[] = {
0, 15, 14, 13, 12, 11, 10, 9,
8, 7, 6, 5, 4, 3, 2, 1,
2, 1, 0, 14, 13, 12, 11, 10,
9, 8, 7, 6, 5, 4, 3, 0,
31, 30, 29, 28, 27, 26, 25, 24,
23, 22, 21, 20, 19, 18, 17, 16,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
};
static void cpm2_mask_irq(unsigned int irq_nr)
{
int bit, word;
volatile uint *simr;
irq_nr -= CPM_IRQ_OFFSET;
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
simr = &(cpm2_intctl->ic_simrh);
ppc_cached_irq_mask[word] &= ~(1 << bit);
simr[word] = ppc_cached_irq_mask[word];
}
static void cpm2_unmask_irq(unsigned int irq_nr)
{
int bit, word;
volatile uint *simr;
irq_nr -= CPM_IRQ_OFFSET;
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
simr = &(cpm2_intctl->ic_simrh);
ppc_cached_irq_mask[word] |= 1 << bit;
simr[word] = ppc_cached_irq_mask[word];
}
static void cpm2_mask_and_ack(unsigned int irq_nr)
{
int bit, word;
volatile uint *simr, *sipnr;
irq_nr -= CPM_IRQ_OFFSET;
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
simr = &(cpm2_intctl->ic_simrh);
sipnr = &(cpm2_intctl->ic_sipnrh);
ppc_cached_irq_mask[word] &= ~(1 << bit);
simr[word] = ppc_cached_irq_mask[word];
sipnr[word] = 1 << bit;
}
static void cpm2_end_irq(unsigned int irq_nr)
{
int bit, word;
volatile uint *simr;
if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
&& irq_desc[irq_nr].action) {
irq_nr -= CPM_IRQ_OFFSET;
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
simr = &(cpm2_intctl->ic_simrh);
ppc_cached_irq_mask[word] |= 1 << bit;
simr[word] = ppc_cached_irq_mask[word];
/*
* Work around large numbers of spurious IRQs on PowerPC 82xx
* systems.
*/
mb();
}
}
static struct irq_chip cpm2_pic = {
.typename = " CPM2 SIU ",
.enable = cpm2_unmask_irq,
.disable = cpm2_mask_irq,
.unmask = cpm2_unmask_irq,
.mask_ack = cpm2_mask_and_ack,
.end = cpm2_end_irq,
};
int cpm2_get_irq(struct pt_regs *regs)
{
int irq;
unsigned long bits;
/* For CPM2, read the SIVEC register and shift the bits down
* to get the irq number. */
bits = cpm2_intctl->ic_sivec;
irq = bits >> 26;
if (irq == 0)
return(-1);
return irq+CPM_IRQ_OFFSET;
}
static int cpm2_pic_host_match(struct irq_host *h, struct device_node *node)
{
return cpm2_pic_node == NULL || cpm2_pic_node == node;
}
static int cpm2_pic_host_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hw)
{
pr_debug("cpm2_pic_host_map(%d, 0x%lx)\n", virq, hw);
get_irq_desc(virq)->status |= IRQ_LEVEL;
set_irq_chip_and_handler(virq, &cpm2_pic, handle_level_irq);
return 0;
}
static void cpm2_host_unmap(struct irq_host *h, unsigned int virq)
{
/* Make sure irq is masked in hardware */
cpm2_mask_irq(virq);
/* remove chip and handler */
set_irq_chip_and_handler(virq, NULL, NULL);
}
static int cpm2_pic_host_xlate(struct irq_host *h, struct device_node *ct,
u32 *intspec, unsigned int intsize,
irq_hw_number_t *out_hwirq, unsigned int *out_flags)
{
static const unsigned char map_cpm2_senses[4] = {
IRQ_TYPE_LEVEL_LOW,
IRQ_TYPE_LEVEL_HIGH,
IRQ_TYPE_EDGE_FALLING,
IRQ_TYPE_EDGE_RISING,
};
*out_hwirq = intspec[0];
if (intsize > 1 && intspec[1] < 4)
*out_flags = map_cpm2_senses[intspec[1]];
else
*out_flags = IRQ_TYPE_NONE;
return 0;
}
static struct irq_host_ops cpm2_pic_host_ops = {
.match = cpm2_pic_host_match,
.map = cpm2_pic_host_map,
.unmap = cpm2_host_unmap,
.xlate = cpm2_pic_host_xlate,
};
void cpm2_pic_init(struct device_node *node)
{
int i;
/* Clear the CPM IRQ controller, in case it has any bits set
* from the bootloader
*/
/* Mask out everything */
cpm2_intctl->ic_simrh = 0x00000000;
cpm2_intctl->ic_simrl = 0x00000000;
wmb();
/* Ack everything */
cpm2_intctl->ic_sipnrh = 0xffffffff;
cpm2_intctl->ic_sipnrl = 0xffffffff;
wmb();
/* Dummy read of the vector */
i = cpm2_intctl->ic_sivec;
rmb();
/* Initialize the default interrupt mapping priorities,
* in case the boot rom changed something on us.
*/
cpm2_intctl->ic_sicr = 0;
cpm2_intctl->ic_scprrh = 0x05309770;
cpm2_intctl->ic_scprrl = 0x05309770;
/* create a legacy host */
if (node)
cpm2_pic_node = of_node_get(node);
cpm2_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 64, &cpm2_pic_host_ops, 64);
if (cpm2_pic_host == NULL) {
printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");
return;
}
}
#ifndef _PPC_KERNEL_CPM2_H
#define _PPC_KERNEL_CPM2_H
extern intctl_cpm2_t *cpm2_intctl;
extern int cpm2_get_irq(struct pt_regs *regs);
extern void cpm2_pic_init(struct device_node*);
#endif /* _PPC_KERNEL_CPM2_H */
......@@ -3,6 +3,9 @@
*
* Maintained by Kumar Gala (see MAINTAINERS for contact information)
*
* 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 the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
......@@ -20,15 +23,20 @@
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/fsl_devices.h>
#include <linux/fs_enet_pd.h>
#include <linux/fs_uart_pd.h>
#include <asm/system.h>
#include <asm/atomic.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/time.h>
#include <asm/prom.h>
#include <sysdev/fsl_soc.h>
#include <mm/mmu_decl.h>
#include <asm/cpm2.h>
extern void init_fcc_ioports(struct fs_platform_info*);
static phys_addr_t immrbase = -1;
phys_addr_t get_immrbase(void)
......@@ -42,7 +50,9 @@ phys_addr_t get_immrbase(void)
if (soc) {
unsigned int size;
const void *prop = get_property(soc, "reg", &size);
immrbase = of_translate_address(soc, prop);
if (prop)
immrbase = of_translate_address(soc, prop);
of_node_put(soc);
};
......@@ -51,6 +61,59 @@ phys_addr_t get_immrbase(void)
EXPORT_SYMBOL(get_immrbase);
#ifdef CONFIG_CPM2
static u32 brgfreq = -1;
u32 get_brgfreq(void)
{
struct device_node *node;
if (brgfreq != -1)
return brgfreq;
node = of_find_node_by_type(NULL, "cpm");
if (node) {
unsigned int size;
const unsigned int *prop = get_property(node, "brg-frequency",
&size);
if (prop)
brgfreq = *prop;
of_node_put(node);
};
return brgfreq;
}
EXPORT_SYMBOL(get_brgfreq);
static u32 fs_baudrate = -1;
u32 get_baudrate(void)
{
struct device_node *node;
if (fs_baudrate != -1)
return fs_baudrate;
node = of_find_node_by_type(NULL, "serial");
if (node) {
unsigned int size;
const unsigned int *prop = get_property(node, "current-speed",
&size);
if (prop)
fs_baudrate = *prop;
of_node_put(node);
};
return fs_baudrate;
}
EXPORT_SYMBOL(get_baudrate);
#endif /* CONFIG_CPM2 */
static int __init gfar_mdio_of_init(void)
{
struct device_node *np;
......@@ -85,8 +148,11 @@ static int __init gfar_mdio_of_init(void)
mdio_data.irq[k] = -1;
while ((child = of_get_next_child(np, child)) != NULL) {
const u32 *id = get_property(child, "reg", NULL);
mdio_data.irq[*id] = irq_of_parse_and_map(child, 0);
int irq = irq_of_parse_and_map(child, 0);
if (irq != NO_IRQ) {
const u32 *id = get_property(child, "reg", NULL);
mdio_data.irq[*id] = irq;
}
}
ret =
......@@ -128,7 +194,7 @@ static int __init gfar_of_init(void)
const char *model;
const void *mac_addr;
const phandle *ph;
int n_res = 1;
int n_res = 2;
memset(r, 0, sizeof(r));
memset(&gfar_data, 0, sizeof(gfar_data));
......@@ -159,7 +225,7 @@ static int __init gfar_of_init(void)
gfar_dev =
platform_device_register_simple("fsl-gianfar", i, &r[0],
n_res + 1);
n_res);
if (IS_ERR(gfar_dev)) {
ret = PTR_ERR(gfar_dev);
......@@ -478,3 +544,208 @@ static int __init fsl_usb_of_init(void)
}
arch_initcall(fsl_usb_of_init);
#ifdef CONFIG_CPM2
static const char fcc_regs[] = "fcc_regs";
static const char fcc_regs_c[] = "fcc_regs_c";
static const char fcc_pram[] = "fcc_pram";
static char bus_id[9][BUS_ID_SIZE];
static int __init fs_enet_of_init(void)
{
struct device_node *np;
unsigned int i;
struct platform_device *fs_enet_dev;
struct resource res;
int ret;
for (np = NULL, i = 0;
(np = of_find_compatible_node(np, "network", "fs_enet")) != NULL;
i++) {
struct resource r[4];
struct device_node *phy, *mdio;
struct fs_platform_info fs_enet_data;
const unsigned int *id, *phy_addr;
const void *mac_addr;
const phandle *ph;
const char *model;
memset(r, 0, sizeof(r));
memset(&fs_enet_data, 0, sizeof(fs_enet_data));
ret = of_address_to_resource(np, 0, &r[0]);
if (ret)
goto err;
r[0].name = fcc_regs;
ret = of_address_to_resource(np, 1, &r[1]);
if (ret)
goto err;
r[1].name = fcc_pram;
ret = of_address_to_resource(np, 2, &r[2]);
if (ret)
goto err;
r[2].name = fcc_regs_c;
r[3].start = r[3].end = irq_of_parse_and_map(np, 0);
r[3].flags = IORESOURCE_IRQ;
fs_enet_dev =
platform_device_register_simple("fsl-cpm-fcc", i, &r[0], 4);
if (IS_ERR(fs_enet_dev)) {
ret = PTR_ERR(fs_enet_dev);
goto err;
}
model = get_property(np, "model", NULL);
if (model == NULL) {
ret = -ENODEV;
goto unreg;
}
mac_addr = get_property(np, "mac-address", NULL);
memcpy(fs_enet_data.macaddr, mac_addr, 6);
ph = get_property(np, "phy-handle", NULL);
phy = of_find_node_by_phandle(*ph);
if (phy == NULL) {
ret = -ENODEV;
goto unreg;
}
phy_addr = get_property(phy, "reg", NULL);
fs_enet_data.phy_addr = *phy_addr;
id = get_property(np, "device-id", NULL);
fs_enet_data.fs_no = *id;
strcpy(fs_enet_data.fs_type, model);
mdio = of_get_parent(phy);
ret = of_address_to_resource(mdio, 0, &res);
if (ret) {
of_node_put(phy);
of_node_put(mdio);
goto unreg;
}
fs_enet_data.clk_rx = *((u32 *) get_property(np, "rx-clock", NULL));
fs_enet_data.clk_tx = *((u32 *) get_property(np, "tx-clock", NULL));
if (strstr(model, "FCC")) {
int fcc_index = *id - 1;
fs_enet_data.dpram_offset = (u32)cpm_dpram_addr(0);
fs_enet_data.rx_ring = 32;
fs_enet_data.tx_ring = 32;
fs_enet_data.rx_copybreak = 240;
fs_enet_data.use_napi = 0;
fs_enet_data.napi_weight = 17;
fs_enet_data.mem_offset = FCC_MEM_OFFSET(fcc_index);
fs_enet_data.cp_page = CPM_CR_FCC_PAGE(fcc_index);
fs_enet_data.cp_block = CPM_CR_FCC_SBLOCK(fcc_index);
snprintf((char*)&bus_id[(*id)], BUS_ID_SIZE, "%x:%02x",
(u32)res.start, fs_enet_data.phy_addr);
fs_enet_data.bus_id = (char*)&bus_id[(*id)];
fs_enet_data.init_ioports = init_fcc_ioports;
}
of_node_put(phy);
of_node_put(mdio);
ret = platform_device_add_data(fs_enet_dev, &fs_enet_data,
sizeof(struct
fs_platform_info));
if (ret)
goto unreg;
}
return 0;
unreg:
platform_device_unregister(fs_enet_dev);
err:
return ret;
}
arch_initcall(fs_enet_of_init);
static const char scc_regs[] = "regs";
static const char scc_pram[] = "pram";
static int __init cpm_uart_of_init(void)
{
struct device_node *np;
unsigned int i;
struct platform_device *cpm_uart_dev;
int ret;
for (np = NULL, i = 0;
(np = of_find_compatible_node(np, "serial", "cpm_uart")) != NULL;
i++) {
struct resource r[3];
struct fs_uart_platform_info cpm_uart_data;
const int *id;
const char *model;
memset(r, 0, sizeof(r));
memset(&cpm_uart_data, 0, sizeof(cpm_uart_data));
ret = of_address_to_resource(np, 0, &r[0]);
if (ret)
goto err;
r[0].name = scc_regs;
ret = of_address_to_resource(np, 1, &r[1]);
if (ret)
goto err;
r[1].name = scc_pram;
r[2].start = r[2].end = irq_of_parse_and_map(np, 0);
r[2].flags = IORESOURCE_IRQ;
cpm_uart_dev =
platform_device_register_simple("fsl-cpm-scc:uart", i, &r[0], 3);
if (IS_ERR(cpm_uart_dev)) {
ret = PTR_ERR(cpm_uart_dev);
goto err;
}
id = get_property(np, "device-id", NULL);
cpm_uart_data.fs_no = *id;
model = (char*)get_property(np, "model", NULL);
strcpy(cpm_uart_data.fs_type, model);
cpm_uart_data.uart_clk = ppc_proc_freq;
cpm_uart_data.tx_num_fifo = 4;
cpm_uart_data.tx_buf_size = 32;
cpm_uart_data.rx_num_fifo = 4;
cpm_uart_data.rx_buf_size = 32;
cpm_uart_data.clk_rx = *((u32 *) get_property(np, "rx-clock", NULL));
cpm_uart_data.clk_tx = *((u32 *) get_property(np, "tx-clock", NULL));
ret =
platform_device_add_data(cpm_uart_dev, &cpm_uart_data,
sizeof(struct
fs_uart_platform_info));
if (ret)
goto unreg;
}
return 0;
unreg:
platform_device_unregister(cpm_uart_dev);
err:
return ret;
}
arch_initcall(cpm_uart_of_init);
#endif /* CONFIG_CPM2 */
......@@ -5,6 +5,8 @@
#include <asm/mmu.h>
extern phys_addr_t get_immrbase(void);
extern u32 get_brgfreq(void);
extern u32 get_baudrate(void);
#endif
#endif
......@@ -103,7 +103,7 @@ static struct fs_platform_info mpc82xx_enet_pdata[] = {
},
};
static void init_fcc1_ioports(void)
static void init_fcc1_ioports(struct fs_platform_info*)
{
struct io_port *io;
u32 tempval;
......@@ -144,7 +144,7 @@ static void init_fcc1_ioports(void)
iounmap(immap);
}
static void init_fcc2_ioports(void)
static void init_fcc2_ioports(struct fs_platform_info*)
{
cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
u32 *bcsr = ioremap(BCSR_ADDR+12, sizeof(u32));
......@@ -229,7 +229,7 @@ static void mpc8272ads_fixup_uart_pdata(struct platform_device *pdev,
}
}
static void init_scc1_uart_ioports(void)
static void init_scc1_uart_ioports(struct fs_uart_platform_info*)
{
cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
......@@ -246,7 +246,7 @@ static void init_scc1_uart_ioports(void)
iounmap(immap);
}
static void init_scc4_uart_ioports(void)
static void init_scc4_uart_ioports(struct fs_uart_platform_info*)
{
cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
......
......@@ -137,7 +137,7 @@ void __init board_init(void)
iounmap(bcsr_io);
}
static void setup_fec1_ioports(void)
static void setup_fec1_ioports(struct fs_platform_info*)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
......@@ -145,7 +145,7 @@ static void setup_fec1_ioports(void)
setbits16(&immap->im_ioport.iop_pddir, 0x1fff);
}
static void setup_scc1_ioports(void)
static void setup_scc1_ioports(struct fs_platform_info*)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
unsigned *bcsr_io;
......@@ -194,7 +194,7 @@ static void setup_scc1_ioports(void)
}
static void setup_smc1_ioports(void)
static void setup_smc1_ioports(struct fs_uart_platform_info*)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
unsigned *bcsr_io;
......@@ -216,7 +216,7 @@ static void setup_smc1_ioports(void)
}
static void setup_smc2_ioports(void)
static void setup_smc2_ioports(struct fs_uart_platform_info*)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
unsigned *bcsr_io;
......
......@@ -161,7 +161,7 @@ void __init board_init(void)
#endif
}
static void setup_fec1_ioports(void)
static void setup_fec1_ioports(struct fs_platform_info*)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
......@@ -181,7 +181,7 @@ static void setup_fec1_ioports(void)
clrbits32(&immap->im_cpm.cp_cptr, 0x00000100);
}
static void setup_fec2_ioports(void)
static void setup_fec2_ioports(struct fs_platform_info*)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
......@@ -193,7 +193,7 @@ static void setup_fec2_ioports(void)
clrbits32(&immap->im_cpm.cp_cptr, 0x00000080);
}
static void setup_scc3_ioports(void)
static void setup_scc3_ioports(struct fs_platform_info*)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
unsigned *bcsr_io;
......@@ -315,7 +315,7 @@ static void __init mpc885ads_fixup_scc_enet_pdata(struct platform_device *pdev,
mpc885ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
}
static void setup_smc1_ioports(void)
static void setup_smc1_ioports(struct fs_uart_platform_info*)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
unsigned *bcsr_io;
......@@ -335,7 +335,7 @@ static void setup_smc1_ioports(void)
clrbits16(&immap->im_cpm.cp_pbodr, iobits);
}
static void setup_smc2_ioports(void)
static void setup_smc2_ioports(struct fs_uart_platform_info*)
{
immap_t *immap = (immap_t *) IMAP_ADDR;
unsigned *bcsr_io;
......
......@@ -944,12 +944,13 @@ extern int fs_mii_connect(struct net_device *dev);
extern void fs_mii_disconnect(struct net_device *dev);
static struct net_device *fs_init_instance(struct device *dev,
const struct fs_platform_info *fpi)
struct fs_platform_info *fpi)
{
struct net_device *ndev = NULL;
struct fs_enet_private *fep = NULL;
int privsize, i, r, err = 0, registered = 0;
fpi->fs_no = fs_get_id(fpi);
/* guard */
if ((unsigned int)fpi->fs_no >= FS_MAX_INDEX)
return ERR_PTR(-EINVAL);
......@@ -971,7 +972,7 @@ static struct net_device *fs_init_instance(struct device *dev,
dev_set_drvdata(dev, ndev);
fep->fpi = fpi;
if (fpi->init_ioports)
fpi->init_ioports();
fpi->init_ioports((struct fs_platform_info *)fpi);
#ifdef CONFIG_FS_ENET_HAS_FEC
if (fs_get_fec_index(fpi->fs_no) >= 0)
......
......@@ -46,6 +46,7 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/delay.h>
#include <asm/fs_pd.h>
#if defined(CONFIG_SERIAL_CPM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
......@@ -1022,15 +1023,17 @@ int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
{
struct resource *r;
struct fs_uart_platform_info *pdata = pdev->dev.platform_data;
int idx = pdata->fs_no; /* It is UART_SMCx or UART_SCCx index */
int idx; /* It is UART_SMCx or UART_SCCx index */
struct uart_cpm_port *pinfo;
int line;
u32 mem, pram;
idx = pdata->fs_no = fs_uart_get_id(pdata);
line = cpm_uart_id2nr(idx);
if(line < 0) {
printk(KERN_ERR"%s(): port %d is not registered", __FUNCTION__, idx);
return -1;
return -EINVAL;
}
pinfo = (struct uart_cpm_port *) &cpm_uart_ports[idx];
......@@ -1044,11 +1047,11 @@ int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs")))
return -EINVAL;
mem = r->start;
mem = (u32)ioremap(r->start, r->end - r->start + 1);
if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram")))
return -EINVAL;
pram = r->start;
pram = (u32)ioremap(r->start, r->end - r->start + 1);
if(idx > fsid_smc2_uart) {
pinfo->sccp = (scc_t *)mem;
......@@ -1179,7 +1182,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
pdata = pdev->dev.platform_data;
if (pdata)
if (pdata->init_ioports)
pdata->init_ioports();
pdata->init_ioports(pdata);
cpm_uart_drv_get_platform_data(pdev, 1);
}
......@@ -1189,11 +1192,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
if (options) {
uart_parse_options(options, &baud, &parity, &bits, &flow);
} else {
bd_t *bd = (bd_t *) __res;
if (bd->bi_baudrate)
baud = bd->bi_baudrate;
else
if ((baud = uart_baudrate()) == -1)
baud = 9600;
}
......@@ -1266,13 +1265,14 @@ static int cpm_uart_drv_probe(struct device *dev)
}
pdata = pdev->dev.platform_data;
pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n", cpm_uart_id2nr(pdata->fs_no));
if ((ret = cpm_uart_drv_get_platform_data(pdev, 0)))
return ret;
pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n", cpm_uart_id2nr(pdata->fs_no));
if (pdata->init_ioports)
pdata->init_ioports();
pdata->init_ioports(pdata);
ret = uart_add_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port);
......
......@@ -40,6 +40,7 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/fs_pd.h>
#include <linux/serial_core.h>
#include <linux/kernel.h>
......@@ -50,8 +51,9 @@
void cpm_line_cr_cmd(int line, int cmd)
{
volatile cpm_cpm2_t *cp = cpmp;
ulong val;
volatile cpm_cpm2_t *cp = cpm2_map(im_cpm);
switch (line) {
case UART_SMC1:
......@@ -84,11 +86,14 @@ void cpm_line_cr_cmd(int line, int cmd)
}
cp->cp_cpcr = val;
while (cp->cp_cpcr & CPM_CR_FLG) ;
cpm2_unmap(cp);
}
void smc1_lineif(struct uart_cpm_port *pinfo)
{
volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
volatile iop_cpm2_t *io = cpm2_map(im_ioport);
volatile cpmux_t *cpmux = cpm2_map(im_cpmux);
/* SMC1 is only on port D */
io->iop_ppard |= 0x00c00000;
......@@ -97,13 +102,17 @@ void smc1_lineif(struct uart_cpm_port *pinfo)
io->iop_psord &= ~0x00c00000;
/* Wire BRG1 to SMC1 */
cpm2_immr->im_cpmux.cmx_smr &= 0x0f;
cpmux->cmx_smr &= 0x0f;
pinfo->brg = 1;
cpm2_unmap(cpmux);
cpm2_unmap(io);
}
void smc2_lineif(struct uart_cpm_port *pinfo)
{
volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
volatile iop_cpm2_t *io = cpm2_map(im_ioport);
volatile cpmux_t *cpmux = cpm2_map(im_cpmux);
/* SMC2 is only on port A */
io->iop_ppara |= 0x00c00000;
......@@ -112,13 +121,17 @@ void smc2_lineif(struct uart_cpm_port *pinfo)
io->iop_psora &= ~0x00c00000;
/* Wire BRG2 to SMC2 */
cpm2_immr->im_cpmux.cmx_smr &= 0xf0;
cpmux->cmx_smr &= 0xf0;
pinfo->brg = 2;
cpm2_unmap(cpmux);
cpm2_unmap(io);
}
void scc1_lineif(struct uart_cpm_port *pinfo)
{
volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
volatile iop_cpm2_t *io = cpm2_map(im_ioport);
volatile cpmux_t *cpmux = cpm2_map(im_cpmux);
/* Use Port D for SCC1 instead of other functions. */
io->iop_ppard |= 0x00000003;
......@@ -128,9 +141,12 @@ void scc1_lineif(struct uart_cpm_port *pinfo)
io->iop_pdird |= 0x00000002; /* Tx */
/* Wire BRG1 to SCC1 */
cpm2_immr->im_cpmux.cmx_scr &= 0x00ffffff;
cpm2_immr->im_cpmux.cmx_scr |= 0x00000000;
cpmux->cmx_scr &= 0x00ffffff;
cpmux->cmx_scr |= 0x00000000;
pinfo->brg = 1;
cpm2_unmap(cpmux);
cpm2_unmap(io);
}
void scc2_lineif(struct uart_cpm_port *pinfo)
......@@ -143,43 +159,57 @@ void scc2_lineif(struct uart_cpm_port *pinfo)
* be supported in a sane fashion.
*/
#ifndef CONFIG_STX_GP3
volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
volatile iop_cpm2_t *io = cpm2_map(im_ioport);
volatile cpmux_t *cpmux = cpm2_map(im_cpmux);
io->iop_pparb |= 0x008b0000;
io->iop_pdirb |= 0x00880000;
io->iop_psorb |= 0x00880000;
io->iop_pdirb &= ~0x00030000;
io->iop_psorb &= ~0x00030000;
#endif
cpm2_immr->im_cpmux.cmx_scr &= 0xff00ffff;
cpm2_immr->im_cpmux.cmx_scr |= 0x00090000;
cpmux->cmx_scr &= 0xff00ffff;
cpmux->cmx_scr |= 0x00090000;
pinfo->brg = 2;
cpm2_unmap(cpmux);
cpm2_unmap(io);
}
void scc3_lineif(struct uart_cpm_port *pinfo)
{
volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
volatile iop_cpm2_t *io = cpm2_map(im_ioport);
volatile cpmux_t *cpmux = cpm2_map(im_cpmux);
io->iop_pparb |= 0x008b0000;
io->iop_pdirb |= 0x00880000;
io->iop_psorb |= 0x00880000;
io->iop_pdirb &= ~0x00030000;
io->iop_psorb &= ~0x00030000;
cpm2_immr->im_cpmux.cmx_scr &= 0xffff00ff;
cpm2_immr->im_cpmux.cmx_scr |= 0x00001200;
cpmux->cmx_scr &= 0xffff00ff;
cpmux->cmx_scr |= 0x00001200;
pinfo->brg = 3;
cpm2_unmap(cpmux);
cpm2_unmap(io);
}
void scc4_lineif(struct uart_cpm_port *pinfo)
{
volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
volatile iop_cpm2_t *io = cpm2_map(im_ioport);
volatile cpmux_t *cpmux = cpm2_map(im_cpmux);
io->iop_ppard |= 0x00000600;
io->iop_psord &= ~0x00000600; /* Tx/Rx */
io->iop_pdird &= ~0x00000200; /* Rx */
io->iop_pdird |= 0x00000400; /* Tx */
cpm2_immr->im_cpmux.cmx_scr &= 0xffffff00;
cpm2_immr->im_cpmux.cmx_scr |= 0x0000001b;
cpmux->cmx_scr &= 0xffffff00;
cpmux->cmx_scr |= 0x0000001b;
pinfo->brg = 4;
cpm2_unmap(cpmux);
cpm2_unmap(io);
}
/*
......@@ -254,88 +284,103 @@ void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
/* Setup any dynamic params in the uart desc */
int cpm_uart_init_portdesc(void)
{
#if defined(CONFIG_SERIAL_CPM_SMC1) || defined(CONFIG_SERIAL_CPM_SMC2)
u32 addr;
#endif
pr_debug("CPM uart[-]:init portdesc\n");
cpm_uart_nr = 0;
#ifdef CONFIG_SERIAL_CPM_SMC1
cpm_uart_ports[UART_SMC1].smcp = (smc_t *) & cpm2_immr->im_smc[0];
cpm_uart_ports[UART_SMC1].smcup =
(smc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SMC1];
*(u16 *)(&cpm2_immr->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
cpm_uart_ports[UART_SMC1].smcp = (smc_t *) cpm2_map(im_smc[0]);
cpm_uart_ports[UART_SMC1].port.mapbase =
(unsigned long)&cpm2_immr->im_smc[0];
(unsigned long)cpm_uart_ports[UART_SMC1].smcp;
cpm_uart_ports[UART_SMC1].smcup =
(smc_uart_t *) cpm2_map_size(im_dprambase[PROFF_SMC1], PROFF_SMC_SIZE);
addr = (u16 *)cpm2_map_size(im_dprambase[PROFF_SMC1_BASE], 2);
*addr = PROFF_SMC1;
cpm2_unmap(addr);
cpm_uart_ports[UART_SMC1].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
cpm_uart_ports[UART_SMC1].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
cpm_uart_ports[UART_SMC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
cpm_uart_ports[UART_SMC1].port.uartclk = uart_clock();
cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1;
#endif
#ifdef CONFIG_SERIAL_CPM_SMC2
cpm_uart_ports[UART_SMC2].smcp = (smc_t *) & cpm2_immr->im_smc[1];
cpm_uart_ports[UART_SMC2].smcup =
(smc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SMC2];
*(u16 *)(&cpm2_immr->im_dprambase[PROFF_SMC2_BASE]) = PROFF_SMC2;
cpm_uart_ports[UART_SMC2].smcp = (smc_t *) cpm2_map(im_smc[1]);
cpm_uart_ports[UART_SMC2].port.mapbase =
(unsigned long)&cpm2_immr->im_smc[1];
(unsigned long)cpm_uart_ports[UART_SMC2].smcp;
cpm_uart_ports[UART_SMC2].smcup =
(smc_uart_t *) cpm2_map_size(im_dprambase[PROFF_SMC2], PROFF_SMC_SIZE);
addr = (u16 *)cpm2_map_size(im_dprambase[PROFF_SMC2_BASE], 2);
*addr = PROFF_SMC2;
cpm2_unmap(addr);
cpm_uart_ports[UART_SMC2].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
cpm_uart_ports[UART_SMC2].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
cpm_uart_ports[UART_SMC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
cpm_uart_ports[UART_SMC2].port.uartclk = uart_clock();
cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2;
#endif
#ifdef CONFIG_SERIAL_CPM_SCC1
cpm_uart_ports[UART_SCC1].sccp = (scc_t *) & cpm2_immr->im_scc[0];
cpm_uart_ports[UART_SCC1].sccup =
(scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC1];
cpm_uart_ports[UART_SCC1].sccp = (scc_t *) cpm2_map(im_scc[0]);
cpm_uart_ports[UART_SCC1].port.mapbase =
(unsigned long)&cpm2_immr->im_scc[0];
(unsigned long)cpm_uart_ports[UART_SCC1].sccp;
cpm_uart_ports[UART_SCC1].sccup =
(scc_uart_t *) cpm2_map_size(im_dprambase[PROFF_SCC1], PROFF_SCC_SIZE);
cpm_uart_ports[UART_SCC1].sccp->scc_sccm &=
~(UART_SCCM_TX | UART_SCCM_RX);
cpm_uart_ports[UART_SCC1].sccp->scc_gsmrl &=
~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
cpm_uart_ports[UART_SCC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
cpm_uart_ports[UART_SCC1].port.uartclk = uart_clock();
cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1;
#endif
#ifdef CONFIG_SERIAL_CPM_SCC2
cpm_uart_ports[UART_SCC2].sccp = (scc_t *) & cpm2_immr->im_scc[1];
cpm_uart_ports[UART_SCC2].sccup =
(scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC2];
cpm_uart_ports[UART_SCC2].sccp = (scc_t *) cpm2_map(im_scc[1]);
cpm_uart_ports[UART_SCC2].port.mapbase =
(unsigned long)&cpm2_immr->im_scc[1];
(unsigned long)cpm_uart_ports[UART_SCC2].sccp;
cpm_uart_ports[UART_SCC2].sccup =
(scc_uart_t *) cpm2_map_size(im_dprambase[PROFF_SCC2], PROFF_SCC_SIZE);
cpm_uart_ports[UART_SCC2].sccp->scc_sccm &=
~(UART_SCCM_TX | UART_SCCM_RX);
cpm_uart_ports[UART_SCC2].sccp->scc_gsmrl &=
~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
cpm_uart_ports[UART_SCC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
cpm_uart_ports[UART_SCC2].port.uartclk = uart_clock();
cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2;
#endif
#ifdef CONFIG_SERIAL_CPM_SCC3
cpm_uart_ports[UART_SCC3].sccp = (scc_t *) & cpm2_immr->im_scc[2];
cpm_uart_ports[UART_SCC3].sccup =
(scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC3];
cpm_uart_ports[UART_SCC3].sccp = (scc_t *) cpm2_map(im_scc[2]);
cpm_uart_ports[UART_SCC3].port.mapbase =
(unsigned long)&cpm2_immr->im_scc[2];
(unsigned long)cpm_uart_ports[UART_SCC3].sccp;
cpm_uart_ports[UART_SCC3].sccup =
(scc_uart_t *) cpm2_map_size(im_dprambase[PROFF_SCC3], PROFF_SCC_SIZE);
cpm_uart_ports[UART_SCC3].sccp->scc_sccm &=
~(UART_SCCM_TX | UART_SCCM_RX);
cpm_uart_ports[UART_SCC3].sccp->scc_gsmrl &=
~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
cpm_uart_ports[UART_SCC3].port.uartclk = (((bd_t *) __res)->bi_intfreq);
cpm_uart_ports[UART_SCC3].port.uartclk = uart_clock();
cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3;
#endif
#ifdef CONFIG_SERIAL_CPM_SCC4
cpm_uart_ports[UART_SCC4].sccp = (scc_t *) & cpm2_immr->im_scc[3];
cpm_uart_ports[UART_SCC4].sccup =
(scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC4];
cpm_uart_ports[UART_SCC4].sccp = (scc_t *) cpm2_map(im_scc[3]);
cpm_uart_ports[UART_SCC4].port.mapbase =
(unsigned long)&cpm2_immr->im_scc[3];
(unsigned long)cpm_uart_ports[UART_SCC4].sccp;
cpm_uart_ports[UART_SCC4].sccup =
(scc_uart_t *) cpm2_map_size(im_dprambase[PROFF_SCC4], PROFF_SCC_SIZE);
cpm_uart_ports[UART_SCC4].sccp->scc_sccm &=
~(UART_SCCM_TX | UART_SCCM_RX);
cpm_uart_ports[UART_SCC4].sccp->scc_gsmrl &=
~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
cpm_uart_ports[UART_SCC4].port.uartclk = (((bd_t *) __res)->bi_intfreq);
cpm_uart_ports[UART_SCC4].port.uartclk = uart_clock();
cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4;
#endif
......
......@@ -40,6 +40,6 @@ static inline void cpm_set_smc_fcr(volatile smc_uart_t * up)
up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
}
#define DPRAM_BASE ((unsigned char *)&cpm2_immr->im_dprambase[0])
#define DPRAM_BASE ((unsigned char *)cpm_dpram_addr(0))
#endif
/*
* Platform information definitions.
*
* 2006 (c) MontaVista Software, Inc.
* Vitaly Bordug <vbordug@ru.mvista.com>
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
#ifndef FS_PD_H
#define FS_PD_H
#include <asm/cpm2.h>
#include <sysdev/fsl_soc.h>
#include <asm/time.h>
static inline int uart_baudrate(void)
{
return get_baudrate();
}
static inline int uart_clock(void)
{
return ppc_proc_freq;
}
#define cpm2_map(member) \
({ \
u32 offset = offsetof(cpm2_map_t, member); \
void *addr = ioremap (CPM_MAP_ADDR + offset, \
sizeof( ((cpm2_map_t*)0)->member)); \
addr; \
})
#define cpm2_map_size(member, size) \
({ \
u32 offset = offsetof(cpm2_map_t, member); \
void *addr = ioremap (CPM_MAP_ADDR + offset, size); \
addr; \
})
#define cpm2_unmap(addr) iounmap(addr)
#endif
/*
* include/asm-powerpc/mpc85xx.h
*
* MPC85xx definitions
*
* Maintainer: Kumar Gala <galak@kernel.crashing.org>
*
* Copyright 2004 Freescale Semiconductor, Inc
*
* 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.
*/
#ifdef __KERNEL__
#ifndef __ASM_MPC85xx_H__
#define __ASM_MPC85xx_H__
#include <asm/mmu.h>
#ifdef CONFIG_85xx
#if defined(CONFIG_MPC8540_ADS) || defined(CONFIG_MPC8560_ADS)
#include <platforms/85xx/mpc85xx_ads.h>
#endif
#if defined(CONFIG_MPC8555_CDS) || defined(CONFIG_MPC8548_CDS)
#include <platforms/85xx/mpc8555_cds.h>
#endif
#ifdef CONFIG_MPC85xx_CDS
#include <platforms/85xx/mpc85xx_cds.h>
#endif
#define _IO_BASE isa_io_base
#define _ISA_MEM_BASE isa_mem_base
#ifdef CONFIG_PCI
#define PCI_DRAM_OFFSET pci_dram_offset
#else
#define PCI_DRAM_OFFSET 0
#endif
/* Let modules/drivers get at CCSRBAR */
extern phys_addr_t get_ccsrbar(void);
#ifdef MODULE
#define CCSRBAR get_ccsrbar()
#else
#define CCSRBAR BOARD_CCSRBAR
#endif
#endif /* CONFIG_85xx */
#endif /* __ASM_MPC85xx_H__ */
#endif /* __KERNEL__ */
......@@ -42,6 +42,8 @@
#define CPM_CR_IDMA4_SBLOCK (0x17)
#define CPM_CR_MCC1_SBLOCK (0x1c)
#define CPM_CR_FCC_SBLOCK(x) (x + 0x10)
#define CPM_CR_SCC1_PAGE (0x00)
#define CPM_CR_SCC2_PAGE (0x01)
#define CPM_CR_SCC3_PAGE (0x02)
......@@ -62,6 +64,8 @@
#define CPM_CR_MCC1_PAGE (0x07)
#define CPM_CR_MCC2_PAGE (0x08)
#define CPM_CR_FCC_PAGE(x) (x + 0x04)
/* Some opcodes (there are more...later)
*/
#define CPM_CR_INIT_TRX ((ushort)0x0000)
......@@ -173,6 +177,10 @@ typedef struct cpm_buf_desc {
#define PROFF_I2C_BASE ((uint)0x8afc)
#define PROFF_IDMA4_BASE ((uint)0x8afe)
#define PROFF_SCC_SIZE ((uint)0x100)
#define PROFF_FCC_SIZE ((uint)0x100)
#define PROFF_SMC_SIZE ((uint)64)
/* The SMCs are relocated to any of the first eight DPRAM pages.
* We will fix these at the first locations of DPRAM, until we
* get some microcode patches :-).
......@@ -1186,7 +1194,60 @@ typedef struct im_idma {
#define FCC_MEM_OFFSET(x) (CPM_FCC_SPECIAL_BASE + (x*128))
#define FCC1_MEM_OFFSET FCC_MEM_OFFSET(0)
#define FCC2_MEM_OFFSET FCC_MEM_OFFSET(1)
#define FCC2_MEM_OFFSET FCC_MEM_OFFSET(2)
#define FCC3_MEM_OFFSET FCC_MEM_OFFSET(2)
/* Clocks and GRG's */
enum cpm_clk_dir {
CPM_CLK_RX,
CPM_CLK_TX,
CPM_CLK_RTX
};
enum cpm_clk_target {
CPM_CLK_SCC1,
CPM_CLK_SCC2,
CPM_CLK_SCC3,
CPM_CLK_SCC4,
CPM_CLK_FCC1,
CPM_CLK_FCC2,
CPM_CLK_FCC3
};
enum cpm_clk {
CPM_CLK_NONE = 0,
CPM_BRG1, /* Baud Rate Generator 1 */
CPM_BRG2, /* Baud Rate Generator 2 */
CPM_BRG3, /* Baud Rate Generator 3 */
CPM_BRG4, /* Baud Rate Generator 4 */
CPM_BRG5, /* Baud Rate Generator 5 */
CPM_BRG6, /* Baud Rate Generator 6 */
CPM_BRG7, /* Baud Rate Generator 7 */
CPM_BRG8, /* Baud Rate Generator 8 */
CPM_CLK1, /* Clock 1 */
CPM_CLK2, /* Clock 2 */
CPM_CLK3, /* Clock 3 */
CPM_CLK4, /* Clock 4 */
CPM_CLK5, /* Clock 5 */
CPM_CLK6, /* Clock 6 */
CPM_CLK7, /* Clock 7 */
CPM_CLK8, /* Clock 8 */
CPM_CLK9, /* Clock 9 */
CPM_CLK10, /* Clock 10 */
CPM_CLK11, /* Clock 11 */
CPM_CLK12, /* Clock 12 */
CPM_CLK13, /* Clock 13 */
CPM_CLK14, /* Clock 14 */
CPM_CLK15, /* Clock 15 */
CPM_CLK16, /* Clock 16 */
CPM_CLK17, /* Clock 17 */
CPM_CLK18, /* Clock 18 */
CPM_CLK19, /* Clock 19 */
CPM_CLK20, /* Clock 20 */
CPM_CLK_DUMMY
};
extern int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode);
#endif /* __CPM2__ */
#endif /* __KERNEL__ */
/*
* Platform information definitions.
*
* 2006 (c) MontaVista Software, Inc.
* Vitaly Bordug <vbordug@ru.mvista.com>
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
#ifndef FS_PD_H
#define FS_PD_H
static inline int uart_baudrate(void)
{
int baud;
bd_t *bd = (bd_t *) __res;
if (bd->bi_baudrate)
baud = bd->bi_baudrate;
else
baud = -1;
return baud;
}
static inline int uart_clock(void)
{
return (((bd_t *) __res)->bi_intfreq);
}
#define cpm2_map(member) (&cpm2_immr->member)
#define cpm2_map_size(member, size) (&cpm2_immr->member)
#define cpm2_unmap(addr) do {} while(0)
#endif
......@@ -55,6 +55,30 @@ static inline int fs_get_scc_index(enum fs_id id)
return -1;
}
static inline int fs_fec_index2id(int index)
{
int id = fsid_fec1 + index - 1;
if (id >= fsid_fec1 && id <= fsid_fec2)
return id;
return FS_MAX_INDEX;
}
static inline int fs_fcc_index2id(int index)
{
int id = fsid_fcc1 + index - 1;
if (id >= fsid_fcc1 && id <= fsid_fcc3)
return id;
return FS_MAX_INDEX;
}
static inline int fs_scc_index2id(int index)
{
int id = fsid_scc1 + index - 1;
if (id >= fsid_scc1 && id <= fsid_scc4)
return id;
return FS_MAX_INDEX;
}
enum fs_mii_method {
fsmii_fixed,
fsmii_fec,
......@@ -87,18 +111,21 @@ struct fs_mii_bb_platform_info {
};
struct fs_platform_info {
void(*init_ioports)(void);
void(*init_ioports)(struct fs_platform_info *);
/* device specific information */
int fs_no; /* controller index */
char fs_type[4]; /* controller type */
u32 cp_page; /* CPM page */
u32 cp_block; /* CPM sblock */
u32 clk_trx; /* some stuff for pins & mux configuration*/
u32 clk_rx;
u32 clk_tx;
u32 clk_route;
u32 clk_mask;
u32 mem_offset;
u32 dpram_offset;
u32 fcc_regs_c;
......@@ -124,4 +151,16 @@ struct fs_mii_fec_platform_info {
u32 irq[32];
u32 mii_speed;
};
static inline int fs_get_id(struct fs_platform_info *fpi)
{
if(strstr(fpi->fs_type, "SCC"))
return fs_scc_index2id(fpi->fs_no);
if(strstr(fpi->fs_type, "FCC"))
return fs_fcc_index2id(fpi->fs_no);
if(strstr(fpi->fs_type, "FEC"))
return fs_fec_index2id(fpi->fs_no);
return fpi->fs_no;
}
#endif
......@@ -46,15 +46,27 @@ static inline int fs_uart_id_fsid2smc(int id)
}
struct fs_uart_platform_info {
void(*init_ioports)(void);
void(*init_ioports)(struct fs_uart_platform_info *);
/* device specific information */
int fs_no; /* controller index */
char fs_type[4]; /* controller type */
u32 uart_clk;
u8 tx_num_fifo;
u8 tx_buf_size;
u8 rx_num_fifo;
u8 rx_buf_size;
u8 brg;
u8 clk_rx;
u8 clk_tx;
};
static inline int fs_uart_get_id(struct fs_uart_platform_info *fpi)
{
if(strstr(fpi->fs_type, "SMC"))
return fs_uart_id_smc2fsid(fpi->fs_no);
if(strstr(fpi->fs_type, "SCC"))
return fs_uart_id_scc2fsid(fpi->fs_no);
return fpi->fs_no;
}
#endif
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