Commit 7fb3e7a2 authored by Andre Schwarz's avatar Andre Schwarz Committed by Kim Phillips

mpc83xx: Add support for MergerBox board

Includes board config file, documentation, maintainer and boards.cfg
entries, and board specific files in vendor dir.
Signed-off-by: default avatarAndre Schwarz <andre.schwarz@matrix-vision.de>
Signed-off-by: default avatarKim Phillips <kim.phillips@freescale.com>
parent 03c0a924
......@@ -451,6 +451,7 @@ Peter De Schrijver <p2@mind.be>
Andre Schwarz <andre.schwarz@matrix-vision.de>
mergerbox MPC8377
mvbc_p MPC5200
mvblm7 MPC8343
mvsmr MPC5200
......
#
# (C) Copyright 2006
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# 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 $(TOPDIR)/config.mk
LIB = $(obj)lib$(BOARD).o
COBJS-y += $(BOARD).o pci.o fpga.o sm107.o
COBJS := $(COBJS-y)
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
SOBJS := $(addprefix $(obj),$(SOBJS))
$(LIB): $(obj).depend $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)
clean:
rm -f $(SOBJS) $(OBJS)
distclean: clean
rm -f $(LIB) core *.bak $(obj).depend
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################
/*
* (C) Copyright 2002
* Rich Ireland, Enterasys Networks, rireland@enterasys.com.
* Keith Outwater, keith_outwater@mvis.com.
*
* (C) Copyright 2011
* Andre Schwarz, Matrix Vision GmbH, andre.schwarz@matrix-vision.de
*
* 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 <ACEX1K.h>
#include <command.h>
#include "mergerbox.h"
#include "fpga.h"
Altera_CYC2_Passive_Serial_fns altera_fns = {
fpga_null_fn,
fpga_config_fn,
fpga_status_fn,
fpga_done_fn,
fpga_wr_fn,
fpga_null_fn,
fpga_null_fn,
};
Altera_desc cyclone2 = {
Altera_CYC2,
passive_serial,
Altera_EP2C20_SIZE,
(void *) &altera_fns,
NULL,
0
};
DECLARE_GLOBAL_DATA_PTR;
int mergerbox_init_fpga(void)
{
debug("Initialize FPGA interface\n");
fpga_init();
fpga_add(fpga_altera, &cyclone2);
return 1;
}
int fpga_null_fn(int cookie)
{
return 0;
}
int fpga_config_fn(int assert, int flush, int cookie)
{
volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
volatile gpio83xx_t *gpio = (gpio83xx_t *)&im->gpio[0];
u32 dvo = gpio->dat;
dvo &= ~FPGA_CONFIG;
gpio->dat = dvo;
udelay(5);
dvo |= FPGA_CONFIG;
gpio->dat = dvo;
return assert;
}
int fpga_done_fn(int cookie)
{
volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
volatile gpio83xx_t *gpio = (gpio83xx_t *)&im->gpio[0];
int result = 0;
udelay(10);
debug("CONF_DONE check ... ");
if (gpio->dat & FPGA_CONF_DONE) {
debug("high\n");
result = 1;
} else
debug("low\n");
return result;
}
int fpga_status_fn(int cookie)
{
volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
volatile gpio83xx_t *gpio = (gpio83xx_t *)&im->gpio[0];
int result = 0;
debug("STATUS check ... ");
if (gpio->dat & FPGA_STATUS) {
debug("high\n");
result = 1;
} else
debug("low\n");
return result;
}
int fpga_clk_fn(int assert_clk, int flush, int cookie)
{
volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
volatile gpio83xx_t *gpio = (gpio83xx_t *)&im->gpio[0];
u32 dvo = gpio->dat;
debug("CLOCK %s\n", assert_clk ? "high" : "low");
if (assert_clk)
dvo |= FPGA_CCLK;
else
dvo &= ~FPGA_CCLK;
if (flush)
gpio->dat = dvo;
return assert_clk;
}
static inline int _write_fpga(u8 val, int dump)
{
volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
volatile gpio83xx_t *gpio = (gpio83xx_t *)&im->gpio[0];
int i;
u32 dvo = gpio->dat;
if (dump)
debug(" %02x -> ", val);
for (i = 0; i < 8; i++) {
dvo &= ~FPGA_CCLK;
gpio->dat = dvo;
dvo &= ~FPGA_DIN;
if (dump)
debug("%d ", val&1);
if (val & 1)
dvo |= FPGA_DIN;
gpio->dat = dvo;
dvo |= FPGA_CCLK;
gpio->dat = dvo;
val >>= 1;
}
if (dump)
debug("\n");
return 0;
}
int fpga_wr_fn(void *buf, size_t len, int flush, int cookie)
{
unsigned char *data = (unsigned char *) buf;
int i;
debug("fpga_wr: buf %p / size %d\n", buf, len);
for (i = 0; i < len; i++)
_write_fpga(data[i], 0);
debug("\n");
return FPGA_SUCCESS;
}
/*
* 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
*
*/
extern int mergerbox_init_fpga(void);
extern int fpga_pgm_fn(int assert_pgm, int flush, int cookie);
extern int fpga_status_fn(int cookie);
extern int fpga_config_fn(int assert, int flush, int cookie);
extern int fpga_done_fn(int cookie);
extern int fpga_clk_fn(int assert_clk, int flush, int cookie);
extern int fpga_wr_fn(void *buf, size_t len, int flush, int cookie);
extern int fpga_null_fn(int cookie);
/*
* Copyright (C) 2007 Freescale Semiconductor, Inc.
*
* Copyright (C) 2011 Matrix Vision GmbH
* Andre Schwarz <andre.schwarz@matrix-vision.de>
*
* 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.
*/
#include <common.h>
#include <hwconfig.h>
#include <i2c.h>
#include <spi.h>
#include <asm/io.h>
#include <asm/fsl_mpc83xx_serdes.h>
#include <fdt_support.h>
#include <spd_sdram.h>
#include "mergerbox.h"
#include "fpga.h"
#include "../common/mv_common.h"
static void setup_serdes(void)
{
fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_SATA,
FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V);
fsl_setup_serdes(CONFIG_FSL_SERDES2, FSL_SERDES_PROTO_PEX,
FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V);
}
#if defined(CONFIG_SYS_DRAM_TEST)
int testdram(void)
{
uint *pstart = (uint *) CONFIG_SYS_MEMTEST_START;
uint *pend = (uint *) CONFIG_SYS_MEMTEST_END;
uint *p;
printf("Testing DRAM from 0x%08x to 0x%08x\n",
CONFIG_SYS_MEMTEST_START, CONFIG_SYS_MEMTEST_END);
printf("DRAM test phase 1:\n");
for (p = pstart; p < pend; p++)
*p = 0xaaaaaaaa;
for (p = pstart; p < pend; p++) {
if (*p != 0xaaaaaaaa) {
printf("DRAM test fails at: %08x\n", (uint) p);
return 1;
}
}
printf("DRAM test phase 2:\n");
for (p = pstart; p < pend; p++)
*p = 0x55555555;
for (p = pstart; p < pend; p++) {
if (*p != 0x55555555) {
printf("DRAM test fails at: %08x\n", (uint) p);
return 1;
}
}
printf("DRAM test passed.\n");
return 0;
}
#endif
phys_size_t initdram(int board_type)
{
u32 msize;
volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
volatile clk83xx_t *clk = (clk83xx_t *)&immr->clk;
/* Enable PCI_CLK[0:1] */
clk->occr |= 0xc0000000;
udelay(2000);
#if defined(CONFIG_SPD_EEPROM)
msize = spd_sdram();
#else
immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
u32 msize_log2;
msize = CONFIG_SYS_DDR_SIZE;
msize_log2 = __ilog2(msize);
im->sysconf.ddrlaw[0].bar = CONFIG_SYS_DDR_SDRAM_BASE & 0xfffff000;
im->sysconf.ddrlaw[0].ar = LBLAWAR_EN | (msize_log2 - 1);
im->sysconf.ddrcdr = CONFIG_SYS_DDRCDR_VALUE;
udelay(50000);
im->ddr.sdram_clk_cntl = CONFIG_SYS_DDR_SDRAM_CLK_CNTL;
udelay(1000);
im->ddr.csbnds[0].csbnds = CONFIG_SYS_DDR_CS0_BNDS;
im->ddr.cs_config[0] = CONFIG_SYS_DDR_CS0_CONFIG;
udelay(1000);
im->ddr.timing_cfg_0 = CONFIG_SYS_DDR_TIMING_0;
im->ddr.timing_cfg_1 = CONFIG_SYS_DDR_TIMING_1;
im->ddr.timing_cfg_2 = CONFIG_SYS_DDR_TIMING_2;
im->ddr.timing_cfg_3 = CONFIG_SYS_DDR_TIMING_3;
im->ddr.sdram_cfg = CONFIG_SYS_DDR_SDRAM_CFG;
im->ddr.sdram_cfg2 = CONFIG_SYS_DDR_SDRAM_CFG2;
im->ddr.sdram_mode = CONFIG_SYS_DDR_MODE;
im->ddr.sdram_mode2 = CONFIG_SYS_DDR_MODE2;
im->ddr.sdram_interval = CONFIG_SYS_DDR_INTERVAL;
__asm__ __volatile__("sync");
udelay(1000);
im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN;
udelay(2000);
#endif
setup_serdes();
return msize << 20;
}
int checkboard(void)
{
puts("Board: Matrix Vision MergerBox\n");
return 0;
}
int misc_init_r(void)
{
u16 dim;
int result;
volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
volatile gpio83xx_t *gpio = (gpio83xx_t *)&immr->gpio[1];
unsigned char mac[6], mac_verify[6];
char *s = getenv("reset_env");
for (dim = 10; dim < 180; dim += 5) {
mergerbox_tft_dim(dim);
udelay(100000);
}
if (s)
mv_reset_environment();
i2c_read(SPD_EEPROM_ADDRESS, 0x80, 2, mac, sizeof(mac));
/* check if Matrix Vision prefix present and export to env */
if (mac[0] == 0x00 && mac[1] == 0x0c && mac[2] == 0x8d) {
printf("valid MAC found in eeprom: %pM\n", mac);
eth_setenv_enetaddr("ethaddr", mac);
} else {
printf("no valid MAC found in eeprom.\n");
/* no: check the env */
if (!eth_getenv_enetaddr("ethaddr", mac)) {
printf("no valid MAC found in env either.\n");
/* TODO: ask for valid MAC */
} else {
printf("valid MAC found in env: %pM\n", mac);
printf("updating MAC in eeprom.\n");
do {
result = test_and_clear_bit(20, &gpio->dat);
if (result)
printf("unprotect EEPROM failed !\n");
udelay(20000);
} while(result);
i2c_write(SPD_EEPROM_ADDRESS, 0x80, 2, mac, 6);
udelay(20000);
do {
result = test_and_set_bit(20, &gpio->dat);
if (result)
printf("protect EEPROM failed !\n");
udelay(20000);
} while(result);
printf("verify MAC %pM ... ", mac);
i2c_read(SPD_EEPROM_ADDRESS, 0x80, 2, mac_verify, 6);
if (!strncmp((char *)mac, (char *)mac_verify, 6))
printf("ok.\n");
else
/* TODO: retry or do something useful */
printf("FAILED (got %pM) !\n", mac_verify);
}
}
return 0;
}
int spi_cs_is_valid(unsigned int bus, unsigned int cs)
{
return bus == 0 && cs == 0;
}
void spi_cs_activate(struct spi_slave *slave)
{
volatile gpio83xx_t *iopd = &((immap_t *)CONFIG_SYS_IMMR)->gpio[0];
iopd->dat &= ~TFT_SPI_CPLD_CS;
}
void spi_cs_deactivate(struct spi_slave *slave)
{
volatile gpio83xx_t *iopd = &((immap_t *)CONFIG_SYS_IMMR)->gpio[0];
iopd->dat |= TFT_SPI_CPLD_CS;
}
/* control backlight pwm (display brightness).
* allow values 0-250 with 0 = turn off and 250 = max brightness
*/
void mergerbox_tft_dim(u16 value)
{
struct spi_slave *slave;
u16 din;
u16 dout = 0;
if (value > 0 && value < 250)
dout = 0x4000 | value;
slave = spi_setup_slave(0, 0, 1000000, SPI_MODE_0 | SPI_CS_HIGH);
spi_claim_bus(slave);
spi_xfer(slave, 16, &dout, &din, SPI_XFER_BEGIN | SPI_XFER_END);
spi_release_bus(slave);
spi_free_slave(slave);
}
void ft_board_setup(void *blob, bd_t *bd)
{
ft_cpu_setup(blob, bd);
fdt_fixup_dr_usb(blob, bd);
ft_pci_setup(blob, bd);
}
/*
* Copyright (C) 2011 Matrix Vision GmbH
* Andre Schwarz <andre.schwarz@matrix-vision.de>
*
* 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.
*/
#ifndef __MERGERBOX_H__
#define __MERGERBOX_H__
#define MV_GPIO
/*
* GPIO Bank 1
*/
#define TFT_SPI_EN (0x80000000>>0)
#define FPGA_CONFIG (0x80000000>>1)
#define FPGA_STATUS (0x80000000>>2)
#define FPGA_CONF_DONE (0x80000000>>3)
#define FPGA_DIN (0x80000000>>4)
#define FPGA_CCLK (0x80000000>>5)
#define MAN_RST (0x80000000>>6)
#define FPGA_SYS_RST (0x80000000>>7)
#define WD_WDI (0x80000000>>8)
#define TFT_RST (0x80000000>>9)
#define HISCON_GPIO1 (0x80000000>>10)
#define HISCON_GPIO2 (0x80000000>>11)
#define B2B_GPIO2 (0x80000000>>12)
#define CCU_GPIN (0x80000000>>13)
#define CCU_GPOUT (0x80000000>>14)
#define TFT_GPIO0 (0x80000000>>15)
#define TFT_GPIO1 (0x80000000>>16)
#define TFT_GPIO2 (0x80000000>>17)
#define TFT_GPIO3 (0x80000000>>18)
#define B2B_GPIO0 (0x80000000>>19)
#define B2B_GPIO1 (0x80000000>>20)
#define TFT_SPI_CPLD_CS (0x80000000>>21)
#define TFT_SPI_CS (0x80000000>>22)
#define CCU_PWR_EN (0x80000000>>23)
#define B2B_GPIO3 (0x80000000>>24)
#define CCU_PWR_STAT (0x80000000>>25)
#define MV_GPIO1_DAT (FPGA_CONFIG|CCU_PWR_EN|TFT_SPI_CPLD_CS)
#define MV_GPIO1_OUT (TFT_SPI_EN|FPGA_CONFIG|FPGA_DIN|FPGA_CCLK|CCU_PWR_EN| \
TFT_SPI_CPLD_CS)
#define MV_GPIO1_ODE (FPGA_CONFIG|MAN_RST)
/*
* GPIO Bank 2
*/
#define SPI_FLASH_WP (0x80000000>>10)
#define SYS_EEPROM_WP (0x80000000>>11)
#define SPI_FLASH_CS (0x80000000>>22)
#define MV_GPIO2_DAT (SYS_EEPROM_WP|SPI_FLASH_CS)
#define MV_GPIO2_OUT (SPI_FLASH_WP|SYS_EEPROM_WP|SPI_FLASH_CS)
#define MV_GPIO2_ODE 0
void mergerbox_tft_dim(u16 value);
#endif
/*
* Copyright (C) 2006-2009 Freescale Semiconductor, Inc.
*
* Copyright (C) 2011 Matrix Vision GmbH
* Andre Schwarz <andre.schwarz@matrix-vision.de>
*
* 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.
*/
#include <common.h>
#include <mpc83xx.h>
#include <pci.h>
#include <asm/io.h>
#include <asm/fsl_mpc83xx_serdes.h>
#include "mergerbox.h"
#include "fpga.h"
#include "../common/mv_common.h"
static struct pci_region pci_regions[] = {
{
.bus_start = CONFIG_SYS_PCI_MEM_BASE,
.phys_start = CONFIG_SYS_PCI_MEM_PHYS,
.size = CONFIG_SYS_PCI_MEM_SIZE,
.flags = PCI_REGION_MEM | PCI_REGION_PREFETCH
},
{
.bus_start = CONFIG_SYS_PCI_MMIO_BASE,
.phys_start = CONFIG_SYS_PCI_MMIO_PHYS,
.size = CONFIG_SYS_PCI_MMIO_SIZE,
.flags = PCI_REGION_MEM
},
{
.bus_start = CONFIG_SYS_PCI_IO_BASE,
.phys_start = CONFIG_SYS_PCI_IO_PHYS,
.size = CONFIG_SYS_PCI_IO_SIZE,
.flags = PCI_REGION_IO
}
};
static struct pci_region pcie_regions_0[] = {
{
.bus_start = CONFIG_SYS_PCIE1_MEM_BASE,
.phys_start = CONFIG_SYS_PCIE1_MEM_PHYS,
.size = CONFIG_SYS_PCIE1_MEM_SIZE,
.flags = PCI_REGION_MEM,
},
{
.bus_start = CONFIG_SYS_PCIE1_IO_BASE,
.phys_start = CONFIG_SYS_PCIE1_IO_PHYS,
.size = CONFIG_SYS_PCIE1_IO_SIZE,
.flags = PCI_REGION_IO,
},
};
static struct pci_region pcie_regions_1[] = {
{
.bus_start = CONFIG_SYS_PCIE2_MEM_BASE,
.phys_start = CONFIG_SYS_PCIE2_MEM_PHYS,
.size = CONFIG_SYS_PCIE2_MEM_SIZE,
.flags = PCI_REGION_MEM,
},
{
.bus_start = CONFIG_SYS_PCIE2_IO_BASE,
.phys_start = CONFIG_SYS_PCIE2_IO_PHYS,
.size = CONFIG_SYS_PCIE2_IO_SIZE,
.flags = PCI_REGION_IO,
},
};
void pci_init_board(void)
{
volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
volatile sysconf83xx_t *sysconf = &immr->sysconf;
volatile clk83xx_t *clk = (clk83xx_t *)&immr->clk;
volatile law83xx_t *pci_law = immr->sysconf.pcilaw;
volatile law83xx_t *pcie_law = sysconf->pcielaw;
struct pci_region *reg[] = { pci_regions };
struct pci_region *pcie_reg[] = { pcie_regions_0, pcie_regions_1, };
volatile gpio83xx_t *gpio;
gpio = (gpio83xx_t *)&immr->gpio[0];
gpio->dat = MV_GPIO1_DAT;
gpio->odr = MV_GPIO1_ODE;
gpio->dir = MV_GPIO1_OUT;
gpio = (gpio83xx_t *)&immr->gpio[1];
gpio->dat = MV_GPIO2_DAT;
gpio->odr = MV_GPIO2_ODE;
gpio->dir = MV_GPIO2_OUT;
printf("SICRH / SICRL : 0x%08x / 0x%08x\n", immr->sysconf.sicrh,
immr->sysconf.sicrl);
/* Enable PCI_CLK[0:1] */
clk->occr |= 0xc0000000;
udelay(2000);
mergerbox_init_fpga();
mv_load_fpga();
mergerbox_tft_dim(0);
/* Configure PCI Local Access Windows */
pci_law[0].bar = CONFIG_SYS_PCI_MEM_PHYS & LAWBAR_BAR;
pci_law[0].ar = LBLAWAR_EN | LBLAWAR_512MB;
pci_law[1].bar = CONFIG_SYS_PCI_IO_PHYS & LAWBAR_BAR;
pci_law[1].ar = LBLAWAR_EN | LBLAWAR_1MB;
udelay(2000);
mpc83xx_pci_init(1, reg);
/* Deassert the resets in the control register */
out_be32(&sysconf->pecr1, 0xE0008000);
out_be32(&sysconf->pecr2, 0xE0008000);
udelay(2000);
out_be32(&pcie_law[0].bar, CONFIG_SYS_PCIE1_BASE & LAWBAR_BAR);
out_be32(&pcie_law[0].ar, LBLAWAR_EN | LBLAWAR_512MB);
out_be32(&pcie_law[1].bar, CONFIG_SYS_PCIE2_BASE & LAWBAR_BAR);
out_be32(&pcie_law[1].ar, LBLAWAR_EN | LBLAWAR_512MB);
mpc83xx_pcie_init(2, pcie_reg);
}