1
0
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:
florian
2008-11-15 11:21:42 +00:00
parent e3c583df0f
commit 42dd4ac5f0
47 changed files with 0 additions and 7502 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);

View File

@@ -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 */
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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");

View File

@@ -1,5 +0,0 @@
#
# Makefile for the Broadcom Common Firmware Environment support
#
obj-y += cfe.o

View File

@@ -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;
}

View File

@@ -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_ */

View File

@@ -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}
};*/

View File

@@ -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
};

View File

@@ -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);