Merge commit 'kumar/kumar-next'
This commit is contained in:
commit
3a1a8acf69
|
@ -20,8 +20,6 @@ mpc52xx-device-tree-bindings.txt
|
|||
- MPC5200 Device Tree Bindings
|
||||
ppc_htab.txt
|
||||
- info about the Linux/PPC /proc/ppc_htab entry
|
||||
SBC8260_memory_mapping.txt
|
||||
- EST SBC8260 board info
|
||||
smp.txt
|
||||
- use and state info about Linux/PPC on MP machines
|
||||
sound.txt
|
||||
|
|
|
@ -1,197 +0,0 @@
|
|||
Please mail me (Jon Diekema, diekema_jon@si.com or diekema@cideas.com)
|
||||
if you have questions, comments or corrections.
|
||||
|
||||
* EST SBC8260 Linux memory mapping rules
|
||||
|
||||
http://www.estc.com/
|
||||
http://www.estc.com/products/boards/SBC8260-8240_ds.html
|
||||
|
||||
Initial conditions:
|
||||
-------------------
|
||||
|
||||
Tasks that need to be perform by the boot ROM before control is
|
||||
transferred to zImage (compressed Linux kernel):
|
||||
|
||||
- Define the IMMR to 0xf0000000
|
||||
|
||||
- Initialize the memory controller so that RAM is available at
|
||||
physical address 0x00000000. On the SBC8260 is this 16M (64M)
|
||||
SDRAM.
|
||||
|
||||
- The boot ROM should only clear the RAM that it is using.
|
||||
|
||||
The reason for doing this is to enhances the chances of a
|
||||
successful post mortem on a Linux panic. One of the first
|
||||
items to examine is the 16k (LOG_BUF_LEN) circular console
|
||||
buffer called log_buf which is defined in kernel/printk.c.
|
||||
|
||||
- To enhance boot ROM performance, the I-cache can be enabled.
|
||||
|
||||
Date: Mon, 22 May 2000 14:21:10 -0700
|
||||
From: Neil Russell <caret@c-side.com>
|
||||
|
||||
LiMon (LInux MONitor) runs with and starts Linux with MMU
|
||||
off, I-cache enabled, D-cache disabled. The I-cache doesn't
|
||||
need hints from the MMU to work correctly as the D-cache
|
||||
does. No D-cache means no special code to handle devices in
|
||||
the presence of cache (no snooping, etc). The use of the
|
||||
I-cache means that the monitor can run acceptably fast
|
||||
directly from ROM, rather than having to copy it to RAM.
|
||||
|
||||
- Build the board information structure (see
|
||||
include/asm-ppc/est8260.h for its definition)
|
||||
|
||||
- The compressed Linux kernel (zImage) contains a bootstrap loader
|
||||
that is position independent; you can load it into any RAM,
|
||||
ROM or FLASH memory address >= 0x00500000 (above 5 MB), or
|
||||
at its link address of 0x00400000 (4 MB).
|
||||
|
||||
Note: If zImage is loaded at its link address of 0x00400000 (4 MB),
|
||||
then zImage will skip the step of moving itself to
|
||||
its link address.
|
||||
|
||||
- Load R3 with the address of the board information structure
|
||||
|
||||
- Transfer control to zImage
|
||||
|
||||
- The Linux console port is SMC1, and the baud rate is controlled
|
||||
from the bi_baudrate field of the board information structure.
|
||||
On thing to keep in mind when picking the baud rate, is that
|
||||
there is no flow control on the SMC ports. I would stick
|
||||
with something safe and standard like 19200.
|
||||
|
||||
On the EST SBC8260, the SMC1 port is on the COM1 connector of
|
||||
the board.
|
||||
|
||||
|
||||
EST SBC8260 defaults:
|
||||
---------------------
|
||||
|
||||
Chip
|
||||
Memory Sel Bus Use
|
||||
--------------------- --- --- ----------------------------------
|
||||
0x00000000-0x03FFFFFF CS2 60x (16M or 64M)/64M SDRAM
|
||||
0x04000000-0x04FFFFFF CS4 local 4M/16M SDRAM (soldered to the board)
|
||||
0x21000000-0x21000000 CS7 60x 1B/64K Flash present detect (from the flash SIMM)
|
||||
0x21000001-0x21000001 CS7 60x 1B/64K Switches (read) and LEDs (write)
|
||||
0x22000000-0x2200FFFF CS5 60x 8K/64K EEPROM
|
||||
0xFC000000-0xFCFFFFFF CS6 60x 2M/16M flash (8 bits wide, soldered to the board)
|
||||
0xFE000000-0xFFFFFFFF CS0 60x 4M/16M flash (SIMM)
|
||||
|
||||
Notes:
|
||||
------
|
||||
|
||||
- The chip selects can map 32K blocks and up (powers of 2)
|
||||
|
||||
- The SDRAM machine can handled up to 128Mbytes per chip select
|
||||
|
||||
- Linux uses the 60x bus memory (the SDRAM DIMM) for the
|
||||
communications buffers.
|
||||
|
||||
- BATs can map 128K-256Mbytes each. There are four data BATs and
|
||||
four instruction BATs. Generally the data and instruction BATs
|
||||
are mapped the same.
|
||||
|
||||
- The IMMR must be set above the kernel virtual memory addresses,
|
||||
which start at 0xC0000000. Otherwise, the kernel may crash as
|
||||
soon as you start any threads or processes due to VM collisions
|
||||
in the kernel or user process space.
|
||||
|
||||
|
||||
Details from Dan Malek <dan_malek@mvista.com> on 10/29/1999:
|
||||
|
||||
The user application virtual space consumes the first 2 Gbytes
|
||||
(0x00000000 to 0x7FFFFFFF). The kernel virtual text starts at
|
||||
0xC0000000, with data following. There is a "protection hole"
|
||||
between the end of kernel data and the start of the kernel
|
||||
dynamically allocated space, but this space is still within
|
||||
0xCxxxxxxx.
|
||||
|
||||
Obviously the kernel can't map any physical addresses 1:1 in
|
||||
these ranges.
|
||||
|
||||
|
||||
Details from Dan Malek <dan_malek@mvista.com> on 5/19/2000:
|
||||
|
||||
During the early kernel initialization, the kernel virtual
|
||||
memory allocator is not operational. Prior to this KVM
|
||||
initialization, we choose to map virtual to physical addresses
|
||||
1:1. That is, the kernel virtual address exactly matches the
|
||||
physical address on the bus. These mappings are typically done
|
||||
in arch/ppc/kernel/head.S, or arch/ppc/mm/init.c. Only
|
||||
absolutely necessary mappings should be done at this time, for
|
||||
example board control registers or a serial uart. Normal device
|
||||
driver initialization should map resources later when necessary.
|
||||
|
||||
Although platform dependent, and certainly the case for embedded
|
||||
8xx, traditionally memory is mapped at physical address zero,
|
||||
and I/O devices above physical address 0x80000000. The lowest
|
||||
and highest (above 0xf0000000) I/O addresses are traditionally
|
||||
used for devices or registers we need to map during kernel
|
||||
initialization and prior to KVM operation. For this reason,
|
||||
and since it followed prior PowerPC platform examples, I chose
|
||||
to map the embedded 8xx kernel to the 0xc0000000 virtual address.
|
||||
This way, we can enable the MMU to map the kernel for proper
|
||||
operation, and still map a few windows before the KVM is operational.
|
||||
|
||||
On some systems, you could possibly run the kernel at the
|
||||
0x80000000 or any other virtual address. It just depends upon
|
||||
mapping that must be done prior to KVM operational. You can never
|
||||
map devices or kernel spaces that overlap with the user virtual
|
||||
space. This is why default IMMR mapping used by most BDM tools
|
||||
won't work. They put the IMMR at something like 0x10000000 or
|
||||
0x02000000 for example. You simply can't map these addresses early
|
||||
in the kernel, and continue proper system operation.
|
||||
|
||||
The embedded 8xx/82xx kernel is mature enough that all you should
|
||||
need to do is map the IMMR someplace at or above 0xf0000000 and it
|
||||
should boot far enough to get serial console messages and KGDB
|
||||
connected on any platform. There are lots of other subtle memory
|
||||
management design features that you simply don't need to worry
|
||||
about. If you are changing functions related to MMU initialization,
|
||||
you are likely breaking things that are known to work and are
|
||||
heading down a path of disaster and frustration. Your changes
|
||||
should be to make the flexibility of the processor fit Linux,
|
||||
not force arbitrary and non-workable memory mappings into Linux.
|
||||
|
||||
- You don't want to change KERNELLOAD or KERNELBASE, otherwise the
|
||||
virtual memory and MMU code will get confused.
|
||||
|
||||
arch/ppc/Makefile:KERNELLOAD = 0xc0000000
|
||||
|
||||
include/asm-ppc/page.h:#define PAGE_OFFSET 0xc0000000
|
||||
include/asm-ppc/page.h:#define KERNELBASE PAGE_OFFSET
|
||||
|
||||
- RAM is at physical address 0x00000000, and gets mapped to
|
||||
virtual address 0xC0000000 for the kernel.
|
||||
|
||||
|
||||
Physical addresses used by the Linux kernel:
|
||||
--------------------------------------------
|
||||
|
||||
0x00000000-0x3FFFFFFF 1GB reserved for RAM
|
||||
0xF0000000-0xF001FFFF 128K IMMR 64K used for dual port memory,
|
||||
64K for 8260 registers
|
||||
|
||||
|
||||
Logical addresses used by the Linux kernel:
|
||||
-------------------------------------------
|
||||
|
||||
0xF0000000-0xFFFFFFFF 256M BAT0 (IMMR: dual port RAM, registers)
|
||||
0xE0000000-0xEFFFFFFF 256M BAT1 (I/O space for custom boards)
|
||||
0xC0000000-0xCFFFFFFF 256M BAT2 (RAM)
|
||||
0xD0000000-0xDFFFFFFF 256M BAT3 (if RAM > 256MByte)
|
||||
|
||||
|
||||
EST SBC8260 Linux mapping:
|
||||
--------------------------
|
||||
|
||||
DBAT0, IBAT0, cache inhibited:
|
||||
|
||||
Chip
|
||||
Memory Sel Use
|
||||
--------------------- --- ---------------------------------
|
||||
0xF0000000-0xF001FFFF n/a IMMR: dual port RAM, registers
|
||||
|
||||
DBAT1, IBAT1, cache inhibited:
|
||||
|
|
@ -7,6 +7,15 @@ Currently defined compatibles:
|
|||
- fsl,cpm2-scc-uart
|
||||
- fsl,qe-uart
|
||||
|
||||
Modem control lines connected to GPIO controllers are listed in the gpios
|
||||
property as described in booting-without-of.txt, section IX.1 in the following
|
||||
order:
|
||||
|
||||
CTS, RTS, DCD, DSR, DTR, and RI.
|
||||
|
||||
The gpios property is optional and can be left out when control lines are
|
||||
not used.
|
||||
|
||||
Example:
|
||||
|
||||
serial@11a00 {
|
||||
|
@ -18,4 +27,6 @@ Example:
|
|||
interrupt-parent = <&PIC>;
|
||||
fsl,cpm-brg = <1>;
|
||||
fsl,cpm-command = <00800000>;
|
||||
gpios = <&gpio_c 15 0
|
||||
&gpio_d 29 0>;
|
||||
};
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xe0000000 0x00100000>;
|
||||
reg = <0xe0000000 0x00000200>;
|
||||
bus-frequency = <132000000>;
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xe0000000 0x00100000>;
|
||||
reg = <0xe0000000 0x00000200>;
|
||||
bus-frequency = <0>;
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xe0000000 0x00100000>;
|
||||
reg = <0xe0000000 0x00000200>;
|
||||
bus-frequency = <0>; // from bootloader
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xe0000000 0x00100000>;
|
||||
reg = <0xe0000000 0x00000200>;
|
||||
bus-frequency = <0>; // from bootloader
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xe0000000 0x00100000>;
|
||||
reg = <0xe0000000 0x00000200>;
|
||||
bus-frequency = <0>;
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xe0000000 0x00100000>;
|
||||
reg = <0xe0000000 0x00000200>;
|
||||
bus-frequency = <264000000>;
|
||||
|
|
|
@ -149,18 +149,14 @@
|
|||
};
|
||||
|
||||
crypto@30000 {
|
||||
compatible = "fsl,sec2-crypto";
|
||||
compatible = "fsl,sec2.0";
|
||||
reg = <0x30000 0x10000>;
|
||||
interrupts = <11 8>;
|
||||
interrupts = <11 0x8>;
|
||||
interrupt-parent = <&ipic>;
|
||||
num-channels = <4>;
|
||||
channel-fifo-len = <24>;
|
||||
exec-units-mask = <0x7e>;
|
||||
/*
|
||||
* desc mask is for rev1.x, we need runtime fixup
|
||||
* for >=2.x
|
||||
*/
|
||||
descriptor-types-mask = <0x1010ebf>;
|
||||
fsl,num-channels = <4>;
|
||||
fsl,channel-fifo-len = <24>;
|
||||
fsl,exec-units-mask = <0x7e>;
|
||||
fsl,descriptor-types-mask = <0x01010ebf>;
|
||||
};
|
||||
|
||||
ipic: interrupt-controller@700 {
|
||||
|
|
|
@ -117,6 +117,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xe0000000 0x00100000>;
|
||||
reg = <0xe0000000 0x00000200>;
|
||||
bus-frequency = <0>;
|
||||
|
|
|
@ -117,6 +117,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xe0000000 0x00100000>;
|
||||
reg = <0xe0000000 0x00000200>;
|
||||
bus-frequency = <0>;
|
||||
|
|
|
@ -117,6 +117,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xe0000000 0x00100000>;
|
||||
reg = <0xe0000000 0x00000200>;
|
||||
bus-frequency = <0>;
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xffe00000 0x100000>;
|
||||
reg = <0xffe00000 0x1000>;
|
||||
bus-frequency = <0>; // Filled out by uboot.
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xe0000000 0x100000>;
|
||||
reg = <0xe0000000 0x100000>; // CCSRBAR 1M
|
||||
bus-frequency = <0>;
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xe0000000 0x100000>;
|
||||
reg = <0xe0000000 0x1000>; // CCSRBAR 1M
|
||||
bus-frequency = <0>;
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
|
||||
ranges = <0x0 0xe0000000 0x100000>;
|
||||
reg = <0xe0000000 0x1000>; // CCSRBAR 1M
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xe0000000 0x100000>;
|
||||
reg = <0xe0000000 0x1000>; // CCSRBAR
|
||||
bus-frequency = <0>;
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xe0000000 0x100000>;
|
||||
reg = <0xe0000000 0x1000>; // CCSRBAR 1M
|
||||
bus-frequency = <0>;
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xe0000000 0x100000>;
|
||||
reg = <0xe0000000 0x200>;
|
||||
bus-frequency = <330000000>;
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xe0000000 0x100000>;
|
||||
reg = <0xe0000000 0x1000>;
|
||||
bus-frequency = <0>;
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0xffe00000 0x100000>;
|
||||
reg = <0xffe00000 0x1000>; // CCSRBAR & soc regs, remove once parse code for immrbase fixed
|
||||
bus-frequency = <0>; // Filled out by uboot.
|
||||
|
|
|
@ -105,6 +105,7 @@ static void __init mpc832x_sys_setup_arch(void)
|
|||
static struct of_device_id mpc832x_ids[] = {
|
||||
{ .type = "soc", },
|
||||
{ .compatible = "soc", },
|
||||
{ .compatible = "simple-bus", },
|
||||
{ .type = "qe", },
|
||||
{ .compatible = "fsl,qe", },
|
||||
{},
|
||||
|
|
|
@ -115,6 +115,7 @@ static void __init mpc832x_rdb_setup_arch(void)
|
|||
static struct of_device_id mpc832x_ids[] = {
|
||||
{ .type = "soc", },
|
||||
{ .compatible = "soc", },
|
||||
{ .compatible = "simple-bus", },
|
||||
{ .type = "qe", },
|
||||
{ .compatible = "fsl,qe", },
|
||||
{},
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
static struct of_device_id __initdata mpc834x_itx_ids[] = {
|
||||
{ .compatible = "fsl,pq2pro-localbus", },
|
||||
{ .compatible = "simple-bus", },
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -111,6 +111,7 @@ static void __init mpc834x_mds_init_IRQ(void)
|
|||
static struct of_device_id mpc834x_ids[] = {
|
||||
{ .type = "soc", },
|
||||
{ .compatible = "soc", },
|
||||
{ .compatible = "simple-bus", },
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -136,6 +136,7 @@ static void __init mpc836x_mds_setup_arch(void)
|
|||
static struct of_device_id mpc836x_ids[] = {
|
||||
{ .type = "soc", },
|
||||
{ .compatible = "soc", },
|
||||
{ .compatible = "simple-bus", },
|
||||
{ .type = "qe", },
|
||||
{ .compatible = "fsl,qe", },
|
||||
{},
|
||||
|
|
|
@ -83,6 +83,7 @@ static void __init sbc834x_init_IRQ(void)
|
|||
static struct __initdata of_device_id sbc834x_ids[] = {
|
||||
{ .type = "soc", },
|
||||
{ .compatible = "soc", },
|
||||
{ .compatible = "simple-bus", },
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -222,6 +222,7 @@ static void ksi8560_show_cpuinfo(struct seq_file *m)
|
|||
|
||||
static struct of_device_id __initdata of_bus_ids[] = {
|
||||
{ .type = "soc", },
|
||||
{ .type = "simple-bus", },
|
||||
{ .name = "cpm", },
|
||||
{ .name = "localbus", },
|
||||
{},
|
||||
|
|
|
@ -91,6 +91,7 @@ static void __init mpc8536_ds_setup_arch(void)
|
|||
static struct of_device_id __initdata mpc8536_ds_ids[] = {
|
||||
{ .type = "soc", },
|
||||
{ .compatible = "soc", },
|
||||
{ .compatible = "simple-bus", },
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -230,6 +230,7 @@ static struct of_device_id __initdata of_bus_ids[] = {
|
|||
{ .type = "soc", },
|
||||
{ .name = "cpm", },
|
||||
{ .name = "localbus", },
|
||||
{ .compatible = "simple-bus", },
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -186,6 +186,7 @@ static int __init mpc8544_ds_probe(void)
|
|||
static struct of_device_id __initdata mpc85xxds_ids[] = {
|
||||
{ .type = "soc", },
|
||||
{ .compatible = "soc", },
|
||||
{ .compatible = "simple-bus", },
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -260,6 +260,7 @@ machine_arch_initcall(mpc85xx_mds, board_fixups);
|
|||
static struct of_device_id mpc85xx_ids[] = {
|
||||
{ .type = "soc", },
|
||||
{ .compatible = "soc", },
|
||||
{ .compatible = "simple-bus", },
|
||||
{ .type = "qe", },
|
||||
{ .compatible = "fsl,qe", },
|
||||
{},
|
||||
|
|
|
@ -217,6 +217,7 @@ static struct of_device_id __initdata of_bus_ids[] = {
|
|||
{ .type = "soc", },
|
||||
{ .name = "cpm", },
|
||||
{ .name = "localbus", },
|
||||
{ .compatible = "simple-bus", },
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -105,6 +105,16 @@ config 8xx_COPYBACK
|
|||
|
||||
If in doubt, say Y here.
|
||||
|
||||
config 8xx_GPIO
|
||||
bool "GPIO API Support"
|
||||
select GENERIC_GPIO
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
help
|
||||
Saying Y here will cause the ports on an MPC8xx processor to be used
|
||||
with the GPIO API. If you say N here, the kernel needs less memory.
|
||||
|
||||
If in doubt, say Y here.
|
||||
|
||||
config 8xx_CPU6
|
||||
bool "CPU6 Silicon Errata (860 Pre Rev. C)"
|
||||
help
|
||||
|
|
|
@ -254,6 +254,8 @@ config CPM2
|
|||
select CPM
|
||||
select PPC_LIB_RHEAP
|
||||
select PPC_PCI_CHOICE
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select GENERIC_GPIO
|
||||
help
|
||||
The CPM2 (Communications Processor Module) is a coprocessor on
|
||||
embedded CPUs made by Freescale. Selecting this option means that
|
||||
|
@ -281,6 +283,7 @@ config FSL_ULI1575
|
|||
|
||||
config CPM
|
||||
bool
|
||||
select PPC_CLOCK
|
||||
|
||||
config OF_RTC
|
||||
bool
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/8xx_immap.h>
|
||||
|
@ -42,6 +43,10 @@
|
|||
|
||||
#include <asm/fs_pd.h>
|
||||
|
||||
#ifdef CONFIG_8xx_GPIO
|
||||
#include <linux/of_gpio.h>
|
||||
#endif
|
||||
|
||||
#define CPM_MAP_SIZE (0x4000)
|
||||
|
||||
cpm8xx_t __iomem *cpmp; /* Pointer to comm processor space */
|
||||
|
@ -290,20 +295,24 @@ struct cpm_ioport16 {
|
|||
__be16 res[3];
|
||||
};
|
||||
|
||||
struct cpm_ioport32 {
|
||||
__be32 dir, par, sor;
|
||||
struct cpm_ioport32b {
|
||||
__be32 dir, par, odr, dat;
|
||||
};
|
||||
|
||||
struct cpm_ioport32e {
|
||||
__be32 dir, par, sor, odr, dat;
|
||||
};
|
||||
|
||||
static void cpm1_set_pin32(int port, int pin, int flags)
|
||||
{
|
||||
struct cpm_ioport32 __iomem *iop;
|
||||
struct cpm_ioport32e __iomem *iop;
|
||||
pin = 1 << (31 - pin);
|
||||
|
||||
if (port == CPM_PORTB)
|
||||
iop = (struct cpm_ioport32 __iomem *)
|
||||
iop = (struct cpm_ioport32e __iomem *)
|
||||
&mpc8xx_immr->im_cpm.cp_pbdir;
|
||||
else
|
||||
iop = (struct cpm_ioport32 __iomem *)
|
||||
iop = (struct cpm_ioport32e __iomem *)
|
||||
&mpc8xx_immr->im_cpm.cp_pedir;
|
||||
|
||||
if (flags & CPM_PIN_OUTPUT)
|
||||
|
@ -498,3 +507,251 @@ int cpm1_clk_setup(enum cpm_clk_target target, int clock, int mode)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* GPIO LIB API implementation
|
||||
*/
|
||||
#ifdef CONFIG_8xx_GPIO
|
||||
|
||||
struct cpm1_gpio16_chip {
|
||||
struct of_mm_gpio_chip mm_gc;
|
||||
spinlock_t lock;
|
||||
|
||||
/* shadowed data register to clear/set bits safely */
|
||||
u16 cpdata;
|
||||
};
|
||||
|
||||
static inline struct cpm1_gpio16_chip *
|
||||
to_cpm1_gpio16_chip(struct of_mm_gpio_chip *mm_gc)
|
||||
{
|
||||
return container_of(mm_gc, struct cpm1_gpio16_chip, mm_gc);
|
||||
}
|
||||
|
||||
static void cpm1_gpio16_save_regs(struct of_mm_gpio_chip *mm_gc)
|
||||
{
|
||||
struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc);
|
||||
struct cpm_ioport16 __iomem *iop = mm_gc->regs;
|
||||
|
||||
cpm1_gc->cpdata = in_be16(&iop->dat);
|
||||
}
|
||||
|
||||
static int cpm1_gpio16_get(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||
struct cpm_ioport16 __iomem *iop = mm_gc->regs;
|
||||
u16 pin_mask;
|
||||
|
||||
pin_mask = 1 << (15 - gpio);
|
||||
|
||||
return !!(in_be16(&iop->dat) & pin_mask);
|
||||
}
|
||||
|
||||
static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value)
|
||||
{
|
||||
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||
struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc);
|
||||
struct cpm_ioport16 __iomem *iop = mm_gc->regs;
|
||||
unsigned long flags;
|
||||
u16 pin_mask = 1 << (15 - gpio);
|
||||
|
||||
spin_lock_irqsave(&cpm1_gc->lock, flags);
|
||||
|
||||
if (value)
|
||||
cpm1_gc->cpdata |= pin_mask;
|
||||
else
|
||||
cpm1_gc->cpdata &= ~pin_mask;
|
||||
|
||||
out_be16(&iop->dat, cpm1_gc->cpdata);
|
||||
|
||||
spin_unlock_irqrestore(&cpm1_gc->lock, flags);
|
||||
}
|
||||
|
||||
static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
{
|
||||
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||
struct cpm_ioport16 __iomem *iop = mm_gc->regs;
|
||||
u16 pin_mask;
|
||||
|
||||
pin_mask = 1 << (15 - gpio);
|
||||
|
||||
setbits16(&iop->dir, pin_mask);
|
||||
|
||||
cpm1_gpio16_set(gc, gpio, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpm1_gpio16_dir_in(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||
struct cpm_ioport16 __iomem *iop = mm_gc->regs;
|
||||
u16 pin_mask;
|
||||
|
||||
pin_mask = 1 << (15 - gpio);
|
||||
|
||||
clrbits16(&iop->dir, pin_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpm1_gpiochip_add16(struct device_node *np)
|
||||
{
|
||||
struct cpm1_gpio16_chip *cpm1_gc;
|
||||
struct of_mm_gpio_chip *mm_gc;
|
||||
struct of_gpio_chip *of_gc;
|
||||
struct gpio_chip *gc;
|
||||
|
||||
cpm1_gc = kzalloc(sizeof(*cpm1_gc), GFP_KERNEL);
|
||||
if (!cpm1_gc)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&cpm1_gc->lock);
|
||||
|
||||
mm_gc = &cpm1_gc->mm_gc;
|
||||
of_gc = &mm_gc->of_gc;
|
||||
gc = &of_gc->gc;
|
||||
|
||||
mm_gc->save_regs = cpm1_gpio16_save_regs;
|
||||
of_gc->gpio_cells = 2;
|
||||
gc->ngpio = 16;
|
||||
gc->direction_input = cpm1_gpio16_dir_in;
|
||||
gc->direction_output = cpm1_gpio16_dir_out;
|
||||
gc->get = cpm1_gpio16_get;
|
||||
gc->set = cpm1_gpio16_set;
|
||||
|
||||
return of_mm_gpiochip_add(np, mm_gc);
|
||||
}
|
||||
|
||||
struct cpm1_gpio32_chip {
|
||||
struct of_mm_gpio_chip mm_gc;
|
||||
spinlock_t lock;
|
||||
|
||||
/* shadowed data register to clear/set bits safely */
|
||||
u32 cpdata;
|
||||
};
|
||||
|
||||
static inline struct cpm1_gpio32_chip *
|
||||
to_cpm1_gpio32_chip(struct of_mm_gpio_chip *mm_gc)
|
||||
{
|
||||
return container_of(mm_gc, struct cpm1_gpio32_chip, mm_gc);
|
||||
}
|
||||
|
||||
static void cpm1_gpio32_save_regs(struct of_mm_gpio_chip *mm_gc)
|
||||
{
|
||||
struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc);
|
||||
struct cpm_ioport32b __iomem *iop = mm_gc->regs;
|
||||
|
||||
cpm1_gc->cpdata = in_be32(&iop->dat);
|
||||
}
|
||||
|
||||
static int cpm1_gpio32_get(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||
struct cpm_ioport32b __iomem *iop = mm_gc->regs;
|
||||
u32 pin_mask;
|
||||
|
||||
pin_mask = 1 << (31 - gpio);
|
||||
|
||||
return !!(in_be32(&iop->dat) & pin_mask);
|
||||
}
|
||||
|
||||
static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value)
|
||||
{
|
||||
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||
struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc);
|
||||
struct cpm_ioport32b __iomem *iop = mm_gc->regs;
|
||||
unsigned long flags;
|
||||
u32 pin_mask = 1 << (31 - gpio);
|
||||
|
||||
spin_lock_irqsave(&cpm1_gc->lock, flags);
|
||||
|
||||
if (value)
|
||||
cpm1_gc->cpdata |= pin_mask;
|
||||
else
|
||||
cpm1_gc->cpdata &= ~pin_mask;
|
||||
|
||||
out_be32(&iop->dat, cpm1_gc->cpdata);
|
||||
|
||||
spin_unlock_irqrestore(&cpm1_gc->lock, flags);
|
||||
}
|
||||
|
||||
static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
{
|
||||
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||
struct cpm_ioport32b __iomem *iop = mm_gc->regs;
|
||||
u32 pin_mask;
|
||||
|
||||
pin_mask = 1 << (31 - gpio);
|
||||
|
||||
setbits32(&iop->dir, pin_mask);
|
||||
|
||||
cpm1_gpio32_set(gc, gpio, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpm1_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||
struct cpm_ioport32b __iomem *iop = mm_gc->regs;
|
||||
u32 pin_mask;
|
||||
|
||||
pin_mask = 1 << (31 - gpio);
|
||||
|
||||
clrbits32(&iop->dir, pin_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpm1_gpiochip_add32(struct device_node *np)
|
||||
{
|
||||
struct cpm1_gpio32_chip *cpm1_gc;
|
||||
struct of_mm_gpio_chip *mm_gc;
|
||||
struct of_gpio_chip *of_gc;
|
||||
struct gpio_chip *gc;
|
||||
|
||||
cpm1_gc = kzalloc(sizeof(*cpm1_gc), GFP_KERNEL);
|
||||
if (!cpm1_gc)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&cpm1_gc->lock);
|
||||
|
||||
mm_gc = &cpm1_gc->mm_gc;
|
||||
of_gc = &mm_gc->of_gc;
|
||||
gc = &of_gc->gc;
|
||||
|
||||
mm_gc->save_regs = cpm1_gpio32_save_regs;
|
||||
of_gc->gpio_cells = 2;
|
||||
gc->ngpio = 32;
|
||||
gc->direction_input = cpm1_gpio32_dir_in;
|
||||
gc->direction_output = cpm1_gpio32_dir_out;
|
||||
gc->get = cpm1_gpio32_get;
|
||||
gc->set = cpm1_gpio32_set;
|
||||
|
||||
return of_mm_gpiochip_add(np, mm_gc);
|
||||
}
|
||||
|
||||
static int cpm_init_par_io(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-a")
|
||||
cpm1_gpiochip_add16(np);
|
||||
|
||||
for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-b")
|
||||
cpm1_gpiochip_add32(np);
|
||||
|
||||
for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-c")
|
||||
cpm1_gpiochip_add16(np);
|
||||
|
||||
for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-d")
|
||||
cpm1_gpiochip_add16(np);
|
||||
|
||||
/* Port E uses CPM2 layout */
|
||||
for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-e")
|
||||
cpm2_gpiochip_add32(np);
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(cpm_init_par_io);
|
||||
|
||||
#endif /* CONFIG_8xx_GPIO */
|
||||
|
|
|
@ -115,16 +115,10 @@ EXPORT_SYMBOL(cpm_command);
|
|||
* 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)
|
||||
void __cpm2_setbrg(uint brg, uint rate, uint clk, int div16, int src)
|
||||
{
|
||||
u32 __iomem *bp;
|
||||
u32 val;
|
||||
|
||||
/* This is good enough to get SMCs running.....
|
||||
*/
|
||||
|
@ -135,34 +129,14 @@ cpm_setbrg(uint brg, uint rate)
|
|||
brg -= 4;
|
||||
}
|
||||
bp += brg;
|
||||
out_be32(bp, (((BRG_UART_CLK / rate) - 1) << 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)
|
||||
{
|
||||
u32 __iomem *bp;
|
||||
u32 val;
|
||||
|
||||
if (brg < 4) {
|
||||
bp = cpm2_map_size(im_brgc1, 16);
|
||||
} else {
|
||||
bp = cpm2_map_size(im_brgc5, 16);
|
||||
brg -= 4;
|
||||
}
|
||||
bp += brg;
|
||||
val = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
|
||||
val = (((clk / rate) - 1) << 1) | CPM_BRG_EN | src;
|
||||
if (div16)
|
||||
val |= CPM_BRG_DIV16;
|
||||
|
||||
out_be32(bp, val);
|
||||
cpm2_unmap(bp);
|
||||
}
|
||||
EXPORT_SYMBOL(__cpm2_setbrg);
|
||||
|
||||
int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode)
|
||||
{
|
||||
|
@ -377,3 +351,14 @@ void cpm2_set_pin(int port, int pin, int flags)
|
|||
else
|
||||
clrbits32(&iop[port].odr, pin);
|
||||
}
|
||||
|
||||
static int cpm_init_par_io(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
for_each_compatible_node(np, NULL, "fsl,cpm2-pario-bank")
|
||||
cpm2_gpiochip_add32(np);
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(cpm_init_par_io);
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include <linux/init.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/udbg.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -28,6 +30,10 @@
|
|||
|
||||
#include <mm/mmu_decl.h>
|
||||
|
||||
#if defined(CONFIG_CPM2) || defined(CONFIG_8xx_GPIO)
|
||||
#include <linux/of_gpio.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_EARLY_DEBUG_CPM
|
||||
static u32 __iomem *cpm_udbg_txdesc =
|
||||
(u32 __iomem __force *)CONFIG_PPC_EARLY_DEBUG_CPM_ADDR;
|
||||
|
@ -207,3 +213,120 @@ dma_addr_t cpm_muram_dma(void __iomem *addr)
|
|||
return muram_pbase + ((u8 __iomem *)addr - muram_vbase);
|
||||
}
|
||||
EXPORT_SYMBOL(cpm_muram_dma);
|
||||
|
||||
#if defined(CONFIG_CPM2) || defined(CONFIG_8xx_GPIO)
|
||||
|
||||
struct cpm2_ioports {
|
||||
u32 dir, par, sor, odr, dat;
|
||||
u32 res[3];
|
||||
};
|
||||
|
||||
struct cpm2_gpio32_chip {
|
||||
struct of_mm_gpio_chip mm_gc;
|
||||
spinlock_t lock;
|
||||
|
||||
/* shadowed data register to clear/set bits safely */
|
||||
u32 cpdata;
|
||||
};
|
||||
|
||||
static inline struct cpm2_gpio32_chip *
|
||||
to_cpm2_gpio32_chip(struct of_mm_gpio_chip *mm_gc)
|
||||
{
|
||||
return container_of(mm_gc, struct cpm2_gpio32_chip, mm_gc);
|
||||
}
|
||||
|
||||
static void cpm2_gpio32_save_regs(struct of_mm_gpio_chip *mm_gc)
|
||||
{
|
||||
struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc);
|
||||
struct cpm2_ioports __iomem *iop = mm_gc->regs;
|
||||
|
||||
cpm2_gc->cpdata = in_be32(&iop->dat);
|
||||
}
|
||||
|
||||
static int cpm2_gpio32_get(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||
struct cpm2_ioports __iomem *iop = mm_gc->regs;
|
||||
u32 pin_mask;
|
||||
|
||||
pin_mask = 1 << (31 - gpio);
|
||||
|
||||
return !!(in_be32(&iop->dat) & pin_mask);
|
||||
}
|
||||
|
||||
static void cpm2_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value)
|
||||
{
|
||||
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||
struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc);
|
||||
struct cpm2_ioports __iomem *iop = mm_gc->regs;
|
||||
unsigned long flags;
|
||||
u32 pin_mask = 1 << (31 - gpio);
|
||||
|
||||
spin_lock_irqsave(&cpm2_gc->lock, flags);
|
||||
|
||||
if (value)
|
||||
cpm2_gc->cpdata |= pin_mask;
|
||||
else
|
||||
cpm2_gc->cpdata &= ~pin_mask;
|
||||
|
||||
out_be32(&iop->dat, cpm2_gc->cpdata);
|
||||
|
||||
spin_unlock_irqrestore(&cpm2_gc->lock, flags);
|
||||
}
|
||||
|
||||
static int cpm2_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
{
|
||||
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||
struct cpm2_ioports __iomem *iop = mm_gc->regs;
|
||||
u32 pin_mask;
|
||||
|
||||
pin_mask = 1 << (31 - gpio);
|
||||
|
||||
setbits32(&iop->dir, pin_mask);
|
||||
|
||||
cpm2_gpio32_set(gc, gpio, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpm2_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||
struct cpm2_ioports __iomem *iop = mm_gc->regs;
|
||||
u32 pin_mask;
|
||||
|
||||
pin_mask = 1 << (31 - gpio);
|
||||
|
||||
clrbits32(&iop->dir, pin_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpm2_gpiochip_add32(struct device_node *np)
|
||||
{
|
||||
struct cpm2_gpio32_chip *cpm2_gc;
|
||||
struct of_mm_gpio_chip *mm_gc;
|
||||
struct of_gpio_chip *of_gc;
|
||||
struct gpio_chip *gc;
|
||||
|
||||
cpm2_gc = kzalloc(sizeof(*cpm2_gc), GFP_KERNEL);
|
||||
if (!cpm2_gc)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&cpm2_gc->lock);
|
||||
|
||||
mm_gc = &cpm2_gc->mm_gc;
|
||||
of_gc = &mm_gc->of_gc;
|
||||
gc = &of_gc->gc;
|
||||
|
||||
mm_gc->save_regs = cpm2_gpio32_save_regs;
|
||||
of_gc->gpio_cells = 2;
|
||||
gc->ngpio = 32;
|
||||
gc->direction_input = cpm2_gpio32_dir_in;
|
||||
gc->direction_output = cpm2_gpio32_dir_out;
|
||||
gc->get = cpm2_gpio32_get;
|
||||
gc->set = cpm2_gpio32_set;
|
||||
|
||||
return of_mm_gpiochip_add(np, mm_gc);
|
||||
}
|
||||
#endif /* CONFIG_CPM2 || CONFIG_8xx_GPIO */
|
||||
|
|
|
@ -21,6 +21,7 @@ static int __init add_rtc(void)
|
|||
struct device_node *np;
|
||||
struct platform_device *pd;
|
||||
struct resource res[2];
|
||||
unsigned int num_res = 1;
|
||||
int ret;
|
||||
|
||||
memset(&res, 0, sizeof(res));
|
||||
|
@ -41,14 +42,24 @@ static int __init add_rtc(void)
|
|||
if (res[0].start != RTC_PORT(0))
|
||||
return -EINVAL;
|
||||
|
||||
/* Use a fixed interrupt value of 8 since on PPC if we are using this
|
||||
* its off an i8259 which we ensure has interrupt numbers 0..15. */
|
||||
res[1].start = 8;
|
||||
res[1].end = 8;
|
||||
res[1].flags = IORESOURCE_IRQ;
|
||||
np = of_find_compatible_node(NULL, NULL, "chrp,iic");
|
||||
if (!np)
|
||||
np = of_find_compatible_node(NULL, NULL, "pnpPNP,000");
|
||||
if (np) {
|
||||
of_node_put(np);
|
||||
/*
|
||||
* Use a fixed interrupt value of 8 since on PPC if we are
|
||||
* using this its off an i8259 which we ensure has interrupt
|
||||
* numbers 0..15.
|
||||
*/
|
||||
res[1].start = 8;
|
||||
res[1].end = 8;
|
||||
res[1].flags = IORESOURCE_IRQ;
|
||||
num_res++;
|
||||
}
|
||||
|
||||
pd = platform_device_register_simple("rtc_cmos", -1,
|
||||
&res[0], 2);
|
||||
&res[0], num_res);
|
||||
|
||||
if (IS_ERR(pd))
|
||||
return PTR_ERR(pd);
|
||||
|
|
|
@ -50,6 +50,15 @@
|
|||
|
||||
#define SCC_WAIT_CLOSING 100
|
||||
|
||||
#define GPIO_CTS 0
|
||||
#define GPIO_RTS 1
|
||||
#define GPIO_DCD 2
|
||||
#define GPIO_DSR 3
|
||||
#define GPIO_DTR 4
|
||||
#define GPIO_RI 5
|
||||
|
||||
#define NUM_GPIOS (GPIO_RI+1)
|
||||
|
||||
struct uart_cpm_port {
|
||||
struct uart_port port;
|
||||
u16 rx_nrfifos;
|
||||
|
@ -68,6 +77,7 @@ struct uart_cpm_port {
|
|||
unsigned char *rx_buf;
|
||||
u32 flags;
|
||||
void (*set_lineif)(struct uart_cpm_port *);
|
||||
struct clk *clk;
|
||||
u8 brg;
|
||||
uint dp_addr;
|
||||
void *mem_addr;
|
||||
|
@ -82,6 +92,7 @@ struct uart_cpm_port {
|
|||
int wait_closing;
|
||||
/* value to combine with opcode to form cpm command */
|
||||
u32 command;
|
||||
int gpios[NUM_GPIOS];
|
||||
};
|
||||
|
||||
extern int cpm_uart_nr;
|
||||
|
|
|
@ -43,6 +43,9 @@
|
|||
#include <linux/dma-mapping.h>
|
||||
#include <linux/fs_uart_pd.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
|
@ -96,13 +99,41 @@ static unsigned int cpm_uart_tx_empty(struct uart_port *port)
|
|||
|
||||
static void cpm_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
/* Whee. Do nothing. */
|
||||
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
|
||||
|
||||
if (pinfo->gpios[GPIO_RTS] >= 0)
|
||||
gpio_set_value(pinfo->gpios[GPIO_RTS], !(mctrl & TIOCM_RTS));
|
||||
|
||||
if (pinfo->gpios[GPIO_DTR] >= 0)
|
||||
gpio_set_value(pinfo->gpios[GPIO_DTR], !(mctrl & TIOCM_DTR));
|
||||
}
|
||||
|
||||
static unsigned int cpm_uart_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
/* Whee. Do nothing. */
|
||||
return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
|
||||
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
|
||||
unsigned int mctrl = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
|
||||
|
||||
if (pinfo->gpios[GPIO_CTS] >= 0) {
|
||||
if (gpio_get_value(pinfo->gpios[GPIO_CTS]))
|
||||
mctrl &= ~TIOCM_CTS;
|
||||
}
|
||||
|
||||
if (pinfo->gpios[GPIO_DSR] >= 0) {
|
||||
if (gpio_get_value(pinfo->gpios[GPIO_DSR]))
|
||||
mctrl &= ~TIOCM_DSR;
|
||||
}
|
||||
|
||||
if (pinfo->gpios[GPIO_DCD] >= 0) {
|
||||
if (gpio_get_value(pinfo->gpios[GPIO_DCD]))
|
||||
mctrl &= ~TIOCM_CAR;
|
||||
}
|
||||
|
||||
if (pinfo->gpios[GPIO_RI] >= 0) {
|
||||
if (!gpio_get_value(pinfo->gpios[GPIO_RI]))
|
||||
mctrl |= TIOCM_RNG;
|
||||
}
|
||||
|
||||
return mctrl;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -566,7 +597,10 @@ static void cpm_uart_set_termios(struct uart_port *port,
|
|||
out_be16(&sccp->scc_psmr, (sbits << 12) | scval);
|
||||
}
|
||||
|
||||
cpm_set_brg(pinfo->brg - 1, baud);
|
||||
if (pinfo->clk)
|
||||
clk_set_rate(pinfo->clk, baud);
|
||||
else
|
||||
cpm_set_brg(pinfo->brg - 1, baud);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
|
@ -991,14 +1025,23 @@ static int cpm_uart_init_port(struct device_node *np,
|
|||
void __iomem *mem, *pram;
|
||||
int len;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
data = of_get_property(np, "fsl,cpm-brg", &len);
|
||||
if (!data || len != 4) {
|
||||
printk(KERN_ERR "CPM UART %s has no/invalid "
|
||||
"fsl,cpm-brg property.\n", np->name);
|
||||
return -EINVAL;
|
||||
data = of_get_property(np, "clock", NULL);
|
||||
if (data) {
|
||||
struct clk *clk = clk_get(NULL, (const char*)data);
|
||||
if (!IS_ERR(clk))
|
||||
pinfo->clk = clk;
|
||||
}
|
||||
if (!pinfo->clk) {
|
||||
data = of_get_property(np, "fsl,cpm-brg", &len);
|
||||
if (!data || len != 4) {
|
||||
printk(KERN_ERR "CPM UART %s has no/invalid "
|
||||
"fsl,cpm-brg property.\n", np->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
pinfo->brg = *data;
|
||||
}
|
||||
pinfo->brg = *data;
|
||||
|
||||
data = of_get_property(np, "fsl,cpm-command", &len);
|
||||
if (!data || len != 4) {
|
||||
|
@ -1050,6 +1093,9 @@ static int cpm_uart_init_port(struct device_node *np,
|
|||
goto out_pram;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_GPIOS; i++)
|
||||
pinfo->gpios[i] = of_get_gpio(np, i);
|
||||
|
||||
return cpm_uart_request_port(&pinfo->port);
|
||||
|
||||
out_pram:
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
/* Opcodes common to CPM1 and CPM2
|
||||
*/
|
||||
|
@ -100,4 +101,6 @@ unsigned long cpm_muram_offset(void __iomem *addr);
|
|||
dma_addr_t cpm_muram_dma(void __iomem *addr);
|
||||
int cpm_command(u32 command, u8 opcode);
|
||||
|
||||
int cpm2_gpiochip_add32(struct device_node *np);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <asm/immap_cpm2.h>
|
||||
#include <asm/cpm.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
|
||||
#ifdef CONFIG_PPC_85xx
|
||||
#define CPM_MAP_ADDR (get_immrbase() + 0x80000)
|
||||
|
@ -93,10 +94,40 @@ extern cpm_cpm2_t __iomem *cpmp; /* Pointer to comm processor */
|
|||
#define cpm_dpfree cpm_muram_free
|
||||
#define cpm_dpram_addr cpm_muram_addr
|
||||
|
||||
extern void cpm_setbrg(uint brg, uint rate);
|
||||
extern void cpm2_fastbrg(uint brg, uint rate, int div16);
|
||||
extern void cpm2_reset(void);
|
||||
|
||||
/* Baud rate generators.
|
||||
*/
|
||||
#define CPM_BRG_RST ((uint)0x00020000)
|
||||
#define CPM_BRG_EN ((uint)0x00010000)
|
||||
#define CPM_BRG_EXTC_INT ((uint)0x00000000)
|
||||
#define CPM_BRG_EXTC_CLK3_9 ((uint)0x00004000)
|
||||
#define CPM_BRG_EXTC_CLK5_15 ((uint)0x00008000)
|
||||
#define CPM_BRG_ATB ((uint)0x00002000)
|
||||
#define CPM_BRG_CD_MASK ((uint)0x00001ffe)
|
||||
#define CPM_BRG_DIV16 ((uint)0x00000001)
|
||||
|
||||
#define CPM2_BRG_INT_CLK (get_brgfreq())
|
||||
#define CPM2_BRG_UART_CLK (CPM2_BRG_INT_CLK/16)
|
||||
|
||||
extern void __cpm2_setbrg(uint brg, uint rate, uint clk, int div16, int src);
|
||||
|
||||
/* This function is used by UARTS, or anything else that uses a 16x
|
||||
* oversampled clock.
|
||||
*/
|
||||
static inline void cpm_setbrg(uint brg, uint rate)
|
||||
{
|
||||
__cpm2_setbrg(brg, rate, CPM2_BRG_UART_CLK, 0, CPM_BRG_EXTC_INT);
|
||||
}
|
||||
|
||||
/* This function is used to set high speed synchronous baud rate
|
||||
* clocks.
|
||||
*/
|
||||
static inline void cpm2_fastbrg(uint brg, uint rate, int div16)
|
||||
{
|
||||
__cpm2_setbrg(brg, rate, CPM2_BRG_INT_CLK, div16, CPM_BRG_EXTC_INT);
|
||||
}
|
||||
|
||||
/* Function code bits, usually generic to devices.
|
||||
*/
|
||||
#define CPMFCR_GBL ((u_char)0x20) /* Set memory snooping */
|
||||
|
@ -195,17 +226,6 @@ typedef struct smc_uart {
|
|||
#define SMCM_TX ((unsigned char)0x02)
|
||||
#define SMCM_RX ((unsigned char)0x01)
|
||||
|
||||
/* Baud rate generators.
|
||||
*/
|
||||
#define CPM_BRG_RST ((uint)0x00020000)
|
||||
#define CPM_BRG_EN ((uint)0x00010000)
|
||||
#define CPM_BRG_EXTC_INT ((uint)0x00000000)
|
||||
#define CPM_BRG_EXTC_CLK3_9 ((uint)0x00004000)
|
||||
#define CPM_BRG_EXTC_CLK5_15 ((uint)0x00008000)
|
||||
#define CPM_BRG_ATB ((uint)0x00002000)
|
||||
#define CPM_BRG_CD_MASK ((uint)0x00001ffe)
|
||||
#define CPM_BRG_DIV16 ((uint)0x00000001)
|
||||
|
||||
/* SCCs.
|
||||
*/
|
||||
#define SCC_GSMRH_IRP ((uint)0x00040000)
|
||||
|
|
Loading…
Reference in New Issue