mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2025-04-21 12:27:27 +03:00
Delete old brcm63xx files
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@13210 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
@@ -1,9 +0,0 @@
|
||||
#
|
||||
# Makefile for the Broadcom BCM963xx SoC specific parts of the kernel
|
||||
#
|
||||
# Copyright (C) 2004 Broadcom Corporation
|
||||
#
|
||||
obj-y := irq.o prom.o setup.o time.o ser_init.o int-handler.o info.o wdt.o
|
||||
|
||||
SRCBASE := $(TOPDIR)
|
||||
EXTRA_CFLAGS += -I$(SRCBASE)/include
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2007 OpenWrt.org
|
||||
* Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org>
|
||||
* Copyright (C) 2007 Florian Fainelli <florian@openwrt.org>
|
||||
*
|
||||
* 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 <linux/types.h>
|
||||
#include <linux/autoconf.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/string.h>
|
||||
#include <asm/mach-bcm963xx/bootloaders.h>
|
||||
|
||||
static char *boot_loader_names[BOOT_LOADER_LAST+1] = {
|
||||
[BOOT_LOADER_UNKNOWN] = "Unknown",
|
||||
[BOOT_LOADER_CFE] = "CFE",
|
||||
[BOOT_LOADER_REDBOOT] = "RedBoot",
|
||||
[BOOT_LOADER_CFE2] = "CFEv2"
|
||||
};
|
||||
|
||||
/* boot loaders specific definitions */
|
||||
#define CFE_EPTSEAL 0x43464531 /* CFE1 is the magic number to recognize CFE from other bootloaders */
|
||||
|
||||
int boot_loader_type;
|
||||
/*
|
||||
* Boot loader detection routines
|
||||
*/
|
||||
static int __init detect_cfe(void)
|
||||
{
|
||||
/*
|
||||
* This method only works, when we are booted directly from the CFE.
|
||||
*/
|
||||
uint32_t cfe_handle = (uint32_t) fw_arg0;
|
||||
uint32_t cfe_a1_val = (uint32_t) fw_arg1;
|
||||
uint32_t cfe_entry = (uint32_t) fw_arg2;
|
||||
uint32_t cfe_seal = (uint32_t) fw_arg3;
|
||||
|
||||
/* Check for CFE by finding the CFE magic number */
|
||||
if (cfe_seal != CFE_EPTSEAL)
|
||||
/* We are not booted from CFE */
|
||||
return 0;
|
||||
|
||||
/* cfe_a1_val must be 0, because only one CPU present in the ADM5120 SoC */
|
||||
if (cfe_a1_val != 0)
|
||||
return 0;
|
||||
|
||||
/* The cfe_handle, and the cfe_entry must be kernel mode addresses */
|
||||
if ((cfe_handle < KSEG0) || (cfe_entry < KSEG0))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init detect_redboot(void)
|
||||
{
|
||||
/* On Inventel Livebox, the boot loader is passed as a command line argument, check for it */
|
||||
if (!strncmp(arcs_cmdline, "boot_loader=RedBoot", 19))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init detect_bootloader(void)
|
||||
{
|
||||
if (detect_cfe()) {
|
||||
boot_loader_type = BOOT_LOADER_CFE;
|
||||
}
|
||||
|
||||
if (detect_redboot()) {
|
||||
boot_loader_type = BOOT_LOADER_REDBOOT;
|
||||
}
|
||||
else {
|
||||
/* Some devices are using CFE, but it is not detected as is */
|
||||
boot_loader_type = BOOT_LOADER_CFE2;
|
||||
}
|
||||
printk("Boot loader is : %s\n", boot_loader_names[boot_loader_type]);
|
||||
}
|
||||
|
||||
void __init detect_board(void)
|
||||
{
|
||||
switch (boot_loader_type)
|
||||
{
|
||||
case BOOT_LOADER_CFE:
|
||||
break;
|
||||
case BOOT_LOADER_REDBOOT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(boot_loader_type);
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
<:copyright-gpl
|
||||
Copyright 2002 Broadcom Corp. All Rights Reserved.
|
||||
|
||||
This program is free software; you can distribute 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 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.
|
||||
:>
|
||||
*/
|
||||
/*
|
||||
* Generic interrupt handler for Broadcom MIPS boards
|
||||
*/
|
||||
|
||||
#include <linux/autoconf.h>
|
||||
|
||||
#include <asm/asm.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/regdef.h>
|
||||
#include <asm/stackframe.h>
|
||||
|
||||
/*
|
||||
* MIPS IRQ Source
|
||||
* -------- ------
|
||||
* 0 Software (ignored)
|
||||
* 1 Software (ignored)
|
||||
* 2 Combined hardware interrupt (hw0)
|
||||
* 3 Hardware
|
||||
* 4 Hardware
|
||||
* 5 Hardware
|
||||
* 6 Hardware
|
||||
* 7 R4k timer
|
||||
*/
|
||||
|
||||
.text
|
||||
.set noreorder
|
||||
.set noat
|
||||
.align 5
|
||||
NESTED(brcmIRQ, PT_SIZE, sp)
|
||||
SAVE_ALL
|
||||
CLI
|
||||
.set noreorder
|
||||
.set at
|
||||
|
||||
jal plat_irq_dispatch
|
||||
move a0, sp
|
||||
|
||||
j ret_from_irq
|
||||
nop
|
||||
|
||||
END(brcmIRQ)
|
||||
@@ -1,259 +0,0 @@
|
||||
/*
|
||||
<:copyright-gpl
|
||||
Copyright 2002 Broadcom Corp. All Rights Reserved.
|
||||
|
||||
This program is free software; you can distribute 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 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.
|
||||
:>
|
||||
*/
|
||||
/*
|
||||
* Interrupt control functions for Broadcom 963xx MIPS boards
|
||||
*/
|
||||
|
||||
#include <asm/atomic.h>
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/signal.h>
|
||||
#include <6348_map_part.h>
|
||||
#include <6348_intr.h>
|
||||
#include <bcm_map_part.h>
|
||||
#include <bcm_intr.h>
|
||||
|
||||
static void irq_dispatch_int(void)
|
||||
{
|
||||
unsigned int pendingIrqs;
|
||||
static unsigned int irqBit;
|
||||
static unsigned int isrNumber = 31;
|
||||
|
||||
pendingIrqs = PERF->IrqStatus & PERF->IrqMask;
|
||||
if (!pendingIrqs) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
irqBit <<= 1;
|
||||
isrNumber++;
|
||||
if (isrNumber == 32) {
|
||||
isrNumber = 0;
|
||||
irqBit = 0x1;
|
||||
}
|
||||
if (pendingIrqs & irqBit) {
|
||||
PERF->IrqMask &= ~irqBit; // mask
|
||||
do_IRQ(isrNumber + INTERNAL_ISR_TABLE_OFFSET);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void irq_dispatch_ext(uint32 irq)
|
||||
{
|
||||
if (!(PERF->ExtIrqCfg & (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)))) {
|
||||
printk("**** Ext IRQ mask. Should not dispatch ****\n");
|
||||
}
|
||||
/* disable and clear interrupt in the controller */
|
||||
PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT));
|
||||
PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT));
|
||||
do_IRQ(irq);
|
||||
}
|
||||
|
||||
|
||||
//extern void brcm_timer_interrupt(struct pt_regs *regs);
|
||||
|
||||
asmlinkage void plat_irq_dispatch(void)
|
||||
{
|
||||
unsigned long cause;
|
||||
|
||||
cause = read_c0_status() & read_c0_cause() & ST0_IM;
|
||||
if (cause & CAUSEF_IP7)
|
||||
do_IRQ(7);
|
||||
else if (cause & CAUSEF_IP2)
|
||||
irq_dispatch_int();
|
||||
else if (cause & CAUSEF_IP3)
|
||||
irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_0);
|
||||
else if (cause & CAUSEF_IP4)
|
||||
irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_1);
|
||||
else if (cause & CAUSEF_IP5)
|
||||
irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_2);
|
||||
else if (cause & CAUSEF_IP6) {
|
||||
irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_3);
|
||||
local_irq_disable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void enable_brcm_irq(unsigned int irq)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
if( irq >= INTERNAL_ISR_TABLE_OFFSET ) {
|
||||
PERF->IrqMask |= (1 << (irq - INTERNAL_ISR_TABLE_OFFSET));
|
||||
}
|
||||
else if (irq >= INTERRUPT_ID_EXTERNAL_0 && irq <= INTERRUPT_ID_EXTERNAL_3) {
|
||||
/* enable and clear interrupt in the controller */
|
||||
PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT));
|
||||
PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT));
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
void disable_brcm_irq(unsigned int irq)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
if( irq >= INTERNAL_ISR_TABLE_OFFSET ) {
|
||||
PERF->IrqMask &= ~(1 << (irq - INTERNAL_ISR_TABLE_OFFSET));
|
||||
}
|
||||
else if (irq >= INTERRUPT_ID_EXTERNAL_0 && irq <= INTERRUPT_ID_EXTERNAL_3) {
|
||||
/* disable interrupt in the controller */
|
||||
PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT));
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
void ack_brcm_irq(unsigned int irq)
|
||||
{
|
||||
/* Already done in brcm_irq_dispatch */
|
||||
}
|
||||
|
||||
unsigned int startup_brcm_irq(unsigned int irq)
|
||||
{
|
||||
enable_brcm_irq(irq);
|
||||
|
||||
return 0; /* never anything pending */
|
||||
}
|
||||
|
||||
unsigned int startup_brcm_none(unsigned int irq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void end_brcm_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
|
||||
enable_brcm_irq(irq);
|
||||
}
|
||||
|
||||
void end_brcm_none(unsigned int irq)
|
||||
{
|
||||
}
|
||||
|
||||
static struct hw_interrupt_type brcm_irq_type = {
|
||||
.typename = "MIPS",
|
||||
.startup = startup_brcm_irq,
|
||||
.shutdown = disable_brcm_irq,
|
||||
.enable = enable_brcm_irq,
|
||||
.disable = disable_brcm_irq,
|
||||
.ack = ack_brcm_irq,
|
||||
.end = end_brcm_irq,
|
||||
.set_affinity = NULL
|
||||
};
|
||||
|
||||
static struct hw_interrupt_type brcm_irq_no_end_type = {
|
||||
.typename = "MIPS",
|
||||
.startup = startup_brcm_none,
|
||||
.shutdown = disable_brcm_irq,
|
||||
.enable = enable_brcm_irq,
|
||||
.disable = disable_brcm_irq,
|
||||
.ack = ack_brcm_irq,
|
||||
.end = end_brcm_none,
|
||||
.set_affinity = NULL
|
||||
};
|
||||
|
||||
void __init arch_init_irq(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
clear_c0_status(ST0_BEV);
|
||||
change_c0_status(ST0_IM, (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4));
|
||||
|
||||
for (i = 0; i < NR_IRQS; i++) {
|
||||
irq_desc[i].status = IRQ_DISABLED;
|
||||
irq_desc[i].action = 0;
|
||||
irq_desc[i].depth = 1;
|
||||
irq_desc[i].chip = &brcm_irq_type;
|
||||
}
|
||||
}
|
||||
|
||||
int request_external_irq(unsigned int irq,
|
||||
FN_HANDLER handler,
|
||||
unsigned long irqflags,
|
||||
const char * devname,
|
||||
void *dev_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT)); // Clear
|
||||
PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)); // Mask
|
||||
PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_INSENS_SHFT)); // Edge insesnsitive
|
||||
PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_LEVEL_SHFT)); // Level triggered
|
||||
PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_SENSE_SHFT)); // Low level
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
return( request_irq(irq, handler, irqflags, devname, dev_id) );
|
||||
}
|
||||
|
||||
/* VxWorks compatibility function(s). */
|
||||
|
||||
unsigned int BcmHalMapInterrupt(FN_HANDLER pfunc, unsigned int param,
|
||||
unsigned int interruptId)
|
||||
{
|
||||
int nRet = -1;
|
||||
char *devname;
|
||||
|
||||
devname = kmalloc(16, GFP_KERNEL);
|
||||
if (devname)
|
||||
sprintf( devname, "brcm_%d", interruptId );
|
||||
|
||||
/* Set the IRQ description to not automatically enable the interrupt at
|
||||
* the end of an ISR. The driver that handles the interrupt must
|
||||
* explicitly call BcmHalInterruptEnable or enable_brcm_irq. This behavior
|
||||
* is consistent with interrupt handling on VxWorks.
|
||||
*/
|
||||
irq_desc[interruptId].chip = &brcm_irq_no_end_type;
|
||||
|
||||
if( interruptId >= INTERNAL_ISR_TABLE_OFFSET )
|
||||
{
|
||||
printk("BcmHalMapInterrupt : internal IRQ\n");
|
||||
nRet = request_irq( interruptId, pfunc, IRQF_DISABLED, devname, (void *) param );
|
||||
}
|
||||
else if (interruptId >= INTERRUPT_ID_EXTERNAL_0 && interruptId <= INTERRUPT_ID_EXTERNAL_3)
|
||||
{
|
||||
printk("BcmHalMapInterrupt : external IRQ\n");
|
||||
nRet = request_external_irq( interruptId, pfunc, IRQF_DISABLED, devname, (void *) param );
|
||||
}
|
||||
|
||||
return( nRet );
|
||||
}
|
||||
|
||||
|
||||
EXPORT_SYMBOL(enable_brcm_irq);
|
||||
EXPORT_SYMBOL(disable_brcm_irq);
|
||||
EXPORT_SYMBOL(request_external_irq);
|
||||
EXPORT_SYMBOL(BcmHalMapInterrupt);
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
Copyright 2004 Broadcom Corp. All Rights Reserved.
|
||||
Copyright 2007 OpenWrt,org, Florian Fainelli <florian@openwrt.org>
|
||||
|
||||
This program is free software; you can distribute 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 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.
|
||||
*/
|
||||
/*
|
||||
* prom.c: PROM library initialization code.
|
||||
*
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/blkdev.h>
|
||||
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/mach-bcm963xx/bootloaders.h>
|
||||
#include <asm/mach-bcm963xx/6348_map_part.h>
|
||||
|
||||
#include "../cfe/cfe_private.h"
|
||||
|
||||
extern void __init detect_bootloader(void);
|
||||
extern void serial_init(void);
|
||||
extern int boot_loader_type;
|
||||
|
||||
#define MACH_BCM MACH_BCM96348
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
return "Broadcom BCM963xx";
|
||||
}
|
||||
|
||||
void __init prom_init(void)
|
||||
{
|
||||
serial_init();
|
||||
|
||||
printk("%s prom init\n", get_system_type() );
|
||||
|
||||
PERF->IrqMask = 0;
|
||||
|
||||
/* Detect the bootloader */
|
||||
detect_bootloader();
|
||||
|
||||
/* Register 16MB RAM minus the ADSL SDRAM by default */
|
||||
add_memory_region(0, (0x01000000 - ADSL_SDRAM_IMAGE_SIZE), BOOT_MEM_RAM);
|
||||
|
||||
}
|
||||
|
||||
void __init prom_free_prom_memory(void)
|
||||
{
|
||||
/* We do not have any memory to free */
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
/*
|
||||
<:copyright-gpl
|
||||
Copyright 2004 Broadcom Corp. All Rights Reserved.
|
||||
|
||||
This program is free software; you can distribute 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 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.
|
||||
:>
|
||||
*/
|
||||
/*
|
||||
* Broadcom bcm63xx serial port initialization, also prepare for printk
|
||||
* by registering with console_init
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/autoconf.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/gdb-stub.h>
|
||||
#include <asm/mc146818rtc.h>
|
||||
|
||||
#include <bcm_map_part.h>
|
||||
#include <6348_map_part.h>
|
||||
#include <board.h>
|
||||
|
||||
#define SER63XX_DEFAULT_BAUD 115200
|
||||
#define BD_BCM63XX_TIMER_CLOCK_INPUT (FPERIPH)
|
||||
#define stUart ((volatile Uart * const) UART_BASE)
|
||||
|
||||
// Transmit interrupts
|
||||
#define TXINT (TXFIFOEMT | TXUNDERR | TXOVFERR)
|
||||
// Receive interrupts
|
||||
#define RXINT (RXFIFONE | RXOVFERR)
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Name: serial_init
|
||||
Purpose: Initalize the UART
|
||||
-------------------------------------------------------------------------- */
|
||||
void __init serial_init(void)
|
||||
{
|
||||
u32 tmpVal = SER63XX_DEFAULT_BAUD;
|
||||
ULONG clockFreqHz;
|
||||
|
||||
#if defined(CONFIG_BCM96345)
|
||||
// Make sure clock is ticking
|
||||
PERF->blkEnables |= UART_CLK_EN;
|
||||
#endif
|
||||
|
||||
/* Dissable channel's receiver and transmitter. */
|
||||
stUart->control &= ~(BRGEN|TXEN|RXEN);
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
/* Write the table value to the clock select register. */
|
||||
/* DPullen - this is the equation to use: */
|
||||
/* value = clockFreqHz / baud / 32-1; */
|
||||
/* (snmod) Actually you should also take into account any necessary */
|
||||
/* rounding. Divide by 16, look at lsb, if 0, divide by 2 */
|
||||
/* and subtract 1. If 1, just divide by 2 */
|
||||
/*--------------------------------------------------------------------*/
|
||||
clockFreqHz = BD_BCM63XX_TIMER_CLOCK_INPUT;
|
||||
tmpVal = (clockFreqHz / tmpVal) / 16;
|
||||
if( tmpVal & 0x01 )
|
||||
tmpVal /= 2; //Rounding up, so sub is already accounted for
|
||||
else
|
||||
tmpVal = (tmpVal / 2) - 1; // Rounding down so we must sub 1
|
||||
stUart->baudword = tmpVal;
|
||||
|
||||
/* Finally, re-enable the transmitter and receiver. */
|
||||
stUart->control |= (BRGEN|TXEN|RXEN);
|
||||
|
||||
stUart->config = (BITS8SYM | ONESTOP);
|
||||
// Set the FIFO interrupt depth ... stUart->fifocfg = 0xAA;
|
||||
stUart->fifoctl = RSTTXFIFOS | RSTRXFIFOS;
|
||||
stUart->intMask = 0;
|
||||
stUart->intMask = RXINT | TXINT;
|
||||
}
|
||||
|
||||
|
||||
/* prom_putc()
|
||||
* Output a character to the UART
|
||||
*/
|
||||
void prom_putc(char c)
|
||||
{
|
||||
/* Wait for Tx uffer to empty */
|
||||
while (! (READ16(stUart->intStatus) & TXFIFOEMT));
|
||||
/* Send character */
|
||||
stUart->Data = c;
|
||||
}
|
||||
|
||||
/* prom_puts()
|
||||
* Write a string to the UART
|
||||
*/
|
||||
void prom_puts(const char *s)
|
||||
{
|
||||
while (*s) {
|
||||
if (*s == '\n') {
|
||||
prom_putc('\r');
|
||||
}
|
||||
prom_putc(*s++);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* prom_getc_nowait()
|
||||
* Returns a character from the UART
|
||||
* Returns -1 if no characters available or corrupted
|
||||
*/
|
||||
int prom_getc_nowait(void)
|
||||
{
|
||||
uint16 uStatus;
|
||||
int cData = -1;
|
||||
|
||||
uStatus = READ16(stUart->intStatus);
|
||||
|
||||
if (uStatus & RXFIFONE) { /* Do we have a character? */
|
||||
cData = READ16(stUart->Data) & 0xff; /* Read character */
|
||||
if (uStatus & (RXFRAMERR | RXPARERR)) { /* If we got an error, throw it away */
|
||||
cData = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return cData;
|
||||
}
|
||||
|
||||
/* prom_getc()
|
||||
* Returns a charcter from the serial port
|
||||
* Will block until it receives a valid character
|
||||
*/
|
||||
char prom_getc(void)
|
||||
{
|
||||
int cData = -1;
|
||||
|
||||
/* Loop until we get a valid character */
|
||||
while(cData == -1) {
|
||||
cData = prom_getc_nowait();
|
||||
}
|
||||
return (char) cData;
|
||||
}
|
||||
|
||||
/* prom_testc()
|
||||
* Returns 0 if no characters available
|
||||
*/
|
||||
int prom_testc(void)
|
||||
{
|
||||
uint16 uStatus;
|
||||
|
||||
uStatus = READ16(stUart->intStatus);
|
||||
|
||||
return (uStatus & RXFIFONE);
|
||||
}
|
||||
|
||||
#if defined (CONFIG_REMOTE_DEBUG)
|
||||
/* Prevent other code from writing to the serial port */
|
||||
void _putc(char c) { }
|
||||
void _puts(const char *ptr) { }
|
||||
#else
|
||||
/* Low level outputs call prom routines */
|
||||
void _putc(char c) {
|
||||
prom_putc(c);
|
||||
}
|
||||
void _puts(const char *ptr) {
|
||||
prom_puts(ptr);
|
||||
}
|
||||
#endif
|
||||
@@ -1,472 +0,0 @@
|
||||
/*
|
||||
<:copyright-gpl
|
||||
Copyright 2002 Broadcom Corp. All Rights Reserved.
|
||||
|
||||
This program is free software; you can distribute 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 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.
|
||||
:>
|
||||
*/
|
||||
/*
|
||||
* Generic setup routines for Broadcom 963xx MIPS boards
|
||||
*/
|
||||
|
||||
#include <linux/autoconf.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/bootmem.h>
|
||||
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/bcache.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/gdb-stub.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/mach-bcm963xx/bootloaders.h>
|
||||
|
||||
extern void brcm_time_init(void);
|
||||
extern int boot_loader_type;
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <bcm_map_part.h>
|
||||
#include <6348_map_part.h>
|
||||
#include <bcmpci.h>
|
||||
|
||||
static volatile MpiRegisters * mpi = (MpiRegisters *)(MPI_BASE);
|
||||
|
||||
/* This function should be in a board specific directory. For now,
|
||||
* assume that all boards that include this file use a Broadcom chip
|
||||
* with a soft reset bit in the PLL control register.
|
||||
*/
|
||||
static void brcm_machine_restart(char *command)
|
||||
{
|
||||
const unsigned long ulSoftReset = 0x00000001;
|
||||
unsigned long *pulPllCtrl = (unsigned long *) 0xfffe0008;
|
||||
*pulPllCtrl |= ulSoftReset;
|
||||
}
|
||||
|
||||
static void brcm_machine_halt(void)
|
||||
{
|
||||
printk("System halted\n");
|
||||
while (1);
|
||||
}
|
||||
|
||||
static void mpi_SetLocalPciConfigReg(uint32 reg, uint32 value)
|
||||
{
|
||||
/* write index then value */
|
||||
mpi->pcicfgcntrl = PCI_CFG_REG_WRITE_EN + reg;;
|
||||
mpi->pcicfgdata = value;
|
||||
}
|
||||
|
||||
static uint32 mpi_GetLocalPciConfigReg(uint32 reg)
|
||||
{
|
||||
/* write index then get value */
|
||||
mpi->pcicfgcntrl = PCI_CFG_REG_WRITE_EN + reg;;
|
||||
return mpi->pcicfgdata;
|
||||
}
|
||||
|
||||
/*
|
||||
* mpi_ResetPcCard: Set/Reset the PcCard
|
||||
*/
|
||||
static void mpi_ResetPcCard(int cardtype, BOOL bReset)
|
||||
{
|
||||
if (cardtype == MPI_CARDTYPE_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cardtype == MPI_CARDTYPE_CARDBUS) {
|
||||
bReset = ! bReset;
|
||||
}
|
||||
|
||||
if (bReset) {
|
||||
mpi->pcmcia_cntl1 = (mpi->pcmcia_cntl1 & ~PCCARD_CARD_RESET);
|
||||
} else {
|
||||
mpi->pcmcia_cntl1 = (mpi->pcmcia_cntl1 | PCCARD_CARD_RESET);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* mpi_ConfigCs: Configure an MPI/EBI chip select
|
||||
*/
|
||||
static void mpi_ConfigCs(uint32 cs, uint32 base, uint32 size, uint32 flags)
|
||||
{
|
||||
mpi->cs[cs].base = ((base & 0x1FFFFFFF) | size);
|
||||
mpi->cs[cs].config = flags;
|
||||
}
|
||||
|
||||
/*
|
||||
* mpi_InitPcmciaSpace
|
||||
*/
|
||||
static void mpi_InitPcmciaSpace(void)
|
||||
{
|
||||
// ChipSelect 4 controls PCMCIA Memory accesses
|
||||
mpi_ConfigCs(PCMCIA_COMMON_BASE, pcmciaMem, EBI_SIZE_1M, (EBI_WORD_WIDE|EBI_ENABLE));
|
||||
// ChipSelect 5 controls PCMCIA Attribute accesses
|
||||
mpi_ConfigCs(PCMCIA_ATTRIBUTE_BASE, pcmciaAttr, EBI_SIZE_1M, (EBI_WORD_WIDE|EBI_ENABLE));
|
||||
// ChipSelect 6 controls PCMCIA I/O accesses
|
||||
mpi_ConfigCs(PCMCIA_IO_BASE, pcmciaIo, EBI_SIZE_64K, (EBI_WORD_WIDE|EBI_ENABLE));
|
||||
|
||||
mpi->pcmcia_cntl2 = ((PCMCIA_ATTR_ACTIVE << RW_ACTIVE_CNT_BIT) |
|
||||
(PCMCIA_ATTR_INACTIVE << INACTIVE_CNT_BIT) |
|
||||
(PCMCIA_ATTR_CE_SETUP << CE_SETUP_CNT_BIT) |
|
||||
(PCMCIA_ATTR_CE_HOLD << CE_HOLD_CNT_BIT));
|
||||
|
||||
mpi->pcmcia_cntl2 |= (PCMCIA_HALFWORD_EN | PCMCIA_BYTESWAP_DIS);
|
||||
}
|
||||
|
||||
/*
|
||||
* cardtype_vcc_detect: PC Card's card detect and voltage sense connection
|
||||
*
|
||||
* CD1#/ CD2#/ VS1#/ VS2#/ Card Initial Vcc
|
||||
* CCD1# CCD2# CVS1 CVS2 Type
|
||||
*
|
||||
* GND GND open open 16-bit 5 vdc
|
||||
*
|
||||
* GND GND GND open 16-bit 3.3 vdc
|
||||
*
|
||||
* GND GND open GND 16-bit x.x vdc
|
||||
*
|
||||
* GND GND GND GND 16-bit 3.3 & x.x vdc
|
||||
*
|
||||
*====================================================================
|
||||
*
|
||||
* CVS1 GND CCD1# open CardBus 3.3 vdc
|
||||
*
|
||||
* GND CVS2 open CCD2# CardBus x.x vdc
|
||||
*
|
||||
* GND CVS1 CCD2# open CardBus y.y vdc
|
||||
*
|
||||
* GND CVS2 GND CCD2# CardBus 3.3 & x.x vdc
|
||||
*
|
||||
* CVS2 GND open CCD1# CardBus x.x & y.y vdc
|
||||
*
|
||||
* GND CVS1 CCD2# open CardBus 3.3, x.x & y.y vdc
|
||||
*
|
||||
*/
|
||||
static int cardtype_vcc_detect(void)
|
||||
{
|
||||
uint32 data32;
|
||||
int cardtype;
|
||||
|
||||
cardtype = MPI_CARDTYPE_NONE;
|
||||
mpi->pcmcia_cntl1 = 0x0000A000; // Turn on the output enables and drive
|
||||
// the CVS pins to 0.
|
||||
data32 = mpi->pcmcia_cntl1;
|
||||
switch (data32 & 0x00000003) // Test CD1# and CD2#, see if card is plugged in.
|
||||
{
|
||||
case 0x00000003: // No Card is in the slot.
|
||||
printk("mpi: No Card is in the PCMCIA slot\n");
|
||||
break;
|
||||
|
||||
case 0x00000002: // Partial insertion, No CD2#.
|
||||
printk("mpi: Card in the PCMCIA slot partial insertion, no CD2 signal\n");
|
||||
break;
|
||||
|
||||
case 0x00000001: // Partial insertion, No CD1#.
|
||||
printk("mpi: Card in the PCMCIA slot partial insertion, no CD1 signal\n");
|
||||
break;
|
||||
|
||||
case 0x00000000:
|
||||
mpi->pcmcia_cntl1 = 0x0000A0C0; // Turn off the CVS output enables and
|
||||
// float the CVS pins.
|
||||
mdelay(1);
|
||||
data32 = mpi->pcmcia_cntl1;
|
||||
// Read the Register.
|
||||
switch (data32 & 0x0000000C) // See what is on the CVS pins.
|
||||
{
|
||||
case 0x00000000: // CVS1 and CVS2 are tied to ground, only 1 option.
|
||||
printk("mpi: Detected 3.3 & x.x 16-bit PCMCIA card\n");
|
||||
cardtype = MPI_CARDTYPE_PCMCIA;
|
||||
break;
|
||||
|
||||
case 0x00000004: // CVS1 is open or tied to CCD1/CCD2 and CVS2 is tied to ground.
|
||||
// 2 valid voltage options.
|
||||
switch (data32 & 0x00000003) // Test the values of CCD1 and CCD2.
|
||||
{
|
||||
case 0x00000003: // CCD1 and CCD2 are tied to 1 of the CVS pins.
|
||||
// This is not a valid combination.
|
||||
printk("mpi: Unknown card plugged into slot\n");
|
||||
break;
|
||||
|
||||
case 0x00000002: // CCD2 is tied to either CVS1 or CVS2.
|
||||
mpi->pcmcia_cntl1 = 0x0000A080; // Drive CVS1 to a 0.
|
||||
mdelay(1);
|
||||
data32 = mpi->pcmcia_cntl1;
|
||||
if (data32 & 0x00000002) { // CCD2 is tied to CVS2, not valid.
|
||||
printk("mpi: Unknown card plugged into slot\n");
|
||||
} else { // CCD2 is tied to CVS1.
|
||||
printk("mpi: Detected 3.3, x.x and y.y Cardbus card\n");
|
||||
cardtype = MPI_CARDTYPE_CARDBUS;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x00000001: // CCD1 is tied to either CVS1 or CVS2.
|
||||
// This is not a valid combination.
|
||||
printk("mpi: Unknown card plugged into slot\n");
|
||||
break;
|
||||
|
||||
case 0x00000000: // CCD1 and CCD2 are tied to ground.
|
||||
printk("mpi: Detected x.x vdc 16-bit PCMCIA card\n");
|
||||
cardtype = MPI_CARDTYPE_PCMCIA;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x00000008: // CVS2 is open or tied to CCD1/CCD2 and CVS1 is tied to ground.
|
||||
// 2 valid voltage options.
|
||||
switch (data32 & 0x00000003) // Test the values of CCD1 and CCD2.
|
||||
{
|
||||
case 0x00000003: // CCD1 and CCD2 are tied to 1 of the CVS pins.
|
||||
// This is not a valid combination.
|
||||
printk("mpi: Unknown card plugged into slot\n");
|
||||
break;
|
||||
|
||||
case 0x00000002: // CCD2 is tied to either CVS1 or CVS2.
|
||||
mpi->pcmcia_cntl1 = 0x0000A040; // Drive CVS2 to a 0.
|
||||
mdelay(1);
|
||||
data32 = mpi->pcmcia_cntl1;
|
||||
if (data32 & 0x00000002) { // CCD2 is tied to CVS1, not valid.
|
||||
printk("mpi: Unknown card plugged into slot\n");
|
||||
} else {// CCD2 is tied to CVS2.
|
||||
printk("mpi: Detected 3.3 and x.x Cardbus card\n");
|
||||
cardtype = MPI_CARDTYPE_CARDBUS;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x00000001: // CCD1 is tied to either CVS1 or CVS2.
|
||||
// This is not a valid combination.
|
||||
printk("mpi: Unknown card plugged into slot\n");
|
||||
break;
|
||||
|
||||
case 0x00000000: // CCD1 and CCD2 are tied to ground.
|
||||
cardtype = MPI_CARDTYPE_PCMCIA;
|
||||
printk("mpi: Detected 3.3 vdc 16-bit PCMCIA card\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0000000C: // CVS1 and CVS2 are open or tied to CCD1/CCD2.
|
||||
// 5 valid voltage options.
|
||||
|
||||
switch (data32 & 0x00000003) // Test the values of CCD1 and CCD2.
|
||||
{
|
||||
case 0x00000003: // CCD1 and CCD2 are tied to 1 of the CVS pins.
|
||||
// This is not a valid combination.
|
||||
printk("mpi: Unknown card plugged into slot\n");
|
||||
break;
|
||||
|
||||
case 0x00000002: // CCD2 is tied to either CVS1 or CVS2.
|
||||
// CCD1 is tied to ground.
|
||||
mpi->pcmcia_cntl1 = 0x0000A040; // Drive CVS2 to a 0.
|
||||
mdelay(1);
|
||||
data32 = mpi->pcmcia_cntl1;
|
||||
if (data32 & 0x00000002) { // CCD2 is tied to CVS1.
|
||||
printk("mpi: Detected y.y vdc Cardbus card\n");
|
||||
} else { // CCD2 is tied to CVS2.
|
||||
printk("mpi: Detected x.x vdc Cardbus card\n");
|
||||
}
|
||||
cardtype = MPI_CARDTYPE_CARDBUS;
|
||||
break;
|
||||
|
||||
case 0x00000001: // CCD1 is tied to either CVS1 or CVS2.
|
||||
// CCD2 is tied to ground.
|
||||
|
||||
mpi->pcmcia_cntl1 = 0x0000A040; // Drive CVS2 to a 0.
|
||||
mdelay(1);
|
||||
data32 = mpi->pcmcia_cntl1;
|
||||
if (data32 & 0x00000001) {// CCD1 is tied to CVS1.
|
||||
printk("mpi: Detected 3.3 vdc Cardbus card\n");
|
||||
} else { // CCD1 is tied to CVS2.
|
||||
printk("mpi: Detected x.x and y.y Cardbus card\n");
|
||||
}
|
||||
cardtype = MPI_CARDTYPE_CARDBUS;
|
||||
break;
|
||||
|
||||
case 0x00000000: // CCD1 and CCD2 are tied to ground.
|
||||
cardtype = MPI_CARDTYPE_PCMCIA;
|
||||
printk("mpi: Detected 5 vdc 16-bit PCMCIA card\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("mpi: Unknown card plugged into slot\n");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return cardtype;
|
||||
}
|
||||
|
||||
/*
|
||||
* mpi_DetectPcCard: Detect the plugged in PC-Card
|
||||
* Return: < 0 => Unknown card detected
|
||||
* 0 => No card detected
|
||||
* 1 => 16-bit card detected
|
||||
* 2 => 32-bit CardBus card detected
|
||||
*/
|
||||
static int mpi_DetectPcCard(void)
|
||||
{
|
||||
int cardtype;
|
||||
|
||||
cardtype = cardtype_vcc_detect();
|
||||
switch(cardtype) {
|
||||
case MPI_CARDTYPE_PCMCIA:
|
||||
mpi->pcmcia_cntl1 &= ~0x0000e000; // disable enable bits
|
||||
//mpi->pcmcia_cntl1 = (mpi->pcmcia_cntl1 & ~PCCARD_CARD_RESET);
|
||||
mpi->pcmcia_cntl1 |= (PCMCIA_ENABLE | PCMCIA_GPIO_ENABLE);
|
||||
mpi_InitPcmciaSpace();
|
||||
mpi_ResetPcCard(cardtype, FALSE);
|
||||
// Hold card in reset for 10ms
|
||||
mdelay(10);
|
||||
mpi_ResetPcCard(cardtype, TRUE);
|
||||
// Let card come out of reset
|
||||
mdelay(100);
|
||||
break;
|
||||
case MPI_CARDTYPE_CARDBUS:
|
||||
// 8 => CardBus Enable
|
||||
// 1 => PCI Slot Number
|
||||
// C => Float VS1 & VS2
|
||||
mpi->pcmcia_cntl1 = (mpi->pcmcia_cntl1 & 0xFFFF0000) |
|
||||
CARDBUS_ENABLE |
|
||||
(CARDBUS_SLOT << 8)|
|
||||
VS2_OEN |
|
||||
VS1_OEN;
|
||||
/* access to this memory window will be to/from CardBus */
|
||||
mpi->l2pmremap1 |= CARDBUS_MEM;
|
||||
|
||||
// Need to reset the Cardbus Card. There's no CardManager to do this,
|
||||
// and we need to be ready for PCI configuration.
|
||||
mpi_ResetPcCard(cardtype, FALSE);
|
||||
// Hold card in reset for 10ms
|
||||
mdelay(10);
|
||||
mpi_ResetPcCard(cardtype, TRUE);
|
||||
// Let card come out of reset
|
||||
mdelay(100);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return cardtype;
|
||||
}
|
||||
|
||||
static int mpi_init(void)
|
||||
{
|
||||
unsigned long data;
|
||||
unsigned int chipid, chiprev, sdramsize;
|
||||
|
||||
printk("Broadcom BCM963xx MPI\n");
|
||||
chipid = (PERF->RevID & 0xFFFF0000) >> 16;
|
||||
chiprev = (PERF->RevID & 0xFF);
|
||||
|
||||
if (boot_loader_type == BOOT_LOADER_CFE)
|
||||
sdramsize = boot_mem_map.map[0].size;
|
||||
else
|
||||
sdramsize = 0x01000000;
|
||||
/*
|
||||
* Init the pci interface
|
||||
*/
|
||||
data = GPIO->GPIOMode; // GPIO mode register
|
||||
data |= GROUP2_PCI | GROUP1_MII_PCCARD; // PCI internal arbiter + Cardbus
|
||||
GPIO->GPIOMode = data; // PCI internal arbiter
|
||||
|
||||
/*
|
||||
* In the BCM6348 CardBus support is defaulted to Slot 0
|
||||
* because there is no external IDSEL for CardBus. To disable
|
||||
* the CardBus and allow a standard PCI card in Slot 0
|
||||
* set the cbus_idsel field to 0x1f.
|
||||
*/
|
||||
/*
|
||||
uData = mpi->pcmcia_cntl1;
|
||||
uData |= CARDBUS_IDSEL;
|
||||
mpi->pcmcia_cntl1 = uData;
|
||||
*/
|
||||
// Setup PCI I/O Window range. Give 64K to PCI I/O
|
||||
mpi->l2piorange = ~(BCM_PCI_IO_SIZE_64KB-1);
|
||||
// UBUS to PCI I/O base address
|
||||
mpi->l2piobase = BCM_PCI_IO_BASE & BCM_PCI_ADDR_MASK;
|
||||
// UBUS to PCI I/O Window remap
|
||||
mpi->l2pioremap = (BCM_PCI_IO_BASE | MEM_WINDOW_EN);
|
||||
|
||||
// enable PCI related GPIO pins and data swap between system and PCI bus
|
||||
mpi->locbuscntrl = (EN_PCI_GPIO | DIR_U2P_NOSWAP);
|
||||
|
||||
/* Enable 6348 BusMaster and Memory access mode */
|
||||
data = mpi_GetLocalPciConfigReg(PCI_COMMAND);
|
||||
data |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
|
||||
mpi_SetLocalPciConfigReg(PCI_COMMAND, data);
|
||||
|
||||
/* Configure two 16 MByte PCI to System memory regions. */
|
||||
/* These memory regions are used when PCI device is a bus master */
|
||||
/* Accesses to the SDRAM from PCI bus will be "byte swapped" for this region */
|
||||
mpi_SetLocalPciConfigReg(PCI_BASE_ADDRESS_3, BCM_HOST_MEM_SPACE1);
|
||||
mpi->sp0remap = 0x0;
|
||||
|
||||
/* Accesses to the SDRAM from PCI bus will not be "byte swapped" for this region */
|
||||
mpi_SetLocalPciConfigReg(PCI_BASE_ADDRESS_4, BCM_HOST_MEM_SPACE2);
|
||||
mpi->sp1remap = 0x0;
|
||||
mpi->pcimodesel |= (PCI_BAR2_NOSWAP | 0x40);
|
||||
|
||||
if ((chipid == 0x6348) && (chiprev == 0xb0)) {
|
||||
mpi->sp0range = ~(sdramsize-1);
|
||||
mpi->sp1range = ~(sdramsize-1);
|
||||
}
|
||||
/*
|
||||
* Change 6348 PCI Cfg Reg. offset 0x40 to PCI memory read retry count infinity
|
||||
* by set 0 in bit 8~15. This resolve read Bcm4306 srom return 0xffff in
|
||||
* first read.
|
||||
*/
|
||||
data = mpi_GetLocalPciConfigReg(BRCM_PCI_CONFIG_TIMER);
|
||||
data &= ~BRCM_PCI_CONFIG_TIMER_RETRY_MASK;
|
||||
data |= 0x00000080;
|
||||
mpi_SetLocalPciConfigReg(BRCM_PCI_CONFIG_TIMER, data);
|
||||
|
||||
/* enable pci interrupt */
|
||||
mpi->locintstat |= (EXT_PCI_INT << 16);
|
||||
|
||||
mpi_DetectPcCard();
|
||||
|
||||
ioport_resource.start = BCM_PCI_IO_BASE;
|
||||
ioport_resource.end = BCM_PCI_IO_BASE + BCM_PCI_IO_SIZE_64KB;
|
||||
|
||||
#if defined(CONFIG_USB)
|
||||
PERF->blkEnables |= USBH_CLK_EN;
|
||||
mdelay(100);
|
||||
*USBH_NON_OHCI = NON_OHCI_BYTE_SWAP;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init plat_mem_setup(void)
|
||||
{
|
||||
_machine_restart = brcm_machine_restart;
|
||||
_machine_halt = brcm_machine_halt;
|
||||
pm_power_off = brcm_machine_halt;
|
||||
|
||||
//board_time_init = brcm_time_init;
|
||||
|
||||
/* mpi initialization */
|
||||
mpi_init();
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
<:copyright-gpl
|
||||
Copyright 2004 Broadcom Corp. All Rights Reserved.
|
||||
|
||||
This program is free software; you can distribute 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 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.
|
||||
:>
|
||||
*/
|
||||
/*
|
||||
* Setup time for Broadcom 963xx MIPS boards
|
||||
*/
|
||||
|
||||
#include <linux/autoconf.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/timex.h>
|
||||
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/div64.h>
|
||||
#include <asm/time.h>
|
||||
|
||||
#include <6348_map_part.h>
|
||||
#include <6348_intr.h>
|
||||
#include <bcm_map_part.h>
|
||||
#include <bcm_intr.h>
|
||||
|
||||
static unsigned long r4k_offset; /* Amount to increment compare reg each time */
|
||||
static unsigned long r4k_cur; /* What counter should be at next timer irq */
|
||||
|
||||
/* *********************************************************************
|
||||
* calculateCpuSpeed()
|
||||
* Calculate the BCM6348 CPU speed by reading the PLL strap register
|
||||
* and applying the following formula:
|
||||
* cpu_clk = (.25 * 64MHz freq) * (N1 + 1) * (N2 + 2) / (M1_CPU + 1)
|
||||
* Input parameters:
|
||||
* none
|
||||
* Return value:
|
||||
* none
|
||||
********************************************************************* */
|
||||
|
||||
static inline unsigned long __init calculateCpuSpeed(void)
|
||||
{
|
||||
u32 pllStrap = PERF->PllStrap;
|
||||
int n1 = (pllStrap & PLL_N1_MASK) >> PLL_N1_SHFT;
|
||||
int n2 = (pllStrap & PLL_N2_MASK) >> PLL_N2_SHFT;
|
||||
int m1cpu = (pllStrap & PLL_M1_CPU_MASK) >> PLL_M1_CPU_SHFT;
|
||||
|
||||
return (16 * (n1 + 1) * (n2 + 2) / (m1cpu + 1)) * 1000000;
|
||||
}
|
||||
|
||||
|
||||
static inline unsigned long __init cal_r4koff(void)
|
||||
{
|
||||
mips_hpt_frequency = calculateCpuSpeed() / 2;
|
||||
return (mips_hpt_frequency / HZ);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* There are a lot of conceptually broken versions of the MIPS timer interrupt
|
||||
* handler floating around. This one is rather different, but the algorithm
|
||||
* is provably more robust.
|
||||
*/
|
||||
#if 0
|
||||
irqreturn_t brcm_timer_interrupt(struct pt_regs *regs)
|
||||
{
|
||||
int irq = MIPS_TIMER_INT;
|
||||
|
||||
irq_enter();
|
||||
kstat_this_cpu.irqs[irq]++;
|
||||
|
||||
timer_interrupt(irq, regs);
|
||||
irq_exit();
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
void __init plat_time_init(void)
|
||||
{
|
||||
unsigned int est_freq, flags;
|
||||
local_irq_save(flags);
|
||||
|
||||
printk("calculating r4koff... ");
|
||||
r4k_offset = cal_r4koff();
|
||||
printk("%08lx(%d)\n", r4k_offset, (int)r4k_offset);
|
||||
|
||||
est_freq = 2 * r4k_offset * HZ;
|
||||
est_freq += 5000; /* round */
|
||||
est_freq -= est_freq % 10000;
|
||||
printk("CPU frequency %d.%02d MHz\n", est_freq / 1000000,
|
||||
(est_freq % 1000000) * 100 / 1000000);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void __init plat_timer_setup(struct irqaction *irq)
|
||||
{
|
||||
r4k_cur = (read_c0_count() + r4k_offset);
|
||||
write_c0_compare(r4k_cur);
|
||||
set_c0_status(IE_IRQ5);
|
||||
}
|
||||
#endif
|
||||
@@ -1,246 +0,0 @@
|
||||
/*
|
||||
* Watchdog driver for the BCM963xx devices
|
||||
*
|
||||
* Copyright (C) 2007 OpenWrt.org
|
||||
* Florian Fainelli <florian@openwrt.org>
|
||||
*
|
||||
* 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 <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/watchdog.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/ioport.h>
|
||||
|
||||
typedef struct bcm963xx_timer {
|
||||
unsigned short unused0;
|
||||
unsigned char timer_mask;
|
||||
#define TIMER0EN 0x01
|
||||
#define TIMER1EN 0x02
|
||||
#define TIMER2EN 0x04
|
||||
unsigned char timer_ints;
|
||||
#define TIMER0 0x01
|
||||
#define TIMER1 0x02
|
||||
#define TIMER2 0x04
|
||||
#define WATCHDOG 0x08
|
||||
unsigned long timer_ctl0;
|
||||
unsigned long timer_ctl1;
|
||||
unsigned long timer_ctl2;
|
||||
#define TIMERENABLE 0x80000000
|
||||
#define RSTCNTCLR 0x40000000
|
||||
unsigned long timer_cnt0;
|
||||
unsigned long timer_cnt1;
|
||||
unsigned long timer_cnt2;
|
||||
unsigned long wdt_def_count;
|
||||
|
||||
/* Write 0xff00 0x00ff to Start timer
|
||||
* Write 0xee00 0x00ee to Stop and re-load default count
|
||||
* Read from this register returns current watch dog count
|
||||
*/
|
||||
unsigned long wdt_ctl;
|
||||
|
||||
/* Number of 40-MHz ticks for WD Reset pulse to last */
|
||||
unsigned long wdt_rst_count;
|
||||
} bcm963xx_timer;
|
||||
|
||||
static struct bcm963xx_wdt_device {
|
||||
struct completion stop;
|
||||
volatile int running;
|
||||
struct timer_list timer;
|
||||
volatile int queue;
|
||||
int default_ticks;
|
||||
unsigned long inuse;
|
||||
} bcm963xx_wdt_device;
|
||||
|
||||
static int ticks = 1000;
|
||||
|
||||
#define WDT_BASE 0xfffe0200
|
||||
#define WDT ((volatile bcm963xx_timer * const) WDT_BASE)
|
||||
|
||||
#define BCM963XX_INTERVAL (HZ/10+1)
|
||||
|
||||
static void bcm963xx_wdt_trigger(unsigned long unused)
|
||||
{
|
||||
if (bcm963xx_wdt_device.running)
|
||||
ticks--;
|
||||
|
||||
/* Load the default ticking value into the reset counter register */
|
||||
WDT->wdt_rst_count = bcm963xx_wdt_device.default_ticks;
|
||||
|
||||
if (bcm963xx_wdt_device.queue && ticks) {
|
||||
bcm963xx_wdt_device.timer.expires = jiffies + BCM963XX_INTERVAL;
|
||||
add_timer(&bcm963xx_wdt_device.timer);
|
||||
}
|
||||
else {
|
||||
complete(&bcm963xx_wdt_device.stop);
|
||||
}
|
||||
}
|
||||
|
||||
static void bcm963xx_wdt_reset(void)
|
||||
{
|
||||
ticks = bcm963xx_wdt_device.default_ticks;
|
||||
/* Also reload default count */
|
||||
WDT->wdt_def_count = ticks;
|
||||
WDT->wdt_ctl = 0xee00;
|
||||
WDT->wdt_ctl = 0x00ee;
|
||||
}
|
||||
|
||||
static void bcm963xx_wdt_start(void)
|
||||
{
|
||||
if (!bcm963xx_wdt_device.queue) {
|
||||
bcm963xx_wdt_device.queue;
|
||||
/* Enable the watchdog by writing 0xff00 ,then 0x00ff to the control register */
|
||||
WDT->wdt_ctl = 0xff00;
|
||||
WDT->wdt_ctl = 0x00ff;
|
||||
bcm963xx_wdt_device.timer.expires = jiffies + BCM963XX_INTERVAL;
|
||||
add_timer(&bcm963xx_wdt_device.timer);
|
||||
}
|
||||
bcm963xx_wdt_device.running++;
|
||||
}
|
||||
|
||||
static int bcm963xx_wdt_stop(void)
|
||||
{
|
||||
if (bcm963xx_wdt_device.running)
|
||||
bcm963xx_wdt_device.running = 0;
|
||||
|
||||
ticks = bcm963xx_wdt_device.default_ticks;
|
||||
|
||||
/* Stop the watchdog by writing 0xee00 then 0x00ee to the control register */
|
||||
WDT->wdt_ctl = 0xee00;
|
||||
WDT->wdt_ctl = 0x00ee;
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int bcm963xx_wdt_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
if (test_and_set_bit(0, &bcm963xx_wdt_device.inuse))
|
||||
return -EBUSY;
|
||||
return nonseekable_open(inode, file);
|
||||
}
|
||||
|
||||
static int bcm963xx_wdt_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
clear_bit(0, &bcm963xx_wdt_device.inuse);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm963xx_wdt_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
void __user *argp = (void __user *)arg;
|
||||
unsigned int value;
|
||||
|
||||
static struct watchdog_info ident = {
|
||||
.options = WDIOF_CARDRESET,
|
||||
.identity = "BCM963xx WDT",
|
||||
};
|
||||
|
||||
switch (cmd) {
|
||||
case WDIOC_KEEPALIVE:
|
||||
bcm963xx_wdt_reset();
|
||||
break;
|
||||
case WDIOC_GETSTATUS:
|
||||
/* Reading from the control register will return the current value */
|
||||
value = WDT->wdt_ctl;
|
||||
if ( copy_to_user(argp, &value, sizeof(int)) )
|
||||
return -EFAULT;
|
||||
break;
|
||||
case WDIOC_GETSUPPORT:
|
||||
if ( copy_to_user(argp, &ident, sizeof(ident)) )
|
||||
return -EFAULT;
|
||||
break;
|
||||
case WDIOC_SETOPTIONS:
|
||||
if ( copy_from_user(&value, argp, sizeof(int)) )
|
||||
return -EFAULT;
|
||||
switch(value) {
|
||||
case WDIOS_ENABLECARD:
|
||||
bcm963xx_wdt_start();
|
||||
break;
|
||||
case WDIOS_DISABLECARD:
|
||||
bcm963xx_wdt_stop();
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -ENOTTY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm963xx_wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
if (!count)
|
||||
return -EIO;
|
||||
bcm963xx_wdt_reset();
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations bcm963xx_wdt_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.write = bcm963xx_wdt_write,
|
||||
.ioctl = bcm963xx_wdt_ioctl,
|
||||
.open = bcm963xx_wdt_open,
|
||||
.release = bcm963xx_wdt_release,
|
||||
};
|
||||
|
||||
static struct miscdevice bcm963xx_wdt_miscdev = {
|
||||
.minor = WATCHDOG_MINOR,
|
||||
.name = "watchdog",
|
||||
.fops = &bcm963xx_wdt_fops,
|
||||
};
|
||||
|
||||
static void __exit bcm963xx_wdt_exit(void)
|
||||
{
|
||||
if (bcm963xx_wdt_device.queue ){
|
||||
bcm963xx_wdt_device.queue = 0;
|
||||
wait_for_completion(&bcm963xx_wdt_device.stop);
|
||||
}
|
||||
misc_deregister(&bcm963xx_wdt_miscdev);
|
||||
}
|
||||
|
||||
static int __init bcm963xx_wdt_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
printk("Broadcom BCM963xx Watchdog timer\n");
|
||||
|
||||
ret = misc_register(&bcm963xx_wdt_miscdev);
|
||||
if (ret) {
|
||||
printk(KERN_CRIT "Cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret);
|
||||
return ret;
|
||||
}
|
||||
init_completion(&bcm963xx_wdt_device.stop);
|
||||
bcm963xx_wdt_device.queue = 0;
|
||||
|
||||
clear_bit(0, &bcm963xx_wdt_device.inuse);
|
||||
|
||||
init_timer(&bcm963xx_wdt_device.timer);
|
||||
bcm963xx_wdt_device.timer.function = bcm963xx_wdt_trigger;
|
||||
bcm963xx_wdt_device.timer.data = 0;
|
||||
|
||||
bcm963xx_wdt_device.default_ticks = ticks;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
module_init(bcm963xx_wdt_init);
|
||||
module_exit(bcm963xx_wdt_exit);
|
||||
|
||||
MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
|
||||
MODULE_DESCRIPTION("Broadcom BCM963xx Watchdog driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -1,5 +0,0 @@
|
||||
#
|
||||
# Makefile for the Broadcom Common Firmware Environment support
|
||||
#
|
||||
|
||||
obj-y += cfe.o
|
||||
@@ -1,533 +0,0 @@
|
||||
/*
|
||||
* Broadcom Common Firmware Environment (CFE) support
|
||||
*
|
||||
* Copyright 2000, 2001, 2002
|
||||
* Broadcom Corporation. All rights reserved.
|
||||
*
|
||||
* Copyright (C) 2006 Michael Buesch
|
||||
*
|
||||
* Original Authors: Mitch Lichtenberg, Chris Demetriou
|
||||
*
|
||||
* This software is furnished under license and may be used and copied only
|
||||
* in accordance with the following terms and conditions. Subject to these
|
||||
* conditions, you may download, copy, install, use, modify and distribute
|
||||
* modified or unmodified copies of this software in source and/or binary
|
||||
* form. No title or ownership is transferred hereby.
|
||||
*
|
||||
* 1) Any source code used, modified or distributed must reproduce and
|
||||
* retain this copyright notice and list of conditions as they appear in
|
||||
* the source file.
|
||||
*
|
||||
* 2) No right is granted to use any trade name, trademark, or logo of
|
||||
* Broadcom Corporation. The "Broadcom Corporation" name may not be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without the prior written permission of Broadcom Corporation.
|
||||
*
|
||||
* 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
||||
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE
|
||||
* FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE
|
||||
* LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/cfe.h>
|
||||
|
||||
#include "cfe_private.h"
|
||||
|
||||
|
||||
static cfe_uint_t cfe_handle;
|
||||
static int (*cfe_trampoline)(long handle, long iocb);
|
||||
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
void __init cfe_setup(unsigned long fwarg0, unsigned long fwarg1,
|
||||
unsigned long fwarg2, unsigned long fwarg3)
|
||||
{
|
||||
if (fwarg3 == 0x80300000) {
|
||||
/* WRT54G workaround */
|
||||
fwarg3 = CFE_EPTSEAL;
|
||||
fwarg2 = 0xBFC00500;
|
||||
}
|
||||
if (fwarg3 != CFE_EPTSEAL) {
|
||||
/* We are not booted from CFE */
|
||||
return;
|
||||
}
|
||||
if (fwarg1 == 0) {
|
||||
/* We are on the boot CPU */
|
||||
cfe_handle = (cfe_uint_t)fwarg0;
|
||||
cfe_trampoline = CFE_TO_PTR(fwarg2);
|
||||
}
|
||||
}
|
||||
|
||||
int cfe_vprintk(const char *fmt, va_list args)
|
||||
{
|
||||
static char buffer[1024];
|
||||
static DEFINE_SPINLOCK(lock);
|
||||
static const char pfx[] = "CFE-console: ";
|
||||
static const size_t pfx_len = sizeof(pfx) - 1;
|
||||
unsigned long flags;
|
||||
int len, cnt, pos;
|
||||
int handle;
|
||||
int res;
|
||||
|
||||
if (!cfe_present())
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock_irqsave(&lock, flags);
|
||||
handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
|
||||
if (CFE_ISERR(handle)) {
|
||||
len = -EIO;
|
||||
goto out;
|
||||
}
|
||||
strcpy(buffer, pfx);
|
||||
len = vscnprintf(buffer + pfx_len,
|
||||
sizeof(buffer) - pfx_len - 2,
|
||||
fmt, args);
|
||||
len += pfx_len;
|
||||
/* The CFE console requires CR-LF line-ends.
|
||||
* Add a CR, if we only terminate lines with a LF.
|
||||
* This does only fix CR-LF at the end of the string.
|
||||
* So for multiple lines, use multiple cfe_vprintk calls.
|
||||
*/
|
||||
if (len > 1 &&
|
||||
buffer[len - 1] == '\n' && buffer[len - 2] != '\r') {
|
||||
buffer[len - 1] = '\r';
|
||||
buffer[len] = '\n';
|
||||
len += 1;
|
||||
}
|
||||
cnt = len;
|
||||
pos = 0;
|
||||
while (cnt > 0) {
|
||||
res = cfe_write(handle, buffer + pos, len - pos);
|
||||
if (CFE_ISERR(res)) {
|
||||
len = -EIO;
|
||||
goto out;
|
||||
}
|
||||
cnt -= res;
|
||||
pos += res;
|
||||
}
|
||||
out:
|
||||
spin_unlock_irqrestore(&lock, flags);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int cfe_printk(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int res;
|
||||
|
||||
va_start(args, fmt);
|
||||
res = cfe_vprintk(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int cfe_iocb_dispatch(struct cfe_iocb *iocb)
|
||||
{
|
||||
if (!cfe_present())
|
||||
return CFE_ERR_UNSUPPORTED;
|
||||
return cfe_trampoline((long)cfe_handle, (long)iocb);
|
||||
}
|
||||
|
||||
int cfe_present(void)
|
||||
{
|
||||
return (cfe_trampoline != NULL);
|
||||
}
|
||||
|
||||
int cfe_close(int handle)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
iocb.fcode = CFE_CMD_DEV_CLOSE;
|
||||
iocb.handle = handle;
|
||||
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
|
||||
return (CFE_ISERR(err)) ? err : iocb.status;
|
||||
}
|
||||
|
||||
int cfe_cpu_start(int cpu, void (*fn)(void), long sp, long gp, long a1)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
iocb.fcode = CFE_CMD_FW_CPUCTL;
|
||||
iocb.psize = sizeof(struct cfe_iocb_cpuctl);
|
||||
iocb.cpuctl.number = cpu;
|
||||
iocb.cpuctl.command = CFE_CPU_CMD_START;
|
||||
iocb.cpuctl.gp = gp;
|
||||
iocb.cpuctl.sp = sp;
|
||||
iocb.cpuctl.a1 = a1;
|
||||
iocb.cpuctl.start_addr = (long)fn;
|
||||
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
|
||||
return (CFE_ISERR(err)) ? err : iocb.status;
|
||||
}
|
||||
|
||||
int cfe_cpu_stop(int cpu)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
iocb.fcode = CFE_CMD_FW_CPUCTL;
|
||||
iocb.psize = sizeof(struct cfe_iocb_cpuctl);
|
||||
iocb.cpuctl.number = cpu;
|
||||
iocb.cpuctl.command = CFE_CPU_CMD_STOP;
|
||||
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
|
||||
return (CFE_ISERR(err)) ? err : iocb.status;
|
||||
}
|
||||
|
||||
int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
iocb.fcode = CFE_CMD_ENV_ENUM;
|
||||
iocb.psize = sizeof(struct cfe_iocb_envbuf);
|
||||
iocb.envbuf.index = idx;
|
||||
iocb.envbuf.name = PTR_TO_CFE(name);
|
||||
iocb.envbuf.name_len = namelen;
|
||||
iocb.envbuf.val = PTR_TO_CFE(val);
|
||||
iocb.envbuf.val_len = vallen;
|
||||
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
|
||||
return (CFE_ISERR(err)) ? err : iocb.status;
|
||||
}
|
||||
|
||||
int cfe_enumdev(int idx, char *name, int namelen)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
|
||||
iocb.fcode = CFE_CMD_DEV_ENUM;
|
||||
iocb.psize = sizeof(struct cfe_iocb_envbuf);
|
||||
iocb.envbuf.index = idx;
|
||||
iocb.envbuf.name = PTR_TO_CFE(name);
|
||||
iocb.envbuf.name_len = namelen;
|
||||
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
|
||||
return (CFE_ISERR(err)) ? err : iocb.status;
|
||||
}
|
||||
|
||||
int cfe_enummem(int idx, int flags, u64 *start, u64 *length,
|
||||
u64 *type)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
|
||||
iocb.fcode = CFE_CMD_FW_MEMENUM;
|
||||
iocb.flags = flags;
|
||||
iocb.psize = sizeof(struct cfe_iocb_meminfo);
|
||||
iocb.meminfo.index = idx;
|
||||
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
if (CFE_ISERR(err))
|
||||
return err;
|
||||
if (!CFE_ISERR(iocb.status)) {
|
||||
*start = iocb.meminfo.addr;
|
||||
*length = iocb.meminfo.size;
|
||||
*type = iocb.meminfo.type;
|
||||
}
|
||||
|
||||
return iocb.status;
|
||||
}
|
||||
|
||||
int cfe_exit(int warm, int status)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
printk("CFE REBOOT\n");
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
iocb.fcode = CFE_CMD_FW_RESTART;
|
||||
if (warm)
|
||||
iocb.flags = CFE_FLG_WARMSTART;
|
||||
iocb.psize = sizeof(struct cfe_iocb_exitstat);
|
||||
iocb.exitstat.status = status;
|
||||
|
||||
printk("CALL\n");
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
printk("DONE\n");
|
||||
|
||||
return (CFE_ISERR(err)) ? err : iocb.status;
|
||||
}
|
||||
|
||||
int cfe_flushcache(int flags)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
iocb.fcode = CFE_CMD_FW_FLUSHCACHE;
|
||||
iocb.flags = flags;
|
||||
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
|
||||
return (CFE_ISERR(err)) ? err : iocb.status;
|
||||
}
|
||||
|
||||
int cfe_getdevinfo(char *name)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
iocb.fcode = CFE_CMD_DEV_GETINFO;
|
||||
iocb.psize = sizeof(struct cfe_iocb_buf);
|
||||
iocb.buffer.ptr = PTR_TO_CFE(name);
|
||||
iocb.buffer.length = strlen(name);
|
||||
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
if (CFE_ISERR(err))
|
||||
return err;
|
||||
if (CFE_ISERR(iocb.status))
|
||||
return iocb.status;
|
||||
|
||||
return iocb.buffer.devflags;
|
||||
}
|
||||
|
||||
int cfe_getenv(char *name, char *dest, int destlen)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
dest[0] = '\0';
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
iocb.fcode = CFE_CMD_ENV_GET;
|
||||
iocb.psize = sizeof(struct cfe_iocb_envbuf);
|
||||
iocb.envbuf.name = PTR_TO_CFE(name);
|
||||
iocb.envbuf.name_len = strlen(name);
|
||||
iocb.envbuf.val = PTR_TO_CFE(dest);
|
||||
iocb.envbuf.val_len = destlen;
|
||||
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
|
||||
return (CFE_ISERR(err)) ? err : iocb.status;
|
||||
}
|
||||
|
||||
int cfe_getfwinfo(struct cfe_fwinfo *info)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
iocb.fcode = CFE_CMD_FW_GETINFO;
|
||||
iocb.psize = sizeof(struct cfe_iocb_fwinfo);
|
||||
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
if (CFE_ISERR(err))
|
||||
return err;
|
||||
if (CFE_ISERR(iocb.status))
|
||||
return err;
|
||||
|
||||
info->version = iocb.fwinfo.version;
|
||||
info->totalmem = iocb.fwinfo.totalmem;
|
||||
info->flags = iocb.fwinfo.flags;
|
||||
info->boardid = iocb.fwinfo.boardid;
|
||||
info->bootarea_va = iocb.fwinfo.bootarea_va;
|
||||
info->bootarea_pa = iocb.fwinfo.bootarea_pa;
|
||||
info->bootarea_size = iocb.fwinfo.bootarea_size;
|
||||
|
||||
return iocb.status;
|
||||
}
|
||||
|
||||
int cfe_getstdhandle(int handletype)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
iocb.fcode = CFE_CMD_DEV_GETHANDLE;
|
||||
iocb.flags = handletype;
|
||||
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
if (CFE_ISERR(err))
|
||||
return err;
|
||||
if (CFE_ISERR(iocb.status))
|
||||
return iocb.status;
|
||||
|
||||
return iocb.handle;
|
||||
}
|
||||
|
||||
int cfe_getticks(s64 *ticks)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
iocb.fcode = CFE_CMD_FW_GETTIME;
|
||||
iocb.psize = sizeof(struct cfe_iocb_time);
|
||||
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
if (CFE_ISERR(err))
|
||||
return err;
|
||||
if (!CFE_ISERR(iocb.status))
|
||||
*ticks = iocb.time.ticks;
|
||||
|
||||
return iocb.status;
|
||||
}
|
||||
|
||||
int cfe_inpstat(int handle)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
iocb.fcode = CFE_CMD_DEV_INPSTAT;
|
||||
iocb.handle = handle;
|
||||
iocb.psize = sizeof(struct cfe_iocb_inpstat);
|
||||
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
if (CFE_ISERR(err))
|
||||
return err;
|
||||
if (CFE_ISERR(iocb.status))
|
||||
return iocb.status;
|
||||
|
||||
return iocb.inpstat.status;
|
||||
}
|
||||
|
||||
int cfe_ioctl(int handle, unsigned int ioctlnum,
|
||||
unsigned char *buffer, int length,
|
||||
int *retlen, u64 offset)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
iocb.fcode = CFE_CMD_DEV_IOCTL;
|
||||
iocb.handle = handle;
|
||||
iocb.psize = sizeof(struct cfe_iocb_buf);
|
||||
iocb.buffer.offset = offset;
|
||||
iocb.buffer.ioctlcmd = ioctlnum;
|
||||
iocb.buffer.ptr = PTR_TO_CFE(buffer);
|
||||
iocb.buffer.length = length;
|
||||
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
if (CFE_ISERR(err))
|
||||
return err;
|
||||
if (CFE_ISERR(iocb.status))
|
||||
return iocb.status;
|
||||
if (retlen)
|
||||
*retlen = iocb.buffer.retlen;
|
||||
|
||||
return iocb.status;
|
||||
}
|
||||
|
||||
int cfe_open(char *name)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
iocb.fcode = CFE_CMD_DEV_OPEN;
|
||||
iocb.psize = sizeof(struct cfe_iocb_buf);
|
||||
iocb.buffer.ptr = PTR_TO_CFE(name);
|
||||
iocb.buffer.length = strlen(name);
|
||||
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
if (CFE_ISERR(err))
|
||||
return err;
|
||||
if (CFE_ISERR(iocb.status))
|
||||
return iocb.status;
|
||||
|
||||
return iocb.handle;
|
||||
}
|
||||
|
||||
int cfe_read(int handle, unsigned char *buffer, int length)
|
||||
{
|
||||
return cfe_readblk(handle, 0, buffer, length);
|
||||
}
|
||||
|
||||
int cfe_readblk(int handle, s64 offset, unsigned char *buffer, int length)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
iocb.fcode = CFE_CMD_DEV_READ;
|
||||
iocb.handle = handle;
|
||||
iocb.psize = sizeof(struct cfe_iocb_buf);
|
||||
iocb.buffer.offset = offset;
|
||||
iocb.buffer.ptr = PTR_TO_CFE(buffer);
|
||||
iocb.buffer.length = length;
|
||||
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
if (CFE_ISERR(err))
|
||||
return err;
|
||||
if (CFE_ISERR(iocb.status))
|
||||
return iocb.status;
|
||||
|
||||
return iocb.buffer.retlen;
|
||||
}
|
||||
|
||||
int cfe_setenv(char *name, char *val)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
iocb.fcode = CFE_CMD_ENV_SET;
|
||||
iocb.psize = sizeof(struct cfe_iocb_envbuf);
|
||||
iocb.envbuf.name = PTR_TO_CFE(name);
|
||||
iocb.envbuf.name_len = strlen(name);
|
||||
iocb.envbuf.val = PTR_TO_CFE(val);
|
||||
iocb.envbuf.val_len = strlen(val);
|
||||
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
|
||||
return (CFE_ISERR(err)) ? err : iocb.status;
|
||||
}
|
||||
|
||||
int cfe_write(int handle, unsigned char *buffer, int length)
|
||||
{
|
||||
return cfe_writeblk(handle, 0, buffer, length);
|
||||
}
|
||||
|
||||
int cfe_writeblk(int handle, s64 offset, unsigned char *buffer, int length)
|
||||
{
|
||||
struct cfe_iocb iocb;
|
||||
int err;
|
||||
|
||||
memset(&iocb, 0, sizeof(iocb));
|
||||
iocb.fcode = CFE_CMD_DEV_WRITE;
|
||||
iocb.handle = handle;
|
||||
iocb.psize = sizeof(struct cfe_iocb_buf);
|
||||
iocb.buffer.offset = offset;
|
||||
iocb.buffer.ptr = PTR_TO_CFE(buffer);
|
||||
iocb.buffer.length = length;
|
||||
|
||||
err = cfe_iocb_dispatch(&iocb);
|
||||
if (CFE_ISERR(err))
|
||||
return err;
|
||||
if (CFE_ISERR(iocb.status))
|
||||
return iocb.status;
|
||||
|
||||
return iocb.buffer.retlen;
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* Broadcom Common Firmware Environment (CFE) support
|
||||
*
|
||||
* Copyright 2000, 2001, 2002
|
||||
* Broadcom Corporation. All rights reserved.
|
||||
*
|
||||
* Copyright (C) 2006 Michael Buesch
|
||||
*
|
||||
* Original Authors: Mitch Lichtenberg, Chris Demetriou
|
||||
*
|
||||
* This software is furnished under license and may be used and copied only
|
||||
* in accordance with the following terms and conditions. Subject to these
|
||||
* conditions, you may download, copy, install, use, modify and distribute
|
||||
* modified or unmodified copies of this software in source and/or binary
|
||||
* form. No title or ownership is transferred hereby.
|
||||
*
|
||||
* 1) Any source code used, modified or distributed must reproduce and
|
||||
* retain this copyright notice and list of conditions as they appear in
|
||||
* the source file.
|
||||
*
|
||||
* 2) No right is granted to use any trade name, trademark, or logo of
|
||||
* Broadcom Corporation. The "Broadcom Corporation" name may not be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without the prior written permission of Broadcom Corporation.
|
||||
*
|
||||
* 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
||||
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE
|
||||
* FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE
|
||||
* LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LINUX_CFE_PRIVATE_H_
|
||||
#define LINUX_CFE_PRIVATE_H_
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/* Seal indicating CFE's presence, passed to the kernel. */
|
||||
#define CFE_EPTSEAL 0x43464531
|
||||
|
||||
#define CFE_CMD_FW_GETINFO 0
|
||||
#define CFE_CMD_FW_RESTART 1
|
||||
#define CFE_CMD_FW_BOOT 2
|
||||
#define CFE_CMD_FW_CPUCTL 3
|
||||
#define CFE_CMD_FW_GETTIME 4
|
||||
#define CFE_CMD_FW_MEMENUM 5
|
||||
#define CFE_CMD_FW_FLUSHCACHE 6
|
||||
|
||||
#define CFE_CMD_DEV_GETHANDLE 9
|
||||
#define CFE_CMD_DEV_ENUM 10
|
||||
#define CFE_CMD_DEV_OPEN 11
|
||||
#define CFE_CMD_DEV_INPSTAT 12
|
||||
#define CFE_CMD_DEV_READ 13
|
||||
#define CFE_CMD_DEV_WRITE 14
|
||||
#define CFE_CMD_DEV_IOCTL 15
|
||||
#define CFE_CMD_DEV_CLOSE 16
|
||||
#define CFE_CMD_DEV_GETINFO 17
|
||||
|
||||
#define CFE_CMD_ENV_ENUM 20
|
||||
#define CFE_CMD_ENV_GET 22
|
||||
#define CFE_CMD_ENV_SET 23
|
||||
#define CFE_CMD_ENV_DEL 24
|
||||
|
||||
#define CFE_CMD_MAX 32
|
||||
|
||||
#define CFE_CMD_VENDOR_USE 0x8000 /* codes above this are for customer use */
|
||||
|
||||
typedef u64 cfe_uint_t;
|
||||
typedef s64 cfe_int_t;
|
||||
typedef s64 cfe_ptr_t;
|
||||
|
||||
/* Cast a pointer from native to CFE-API pointer and back */
|
||||
#define CFE_TO_PTR(p) ((void *)(unsigned long)(p))
|
||||
#define PTR_TO_CFE(p) ((cfe_ptr_t)(unsigned long)(p))
|
||||
|
||||
struct cfe_iocb_buf {
|
||||
cfe_uint_t offset; /* offset on device (bytes) */
|
||||
cfe_ptr_t ptr; /* pointer to a buffer */
|
||||
cfe_uint_t length; /* length of this buffer */
|
||||
cfe_uint_t retlen; /* returned length (for read ops) */
|
||||
union {
|
||||
cfe_uint_t ioctlcmd; /* IOCTL command (used only for IOCTLs) */
|
||||
cfe_uint_t devflags; /* Returned device info flags */
|
||||
};
|
||||
};
|
||||
|
||||
struct cfe_iocb_inpstat {
|
||||
cfe_uint_t status; /* 1 means input available */
|
||||
};
|
||||
|
||||
struct cfe_iocb_envbuf {
|
||||
cfe_int_t index; /* 0-based enumeration index */
|
||||
cfe_ptr_t name; /* name string buffer */
|
||||
cfe_int_t name_len; /* size of name buffer */
|
||||
cfe_ptr_t val; /* value string buffer */
|
||||
cfe_int_t val_len; /* size of value string buffer */
|
||||
};
|
||||
|
||||
struct cfe_iocb_cpuctl {
|
||||
cfe_uint_t number; /* cpu number to control */
|
||||
cfe_uint_t command; /* command to issue to CPU */
|
||||
cfe_uint_t start_addr; /* CPU start address */
|
||||
cfe_uint_t gp; /* starting GP value */
|
||||
cfe_uint_t sp; /* starting SP value */
|
||||
cfe_uint_t a1; /* starting A1 value */
|
||||
};
|
||||
|
||||
struct cfe_iocb_time {
|
||||
cfe_int_t ticks; /* current time in ticks */
|
||||
};
|
||||
|
||||
struct cfe_iocb_exitstat {
|
||||
cfe_int_t status;
|
||||
};
|
||||
|
||||
struct cfe_iocb_meminfo {
|
||||
cfe_int_t index; /* 0-based enumeration index */
|
||||
cfe_int_t type; /* type of memory block */
|
||||
cfe_uint_t addr; /* physical start address */
|
||||
cfe_uint_t size; /* block size */
|
||||
};
|
||||
|
||||
struct cfe_iocb_fwinfo {
|
||||
cfe_int_t version; /* major, minor, eco version */
|
||||
cfe_int_t totalmem; /* total installed mem */
|
||||
cfe_int_t flags; /* various flags */
|
||||
cfe_int_t boardid; /* board ID */
|
||||
cfe_int_t bootarea_va; /* VA of boot area */
|
||||
cfe_int_t bootarea_pa; /* PA of boot area */
|
||||
cfe_int_t bootarea_size; /* size of boot area */
|
||||
cfe_int_t reserved1;
|
||||
cfe_int_t reserved2;
|
||||
cfe_int_t reserved3;
|
||||
};
|
||||
|
||||
/* CFE I/O Control Block */
|
||||
struct cfe_iocb {
|
||||
cfe_uint_t fcode; /* IOCB function code */
|
||||
cfe_int_t status; /* return status */
|
||||
cfe_int_t handle; /* file/device handle */
|
||||
cfe_uint_t flags; /* flags for this IOCB */
|
||||
cfe_uint_t psize; /* size of parameter list */
|
||||
union {
|
||||
struct cfe_iocb_buf buffer; /* buffer parameters */
|
||||
struct cfe_iocb_inpstat inpstat; /* input status parameters */
|
||||
struct cfe_iocb_envbuf envbuf; /* environment function parameters */
|
||||
struct cfe_iocb_cpuctl cpuctl; /* CPU control parameters */
|
||||
struct cfe_iocb_time time; /* timer parameters */
|
||||
struct cfe_iocb_meminfo meminfo; /* memory arena info parameters */
|
||||
struct cfe_iocb_fwinfo fwinfo; /* firmware information */
|
||||
struct cfe_iocb_exitstat exitstat; /* Exit Status */
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#include <linux/init.h>
|
||||
|
||||
void __init cfe_setup(unsigned long fwarg0, unsigned long fwarg1,
|
||||
unsigned long fwarg2, unsigned long fwarg3);
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
.macro cfe_early_init
|
||||
#ifdef CONFIG_CFE
|
||||
jal cfe_setup
|
||||
#endif
|
||||
.endm
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* LINUX_CFE_PRIVATE_H_ */
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
<:copyright-gpl
|
||||
Copyright 2002 Broadcom Corp. All Rights Reserved.
|
||||
|
||||
This program is free software; you can distribute 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 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/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <bcmpci.h>
|
||||
#include <bcm_intr.h>
|
||||
#include <bcm_map_part.h>
|
||||
#include <6348_intr.h>
|
||||
#include <6348_map_part.h>
|
||||
|
||||
static volatile MpiRegisters * mpi = (MpiRegisters *)(MPI_BASE);
|
||||
|
||||
static char irq_tab_bcm96348[] __initdata = {
|
||||
[0] = INTERRUPT_ID_MPI,
|
||||
[1] = INTERRUPT_ID_MPI,
|
||||
#if defined(CONFIG_USB)
|
||||
[USB_HOST_SLOT] = INTERRUPT_ID_USBH
|
||||
#endif
|
||||
};
|
||||
|
||||
int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
return irq_tab_bcm96348[slot];
|
||||
}
|
||||
|
||||
static void bcm96348_fixup(struct pci_dev *dev)
|
||||
{
|
||||
uint32 memaddr;
|
||||
uint32 size;
|
||||
|
||||
memaddr = pci_resource_start(dev, 0);
|
||||
size = pci_resource_len(dev, 0);
|
||||
|
||||
switch (PCI_SLOT(dev->devfn)) {
|
||||
case 0:
|
||||
// UBUS to PCI address range
|
||||
// Memory Window 1. Mask determines which bits are decoded.
|
||||
mpi->l2pmrange1 = ~(size-1);
|
||||
// UBUS to PCI Memory base address. This is akin to the ChipSelect base
|
||||
// register.
|
||||
mpi->l2pmbase1 = memaddr & BCM_PCI_ADDR_MASK;
|
||||
// UBUS to PCI Remap Address. Replaces the masked address bits in the
|
||||
// range register with this setting.
|
||||
// Also, enable direct I/O and direct Memory accesses
|
||||
mpi->l2pmremap1 = (memaddr | MEM_WINDOW_EN);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Memory Window 2
|
||||
mpi->l2pmrange2 = ~(size-1);
|
||||
// UBUS to PCI Memory base address.
|
||||
mpi->l2pmbase2 = memaddr & BCM_PCI_ADDR_MASK;
|
||||
// UBUS to PCI Remap Address
|
||||
mpi->l2pmremap2 = (memaddr | MEM_WINDOW_EN);
|
||||
break;
|
||||
|
||||
#if defined(CONFIG_USB)
|
||||
case USB_HOST_SLOT:
|
||||
dev->resource[0].start = USB_HOST_BASE;
|
||||
dev->resource[0].end = USB_HOST_BASE+USB_BAR0_MEM_SIZE-1;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int pcibios_plat_dev_init(struct pci_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_ANY_ID,
|
||||
bcm96348_fixup);
|
||||
|
||||
/*struct pci_fixup pcibios_fixups[] = {
|
||||
{ PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, bcm96348_fixup },
|
||||
{0}
|
||||
};*/
|
||||
@@ -1,278 +0,0 @@
|
||||
/*
|
||||
<:copyright-gpl
|
||||
Copyright 2002 Broadcom Corp. All Rights Reserved.
|
||||
|
||||
This program is free software; you can distribute 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 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/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/addrspace.h>
|
||||
|
||||
#include <bcm_intr.h>
|
||||
#include <bcm_map_part.h>
|
||||
#include <6348_intr.h>
|
||||
#include <6348_map_part.h>
|
||||
#include <bcmpci.h>
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
||||
#if defined(CONFIG_USB)
|
||||
#if 0
|
||||
#define DPRINT(x...) printk(x)
|
||||
#else
|
||||
#define DPRINT(x...)
|
||||
#endif
|
||||
|
||||
static int
|
||||
pci63xx_int_read(unsigned int devfn, int where, u32 * value, int size);
|
||||
static int
|
||||
pci63xx_int_write(unsigned int devfn, int where, u32 * value, int size);
|
||||
|
||||
static bool usb_mem_size_rd = FALSE;
|
||||
static uint32 usb_mem_base = 0;
|
||||
static uint32 usb_cfg_space_cmd_reg = 0;
|
||||
#endif
|
||||
static bool pci_mem_size_rd = FALSE;
|
||||
|
||||
static volatile MpiRegisters * mpi = (MpiRegisters *)(MPI_BASE);
|
||||
|
||||
static void mpi_SetupPciConfigAccess(uint32 addr)
|
||||
{
|
||||
mpi->l2pcfgctl = (DIR_CFG_SEL | DIR_CFG_USEREG | addr) & ~CONFIG_TYPE;
|
||||
}
|
||||
|
||||
static void mpi_ClearPciConfigAccess(void)
|
||||
{
|
||||
mpi->l2pcfgctl = 0x00000000;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_USB)
|
||||
/* --------------------------------------------------------------------------
|
||||
Name: pci63xx_int_write
|
||||
Abstract: PCI Config write on internal device(s)
|
||||
-------------------------------------------------------------------------- */
|
||||
static int
|
||||
pci63xx_int_write(unsigned int devfn, int where, u32 * value, int size)
|
||||
{
|
||||
if (PCI_SLOT(devfn) != USB_HOST_SLOT) {
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
DPRINT("W => Slot: %d Where: %2X Len: %d Data: %02X\n",
|
||||
PCI_SLOT(devfn), where, size, *value);
|
||||
break;
|
||||
case 2:
|
||||
DPRINT("W => Slot: %d Where: %2X Len: %d Data: %04X\n",
|
||||
PCI_SLOT(devfn), where, size, *value);
|
||||
switch (where) {
|
||||
case PCI_COMMAND:
|
||||
usb_cfg_space_cmd_reg = *value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
DPRINT("W => Slot: %d Where: %2X Len: %d Data: %08lX\n",
|
||||
PCI_SLOT(devfn), where, size, *value);
|
||||
switch (where) {
|
||||
case PCI_BASE_ADDRESS_0:
|
||||
if (*value == 0xffffffff) {
|
||||
usb_mem_size_rd = TRUE;
|
||||
} else {
|
||||
usb_mem_base = *value;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Name: pci63xx_int_read
|
||||
Abstract: PCI Config read on internal device(s)
|
||||
-------------------------------------------------------------------------- */
|
||||
static int
|
||||
pci63xx_int_read(unsigned int devfn, int where, u32 * value, int size)
|
||||
{
|
||||
uint32 retValue = 0xFFFFFFFF;
|
||||
|
||||
if (PCI_SLOT(devfn) != USB_HOST_SLOT) {
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
// For now, this is specific to the USB Host controller. We can
|
||||
// make it more general if we have to...
|
||||
// Emulate PCI Config accesses
|
||||
switch (where) {
|
||||
case PCI_VENDOR_ID:
|
||||
case PCI_DEVICE_ID:
|
||||
retValue = PCI_VENDOR_ID_BROADCOM | 0x63000000;
|
||||
break;
|
||||
case PCI_COMMAND:
|
||||
case PCI_STATUS:
|
||||
retValue = (0x0006 << 16) | usb_cfg_space_cmd_reg;
|
||||
break;
|
||||
case PCI_CLASS_REVISION:
|
||||
case PCI_CLASS_DEVICE:
|
||||
retValue = (PCI_CLASS_SERIAL_USB << 16) | (0x10 << 8) | 0x01;
|
||||
break;
|
||||
case PCI_BASE_ADDRESS_0:
|
||||
if (usb_mem_size_rd) {
|
||||
retValue = USB_BAR0_MEM_SIZE;
|
||||
} else {
|
||||
if (usb_mem_base != 0)
|
||||
retValue = usb_mem_base;
|
||||
else
|
||||
retValue = USB_HOST_BASE;
|
||||
}
|
||||
usb_mem_size_rd = FALSE;
|
||||
break;
|
||||
case PCI_CACHE_LINE_SIZE:
|
||||
case PCI_LATENCY_TIMER:
|
||||
retValue = 0;
|
||||
break;
|
||||
case PCI_HEADER_TYPE:
|
||||
retValue = PCI_HEADER_TYPE_NORMAL;
|
||||
break;
|
||||
case PCI_SUBSYSTEM_VENDOR_ID:
|
||||
retValue = PCI_VENDOR_ID_BROADCOM;
|
||||
break;
|
||||
case PCI_SUBSYSTEM_ID:
|
||||
retValue = 0x6300;
|
||||
break;
|
||||
case PCI_INTERRUPT_LINE:
|
||||
retValue = INTERRUPT_ID_USBH;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
*value = (retValue >> ((where & 3) << 3)) & 0xff;
|
||||
DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %02X\n",
|
||||
PCI_SLOT(devfn), where, size, *value);
|
||||
break;
|
||||
case 2:
|
||||
*value = (retValue >> ((where & 3) << 3)) & 0xffff;
|
||||
DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %04X\n",
|
||||
PCI_SLOT(devfn), where, size, *value);
|
||||
break;
|
||||
case 4:
|
||||
*value = retValue;
|
||||
DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %08lX\n",
|
||||
PCI_SLOT(devfn), where, size, *value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int bcm96348_pcibios_read(struct pci_bus *bus, unsigned int devfn,
|
||||
int where, int size, u32 * val)
|
||||
{
|
||||
volatile unsigned char *ioBase = (unsigned char *)(mpi->l2piobase | KSEG1);
|
||||
uint32 data;
|
||||
|
||||
#if defined(CONFIG_USB)
|
||||
if (PCI_SLOT(devfn) == USB_HOST_SLOT)
|
||||
return pci63xx_int_read(devfn, where, val, size);
|
||||
#endif
|
||||
|
||||
mpi_SetupPciConfigAccess(BCM_PCI_CFG(PCI_SLOT(devfn), PCI_FUNC(devfn), where));
|
||||
data = *(uint32 *)ioBase;
|
||||
switch(size) {
|
||||
case 1:
|
||||
*val = (data >> ((where & 3) << 3)) & 0xff;
|
||||
break;
|
||||
case 2:
|
||||
*val = (data >> ((where & 3) << 3)) & 0xffff;
|
||||
break;
|
||||
case 4:
|
||||
*val = data;
|
||||
/* Special case for reading PCI device range */
|
||||
if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5)) {
|
||||
if (pci_mem_size_rd) {
|
||||
/* bcm6348 PCI memory window minimum size is 64K */
|
||||
*val &= PCI_SIZE_64K;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pci_mem_size_rd = FALSE;
|
||||
mpi_ClearPciConfigAccess();
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int bcm96348_pcibios_write(struct pci_bus *bus, unsigned int devfn,
|
||||
int where, int size, u32 val)
|
||||
{
|
||||
volatile unsigned char *ioBase = (unsigned char *)(mpi->l2piobase | KSEG1);
|
||||
uint32 data;
|
||||
|
||||
#if defined(CONFIG_USB)
|
||||
if (PCI_SLOT(devfn) == USB_HOST_SLOT)
|
||||
return pci63xx_int_write(devfn, where, &val, size);
|
||||
#endif
|
||||
mpi_SetupPciConfigAccess(BCM_PCI_CFG(PCI_SLOT(devfn), PCI_FUNC(devfn), where));
|
||||
data = *(uint32 *)ioBase;
|
||||
switch(size) {
|
||||
case 1:
|
||||
data = (data & ~(0xff << ((where & 3) << 3))) |
|
||||
(val << ((where & 3) << 3));
|
||||
break;
|
||||
case 2:
|
||||
data = (data & ~(0xffff << ((where & 3) << 3))) |
|
||||
(val << ((where & 3) << 3));
|
||||
break;
|
||||
case 4:
|
||||
data = val;
|
||||
/* Special case for reading PCI device range */
|
||||
if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5)) {
|
||||
if (val == 0xffffffff)
|
||||
pci_mem_size_rd = TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*(uint32 *)ioBase = data;
|
||||
udelay(500);
|
||||
mpi_ClearPciConfigAccess();
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
struct pci_ops bcm96348_pci_ops = {
|
||||
.read = bcm96348_pcibios_read,
|
||||
.write = bcm96348_pcibios_write
|
||||
};
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
<:copyright-gpl
|
||||
Copyright 2002 Broadcom Corp. All Rights Reserved.
|
||||
|
||||
This program is free software; you can distribute 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 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/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <bcmpci.h>
|
||||
|
||||
static struct resource bcm_pci_io_resource = {
|
||||
.name = "bcm96348 pci IO space",
|
||||
.start = BCM_PCI_IO_BASE,
|
||||
.end = BCM_PCI_IO_BASE + BCM_PCI_IO_SIZE_64KB - 1,
|
||||
.flags = IORESOURCE_IO
|
||||
};
|
||||
|
||||
static struct resource bcm_pci_mem_resource = {
|
||||
.name = "bcm96348 pci memory space",
|
||||
.start = BCM_PCI_MEM_BASE,
|
||||
.end = BCM_PCI_MEM_BASE + BCM_PCI_MEM_SIZE_16MB - 1,
|
||||
.flags = IORESOURCE_MEM
|
||||
};
|
||||
|
||||
extern struct pci_ops bcm96348_pci_ops;
|
||||
|
||||
struct pci_controller bcm96348_controller = {
|
||||
.pci_ops = &bcm96348_pci_ops,
|
||||
.io_resource = &bcm_pci_io_resource,
|
||||
.mem_resource = &bcm_pci_mem_resource,
|
||||
};
|
||||
|
||||
static __init int bcm96348_pci_init(void)
|
||||
{
|
||||
/* Avoid ISA compat ranges. */
|
||||
PCIBIOS_MIN_IO = 0x00000000;
|
||||
PCIBIOS_MIN_MEM = 0x00000000;
|
||||
|
||||
/* Set I/O resource limits. */
|
||||
ioport_resource.end = 0x1fffffff;
|
||||
iomem_resource.end = 0xffffffff;
|
||||
|
||||
register_pci_controller(&bcm96348_controller);
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_initcall(bcm96348_pci_init);
|
||||
Reference in New Issue
Block a user