diff options
Diffstat (limited to 'target/linux/brcm47xx/files-2.6.23/arch/mips')
11 files changed, 1567 insertions, 0 deletions
| diff --git a/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/Makefile b/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/Makefile new file mode 100644 index 000000000..f80945c8b --- /dev/null +++ b/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the BCM47xx specific kernel interface routines +# under Linux. +# + +obj-y := irq.o prom.o setup.o time.o +obj-y += nvram.o cfe_env.o diff --git a/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/cfe_env.c b/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/cfe_env.c new file mode 100644 index 000000000..c1d5eeef5 --- /dev/null +++ b/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/cfe_env.c @@ -0,0 +1,229 @@ +/* + * CFE environment variable access + * + * Copyright 2001-2003, Broadcom Corporation + * Copyright 2006, Felix Fietkau <nbd@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/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <asm/io.h> +#include <asm/uaccess.h> + +#define NVRAM_SIZE       (0x1ff0) +static char _nvdata[NVRAM_SIZE]; +static char _valuestr[256]; + +/* + * TLV types.  These codes are used in the "type-length-value" + * encoding of the items stored in the NVRAM device (flash or EEPROM) + * + * The layout of the flash/nvram is as follows: + * + * <type> <length> <data ...> <type> <length> <data ...> <type_end> + * + * The type code of "ENV_TLV_TYPE_END" marks the end of the list. + * The "length" field marks the length of the data section, not + * including the type and length fields. + * + * Environment variables are stored as follows: + * + * <type_env> <length> <flags> <name> = <value> + * + * If bit 0 (low bit) is set, the length is an 8-bit value. + * If bit 0 (low bit) is clear, the length is a 16-bit value + *  + * Bit 7 set indicates "user" TLVs.  In this case, bit 0 still + * indicates the size of the length field.   + * + * Flags are from the constants below: + * + */ +#define ENV_LENGTH_16BITS	0x00	/* for low bit */ +#define ENV_LENGTH_8BITS	0x01 + +#define ENV_TYPE_USER		0x80 + +#define ENV_CODE_SYS(n,l) (((n)<<1)|(l)) +#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER) + +/* + * The actual TLV types we support + */ + +#define ENV_TLV_TYPE_END	0x00	 +#define ENV_TLV_TYPE_ENV	ENV_CODE_SYS(0,ENV_LENGTH_8BITS) + +/* + * Environment variable flags  + */ + +#define ENV_FLG_NORMAL		0x00	/* normal read/write */ +#define ENV_FLG_BUILTIN		0x01	/* builtin - not stored in flash */ +#define ENV_FLG_READONLY	0x02	/* read-only - cannot be changed */ + +#define ENV_FLG_MASK		0xFF	/* mask of attributes we keep */ +#define ENV_FLG_ADMIN		0x100	/* lets us internally override permissions */ + + +/*  ********************************************************************* +    *  _nvram_read(buffer,offset,length) +    *   +    *  Read data from the NVRAM device +    *   +    *  Input parameters:  +    *  	   buffer - destination buffer +    *  	   offset - offset of data to read +    *  	   length - number of bytes to read +    *  	    +    *  Return value: +    *  	   number of bytes read, or <0 if error occured +    ********************************************************************* */ +static int +_nvram_read(unsigned char *nv_buf, unsigned char *buffer, int offset, int length) +{ +    int i; +    if (offset > NVRAM_SIZE) +	return -1;  + +    for ( i = 0; i < length; i++) { +	buffer[i] = ((volatile unsigned char*)nv_buf)[offset + i]; +    } +    return length; +} + + +static char* +_strnchr(const char *dest,int c,size_t cnt) +{ +	while (*dest && (cnt > 0)) { +	if (*dest == c) return (char *) dest; +	dest++; +	cnt--; +	} +	return NULL; +} + + + +/* + * Core support API: Externally visible. + */ + +/* + * Get the value of an NVRAM variable + * @param	name	name of variable to get + * @return	value of variable or NULL if undefined + */ + +char*  +cfe_env_get(unsigned char *nv_buf, char* name) +{ +    int size; +    unsigned char *buffer; +    unsigned char *ptr; +    unsigned char *envval; +    unsigned int reclen; +    unsigned int rectype; +    int offset; +    int flg; +     +	if (!strcmp(name, "nvram_type")) +		return "cfe"; +	 +    size = NVRAM_SIZE; +    buffer = &_nvdata[0]; + +    ptr = buffer; +    offset = 0; + +    /* Read the record type and length */ +    if (_nvram_read(nv_buf, ptr,offset,1) != 1) { +	goto error; +    } +     +    while ((*ptr != ENV_TLV_TYPE_END)  && (size > 1)) { + +	/* Adjust pointer for TLV type */ +	rectype = *(ptr); +	offset++; +	size--; + +	/*  +	 * Read the length.  It can be either 1 or 2 bytes +	 * depending on the code  +	 */ +	if (rectype & ENV_LENGTH_8BITS) { +	    /* Read the record type and length - 8 bits */ +	    if (_nvram_read(nv_buf, ptr,offset,1) != 1) { +		goto error; +	    } +	    reclen = *(ptr); +	    size--; +	    offset++; +	} +	else { +	    /* Read the record type and length - 16 bits, MSB first */ +	    if (_nvram_read(nv_buf, ptr,offset,2) != 2) { +		goto error; +	    } +	    reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1); +	    size -= 2; +	    offset += 2; +	} + +	if (reclen > size) +	    break;	/* should not happen, bad NVRAM */ + +	switch (rectype) { +	    case ENV_TLV_TYPE_ENV: +		/* Read the TLV data */ +		if (_nvram_read(nv_buf, ptr,offset,reclen) != reclen) +		    goto error; +		flg = *ptr++; +		envval = (unsigned char *) _strnchr(ptr,'=',(reclen-1)); +		if (envval) { +		    *envval++ = '\0'; +		    memcpy(_valuestr,envval,(reclen-1)-(envval-ptr)); +		    _valuestr[(reclen-1)-(envval-ptr)] = '\0'; +#if 0			 +		    printk(KERN_INFO "NVRAM:%s=%s\n", ptr, _valuestr); +#endif +		    if(!strcmp(ptr, name)){ +			return _valuestr; +		    } +		    if((strlen(ptr) > 1) && !strcmp(&ptr[1], name)) +			return _valuestr; +		} +		break; +		 +	    default:  +		/* Unknown TLV type, skip it. */ +		break; +	    } + +	/* +	 * Advance to next TLV  +	 */ +		 +	size -= (int)reclen; +	offset += reclen; + +	/* Read the next record type */ +	ptr = buffer; +	if (_nvram_read(nv_buf, ptr,offset,1) != 1) +	    goto error; +	} + +error: +    return NULL; + +} + diff --git a/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/include/nvram.h b/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/include/nvram.h new file mode 100644 index 000000000..6bb18e8e5 --- /dev/null +++ b/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/include/nvram.h @@ -0,0 +1,37 @@ +/* + *  Copyright (C) 2006 Felix Fietkau <nbd@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. + */ + +#ifndef __NVRAM_H +#define __NVRAM_H + +struct nvram_header { +	u32 magic; +	u32 len; +	u32 crc_ver_init;	/* 0:7 crc, 8:15 ver, 16:31 sdram_init */ +	u32 config_refresh;	/* 0:15 sdram_config, 16:31 sdram_refresh */ +	u32 config_ncdl;	/* ncdl values for memc */ +}; + +struct nvram_tuple { +	char *name; +	char *value; +	struct nvram_tuple *next; +}; + +#define NVRAM_HEADER		0x48534C46	/* 'FLSH' */ +#define NVRAM_VERSION		1 +#define NVRAM_HEADER_SIZE	20 +#define NVRAM_SPACE		0x8000 + +#define NVRAM_MAX_VALUE_LEN 255 +#define NVRAM_MAX_PARAM_LEN 64 + +char *nvram_get(const char *name); + +#endif diff --git a/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/irq.c b/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/irq.c new file mode 100644 index 000000000..d70789435 --- /dev/null +++ b/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/irq.c @@ -0,0 +1,86 @@ +/* + *  Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org) + *  Copyright (C) 2008 Michael Buesch <mb@bu3sch.de> + * + *  This program is free software; you can redistribute  it and/or modify it + *  under  the terms of  the GNU General  Public License as published by the + *  Free Software Foundation;  either version 2 of the  License, or (at your + *  option) any later version. + * + *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED + *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN + *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   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) ARISING IN ANY WAY OUT OF THE USE OF + *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *  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., + *  675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/module.h> +#include <linux/smp.h> +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/ssb/ssb.h> + +#include <asm/cpu.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/irq_cpu.h> + + +extern struct ssb_bus ssb; + + +void plat_irq_dispatch(void) +{ +	u32 cause; + +	cause = read_c0_cause() & read_c0_status() & CAUSEF_IP; + +	clear_c0_status(cause); + +	if (cause & CAUSEF_IP7) +		do_IRQ(7); +	if (cause & CAUSEF_IP2) +		do_IRQ(2); +	if (cause & CAUSEF_IP3) +		do_IRQ(3); +	if (cause & CAUSEF_IP4) +		do_IRQ(4); +	if (cause & CAUSEF_IP5) +		do_IRQ(5); +	if (cause & CAUSEF_IP6) +		do_IRQ(6); +} + +void __init arch_init_irq(void) +{ +	mips_cpu_irq_init(); +} + +int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ +	int res; + +	res = ssb_pcibios_map_irq(dev, slot, pin); +	if (res < 0) { +		printk(KERN_ALERT "PCI: Failed to map IRQ of device %s\n", +		       dev->dev.bus_id); +		return 0; +	} +	/* IRQ-0 and IRQ-1 are software interrupts. */ +	WARN_ON((res == 0) || (res == 1)); + +	return res; +} diff --git a/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/nvram.c b/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/nvram.c new file mode 100644 index 000000000..3f32ad9d6 --- /dev/null +++ b/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/nvram.c @@ -0,0 +1,125 @@ +/* + * BCM947xx nvram variable access + * + * Copyright 2005, Broadcom Corporation + * Copyright 2006, Felix Fietkau <nbd@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/init.h> +#include <linux/module.h> +#include <linux/ssb/ssb.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/slab.h> +#include <asm/byteorder.h> +#include <asm/bootinfo.h> +#include <asm/addrspace.h> +#include <asm/io.h> +#include <asm/uaccess.h> + +#include <nvram.h> + +#define MB * 1048576 +extern struct ssb_bus ssb; + +static char nvram_buf[NVRAM_SPACE]; +static int cfe_env; +extern char *cfe_env_get(char *nv_buf, const char *name); +		 +/* Probe for NVRAM header */ +static void __init early_nvram_init(void) +{ +	struct ssb_mipscore *mcore = &ssb.mipscore; +	struct nvram_header *header; +	int i; +	u32 base, lim, off; +	u32 *src, *dst; +	 +	base = mcore->flash_window; +	lim = mcore->flash_window_size; +	cfe_env = 0; + +	 +	/* XXX: hack for supporting the CFE environment stuff on WGT634U */ +	if (lim >= 8 MB) { +		src = (u32 *) KSEG1ADDR(base + 8 MB - 0x2000); +		dst = (u32 *) nvram_buf; + +		if ((*src & 0xff00ff) == 0x000001) { +			printk("early_nvram_init: WGT634U NVRAM found.\n"); + +			for (i = 0; i < 0x1ff0; i++) { +				if (*src == 0xFFFFFFFF) +					break; +				*dst++ = *src++; +			} +			cfe_env = 1; +			return; +		} +	} + +	off = 0x20000; +	while (off <= lim) { +		/* Windowed flash access */ +		header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE); +		if (header->magic == NVRAM_HEADER) +			goto found; +		off <<= 1; +	} + +	/* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ +	header = (struct nvram_header *) KSEG1ADDR(base + 4096); +	if (header->magic == NVRAM_HEADER) +		goto found; +	 +	header = (struct nvram_header *) KSEG1ADDR(base + 1024); +	if (header->magic == NVRAM_HEADER) +		goto found; +	 +	return; + +found: +	src = (u32 *) header; +	dst = (u32 *) nvram_buf; +	for (i = 0; i < sizeof(struct nvram_header); i += 4) +		*dst++ = *src++; +	for (; i < header->len && i < NVRAM_SPACE; i += 4) +		*dst++ = le32_to_cpu(*src++); +} + +char *nvram_get(const char *name) +{ +	char *var, *value, *end, *eq; + +	if (!name) +		return NULL; + +	if (!nvram_buf[0]) +		early_nvram_init(); + +	if (cfe_env) +		return cfe_env_get(nvram_buf, name); + +	/* Look for name=value and return value */ +	var = &nvram_buf[sizeof(struct nvram_header)]; +	end = nvram_buf + sizeof(nvram_buf) - 2; +	end[0] = end[1] = '\0'; +	for (; *var; var = value + strlen(value) + 1) { +		if (!(eq = strchr(var, '='))) +			break; +		value = eq + 1; +		if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0) +			return value; +	} + +	return NULL; +} + +EXPORT_SYMBOL(nvram_get); diff --git a/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/prom.c b/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/prom.c new file mode 100644 index 000000000..41ea0870b --- /dev/null +++ b/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/prom.c @@ -0,0 +1,61 @@ +/* + *  Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.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. + * + *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED + *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN + *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   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) ARISING IN ANY WAY OUT OF THE USE OF + *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *  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., + *  675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/bootmem.h> + +#include <asm/addrspace.h> +#include <asm/bootinfo.h> +#include <asm/pmon.h> +#include "../cfe/cfe_private.h" + +const char *get_system_type(void) +{ +	return "Broadcom BCM47xx"; +} + +void __init prom_init(void) +{ +	unsigned long mem; + +        mips_machgroup = MACH_GROUP_BRCM; +        mips_machtype = MACH_BCM47XX; + +	cfe_setup(fw_arg0, fw_arg1, fw_arg2, fw_arg3); +		 +	/* Figure out memory size by finding aliases */ +	for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) { +		if (*(unsigned long *)((unsigned long)(prom_init) + mem) ==  +		    *(unsigned long *)(prom_init)) +			break; +	} + +	add_memory_region(0, mem, BOOT_MEM_RAM); +} + +void __init prom_free_prom_memory(void) +{ +} diff --git a/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/setup.c b/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/setup.c new file mode 100644 index 000000000..41d7b0b75 --- /dev/null +++ b/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/setup.c @@ -0,0 +1,246 @@ +/* + *  Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org) + *  Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org> + *  Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> + *  Copyright (C) 2006-2008 Michael Buesch <mb@bu3sch.de> + * + *  This program is free software; you can redistribute  it and/or modify it + *  under  the terms of  the GNU General  Public License as published by the + *  Free Software Foundation;  either version 2 of the  License, or (at your + *  option) any later version. + * + *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED + *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN + *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   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) ARISING IN ANY WAY OUT OF THE USE OF + *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *  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., + *  675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/init.h> +#include <linux/types.h> +#include <linux/tty.h> +#include <linux/serial.h> +#include <linux/serial_core.h> +#include <linux/serial_reg.h> +#include <linux/serial_8250.h> +#include <asm/bootinfo.h> +#include <asm/time.h> +#include <asm/reboot.h> +#include <asm/cfe.h> +#include <linux/pm.h> +#include <linux/ssb/ssb.h> +#include <linux/ssb/ssb_embedded.h> + +#include <nvram.h> + +extern void bcm47xx_pci_init(void); +extern void bcm47xx_time_init(void); + +struct ssb_bus ssb; + + +int pcibios_plat_dev_init(struct pci_dev *dev) +{ +	int err; + +	err = ssb_pcibios_plat_dev_init(dev); +	if (err) { +		printk(KERN_ALERT "PCI: Failed to init device %s\n", +		       pci_name(dev)); +	} + +	return err; +} + +static void bcm47xx_machine_restart(char *command) +{ +	printk(KERN_ALERT "Please stand by while rebooting the system...\n"); +	local_irq_disable(); +	/* CFE has a reboot callback, but that does not work. +	 * Oopses with: Reserved instruction in kernel code. +	 */ + +	/* Set the watchdog timer to reset immediately */ +	if (ssb_watchdog_timer_set(&ssb, 1)) +		printk(KERN_EMERG "SSB watchdog-triggered reboot failed!\n"); +	while (1) +		cpu_relax(); +} + +static void bcm47xx_machine_halt(void) +{ +	/* Disable interrupts and watchdog and spin forever */ +	local_irq_disable(); +	if (ssb_watchdog_timer_set(&ssb, 0)) +		printk(KERN_EMERG "Failed to disable SSB watchdog!\n"); +	while (1) +		cpu_relax(); +} + +static void e_aton(char *str, char *dest) +{ +	int i = 0; + +	if (str == NULL) { +		memset(dest, 0, 6); +		return; +	} +	 +	for (;;) { +		dest[i++] = (char) simple_strtoul(str, NULL, 16); +		str += 2; +		if (!*str++ || i == 6) +			break; +	} +} + +static void bcm47xx_fill_sprom(struct ssb_sprom *sprom) +{ +	char *s; + +	memset(sprom, 0xFF, sizeof(struct ssb_sprom)); + +	sprom->revision = 1; +	if ((s = nvram_get("il0macaddr"))) +		e_aton(s, sprom->il0mac); +	if ((s = nvram_get("et0macaddr"))) +		e_aton(s, sprom->et0mac); +	if ((s = nvram_get("et1macaddr"))) +		e_aton(s, sprom->et1mac); +	if ((s = nvram_get("et0phyaddr"))) +		sprom->et0phyaddr = simple_strtoul(s, NULL, 0); +	if ((s = nvram_get("et1phyaddr"))) +		sprom->et1phyaddr = simple_strtoul(s, NULL, 0); +	if ((s = nvram_get("et0mdcport"))) +		sprom->et0mdcport = !!simple_strtoul(s, NULL, 10); +	if ((s = nvram_get("et1mdcport"))) +		sprom->et1mdcport = !!simple_strtoul(s, NULL, 10); +	if ((s = nvram_get("pa0b0"))) +		sprom->pa0b0 = simple_strtoul(s, NULL, 0); +	if ((s = nvram_get("pa0b1"))) +		sprom->pa0b1 = simple_strtoul(s, NULL, 0); +	if ((s = nvram_get("pa0b2"))) +		sprom->pa0b2 = simple_strtoul(s, NULL, 0); +	if ((s = nvram_get("pa1b0"))) +		sprom->pa1b0 = simple_strtoul(s, NULL, 0); +	if ((s = nvram_get("pa1b1"))) +		sprom->pa1b1 = simple_strtoul(s, NULL, 0); +	if ((s = nvram_get("pa1b2"))) +		sprom->pa1b2 = simple_strtoul(s, NULL, 0); +	if ((s = nvram_get("wl0gpio0"))) +		sprom->gpio0 = simple_strtoul(s, NULL, 0); +	if ((s = nvram_get("wl0gpio1"))) +		sprom->gpio1 = simple_strtoul(s, NULL, 0); +	if ((s = nvram_get("wl0gpio2"))) +		sprom->gpio2 = simple_strtoul(s, NULL, 0); +	if ((s = nvram_get("wl0gpio3"))) +		sprom->gpio3 = simple_strtoul(s, NULL, 0); +	if ((s = nvram_get("pa0maxpwr"))) +		sprom->maxpwr_bg = simple_strtoul(s, NULL, 0); +	if ((s = nvram_get("pa1maxpwr"))) +		sprom->maxpwr_a = simple_strtoul(s, NULL, 0); +	if ((s = nvram_get("pa0itssit"))) +		sprom->itssi_bg = simple_strtoul(s, NULL, 0); +	if ((s = nvram_get("pa1itssit"))) +		sprom->itssi_a = simple_strtoul(s, NULL, 0); +	sprom->boardflags_lo = 0; +	if ((s = nvram_get("boardflags"))) +		sprom->boardflags_lo = simple_strtoul(s, NULL, 0); +	sprom->boardflags_hi = 0; +	if ((s = nvram_get("boardflags2"))) +		sprom->boardflags_hi = simple_strtoul(s, NULL, 0); +} + +static int bcm47xx_get_invariants(struct ssb_bus *bus, struct ssb_init_invariants *iv) +{ +	char *s; + +	iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM; +	if ((s = nvram_get("boardtype"))) +		iv->boardinfo.type = (u16)simple_strtoul(s, NULL, 0); +	if ((s = nvram_get("boardrev"))) +		iv->boardinfo.rev = (u16)simple_strtoul(s, NULL, 0); + +	bcm47xx_fill_sprom(&iv->sprom); + +	if ((s = nvram_get("cardbus"))) +		iv->has_cardbus_slot = !!simple_strtoul(s, NULL, 10); + +	return 0; +} + +void __init plat_mem_setup(void) +{ +	int i, err; +	char *s; +	struct ssb_mipscore *mcore; + +	err = ssb_bus_ssbbus_register(&ssb, SSB_ENUM_BASE, bcm47xx_get_invariants); +	if (err) { +		const char *msg = "Failed to initialize SSB bus (err %d)\n"; +		cfe_printk(msg, err); /* Make sure the message gets out of the box. */ +		panic(msg, err); +	} +	mcore = &ssb.mipscore; + +	s = nvram_get("kernel_args"); +	if (s && !strncmp(s, "console=ttyS1", 13)) { +		struct ssb_serial_port port; + +		cfe_printk("Swapping serial ports!\n"); +		/* swap serial ports */ +		memcpy(&port, &mcore->serial_ports[0], sizeof(port)); +		memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1], sizeof(port)); +		memcpy(&mcore->serial_ports[1], &port, sizeof(port)); +	} + +	for (i = 0; i < mcore->nr_serial_ports; i++) { +		struct ssb_serial_port *port = &(mcore->serial_ports[i]); +		struct uart_port s; +	 +		memset(&s, 0, sizeof(s)); +		s.line = i; +		s.membase = port->regs; +		s.irq = port->irq + 2; +		s.uartclk = port->baud_base; +		s.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; +		s.iotype = SERIAL_IO_MEM; +		s.regshift = port->reg_shift; + +		early_serial_setup(&s); +	} +	cfe_printk("Serial init done.\n"); + +	_machine_restart = bcm47xx_machine_restart; +	_machine_halt = bcm47xx_machine_halt; +	pm_power_off = bcm47xx_machine_halt; +	board_time_init = bcm47xx_time_init; +} + +static int __init bcm47xx_register_gpiodev(void) +{ +	static struct resource res = { +		.start = 0xFFFFFFFF, +	}; +	struct platform_device *pdev; + +	pdev = platform_device_register_simple("GPIODEV", 0, &res, 1); +	if (!pdev) { +		printk(KERN_ERR "bcm47xx: GPIODEV init failed\n"); +		return -ENODEV; +	} + +	return 0; +} +device_initcall(bcm47xx_register_gpiodev); + +EXPORT_SYMBOL(ssb); diff --git a/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/time.c b/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/time.c new file mode 100644 index 000000000..62120ebc7 --- /dev/null +++ b/target/linux/brcm47xx/files-2.6.23/arch/mips/bcm947xx/time.c @@ -0,0 +1,62 @@ +/* + *  Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.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. + * + *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED + *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN + *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   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) ARISING IN ANY WAY OUT OF THE USE OF + *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *  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., + *  675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/serial_reg.h> +#include <linux/interrupt.h> +#include <linux/ssb/ssb.h> +#include <asm/addrspace.h> +#include <asm/io.h> +#include <asm/time.h> + +extern struct ssb_bus ssb; + +void __init +bcm47xx_time_init(void) +{ +	unsigned long hz; + +	/* +	 * Use deterministic values for initial counter interrupt +	 * so that calibrate delay avoids encountering a counter wrap. +	 */ +	write_c0_count(0); +	write_c0_compare(0xffff); + +	hz = ssb_cpu_clock(&ssb.mipscore) / 2; +	if (!hz) +		hz = 100000000; + +	/* Set MIPS counter frequency for fixed_rate_gettimeoffset() */ +	mips_hpt_frequency = hz; +} + +void __init +plat_timer_setup(struct irqaction *irq) +{ +	/* Enable the timer interrupt */ +	setup_irq(7, irq); +} diff --git a/target/linux/brcm47xx/files-2.6.23/arch/mips/cfe/Makefile b/target/linux/brcm47xx/files-2.6.23/arch/mips/cfe/Makefile new file mode 100644 index 000000000..d9f046adf --- /dev/null +++ b/target/linux/brcm47xx/files-2.6.23/arch/mips/cfe/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the Broadcom Common Firmware Environment support +# + +obj-y += cfe.o diff --git a/target/linux/brcm47xx/files-2.6.23/arch/mips/cfe/cfe.c b/target/linux/brcm47xx/files-2.6.23/arch/mips/cfe/cfe.c new file mode 100644 index 000000000..6d16111e1 --- /dev/null +++ b/target/linux/brcm47xx/files-2.6.23/arch/mips/cfe/cfe.c @@ -0,0 +1,533 @@ +/* + * 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; +} diff --git a/target/linux/brcm47xx/files-2.6.23/arch/mips/cfe/cfe_private.h b/target/linux/brcm47xx/files-2.6.23/arch/mips/cfe/cfe_private.h new file mode 100644 index 000000000..0a604d3bb --- /dev/null +++ b/target/linux/brcm47xx/files-2.6.23/arch/mips/cfe/cfe_private.h @@ -0,0 +1,176 @@ +/* + * 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_ */ | 
