u-boot-brain/board/esd/pmc405de/pmc405de.c
Stefan Roese 952e7760bf ppc4xx: Convert PPC4xx UIC defines from lower case to upper case
The latest PPC4xx register cleanup patch missed the UIC defines.
This patch now changes lower case UIC defines to upper case.

Signed-off-by: Stefan Roese <sr@denx.de>
2009-09-28 10:45:42 +02:00

522 lines
13 KiB
C

/*
* (C) Copyright 2009
* Matthias Fuchs, esd gmbh germany, matthias.fuchs@esd.eu
*
* See file CREDITS for list of people who contributed to this
* project.
*
* 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.
*
* 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 <common.h>
#include <libfdt.h>
#include <fdt_support.h>
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/gpio.h>
#include <asm/4xx_pci.h>
#include <command.h>
#include <malloc.h>
/*
* PMC405-DE cpld registers
* - all registers are 8 bit
* - all registers are on 32 bit addesses
*/
struct pmc405de_cpld {
/* cpld design version */
u8 version;
u8 reserved0[3];
/* misc. status lines */
u8 status;
u8 reserved1[3];
/*
* gated control flags
* gate bit(s) must be written with '1' to
* access control flag
*/
u8 control;
u8 reserved2[3];
};
#define CPLD_VERSION_MASK 0x0f
#define CPLD_CONTROL_POSTLED_N 0x01
#define CPLD_CONTROL_POSTLED_GATE 0x02
#define CPLD_CONTROL_RESETOUT_N 0x40
#define CPLD_CONTROL_RESETOUT_N_GATE 0x80
DECLARE_GLOBAL_DATA_PTR;
extern void __ft_board_setup(void *blob, bd_t *bd);
extern void pll_write(u32 a, u32 b);
static int wait_for_pci_ready_done;
static int is_monarch(void);
static int pci_is_66mhz(void);
static int board_revision(void);
static int cpld_revision(void);
static void upd_plb_pci_div(u32 pllmr0, u32 pllmr1, u32 div);
int board_early_init_f(void)
{
u32 pllmr0, pllmr1;
/*
* check M66EN and patch PLB:PCI divider for 66MHz PCI
*
* fCPU==333MHz && fPCI==66MHz (PLBDiv==3 && M66EN==1): PLB/PCI=1
* fCPU==333MHz && fPCI==33MHz (PLBDiv==3 && M66EN==0): PLB/PCI=2
* fCPU==133|266MHz && fPCI==66MHz (PLBDiv==1|2 && M66EN==1): PLB/PCI=2
* fCPU==133|266MHz && fPCI==33MHz (PLBDiv==1|2 && M66EN==0): PLB/PCI=3
*
* calling upd_plb_pci_div() may end in calling pll_write() which will
* do a chip reset and never return.
*/
pllmr0 = mfdcr(CPC0_PLLMR0);
pllmr1 = mfdcr(CPC0_PLLMR1);
if ((pllmr0 & PLLMR0_CPU_TO_PLB_MASK) == PLLMR0_CPU_PLB_DIV_3) {
/* fCPU=333MHz, fPLB=111MHz */
if (pci_is_66mhz())
upd_plb_pci_div(pllmr0, pllmr1, PLLMR0_PCI_PLB_DIV_1);
else
upd_plb_pci_div(pllmr0, pllmr1, PLLMR0_PCI_PLB_DIV_2);
} else {
/* fCPU=133|266MHz, fPLB=133MHz */
if (pci_is_66mhz())
upd_plb_pci_div(pllmr0, pllmr1, PLLMR0_PCI_PLB_DIV_2);
else
upd_plb_pci_div(pllmr0, pllmr1, PLLMR0_PCI_PLB_DIV_3);
}
/*
* IRQ 25 (EXT IRQ 0) PCI-INTA#; active low; level sensitive
* IRQ 26 (EXT IRQ 1) PCI-INTB#; active low; level sensitive
* IRQ 27 (EXT IRQ 2) PCI-INTC#; active low; level sensitive
* IRQ 28 (EXT IRQ 3) PCI-INTD#; active low; level sensitive
* IRQ 29 (EXT IRQ 4) ETH0-PHY-IRQ#; active low; level sensitive
* IRQ 30 (EXT IRQ 5) ETH1-PHY-IRQ#; active low; level sensitive
* IRQ 31 (EXT IRQ 6) PLD-IRQ#; active low; level sensitive
*/
mtdcr(UIC0SR, 0xFFFFFFFF); /* clear all ints */
mtdcr(UIC0ER, 0x00000000); /* disable all ints */
mtdcr(UIC0CR, 0x00000000); /* set all to be non-critical*/
mtdcr(UIC0PR, 0xFFFFFF80); /* set int polarities */
mtdcr(UIC0TR, 0x10000000); /* set int trigger levels */
mtdcr(UIC0VCR, 0x00000001); /* set vect base=0, INT0 highest prio */
mtdcr(UIC0SR, 0xFFFFFFFF); /* clear all ints */
/*
* EBC Configuration Register:
* - set ready timeout to 512 ebc-clks -> ca. 15 us
* - EBC lines are always driven
*/
mtebc(EBC0_CFG, 0xa8400000);
return 0;
}
static void upd_plb_pci_div(u32 pllmr0, u32 pllmr1, u32 div)
{
if ((pllmr0 & PLLMR0_PCI_TO_PLB_MASK) != div)
pll_write((pllmr0 & ~PLLMR0_PCI_TO_PLB_MASK) | div, pllmr1);
}
int misc_init_r(void)
{
int i;
struct ppc4xx_gpio *gpio0 = (struct ppc4xx_gpio *)GPIO_BASE;
struct pmc405de_cpld *cpld =
(struct pmc405de_cpld *)CONFIG_SYS_CPLD_BASE;
if (!is_monarch()) {
/* PCI configuration done: release EREADY */
setbits_be32(&gpio0->or, CONFIG_SYS_GPIO_EREADY);
setbits_be32(&gpio0->tcr, CONFIG_SYS_GPIO_EREADY);
}
/* turn off POST LED */
out_8(&cpld->control,
CPLD_CONTROL_POSTLED_N | CPLD_CONTROL_POSTLED_GATE);
/* turn on LEDs: RUN, A, B */
clrbits_be32(&gpio0->or,
CONFIG_SYS_GPIO_LEDRUN_N |
CONFIG_SYS_GPIO_LEDA_N |
CONFIG_SYS_GPIO_LEDB_N);
for (i=0; i < 200; i++)
udelay(1000);
/* turn off LEDs: A, B */
setbits_be32(&gpio0->or,
CONFIG_SYS_GPIO_LEDA_N |
CONFIG_SYS_GPIO_LEDB_N);
return (0);
}
static int is_monarch(void)
{
struct ppc4xx_gpio *gpio0 = (struct ppc4xx_gpio *)GPIO_BASE;
return (in_be32(&gpio0->ir) & CONFIG_SYS_GPIO_MONARCH_N) == 0;
}
static int pci_is_66mhz(void)
{
struct ppc4xx_gpio *gpio0 = (struct ppc4xx_gpio *)GPIO_BASE;
return (in_be32(&gpio0->ir) & CONFIG_SYS_GPIO_M66EN);
}
static int board_revision(void)
{
struct ppc4xx_gpio *gpio0 = (struct ppc4xx_gpio *)GPIO_BASE;
return ((in_be32(&gpio0->ir) & CONFIG_SYS_GPIO_HWREV_MASK) >>
CONFIG_SYS_GPIO_HWREV_SHIFT);
}
static int cpld_revision(void)
{
struct pmc405de_cpld *cpld =
(struct pmc405de_cpld *)CONFIG_SYS_CPLD_BASE;
return ((in_8(&cpld->version) & CPLD_VERSION_MASK));
}
/*
* Check Board Identity
*/
int checkboard(void)
{
puts("Board: esd GmbH - PMC-CPU/405-DE");
gd->board_type = board_revision();
printf(", Rev 1.%ld, ", gd->board_type);
if (!is_monarch())
puts("non-");
printf("monarch, PCI=%s MHz, PLD-Rev 1.%d\n",
pci_is_66mhz() ? "66" : "33", cpld_revision());
return 0;
}
static void wait_for_pci_ready(void)
{
struct ppc4xx_gpio *gpio0 = (struct ppc4xx_gpio *)GPIO_BASE;
int i;
char *s = getenv("pcidelay");
/* only wait once */
if (wait_for_pci_ready_done)
return;
/*
* We have our own handling of the pcidelay variable.
* Using CONFIG_PCI_BOOTDELAY enables pausing for host
* and adapter devices. For adapter devices we do not
* want this.
*/
if (s) {
int ms = simple_strtoul(s, NULL, 10);
printf("PCI: Waiting for %d ms\n", ms);
for (i=0; i<ms; i++)
udelay(1000);
}
if (!(in_be32(&gpio0->ir) & CONFIG_SYS_GPIO_EREADY)) {
printf("PCI: Waiting for EREADY (CTRL-C to skip) ... ");
while (1) {
if (ctrlc()) {
puts("abort\n");
break;
}
if (in_be32(&gpio0->ir) & CONFIG_SYS_GPIO_EREADY) {
printf("done\n");
break;
}
}
}
wait_for_pci_ready_done = 1;
}
/*
* Overwrite weak is_pci_host()
*
* This routine is called to determine if a pci scan should be
* performed. With various hardware environments (especially cPCI and
* PPMC) it's insufficient to depend on the state of the arbiter enable
* bit in the strap register, or generic host/adapter assumptions.
*
* Return 0 for adapter mode, non-zero for host (monarch) mode.
*/
int is_pci_host(struct pci_controller *hose)
{
char *s;
if (!is_monarch()) {
/*
* Overwrite PCI identification when running in
* non-monarch mode
* This should be moved into pci_target_init()
* when it is sometimes available for 405 CPUs
*/
pci_write_config_word(PCIDEVID_405GP,
PCI_SUBSYSTEM_ID,
CONFIG_SYS_PCI_SUBSYS_ID_NONMONARCH);
pci_write_config_word(PCIDEVID_405GP,
PCI_CLASS_SUB_CODE,
CONFIG_SYS_PCI_CLASSCODE_NONMONARCH);
}
s = getenv("pciscan");
if (s == NULL) {
if (is_monarch()) {
wait_for_pci_ready();
return 1;
} else {
return 0;
}
} else {
if (!strcmp(s, "yes"))
return 1;
}
return 0;
}
/*
* Overwrite weak pci_pre_init()
*
* The default implementation enables the 405EP
* internal PCI arbiter. We do not want that
* on a PMC module.
*/
int pci_pre_init(struct pci_controller *hose)
{
return 1;
}
#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
void ft_board_setup(void *blob, bd_t *bd)
{
int rc;
__ft_board_setup(blob, bd);
/*
* Disable PCI in non-monarch mode.
*/
if (!is_monarch()) {
rc = fdt_find_and_setprop(blob, "/plb/pci@ec000000", "status",
"disabled", sizeof("disabled"), 1);
if (rc) {
printf("Unable to update property status in PCI node, "
"err=%s\n",
fdt_strerror(rc));
}
}
}
#endif /* defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) */
#if defined(CONFIG_SYS_EEPROM_WREN)
/* Input: <dev_addr> I2C address of EEPROM device to enable.
* <state> -1: deliver current state
* 0: disable write
* 1: enable write
* Returns: -1: wrong device address
* 0: dis-/en- able done
* 0/1: current state if <state> was -1.
*/
int eeprom_write_enable(unsigned dev_addr, int state)
{
struct ppc4xx_gpio *gpio0 = (struct ppc4xx_gpio *)GPIO_BASE;
if (CONFIG_SYS_I2C_EEPROM_ADDR != dev_addr) {
return -1;
} else {
switch (state) {
case 1:
/* Enable write access, clear bit GPIO0. */
clrbits_be32(&gpio0->or, CONFIG_SYS_GPIO_EEPROM_WP);
state = 0;
break;
case 0:
/* Disable write access, set bit GPIO0. */
setbits_be32(&gpio0->or, CONFIG_SYS_GPIO_EEPROM_WP);
state = 0;
break;
default:
/* Read current status back. */
state = (0 == (in_be32(&gpio0->or) &
CONFIG_SYS_GPIO_EEPROM_WP));
break;
}
}
return state;
}
int do_eep_wren(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int query = argc == 1;
int state = 0;
if (query) {
/* Query write access state. */
state = eeprom_write_enable(CONFIG_SYS_I2C_EEPROM_ADDR, - 1);
if (state < 0) {
puts("Query of write access state failed.\n");
} else {
printf("Write access for device 0x%0x is %sabled.\n",
CONFIG_SYS_I2C_EEPROM_ADDR,
state ? "en" : "dis");
state = 0;
}
} else {
if ('0' == argv[1][0]) {
/* Disable write access. */
state = eeprom_write_enable(
CONFIG_SYS_I2C_EEPROM_ADDR, 0);
} else {
/* Enable write access. */
state = eeprom_write_enable(
CONFIG_SYS_I2C_EEPROM_ADDR, 1);
}
if (state < 0)
puts ("Setup of write access state failed.\n");
}
return state;
}
U_BOOT_CMD(eepwren, 2, 0, do_eep_wren,
"Enable / disable / query EEPROM write access",
""
);
#endif /* #if defined(CONFIG_SYS_EEPROM_WREN) */
#if defined(CONFIG_PRAM)
#include <environment.h>
extern env_t *env_ptr;
int do_painit(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
u32 pram, nextbase, base;
char *v;
u32 param;
ulong *lptr;
v = getenv("pram");
if (v)
pram = simple_strtoul(v, NULL, 10);
else {
printf("Error: pram undefined. Please define pram in KiB\n");
return 1;
}
base = gd->bd->bi_memsize;
#if defined(CONFIG_LOGBUFFER)
base -= LOGBUFF_LEN + LOGBUFF_OVERHEAD;
#endif
/*
* gd->bd->bi_memsize == physical ram size - CONFIG_SYS_MM_TOP_HIDE
*/
param = base - (pram << 10);
printf("PARAM: @%08x\n", param);
debug("memsize=0x%08x, base=0x%08x\n", gd->bd->bi_memsize, base);
/* clear entire PA ram */
memset((void*)param, 0, (pram << 10));
/* reserve 4k for pointer field */
nextbase = base - 4096;
lptr = (ulong*)(base);
/*
* *(--lptr) = item_size;
* *(--lptr) = base - item_base = distance from field top;
*/
/* env is first (4k aligned) */
nextbase -= ((CONFIG_ENV_SIZE + 4096 - 1) & ~(4096 - 1));
memcpy((void*)nextbase, env_ptr, CONFIG_ENV_SIZE);
*(--lptr) = CONFIG_ENV_SIZE; /* size */
*(--lptr) = base - nextbase; /* offset | type=0 */
/* free section */
*(--lptr) = nextbase - param; /* size */
*(--lptr) = (base - param) | 126; /* offset | type=126 */
/* terminate pointer field */
*(--lptr) = crc32(0, (void*)(base - 0x10), 0x10);
*(--lptr) = 0; /* offset=0 -> terminator */
return 0;
}
U_BOOT_CMD(
painit, 1, 1, do_painit,
"prepare PciAccess system",
""
);
#endif /* CONFIG_PRAM */
int do_selfreset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
struct ppc4xx_gpio *gpio0 = (struct ppc4xx_gpio *)GPIO_BASE;
setbits_be32(&gpio0->tcr, CONFIG_SYS_GPIO_SELFRST_N);
return 0;
}
U_BOOT_CMD(
selfreset, 1, 1, do_selfreset,
"assert self-reset# signal",
""
);
int do_resetout(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
struct pmc405de_cpld *cpld =
(struct pmc405de_cpld *)CONFIG_SYS_CPLD_BASE;
if (argc > 1) {
if (argv[1][0] == '0') {
/* assert */
printf("PMC-RESETOUT# asserted\n");
out_8(&cpld->control,
CPLD_CONTROL_RESETOUT_N_GATE);
} else {
/* deassert */
printf("PMC-RESETOUT# deasserted\n");
out_8(&cpld->control,
CPLD_CONTROL_RESETOUT_N |
CPLD_CONTROL_RESETOUT_N_GATE);
}
} else {
printf("PMC-RESETOUT# is %s\n",
(in_8(&cpld->control) & CPLD_CONTROL_RESETOUT_N) ?
"inactive" : "active");
}
return 0;
}
U_BOOT_CMD(
resetout, 2, 1, do_resetout,
"assert PMC-RESETOUT# signal",
""
);