Commit dfe218b7 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt

Merge commit 'jwb/jwb-next'

parents 34318c25 1ff0fcfc
...@@ -68,7 +68,8 @@ src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c ...@@ -68,7 +68,8 @@ src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c
fixed-head.S ep88xc.c ep405.c cuboot-c2k.c \ fixed-head.S ep88xc.c ep405.c cuboot-c2k.c \
cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \ cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \
cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \ cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \
virtex405-head.S virtex.c redboot-83xx.c cuboot-sam440ep.c virtex405-head.S virtex.c redboot-83xx.c cuboot-sam440ep.c \
cuboot-acadia.c
src-boot := $(src-wlib) $(src-plat) empty.c src-boot := $(src-wlib) $(src-plat) empty.c
src-boot := $(addprefix $(obj)/, $(src-boot)) src-boot := $(addprefix $(obj)/, $(src-boot))
...@@ -211,6 +212,7 @@ image-$(CONFIG_DEFAULT_UIMAGE) += uImage ...@@ -211,6 +212,7 @@ image-$(CONFIG_DEFAULT_UIMAGE) += uImage
# Board ports in arch/powerpc/platform/40x/Kconfig # Board ports in arch/powerpc/platform/40x/Kconfig
image-$(CONFIG_EP405) += dtbImage.ep405 image-$(CONFIG_EP405) += dtbImage.ep405
image-$(CONFIG_WALNUT) += treeImage.walnut image-$(CONFIG_WALNUT) += treeImage.walnut
image-$(CONFIG_ACADIA) += cuImage.acadia
# Board ports in arch/powerpc/platform/44x/Kconfig # Board ports in arch/powerpc/platform/44x/Kconfig
image-$(CONFIG_EBONY) += treeImage.ebony cuImage.ebony image-$(CONFIG_EBONY) += treeImage.ebony cuImage.ebony
......
/*
* Old U-boot compatibility for Acadia
*
* Author: Josh Boyer <jwboyer@linux.vnet.ibm.com>
*
* Copyright 2008 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
#include "ops.h"
#include "io.h"
#include "dcr.h"
#include "stdio.h"
#include "4xx.h"
#include "44x.h"
#include "cuboot.h"
#define TARGET_4xx
#include "ppcboot.h"
static bd_t bd;
#define CPR_PERD0_SPIDV_MASK 0x000F0000 /* SPI Clock Divider */
#define PLLC_SRC_MASK 0x20000000 /* PLL feedback source */
#define PLLD_FBDV_MASK 0x1F000000 /* PLL feedback divider value */
#define PLLD_FWDVA_MASK 0x000F0000 /* PLL forward divider A value */
#define PLLD_FWDVB_MASK 0x00000700 /* PLL forward divider B value */
#define PRIMAD_CPUDV_MASK 0x0F000000 /* CPU Clock Divisor Mask */
#define PRIMAD_PLBDV_MASK 0x000F0000 /* PLB Clock Divisor Mask */
#define PRIMAD_OPBDV_MASK 0x00000F00 /* OPB Clock Divisor Mask */
#define PRIMAD_EBCDV_MASK 0x0000000F /* EBC Clock Divisor Mask */
#define PERD0_PWMDV_MASK 0xFF000000 /* PWM Divider Mask */
#define PERD0_SPIDV_MASK 0x000F0000 /* SPI Divider Mask */
#define PERD0_U0DV_MASK 0x0000FF00 /* UART 0 Divider Mask */
#define PERD0_U1DV_MASK 0x000000FF /* UART 1 Divider Mask */
static void get_clocks(void)
{
unsigned long sysclk, cpr_plld, cpr_pllc, cpr_primad, plloutb, i;
unsigned long pllFwdDiv, pllFwdDivB, pllFbkDiv, pllPlbDiv, pllExtBusDiv;
unsigned long pllOpbDiv, freqEBC, freqUART, freqOPB;
unsigned long div; /* total divisor udiv * bdiv */
unsigned long umin; /* minimum udiv */
unsigned short diff; /* smallest diff */
unsigned long udiv; /* best udiv */
unsigned short idiff; /* current diff */
unsigned short ibdiv; /* current bdiv */
unsigned long est; /* current estimate */
unsigned long baud;
void *np;
/* read the sysclk value from the CPLD */
sysclk = (in_8((unsigned char *)0x80000000) == 0xc) ? 66666666 : 33333000;
/*
* Read PLL Mode registers
*/
cpr_plld = CPR0_READ(DCRN_CPR0_PLLD);
cpr_pllc = CPR0_READ(DCRN_CPR0_PLLC);
/*
* Determine forward divider A
*/
pllFwdDiv = ((cpr_plld & PLLD_FWDVA_MASK) >> 16);
/*
* Determine forward divider B
*/
pllFwdDivB = ((cpr_plld & PLLD_FWDVB_MASK) >> 8);
if (pllFwdDivB == 0)
pllFwdDivB = 8;
/*
* Determine FBK_DIV.
*/
pllFbkDiv = ((cpr_plld & PLLD_FBDV_MASK) >> 24);
if (pllFbkDiv == 0)
pllFbkDiv = 256;
/*
* Read CPR_PRIMAD register
*/
cpr_primad = CPR0_READ(DCRN_CPR0_PRIMAD);
/*
* Determine PLB_DIV.
*/
pllPlbDiv = ((cpr_primad & PRIMAD_PLBDV_MASK) >> 16);
if (pllPlbDiv == 0)
pllPlbDiv = 16;
/*
* Determine EXTBUS_DIV.
*/
pllExtBusDiv = (cpr_primad & PRIMAD_EBCDV_MASK);
if (pllExtBusDiv == 0)
pllExtBusDiv = 16;
/*
* Determine OPB_DIV.
*/
pllOpbDiv = ((cpr_primad & PRIMAD_OPBDV_MASK) >> 8);
if (pllOpbDiv == 0)
pllOpbDiv = 16;
/* There is a bug in U-Boot that prevents us from using
* bd.bi_opbfreq because U-Boot doesn't populate it for
* 405EZ. We get to calculate it, yay!
*/
freqOPB = (sysclk *pllFbkDiv) /pllOpbDiv;
freqEBC = (sysclk * pllFbkDiv) / pllExtBusDiv;
plloutb = ((sysclk * ((cpr_pllc & PLLC_SRC_MASK) ?
pllFwdDivB : pllFwdDiv) *
pllFbkDiv) / pllFwdDivB);
np = find_node_by_alias("serial0");
if (getprop(np, "current-speed", &baud, sizeof(baud)) != sizeof(baud))
fatal("no current-speed property\n\r");
udiv = 256; /* Assume lowest possible serial clk */
div = plloutb / (16 * baud); /* total divisor */
umin = (plloutb / freqOPB) << 1; /* 2 x OPB divisor */
diff = 256; /* highest possible */
/* i is the test udiv value -- start with the largest
* possible (256) to minimize serial clock and constrain
* search to umin.
*/
for (i = 256; i > umin; i--) {
ibdiv = div / i;
est = i * ibdiv;
idiff = (est > div) ? (est-div) : (div-est);
if (idiff == 0) {
udiv = i;
break; /* can't do better */
} else if (idiff < diff) {
udiv = i; /* best so far */
diff = idiff; /* update lowest diff*/
}
}
freqUART = plloutb / udiv;
dt_fixup_cpu_clocks(bd.bi_procfreq, bd.bi_intfreq, bd.bi_plb_busfreq);
dt_fixup_clock("/plb/ebc", freqEBC);
dt_fixup_clock("/plb/opb", freqOPB);
dt_fixup_clock("/plb/opb/serial@ef600300", freqUART);
dt_fixup_clock("/plb/opb/serial@ef600400", freqUART);
}
static void acadia_fixups(void)
{
dt_fixup_memory(bd.bi_memstart, bd.bi_memsize);
get_clocks();
dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
}
void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
CUBOOT_INIT();
platform_ops.fixups = acadia_fixups;
platform_ops.exit = ibm40x_dbcr_reset;
fdt_init(_dtb_start);
serial_console_init();
}
/*
* Device Tree Source for AMCC Acadia (405EZ)
*
* Copyright IBM Corp. 2008
*
* 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.
*/
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
model = "amcc,acadia";
compatible = "amcc,acadia";
dcr-parent = <&{/cpus/cpu@0}>;
aliases {
ethernet0 = &EMAC0;
serial0 = &UART0;
serial1 = &UART1;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
model = "PowerPC,405EZ";
reg = <0x0>;
clock-frequency = <0>; /* Filled in by wrapper */
timebase-frequency = <0>; /* Filled in by wrapper */
i-cache-line-size = <32>;
d-cache-line-size = <32>;
i-cache-size = <16384>;
d-cache-size = <16384>;
dcr-controller;
dcr-access-method = "native";
};
};
memory {
device_type = "memory";
reg = <0x0 0x0>; /* Filled in by wrapper */
};
UIC0: interrupt-controller {
compatible = "ibm,uic-405ez", "ibm,uic";
interrupt-controller;
dcr-reg = <0x0c0 0x009>;
cell-index = <0>;
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
};
plb {
compatible = "ibm,plb-405ez", "ibm,plb3";
#address-cells = <1>;
#size-cells = <1>;
ranges;
clock-frequency = <0>; /* Filled in by wrapper */
MAL0: mcmal {
compatible = "ibm,mcmal-405ez", "ibm,mcmal";
dcr-reg = <0x380 0x62>;
num-tx-chans = <1>;
num-rx-chans = <1>;
interrupt-parent = <&UIC0>;
/* 405EZ has only 3 interrupts to the UIC, as
* SERR, TXDE, and RXDE are or'd together into
* one UIC bit
*/
interrupts = <
0x13 0x4 /* TXEOB */
0x15 0x4 /* RXEOB */
0x12 0x4 /* SERR, TXDE, RXDE */>;
};
POB0: opb {
compatible = "ibm,opb-405ez", "ibm,opb";
#address-cells = <1>;
#size-cells = <1>;
ranges;
dcr-reg = <0x0a 0x05>;
clock-frequency = <0>; /* Filled in by wrapper */
UART0: serial@ef600300 {
device_type = "serial";
compatible = "ns16550";
reg = <0xef600300 0x8>;
virtual-reg = <0xef600300>;
clock-frequency = <0>; /* Filled in by wrapper */
current-speed = <115200>;
interrupt-parent = <&UIC0>;
interrupts = <0x5 0x4>;
};
UART1: serial@ef600400 {
device_type = "serial";
compatible = "ns16550";
reg = <0xef600400 0x8>;
clock-frequency = <0>; /* Filled in by wrapper */
current-speed = <115200>;
interrupt-parent = <&UIC0>;
interrupts = <0x6 0x4>;
};
IIC: i2c@ef600500 {
compatible = "ibm,iic-405ez", "ibm,iic";
reg = <0xef600500 0x11>;
interrupt-parent = <&UIC0>;
interrupts = <0xa 0x4>;
};
GPIO0: gpio@ef600700 {
compatible = "ibm,gpio-405ez";
reg = <0xef600700 0x20>;
};
GPIO1: gpio@ef600800 {
compatible = "ibm,gpio-405ez";
reg = <0xef600800 0x20>;
};
EMAC0: ethernet@ef600900 {
device_type = "network";
compatible = "ibm,emac-405ez", "ibm,emac";
interrupt-parent = <&UIC0>;
interrupts = <
0x10 0x4 /* Ethernet */
0x11 0x4 /* Ethernet Wake up */>;
local-mac-address = [000000000000]; /* Filled in by wrapper */
reg = <0xef600900 0x70>;
mal-device = <&MAL0>;
mal-tx-channel = <0>;
mal-rx-channel = <0>;
cell-index = <0>;
max-frame-size = <1500>;
rx-fifo-size = <4096>;
tx-fifo-size = <2048>;
phy-mode = "mii";
phy-map = <0x0>;
};
CAN0: can@ef601000 {
compatible = "amcc,can-405ez";
reg = <0xef601000 0x620>;
interrupt-parent = <&UIC0>;
interrupts = <0x7 0x4>;
};
CAN1: can@ef601800 {
compatible = "amcc,can-405ez";
reg = <0xef601800 0x620>;
interrupt-parent = <&UIC0>;
interrupts = <0x8 0x4>;
};
cameleon@ef602000 {
compatible = "amcc,cameleon-405ez";
reg = <0xef602000 0x800>;
interrupt-parent = <&UIC0>;
interrupts = <0xb 0x4 0xc 0x4>;
};
ieee1588@ef602800 {
compatible = "amcc,ieee1588-405ez";
reg = <0xef602800 0x60>;
interrupt-parent = <&UIC0>;
interrupts = <0x4 0x4>;
/* This thing is a bit weird. It has it's own UIC
* that it uses to generate snapshot triggers. We
* don't really support this device yet, and it needs
* work to figure this out.
*/
dcr-reg = <0xe0 0x9>;
};
usb@ef603000 {
compatible = "ohci-be";
reg = <0xef603000 0x80>;
interrupts-parent = <&UIC0>;
interrupts = <0xd 0x4 0xe 0x4>;
};
dac@ef603300 {
compatible = "amcc,dac-405ez";
reg = <0xef603300 0x40>;
interrupt-parent = <&UIC0>;
interrupts = <0x18 0x4>;
};
adc@ef603400 {
compatible = "amcc,adc-405ez";
reg = <0xef603400 0x40>;
interrupt-parent = <&UIC0>;
interrupts = <0x17 0x4>;
};
spi@ef603500 {
compatible = "amcc,spi-405ez";
reg = <0xef603500 0x100>;
interrupt-parent = <&UIC0>;
interrupts = <0x9 0x4>;
};
};
EBC0: ebc {
compatible = "ibm,ebc-405ez", "ibm,ebc";
dcr-reg = <0x12 0x2>;
#address-cells = <2>;
#size-cells = <1>;
clock-frequency = <0>; /* Filled in by wrapper */
};
};
chosen {
linux,stdout-path = "/plb/opb/serial@ef600300";
};
};
/*
* Device Tree Source for Netstal Maschinen HCU4
* based on the IBM Walnut
*
* Copyright 2008
* Niklaus Giger <niklaus.giger@member.fsf.org>
*
* Copyright 2007 IBM Corp.
* Josh Boyer <jwboyer@linux.vnet.ibm.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.
*/
/dts-v1/;
/ {
#address-cells = <0x1>;
#size-cells = <0x1>;
model = "netstal,hcu4";
compatible = "netstal,hcu4";
dcr-parent = <0x1>;
aliases {
ethernet0 = "/plb/opb/ethernet@ef600800";
serial0 = "/plb/opb/serial@ef600300";
};
cpus {
#address-cells = <0x1>;
#size-cells = <0x0>;
cpu@0 {
device_type = "cpu";
model = "PowerPC,405GPr";
reg = <0x0>;
clock-frequency = <0>; /* Filled in by U-Boot */
timebase-frequency = <0x0>; /* Filled in by U-Boot */
i-cache-line-size = <0x20>;
d-cache-line-size = <0x20>;
i-cache-size = <0x4000>;
d-cache-size = <0x4000>;
dcr-controller;
dcr-access-method = "native";
linux,phandle = <0x1>;
};
};
memory {
device_type = "memory";
reg = <0x0 0x0>; /* Filled in by U-Boot */
};
UIC0: interrupt-controller {
compatible = "ibm,uic";
interrupt-controller;
cell-index = <0x0>;
dcr-reg = <0xc0 0x9>;
#address-cells = <0x0>;
#size-cells = <0x0>;
#interrupt-cells = <0x2>;
linux,phandle = <0x2>;
};
plb {
compatible = "ibm,plb3";
#address-cells = <0x1>;
#size-cells = <0x1>;
ranges;
clock-frequency = <0x0>; /* Filled in by U-Boot */
SDRAM0: memory-controller {
compatible = "ibm,sdram-405gp";
dcr-reg = <0x10 0x2>;
};
MAL: mcmal {
compatible = "ibm,mcmal-405gp", "ibm,mcmal";
dcr-reg = <0x180 0x62>;
num-tx-chans = <0x1>;
num-rx-chans = <0x1>;
interrupt-parent = <0x2>;
interrupts = <0xb 0x4 0xc 0x4 0xa 0x4 0xd 0x4 0xe 0x4>;
linux,phandle = <0x3>;
};
POB0: opb {
compatible = "ibm,opb-405gp", "ibm,opb";
#address-cells = <0x1>;
#size-cells = <0x1>;
ranges = <0xef600000 0xef600000 0xa00000>;
dcr-reg = <0xa0 0x5>;
clock-frequency = <0x0>; /* Filled in by U-Boot */
UART0: serial@ef600300 {
device_type = "serial";
compatible = "ns16550";
reg = <0xef600300 0x8>;
virtual-reg = <0xef600300>;
clock-frequency = <0x0>;/* Filled in by U-Boot */
current-speed = <0>; /* Filled in by U-Boot */
interrupt-parent = <0x2>;
interrupts = <0x0 0x4>;
};
IIC: i2c@ef600500 {
compatible = "ibm,iic-405gp", "ibm,iic";
reg = <0xef600500 0x11>;
interrupt-parent = <0x2>;
interrupts = <0x2 0x4>;
};
GPIO: gpio@ef600700 {
compatible = "ibm,gpio-405gp";
reg = <0xef600700 0x20>;
};
EMAC: ethernet@ef600800 {
device_type = "network";
compatible = "ibm,emac-405gp", "ibm,emac";
interrupt-parent = <0x2>;
interrupts = <0xf 0x4 0x9 0x4>;
local-mac-address = [00 00 00 00 00 00];
reg = <0xef600800 0x70>;
mal-device = <0x3>;
mal-tx-channel = <0x0>;
mal-rx-channel = <0x0>;
cell-index = <0x0>;
max-frame-size = <0x5dc>;
rx-fifo-size = <0x1000>;
tx-fifo-size = <0x800>;
phy-mode = "rmii";
phy-map = <0x1>;
};
};
EBC0: ebc {
compatible = "ibm,ebc-405gp", "ibm,ebc";
dcr-reg = <0x12 0x2>;
#address-cells = <0x2>;
#size-cells = <0x1>;
clock-frequency = <0x0>; /* Filled in by U-Boot */
sram@0,0 {
reg = <0x0 0x0 0x80000>;
};
flash@0,80000 {
compatible = "jedec-flash";
bank-width = <0x1>;
reg = <0x0 0x80000 0x80000>;
#address-cells = <0x1>;
#size-cells = <0x1>;
partition@0 {
label = "OpenBIOS";
reg = <0x0 0x80000>;
read-only;
};
};
};
};
chosen {
linux,stdout-path = "/plb/opb/serial@ef600300";
};
};
This diff is collapsed.
This diff is collapsed.
...@@ -1277,6 +1277,19 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -1277,6 +1277,19 @@ static struct cpu_spec __initdata cpu_specs[] = {
.machine_check = machine_check_4xx, .machine_check = machine_check_4xx,
.platform = "ppc405", .platform = "ppc405",
}, },
{
/* 405EZ */
.pvr_mask = 0xffff0000,
.pvr_value = 0x41510000,
.cpu_name = "405EZ",
.cpu_features = CPU_FTRS_40X,
.cpu_user_features = PPC_FEATURE_32 |
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
.machine_check = machine_check_4xx,
.platform = "ppc405",
},
{ /* default match */ { /* default match */
.pvr_mask = 0x00000000, .pvr_mask = 0x00000000,
.pvr_value = 0x00000000, .pvr_value = 0x00000000,
......
...@@ -14,6 +14,15 @@ ...@@ -14,6 +14,15 @@
# help # help
# This option enables support for the CPCI405 board. # This option enables support for the CPCI405 board.
config ACADIA
bool "Acadia"
depends on 40x
default n
select PPC40x_SIMPLE
select 405EZ
help
This option enables support for the AMCC 405EZ Acadia evaluation board.
config EP405 config EP405
bool "EP405/EP405PC" bool "EP405/EP405PC"
depends on 40x depends on 40x
...@@ -23,6 +32,14 @@ config EP405 ...@@ -23,6 +32,14 @@ config EP405
help help
This option enables support for the EP405/EP405PC boards. This option enables support for the EP405/EP405PC boards.
config HCU4
bool "Hcu4"
depends on 40x
default y
select 405GPR
help
This option enables support for the Nestal Maschinen HCU4 board.
config KILAUEA config KILAUEA
bool "Kilauea" bool "Kilauea"
depends on 40x depends on 40x
...@@ -93,6 +110,13 @@ config XILINX_VIRTEX_GENERIC_BOARD ...@@ -93,6 +110,13 @@ config XILINX_VIRTEX_GENERIC_BOARD
Most Virtex designs should use this unless it needs to do some Most Virtex designs should use this unless it needs to do some
special configuration at board probe time. special configuration at board probe time.
config PPC40x_SIMPLE
bool "Simple PowerPC 40x board support"
depends on 40x
default n
help
This option enables the simple PowerPC 40x platform support.
# 40x specific CPU modules, selected based on the board above. # 40x specific CPU modules, selected based on the board above.
config NP405H config NP405H
bool bool
...@@ -118,6 +142,12 @@ config 405EX ...@@ -118,6 +142,12 @@ config 405EX
select IBM_NEW_EMAC_EMAC4 select IBM_NEW_EMAC_EMAC4
select IBM_NEW_EMAC_RGMII select IBM_NEW_EMAC_RGMII
config 405EZ
bool
select IBM_NEW_EMAC_NO_FLOW_CTRL
select IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
select IBM_NEW_EMAC_MAL_COMMON_ERR
config 405GPR config 405GPR
bool bool
...@@ -139,6 +169,14 @@ config STB03xxx ...@@ -139,6 +169,14 @@ config STB03xxx
select IBM405_ERR77 select IBM405_ERR77
select IBM405_ERR51 select IBM405_ERR51
config PPC4xx_GPIO
bool "PPC4xx GPIO support"
depends on 40x
select ARCH_REQUIRE_GPIOLIB
select GENERIC_GPIO
help
Enable gpiolib support for ppc40x based boards
# 40x errata/workaround config symbols, selected by the CPU models above # 40x errata/workaround config symbols, selected by the CPU models above
# All 405-based cores up until the 405GPR and 405EP have this errata. # All 405-based cores up until the 405GPR and 405EP have this errata.
......
obj-$(CONFIG_KILAUEA) += kilauea.o obj-$(CONFIG_KILAUEA) += kilauea.o
obj-$(CONFIG_HCU4) += hcu4.o
obj-$(CONFIG_MAKALU) += makalu.o obj-$(CONFIG_MAKALU) += makalu.o
obj-$(CONFIG_WALNUT) += walnut.o obj-$(CONFIG_WALNUT) += walnut.o
obj-$(CONFIG_XILINX_VIRTEX_GENERIC_BOARD) += virtex.o obj-$(CONFIG_XILINX_VIRTEX_GENERIC_BOARD) += virtex.o
obj-$(CONFIG_EP405) += ep405.o obj-$(CONFIG_EP405) += ep405.o
obj-$(CONFIG_PPC40x_SIMPLE) += ppc40x_simple.o
/*
* Architecture- / platform-specific boot-time initialization code for
* IBM PowerPC 4xx based boards. Adapted from original
* code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
* <dan@net4x.com>.
*
* Copyright(c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
*
* Rewritten and ported to the merged powerpc tree:
* Copyright 2007 IBM Corporation
* Josh Boyer <jwboyer@linux.vnet.ibm.com>
*
* 2002 (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.
*/
#include <linux/init.h>
#include <linux/of_platform.h>
#include <asm/machdep.h>
#include <asm/prom.h>
#include <asm/udbg.h>
#include <asm/time.h>
#include <asm/uic.h>
#include <asm/ppc4xx.h>
static __initdata struct of_device_id hcu4_of_bus[] = {
{ .compatible = "ibm,plb3", },
{ .compatible = "ibm,opb", },
{ .compatible = "ibm,ebc", },
{},
};
static int __init hcu4_device_probe(void)
{
of_platform_bus_probe(NULL, hcu4_of_bus, NULL);
return 0;
}
machine_device_initcall(hcu4, hcu4_device_probe);
static int __init hcu4_probe(void)
{
unsigned long root = of_get_flat_dt_root();
if (!of_flat_dt_is_compatible(root, "netstal,hcu4"))
return 0;
return 1;
}
define_machine(hcu4) {
.name = "HCU4",
.probe = hcu4_probe,
.progress = udbg_progress,
.init_IRQ = uic_init_tree,
.get_irq = uic_get_irq,
.restart = ppc4xx_reset_system,
.calibrate_decr = generic_calibrate_decr,
};
/*
* Generic PowerPC 40x platform support
*
* Copyright 2008 IBM Corporation
*
* 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; version 2 of the License.
*
* This implements simple platform support for PowerPC 44x chips. This is
* mostly used for eval boards or other simple and "generic" 44x boards. If
* your board has custom functions or hardware, then you will likely want to
* implement your own board.c file to accommodate it.
*/
#include <asm/machdep.h>
#include <asm/pci-bridge.h>
#include <asm/ppc4xx.h>
#include <asm/prom.h>
#include <asm/time.h>
#include <asm/udbg.h>
#include <asm/uic.h>
#include <linux/init.h>
#include <linux/of_platform.h>
static __initdata struct of_device_id ppc40x_of_bus[] = {
{ .compatible = "ibm,plb3", },
{ .compatible = "ibm,plb4", },
{ .compatible = "ibm,opb", },
{ .compatible = "ibm,ebc", },
{ .compatible = "simple-bus", },
{},
};
static int __init ppc40x_device_probe(void)
{
of_platform_bus_probe(NULL, ppc40x_of_bus, NULL);
return 0;
}
machine_device_initcall(ppc40x_simple, ppc40x_device_probe);
/* This is the list of boards that can be supported by this simple
* platform code. This does _not_ mean the boards are compatible,
* as they most certainly are not from a device tree perspective.
* However, their differences are handled by the device tree and the
* drivers and therefore they don't need custom board support files.
*
* Again, if your board needs to do things differently then create a
* board.c file for it rather than adding it to this list.
*/
static char *board[] __initdata = {
"amcc,acadia"
};
static int __init ppc40x_probe(void)
{
unsigned long root = of_get_flat_dt_root();
int i = 0;
for (i = 0; i < ARRAY_SIZE(board); i++) {
if (of_flat_dt_is_compatible(root, board[i])) {
ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
return 1;
}
}
return 0;
}
define_machine(ppc40x_simple) {
.name = "PowerPC 40x Platform",
.probe = ppc40x_probe,
.progress = udbg_progress,
.init_IRQ = uic_init_tree,
.get_irq = uic_get_irq,
.restart = ppc4xx_reset_system,
.calibrate_decr = generic_calibrate_decr,
};
...@@ -167,6 +167,14 @@ config PPC44x_SIMPLE ...@@ -167,6 +167,14 @@ config PPC44x_SIMPLE
help help
This option enables the simple PowerPC 44x platform support. This option enables the simple PowerPC 44x platform support.
config PPC4xx_GPIO
bool "PPC4xx GPIO support"
depends on 44x
select ARCH_REQUIRE_GPIOLIB
select GENERIC_GPIO
help
Enable gpiolib support for ppc440 based boards
# 44x specific CPU modules, selected based on the board above. # 44x specific CPU modules, selected based on the board above.
config 440EP config 440EP
bool bool
......
...@@ -37,6 +37,7 @@ obj-$(CONFIG_OF_RTC) += of_rtc.o ...@@ -37,6 +37,7 @@ obj-$(CONFIG_OF_RTC) += of_rtc.o
ifeq ($(CONFIG_PCI),y) ifeq ($(CONFIG_PCI),y)
obj-$(CONFIG_4xx) += ppc4xx_pci.o obj-$(CONFIG_4xx) += ppc4xx_pci.o
endif endif
obj-$(CONFIG_PPC4xx_GPIO) += ppc4xx_gpio.o
obj-$(CONFIG_CPM) += cpm_common.o obj-$(CONFIG_CPM) += cpm_common.o
obj-$(CONFIG_CPM2) += cpm2.o cpm2_pic.o obj-$(CONFIG_CPM2) += cpm2.o cpm2_pic.o
......
/*
* PPC4xx gpio driver
*
* Copyright (c) 2008 Harris Corporation
* Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
* Copyright (c) MontaVista Software, Inc. 2008.
*
* Author: Steve Falco <sfalco@harris.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/types.h>
#define GPIO_MASK(gpio) (0x80000000 >> (gpio))
#define GPIO_MASK2(gpio) (0xc0000000 >> ((gpio) * 2))
/* Physical GPIO register layout */
struct ppc4xx_gpio {
__be32 or;
__be32 tcr;
__be32 osrl;
__be32 osrh;
__be32 tsrl;
__be32 tsrh;
__be32 odr;
__be32 ir;
__be32 rr1;
__be32 rr2;
__be32 rr3;
__be32 reserved1;
__be32 isr1l;
__be32 isr1h;
__be32 isr2l;
__be32 isr2h;
__be32 isr3l;
__be32 isr3h;
};
struct ppc4xx_gpio_chip {
struct of_mm_gpio_chip mm_gc;
spinlock_t lock;
};
/*
* GPIO LIB API implementation for GPIOs
*
* There are a maximum of 32 gpios in each gpio controller.
*/
static inline struct ppc4xx_gpio_chip *
to_ppc4xx_gpiochip(struct of_mm_gpio_chip *mm_gc)
{
return container_of(mm_gc, struct ppc4xx_gpio_chip, mm_gc);
}
static int ppc4xx_gpio_get(struct gpio_chip *gc, unsigned int gpio)
{
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
struct ppc4xx_gpio __iomem *regs = mm_gc->regs;
return in_be32(&regs->ir) & GPIO_MASK(gpio);
}
static inline void
__ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
{
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
struct ppc4xx_gpio __iomem *regs = mm_gc->regs;
if (val)
setbits32(&regs->or, GPIO_MASK(gpio));
else
clrbits32(&regs->or, GPIO_MASK(gpio));
}
static void
ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
{
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
struct ppc4xx_gpio_chip *chip = to_ppc4xx_gpiochip(mm_gc);
unsigned long flags;
spin_lock_irqsave(&chip->lock, flags);
__ppc4xx_gpio_set(gc, gpio, val);
spin_unlock_irqrestore(&chip->lock, flags);
pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
}
static int ppc4xx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
{
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
struct ppc4xx_gpio_chip *chip = to_ppc4xx_gpiochip(mm_gc);
struct ppc4xx_gpio __iomem *regs = mm_gc->regs;
unsigned long flags;
spin_lock_irqsave(&chip->lock, flags);
/* Disable open-drain function */
clrbits32(&regs->odr, GPIO_MASK(gpio));
/* Float the pin */
clrbits32(&regs->tcr, GPIO_MASK(gpio));
/* Bits 0-15 use TSRL/OSRL, bits 16-31 use TSRH/OSRH */
if (gpio < 16) {
clrbits32(&regs->osrl, GPIO_MASK2(gpio));
clrbits32(&regs->tsrl, GPIO_MASK2(gpio));
} else {
clrbits32(&regs->osrh, GPIO_MASK2(gpio));
clrbits32(&regs->tsrh, GPIO_MASK2(gpio));
}
spin_unlock_irqrestore(&chip->lock, flags);
return 0;
}
static int
ppc4xx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
{
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
struct ppc4xx_gpio_chip *chip = to_ppc4xx_gpiochip(mm_gc);
struct ppc4xx_gpio __iomem *regs = mm_gc->regs;
unsigned long flags;
spin_lock_irqsave(&chip->lock, flags);
/* First set initial value */
__ppc4xx_gpio_set(gc, gpio, val);
/* Disable open-drain function */
clrbits32(&regs->odr, GPIO_MASK(gpio));
/* Drive the pin */
setbits32(&regs->tcr, GPIO_MASK(gpio));
/* Bits 0-15 use TSRL, bits 16-31 use TSRH */
if (gpio < 16) {
clrbits32(&regs->osrl, GPIO_MASK2(gpio));
clrbits32(&regs->tsrl, GPIO_MASK2(gpio));
} else {
clrbits32(&regs->osrh, GPIO_MASK2(gpio));
clrbits32(&regs->tsrh, GPIO_MASK2(gpio));
}
spin_unlock_irqrestore(&chip->lock, flags);
pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
return 0;
}
static int __init ppc4xx_add_gpiochips(void)
{
struct device_node *np;
for_each_compatible_node(np, NULL, "ibm,ppc4xx-gpio") {
int ret;
struct ppc4xx_gpio_chip *ppc4xx_gc;
struct of_mm_gpio_chip *mm_gc;
struct of_gpio_chip *of_gc;
struct gpio_chip *gc;
ppc4xx_gc = kzalloc(sizeof(*ppc4xx_gc), GFP_KERNEL);
if (!ppc4xx_gc) {
ret = -ENOMEM;
goto err;
}
spin_lock_init(&ppc4xx_gc->lock);
mm_gc = &ppc4xx_gc->mm_gc;
of_gc = &mm_gc->of_gc;
gc = &of_gc->gc;
of_gc->gpio_cells = 2;
gc->ngpio = 32;
gc->direction_input = ppc4xx_gpio_dir_in;
gc->direction_output = ppc4xx_gpio_dir_out;
gc->get = ppc4xx_gpio_get;
gc->set = ppc4xx_gpio_set;
ret = of_mm_gpiochip_add(np, mm_gc);
if (ret)
goto err;
continue;
err:
pr_err("%s: registration failed with status %d\n",
np->full_name, ret);
kfree(ppc4xx_gc);
/* try others anyway */
}
return 0;
}
arch_initcall(ppc4xx_add_gpiochips);
...@@ -2604,8 +2604,16 @@ static int __devinit emac_init_config(struct emac_instance *dev) ...@@ -2604,8 +2604,16 @@ static int __devinit emac_init_config(struct emac_instance *dev)
if (of_device_is_compatible(np, "ibm,emac-440ep") || if (of_device_is_compatible(np, "ibm,emac-440ep") ||
of_device_is_compatible(np, "ibm,emac-440gr")) of_device_is_compatible(np, "ibm,emac-440gr"))
dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX; dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX;
if (of_device_is_compatible(np, "ibm,emac-405ez")) if (of_device_is_compatible(np, "ibm,emac-405ez")) {
#ifdef CONFIG_IBM_NEW_EMAC_NO_FLOW_CONTROL
dev->features |= EMAC_FTR_NO_FLOW_CONTROL_40x; dev->features |= EMAC_FTR_NO_FLOW_CONTROL_40x;
#else
printk(KERN_ERR "%s: Flow control not disabled!\n",
np->full_name);
return -ENXIO;
#endif
}
} }
/* Fixup some feature bits based on the device tree */ /* Fixup some feature bits based on the device tree */
......
...@@ -280,9 +280,11 @@ static irqreturn_t mal_txeob(int irq, void *dev_instance) ...@@ -280,9 +280,11 @@ static irqreturn_t mal_txeob(int irq, void *dev_instance)
mal_schedule_poll(mal); mal_schedule_poll(mal);
set_mal_dcrn(mal, MAL_TXEOBISR, r); set_mal_dcrn(mal, MAL_TXEOBISR, r);
#ifdef CONFIG_PPC_DCR_NATIVE
if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT)) if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))
mtdcri(SDR0, DCRN_SDR_ICINTSTAT, mtdcri(SDR0, DCRN_SDR_ICINTSTAT,
(mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICTX)); (mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICTX));
#endif
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -298,9 +300,11 @@ static irqreturn_t mal_rxeob(int irq, void *dev_instance) ...@@ -298,9 +300,11 @@ static irqreturn_t mal_rxeob(int irq, void *dev_instance)
mal_schedule_poll(mal); mal_schedule_poll(mal);
set_mal_dcrn(mal, MAL_RXEOBISR, r); set_mal_dcrn(mal, MAL_RXEOBISR, r);
#ifdef CONFIG_PPC_DCR_NATIVE
if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT)) if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))
mtdcri(SDR0, DCRN_SDR_ICINTSTAT, mtdcri(SDR0, DCRN_SDR_ICINTSTAT,
(mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICRX)); (mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICRX));
#endif
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -572,9 +576,18 @@ static int __devinit mal_probe(struct of_device *ofdev, ...@@ -572,9 +576,18 @@ static int __devinit mal_probe(struct of_device *ofdev,
goto fail; goto fail;
} }
if (of_device_is_compatible(ofdev->node, "ibm,mcmal-405ez")) if (of_device_is_compatible(ofdev->node, "ibm,mcmal-405ez")) {
#if defined(CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT) && \
defined(CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR)
mal->features |= (MAL_FTR_CLEAR_ICINTSTAT | mal->features |= (MAL_FTR_CLEAR_ICINTSTAT |
MAL_FTR_COMMON_ERR_INT); MAL_FTR_COMMON_ERR_INT);
#else
printk(KERN_ERR "%s: Support for 405EZ not enabled!\n",
ofdev->node->full_name);
err = -ENODEV;
goto fail;
#endif
}
mal->txeob_irq = irq_of_parse_and_map(ofdev->node, 0); mal->txeob_irq = irq_of_parse_and_map(ofdev->node, 0);
mal->rxeob_irq = irq_of_parse_and_map(ofdev->node, 1); mal->rxeob_irq = irq_of_parse_and_map(ofdev->node, 1);
......
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