Date:2010-07-19 22:25:20 (4 years 3 months ago)
Author:hauke
Commit:9fe2a2d5546fe9370eb9c977d0816dc32e31d461
Message:brcm47xx: prepare brcm47xx patches for sending to mainline.

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@22296 3c298f89-4303-0410-b956-a3cf2f4a3e73
Files: target/linux/brcm47xx/files-2.6.32/arch/mips/bcm47xx/cfe_env.c (1 diff)
target/linux/brcm47xx/files-2.6.32/arch/mips/bcm47xx/include/nvram.h (1 diff)
target/linux/brcm47xx/files-2.6.32/arch/mips/bcm47xx/nvram.c (1 diff)
target/linux/brcm47xx/files-2.6.32/arch/mips/include/asm/mach-bcm47xx/kernel-entry-init.h (1 diff)
target/linux/brcm47xx/files-2.6.32/drivers/mtd/maps/bcm47xx-flash.c (1 diff)
target/linux/brcm47xx/files-2.6.34/drivers/mtd/maps/bcm47xx-flash.c (1 diff)
target/linux/brcm47xx/files-2.6.35/drivers/mtd/maps/bcm47xx-flash.c (1 diff)
target/linux/brcm47xx/files/arch/mips/bcm47xx/cfe_env.c (1 diff)
target/linux/brcm47xx/files/arch/mips/bcm47xx/include/nvram.h (1 diff)
target/linux/brcm47xx/files/arch/mips/bcm47xx/nvram.c (1 diff)
target/linux/brcm47xx/files/arch/mips/include/asm/mach-bcm47xx/kernel-entry-init.h (1 diff)
target/linux/brcm47xx/files/drivers/mtd/maps/bcm47xx-flash.c (1 diff)
target/linux/brcm47xx/patches-2.6.34/001-backport.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/011-MIPS-BCM47xx-Really-fix-128MB-RAM-problem.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/012-MIPS-BCM47xx-Fill-more-values-into-ssb-sprom.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/013-MIPS-BCM47xx-Activate-SSB_B43_PCI_BRIDGE-by-default.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/014-MIPS-BCM47xx-Setup-and-register-serial-early.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/015-MIPS-BCM47xx-Remove-CFE-console.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/021-USB-Add-USB-2.0-to-ssb-ohci-driver.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/022-USB-Add-ehci-ssb-driver.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/130-remove_scache.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/150-cpu_fixes.patch (3 diffs)
target/linux/brcm47xx/patches-2.6.34/170-128MB_ram_bugfix.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/210-b44_phy_fix.patch (3 diffs)
target/linux/brcm47xx/patches-2.6.34/211-b44_timeout_spam.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/220-bcm5354.patch (3 diffs)
target/linux/brcm47xx/patches-2.6.34/250-ohci-ssb-usb2.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/260-ohci-set-dma-mask.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/270-ehci-ssb.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/275-usb2-bcm5354-init.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/301-kmod-fuse-dcache-bug-r4k.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/400-arch-bcm47xx.patch (2 diffs)
target/linux/brcm47xx/patches-2.6.34/800-fix_cfe_detection.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/812-disable_wgt634u_crap.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/900-disable_early_printk.patch (1 diff)
target/linux/brcm47xx/patches-2.6.34/940-bcm47xx-yenta.patch (2 diffs)
target/linux/brcm47xx/patches-2.6.34/999-wl_exports.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/011-MIPS-BCM47xx-Really-fix-128MB-RAM-problem.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/012-MIPS-BCM47xx-Fill-more-values-into-ssb-sprom.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/013-MIPS-BCM47xx-Activate-SSB_B43_PCI_BRIDGE-by-default.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/014-MIPS-BCM47xx-Setup-and-register-serial-early.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/015-MIPS-BCM47xx-Remove-CFE-console.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/021-USB-Add-USB-2.0-to-ssb-ohci-driver.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/022-USB-Add-ehci-ssb-driver.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/130-remove_scache.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/150-cpu_fixes.patch (3 diffs)
target/linux/brcm47xx/patches-2.6.35/170-128MB_ram_bugfix.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/210-b44_phy_fix.patch (3 diffs)
target/linux/brcm47xx/patches-2.6.35/211-b44_timeout_spam.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/220-bcm5354.patch (3 diffs)
target/linux/brcm47xx/patches-2.6.35/250-ohci-ssb-usb2.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/260-ohci-set-dma-mask.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/270-ehci-ssb.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/275-usb2-bcm5354-init.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/301-kmod-fuse-dcache-bug-r4k.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/400-arch-bcm47xx.patch (2 diffs)
target/linux/brcm47xx/patches-2.6.35/700-ssb-gigabit-ethernet-driver.patch (27 diffs)
target/linux/brcm47xx/patches-2.6.35/800-fix_cfe_detection.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/812-disable_wgt634u_crap.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/900-disable_early_printk.patch (1 diff)
target/linux/brcm47xx/patches-2.6.35/940-bcm47xx-yenta.patch (4 diffs)
target/linux/brcm47xx/patches-2.6.35/999-wl_exports.patch (1 diff)
target/linux/generic/patches-2.6.34/975-ssb_update.patch (9 diffs)
target/linux/generic/patches-2.6.34/976-ssb_add_dma_dev.patch (1 diff)
target/linux/generic/patches-2.6.35/975-ssb_update.patch (1 diff)
target/linux/generic/patches-2.6.35/976-ssb_add_dma_dev.patch (1 diff)

Change Details

target/linux/brcm47xx/files-2.6.32/arch/mips/bcm47xx/cfe_env.c
1/*
2 * CFE environment variable access
3 *
4 * Copyright 2001-2003, Broadcom Corporation
5 * Copyright 2006, Felix Fietkau <nbd@openwrt.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/string.h>
17#include <asm/io.h>
18#include <asm/uaccess.h>
19
20#define NVRAM_SIZE (0x1ff0)
21static char _nvdata[NVRAM_SIZE];
22static char _valuestr[256];
23
24/*
25 * TLV types. These codes are used in the "type-length-value"
26 * encoding of the items stored in the NVRAM device (flash or EEPROM)
27 *
28 * The layout of the flash/nvram is as follows:
29 *
30 * <type> <length> <data ...> <type> <length> <data ...> <type_end>
31 *
32 * The type code of "ENV_TLV_TYPE_END" marks the end of the list.
33 * The "length" field marks the length of the data section, not
34 * including the type and length fields.
35 *
36 * Environment variables are stored as follows:
37 *
38 * <type_env> <length> <flags> <name> = <value>
39 *
40 * If bit 0 (low bit) is set, the length is an 8-bit value.
41 * If bit 0 (low bit) is clear, the length is a 16-bit value
42 *
43 * Bit 7 set indicates "user" TLVs. In this case, bit 0 still
44 * indicates the size of the length field.
45 *
46 * Flags are from the constants below:
47 *
48 */
49#define ENV_LENGTH_16BITS 0x00 /* for low bit */
50#define ENV_LENGTH_8BITS 0x01
51
52#define ENV_TYPE_USER 0x80
53
54#define ENV_CODE_SYS(n,l) (((n)<<1)|(l))
55#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER)
56
57/*
58 * The actual TLV types we support
59 */
60
61#define ENV_TLV_TYPE_END 0x00
62#define ENV_TLV_TYPE_ENV ENV_CODE_SYS(0,ENV_LENGTH_8BITS)
63
64/*
65 * Environment variable flags
66 */
67
68#define ENV_FLG_NORMAL 0x00 /* normal read/write */
69#define ENV_FLG_BUILTIN 0x01 /* builtin - not stored in flash */
70#define ENV_FLG_READONLY 0x02 /* read-only - cannot be changed */
71
72#define ENV_FLG_MASK 0xFF /* mask of attributes we keep */
73#define ENV_FLG_ADMIN 0x100 /* lets us internally override permissions */
74
75
76/* *********************************************************************
77    * _nvram_read(buffer,offset,length)
78    *
79    * Read data from the NVRAM device
80    *
81    * Input parameters:
82    * buffer - destination buffer
83    * offset - offset of data to read
84    * length - number of bytes to read
85    *
86    * Return value:
87    * number of bytes read, or <0 if error occured
88    ********************************************************************* */
89static int
90_nvram_read(unsigned char *nv_buf, unsigned char *buffer, int offset, int length)
91{
92    int i;
93    if (offset > NVRAM_SIZE)
94    return -1;
95
96    for ( i = 0; i < length; i++) {
97    buffer[i] = ((volatile unsigned char*)nv_buf)[offset + i];
98    }
99    return length;
100}
101
102
103static char*
104_strnchr(const char *dest,int c,size_t cnt)
105{
106    while (*dest && (cnt > 0)) {
107    if (*dest == c) return (char *) dest;
108    dest++;
109    cnt--;
110    }
111    return NULL;
112}
113
114
115
116/*
117 * Core support API: Externally visible.
118 */
119
120/*
121 * Get the value of an NVRAM variable
122 * @param name name of variable to get
123 * @return value of variable or NULL if undefined
124 */
125
126char*
127cfe_env_get(unsigned char *nv_buf, char* name)
128{
129    int size;
130    unsigned char *buffer;
131    unsigned char *ptr;
132    unsigned char *envval;
133    unsigned int reclen;
134    unsigned int rectype;
135    int offset;
136    int flg;
137
138    if (!strcmp(name, "nvram_type"))
139        return "cfe";
140
141    size = NVRAM_SIZE;
142    buffer = &_nvdata[0];
143
144    ptr = buffer;
145    offset = 0;
146
147    /* Read the record type and length */
148    if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
149    goto error;
150    }
151
152    while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) {
153
154    /* Adjust pointer for TLV type */
155    rectype = *(ptr);
156    offset++;
157    size--;
158
159    /*
160     * Read the length. It can be either 1 or 2 bytes
161     * depending on the code
162     */
163    if (rectype & ENV_LENGTH_8BITS) {
164        /* Read the record type and length - 8 bits */
165        if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
166        goto error;
167        }
168        reclen = *(ptr);
169        size--;
170        offset++;
171    }
172    else {
173        /* Read the record type and length - 16 bits, MSB first */
174        if (_nvram_read(nv_buf, ptr,offset,2) != 2) {
175        goto error;
176        }
177        reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1);
178        size -= 2;
179        offset += 2;
180    }
181
182    if (reclen > size)
183        break; /* should not happen, bad NVRAM */
184
185    switch (rectype) {
186        case ENV_TLV_TYPE_ENV:
187        /* Read the TLV data */
188        if (_nvram_read(nv_buf, ptr,offset,reclen) != reclen)
189            goto error;
190        flg = *ptr++;
191        envval = (unsigned char *) _strnchr(ptr,'=',(reclen-1));
192        if (envval) {
193            *envval++ = '\0';
194            memcpy(_valuestr,envval,(reclen-1)-(envval-ptr));
195            _valuestr[(reclen-1)-(envval-ptr)] = '\0';
196#if 0
197            printk(KERN_INFO "NVRAM:%s=%s\n", ptr, _valuestr);
198#endif
199            if(!strcmp(ptr, name)){
200            return _valuestr;
201            }
202            if((strlen(ptr) > 1) && !strcmp(&ptr[1], name))
203            return _valuestr;
204        }
205        break;
206
207        default:
208        /* Unknown TLV type, skip it. */
209        break;
210        }
211
212    /*
213     * Advance to next TLV
214     */
215
216    size -= (int)reclen;
217    offset += reclen;
218
219    /* Read the next record type */
220    ptr = buffer;
221    if (_nvram_read(nv_buf, ptr,offset,1) != 1)
222        goto error;
223    }
224
225error:
226    return NULL;
227
228}
229
target/linux/brcm47xx/files-2.6.32/arch/mips/bcm47xx/include/nvram.h
1/*
2 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 */
9
10#ifndef __NVRAM_H
11#define __NVRAM_H
12
13struct nvram_header {
14    u32 magic;
15    u32 len;
16    u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
17    u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */
18    u32 config_ncdl; /* ncdl values for memc */
19};
20
21struct nvram_tuple {
22    char *name;
23    char *value;
24    struct nvram_tuple *next;
25};
26
27#define NVRAM_HEADER 0x48534C46 /* 'FLSH' */
28#define NVRAM_VERSION 1
29#define NVRAM_HEADER_SIZE 20
30#define NVRAM_SPACE 0x8000
31
32#define NVRAM_MAX_VALUE_LEN 255
33#define NVRAM_MAX_PARAM_LEN 64
34
35char *nvram_get(const char *name);
36
37#endif
target/linux/brcm47xx/files-2.6.32/arch/mips/bcm47xx/nvram.c
1/*
2 * BCM947xx nvram variable access
3 *
4 * Copyright 2005, Broadcom Corporation
5 * Copyright 2006, Felix Fietkau <nbd@openwrt.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/ssb/ssb.h>
16#include <linux/kernel.h>
17#include <linux/string.h>
18#include <linux/interrupt.h>
19#include <linux/spinlock.h>
20#include <linux/slab.h>
21#include <asm/byteorder.h>
22#include <asm/bootinfo.h>
23#include <asm/addrspace.h>
24#include <asm/io.h>
25#include <asm/uaccess.h>
26
27#include <nvram.h>
28
29#define MB * 1048576
30extern struct ssb_bus ssb;
31
32static char nvram_buf[NVRAM_SPACE];
33static int cfe_env;
34extern char *cfe_env_get(char *nv_buf, const char *name);
35
36/* Probe for NVRAM header */
37static void __init early_nvram_init(void)
38{
39    struct ssb_mipscore *mcore = &ssb.mipscore;
40    struct nvram_header *header;
41    int i;
42    u32 base, lim, off;
43    u32 *src, *dst;
44
45    base = mcore->flash_window;
46    lim = mcore->flash_window_size;
47    cfe_env = 0;
48
49
50    /* XXX: hack for supporting the CFE environment stuff on WGT634U */
51    if (lim >= 8 MB) {
52        src = (u32 *) KSEG1ADDR(base + 8 MB - 0x2000);
53        dst = (u32 *) nvram_buf;
54
55        if ((*src & 0xff00ff) == 0x000001) {
56            printk("early_nvram_init: WGT634U NVRAM found.\n");
57
58            for (i = 0; i < 0x1ff0; i++) {
59                if (*src == 0xFFFFFFFF)
60                    break;
61                *dst++ = *src++;
62            }
63            cfe_env = 1;
64            return;
65        }
66    }
67
68    off = 0x20000;
69    while (off <= lim) {
70        /* Windowed flash access */
71        header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE);
72        if (header->magic == NVRAM_HEADER)
73            goto found;
74        off <<= 1;
75    }
76
77    /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
78    header = (struct nvram_header *) KSEG1ADDR(base + 4096);
79    if (header->magic == NVRAM_HEADER)
80        goto found;
81
82    header = (struct nvram_header *) KSEG1ADDR(base + 1024);
83    if (header->magic == NVRAM_HEADER)
84        goto found;
85
86    return;
87
88found:
89    src = (u32 *) header;
90    dst = (u32 *) nvram_buf;
91    for (i = 0; i < sizeof(struct nvram_header); i += 4)
92        *dst++ = *src++;
93    for (; i < header->len && i < NVRAM_SPACE; i += 4)
94        *dst++ = le32_to_cpu(*src++);
95}
96
97char *nvram_get(const char *name)
98{
99    char *var, *value, *end, *eq;
100
101    if (!name)
102        return NULL;
103
104    if (!nvram_buf[0])
105        early_nvram_init();
106
107    if (cfe_env)
108        return cfe_env_get(nvram_buf, name);
109
110    /* Look for name=value and return value */
111    var = &nvram_buf[sizeof(struct nvram_header)];
112    end = nvram_buf + sizeof(nvram_buf) - 2;
113    end[0] = end[1] = '\0';
114    for (; *var; var = value + strlen(value) + 1) {
115        if (!(eq = strchr(var, '=')))
116            break;
117        value = eq + 1;
118        if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0)
119            return value;
120    }
121
122    return NULL;
123}
124
125EXPORT_SYMBOL(nvram_get);
target/linux/brcm47xx/files-2.6.32/arch/mips/include/asm/mach-bcm47xx/kernel-entry-init.h
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2005 Embedded Alley Solutions, Inc
7 * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
8 * Copyright (C) 2006 Michael Buesch
9 */
10#ifndef __ASM_MACH_GENERIC_KERNEL_ENTRY_H
11#define __ASM_MACH_GENERIC_KERNEL_ENTRY_H
12
13/* Intentionally empty macro, used in head.S. Override in
14 * arch/mips/mach-xxx/kernel-entry-init.h when necessary.
15 */
16    .macro kernel_entry_setup
17    .endm
18
19/*
20 * Do SMP slave processor setup necessary before we can savely execute C code.
21 */
22    .macro smp_slave_setup
23    .endm
24
25
26#endif /* __ASM_MACH_GENERIC_KERNEL_ENTRY_H */
target/linux/brcm47xx/files-2.6.32/drivers/mtd/maps/bcm47xx-flash.c
1/*
2 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
3 * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
4 * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
5 *
6 * original functions for finding root filesystem from Mike Baker
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 675 Mass Ave, Cambridge, MA 02139, USA.
27 *
28 * Copyright 2001-2003, Broadcom Corporation
29 * All Rights Reserved.
30 *
31 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
32 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
33 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
34 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
35 *
36 * Flash mapping for BCM947XX boards
37 */
38
39#include <linux/init.h>
40#include <linux/module.h>
41#include <linux/types.h>
42#include <linux/kernel.h>
43#include <linux/sched.h>
44#include <linux/wait.h>
45#include <linux/mtd/mtd.h>
46#include <linux/mtd/map.h>
47#ifdef CONFIG_MTD_PARTITIONS
48#include <linux/mtd/partitions.h>
49#endif
50#include <linux/crc32.h>
51#ifdef CONFIG_SSB
52#include <linux/ssb/ssb.h>
53#endif
54#include <asm/io.h>
55
56
57#define TRX_MAGIC 0x30524448 /* "HDR0" */
58#define TRX_VERSION 1
59#define TRX_MAX_LEN 0x3A0000
60#define TRX_NO_HEADER 1 /* Do not write TRX header */
61#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */
62#define TRX_MAX_OFFSET 3
63
64struct trx_header {
65    u32 magic; /* "HDR0" */
66    u32 len; /* Length of file including header */
67    u32 crc32; /* 32-bit CRC from flag_version to end of file */
68    u32 flag_version; /* 0:15 flags, 16:31 version */
69    u32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */
70};
71
72#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
73#define NVRAM_SPACE 0x8000
74#define WINDOW_ADDR 0x1fc00000
75#define WINDOW_SIZE 0x400000
76#define BUSWIDTH 2
77
78#ifdef CONFIG_SSB
79extern struct ssb_bus ssb_bcm47xx;
80#endif
81static struct mtd_info *bcm47xx_mtd;
82
83static void bcm47xx_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
84{
85    if (len==1) {
86        memcpy_fromio(to, map->virt + from, len);
87    } else {
88        int i;
89        u16 *dest = (u16 *) to;
90        u16 *src = (u16 *) (map->virt + from);
91        for (i = 0; i < (len / 2); i++) {
92            dest[i] = src[i];
93        }
94        if (len & 1)
95            *((u8 *)dest+len-1) = src[i] & 0xff;
96    }
97}
98
99static struct map_info bcm47xx_map = {
100    name: "Physically mapped flash",
101    size: WINDOW_SIZE,
102    bankwidth: BUSWIDTH,
103    phys: WINDOW_ADDR,
104};
105
106#ifdef CONFIG_MTD_PARTITIONS
107
108static struct mtd_partition bcm47xx_parts[] = {
109    { name: "cfe", offset: 0, size: 0, mask_flags: MTD_WRITEABLE, },
110    { name: "linux", offset: 0, size: 0, },
111    { name: "rootfs", offset: 0, size: 0, },
112    { name: "nvram", offset: 0, size: 0, },
113    { name: NULL, },
114};
115
116static int __init
117find_cfe_size(struct mtd_info *mtd, size_t size)
118{
119    struct trx_header *trx;
120    unsigned char buf[512];
121    int off;
122    size_t len;
123    int blocksize;
124
125    trx = (struct trx_header *) buf;
126
127    blocksize = mtd->erasesize;
128    if (blocksize < 0x10000)
129        blocksize = 0x10000;
130
131    for (off = (128*1024); off < size; off += blocksize) {
132        memset(buf, 0xe5, sizeof(buf));
133
134        /*
135         * Read into buffer
136         */
137        if (mtd->read(mtd, off, sizeof(buf), &len, buf) ||
138            len != sizeof(buf))
139            continue;
140
141        /* found a TRX header */
142        if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
143            goto found;
144        }
145    }
146
147    printk(KERN_NOTICE
148           "%s: Couldn't find bootloader size\n",
149           mtd->name);
150    return -1;
151
152 found:
153    printk(KERN_NOTICE "bootloader size: %d\n", off);
154    return off;
155
156}
157
158/*
159 * Copied from mtdblock.c
160 *
161 * Cache stuff...
162 *
163 * Since typical flash erasable sectors are much larger than what Linux's
164 * buffer cache can handle, we must implement read-modify-write on flash
165 * sectors for each block write requests. To avoid over-erasing flash sectors
166 * and to speed things up, we locally cache a whole flash sector while it is
167 * being written to until a different sector is required.
168 */
169
170static void erase_callback(struct erase_info *done)
171{
172    wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
173    wake_up(wait_q);
174}
175
176static int erase_write (struct mtd_info *mtd, unsigned long pos,
177            int len, const char *buf)
178{
179    struct erase_info erase;
180    DECLARE_WAITQUEUE(wait, current);
181    wait_queue_head_t wait_q;
182    size_t retlen;
183    int ret;
184
185    /*
186     * First, let's erase the flash block.
187     */
188
189    init_waitqueue_head(&wait_q);
190    erase.mtd = mtd;
191    erase.callback = erase_callback;
192    erase.addr = pos;
193    erase.len = len;
194    erase.priv = (u_long)&wait_q;
195
196    set_current_state(TASK_INTERRUPTIBLE);
197    add_wait_queue(&wait_q, &wait);
198
199    ret = mtd->erase(mtd, &erase);
200    if (ret) {
201        set_current_state(TASK_RUNNING);
202        remove_wait_queue(&wait_q, &wait);
203        printk (KERN_WARNING "erase of region [0x%lx, 0x%x] "
204                     "on \"%s\" failed\n",
205            pos, len, mtd->name);
206        return ret;
207    }
208
209    schedule(); /* Wait for erase to finish. */
210    remove_wait_queue(&wait_q, &wait);
211
212    /*
213     * Next, writhe data to flash.
214     */
215
216    ret = mtd->write (mtd, pos, len, &retlen, buf);
217    if (ret)
218        return ret;
219    if (retlen != len)
220        return -EIO;
221    return 0;
222}
223
224
225static int __init
226find_dual_image_off (struct mtd_info *mtd, size_t size)
227{
228    struct trx_header trx;
229    int off, blocksize;
230    size_t len;
231
232    blocksize = mtd->erasesize;
233    if (blocksize < 0x10000)
234        blocksize = 0x10000;
235
236    for (off = (128*1024); off < size; off += blocksize) {
237        memset(&trx, 0xe5, sizeof(trx));
238        /*
239        * Read into buffer
240        */
241        if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) ||
242            len != sizeof(trx))
243            continue;
244        /* found last TRX header */
245        if (le32_to_cpu(trx.magic) == TRX_MAGIC){
246            if (le32_to_cpu(trx.flag_version >> 16)==2){
247                printk("dual image TRX header found\n");
248                return size/2;
249            } else {
250                return 0;
251            }
252        }
253    }
254    return 0;
255}
256
257
258static int __init
259find_root(struct mtd_info *mtd, size_t size, struct mtd_partition *part)
260{
261    struct trx_header trx, *trx2;
262    unsigned char buf[512], *block;
263    int off, blocksize;
264    u32 i, crc = ~0;
265    size_t len;
266
267    blocksize = mtd->erasesize;
268    if (blocksize < 0x10000)
269        blocksize = 0x10000;
270
271    for (off = (128*1024); off < size; off += blocksize) {
272        memset(&trx, 0xe5, sizeof(trx));
273
274        /*
275         * Read into buffer
276         */
277        if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) ||
278            len != sizeof(trx))
279            continue;
280
281        /* found a TRX header */
282        if (le32_to_cpu(trx.magic) == TRX_MAGIC) {
283            part->offset = le32_to_cpu(trx.offsets[2]) ? :
284                le32_to_cpu(trx.offsets[1]);
285            part->size = le32_to_cpu(trx.len);
286
287            part->size -= part->offset;
288            part->offset += off;
289
290            goto found;
291        }
292    }
293
294    printk(KERN_NOTICE
295           "%s: Couldn't find root filesystem\n",
296           mtd->name);
297    return -1;
298
299 found:
300    if (part->size == 0)
301        return 0;
302
303    if (mtd->read(mtd, part->offset, sizeof(buf), &len, buf) || len != sizeof(buf))
304        return 0;
305
306    /* Move the fs outside of the trx */
307    part->size = 0;
308
309    if (trx.len != part->offset + part->size - off) {
310        /* Update the trx offsets and length */
311        trx.len = part->offset + part->size - off;
312
313        /* Update the trx crc32 */
314        for (i = (u32) &(((struct trx_header *)NULL)->flag_version); i <= trx.len; i += sizeof(buf)) {
315            if (mtd->read(mtd, off + i, sizeof(buf), &len, buf) || len != sizeof(buf))
316                return 0;
317            crc = crc32_le(crc, buf, min(sizeof(buf), trx.len - i));
318        }
319        trx.crc32 = crc;
320
321        /* read first eraseblock from the trx */
322        block = kmalloc(mtd->erasesize, GFP_KERNEL);
323        trx2 = (struct trx_header *) block;
324        if (mtd->read(mtd, off, mtd->erasesize, &len, block) || len != mtd->erasesize) {
325            printk("Error accessing the first trx eraseblock\n");
326            return 0;
327        }
328
329        printk("Updating TRX offsets and length:\n");
330        printk("old trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx2->offsets[0], trx2->offsets[1], trx2->offsets[2], trx2->len, trx2->crc32);
331        printk("new trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx.offsets[0], trx.offsets[1], trx.offsets[2], trx.len, trx.crc32);
332
333        /* Write updated trx header to the flash */
334        memcpy(block, &trx, sizeof(trx));
335        if (mtd->unlock)
336            mtd->unlock(mtd, off, mtd->erasesize);
337        erase_write(mtd, off, mtd->erasesize, block);
338        if (mtd->sync)
339            mtd->sync(mtd);
340        kfree(block);
341        printk("Done\n");
342    }
343
344    return part->size;
345}
346
347struct mtd_partition * __init
348init_mtd_partitions(struct mtd_info *mtd, size_t size)
349{
350    int cfe_size;
351    int dual_image_offset = 0;
352
353    if ((cfe_size = find_cfe_size(mtd,size)) < 0)
354        return NULL;
355
356    /* boot loader */
357    bcm47xx_parts[0].offset = 0;
358    bcm47xx_parts[0].size = cfe_size;
359
360    /* nvram */
361    if (cfe_size != 384 * 1024) {
362        bcm47xx_parts[3].offset = size - ROUNDUP(NVRAM_SPACE, mtd->erasesize);
363        bcm47xx_parts[3].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
364    } else {
365        /* nvram (old 128kb config partition on netgear wgt634u) */
366        bcm47xx_parts[3].offset = bcm47xx_parts[0].size;
367        bcm47xx_parts[3].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
368    }
369
370    /* dual image offset*/
371    printk("Looking for dual image\n");
372    dual_image_offset=find_dual_image_off(mtd,size);
373    /* linux (kernel and rootfs) */
374    if (cfe_size != 384 * 1024) {
375        bcm47xx_parts[1].offset = bcm47xx_parts[0].size;
376        bcm47xx_parts[1].size = bcm47xx_parts[3].offset - dual_image_offset -
377            bcm47xx_parts[1].offset;
378    } else {
379        /* do not count the elf loader, which is on one block */
380        bcm47xx_parts[1].offset = bcm47xx_parts[0].size +
381            bcm47xx_parts[3].size + mtd->erasesize;
382        bcm47xx_parts[1].size = size -
383            bcm47xx_parts[0].size -
384            (2*bcm47xx_parts[3].size) -
385            mtd->erasesize;
386    }
387
388    /* find and size rootfs */
389    find_root(mtd,size,&bcm47xx_parts[2]);
390    bcm47xx_parts[2].size = size - dual_image_offset - bcm47xx_parts[2].offset - bcm47xx_parts[3].size;
391
392    return bcm47xx_parts;
393}
394#endif
395
396int __init init_bcm47xx_map(void)
397{
398#ifdef CONFIG_SSB
399    struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
400#endif
401    size_t size;
402    int ret = 0;
403#ifdef CONFIG_MTD_PARTITIONS
404    struct mtd_partition *parts;
405    int i;
406#endif
407
408#ifdef CONFIG_SSB
409    u32 window = mcore->flash_window;
410    u32 window_size = mcore->flash_window_size;
411
412    printk("flash init: 0x%08x 0x%08x\n", window, window_size);
413    bcm47xx_map.phys = window;
414    bcm47xx_map.size = window_size;
415    bcm47xx_map.bankwidth = mcore->flash_buswidth;
416    bcm47xx_map.virt = ioremap_nocache(window, window_size);
417#else
418    printk("flash init: 0x%08x 0x%08x\n", WINDOW_ADDR, WINDOW_SIZE);
419    bcm47xx_map.virt = ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
420#endif
421
422    if (!bcm47xx_map.virt) {
423        printk("Failed to ioremap\n");
424        return -EIO;
425    }
426
427    simple_map_init(&bcm47xx_map);
428
429    if (!(bcm47xx_mtd = do_map_probe("cfi_probe", &bcm47xx_map))) {
430        printk("Failed to do_map_probe\n");
431        iounmap((void *)bcm47xx_map.virt);
432        return -ENXIO;
433    }
434
435    /* override copy_from routine */
436     bcm47xx_map.copy_from = bcm47xx_map_copy_from;
437
438    bcm47xx_mtd->owner = THIS_MODULE;
439
440    size = bcm47xx_mtd->size;
441
442    printk(KERN_NOTICE "Flash device: 0x%x at 0x%x\n", size, WINDOW_ADDR);
443
444#ifdef CONFIG_MTD_PARTITIONS
445    parts = init_mtd_partitions(bcm47xx_mtd, size);
446    for (i = 0; parts[i].name; i++);
447    ret = add_mtd_partitions(bcm47xx_mtd, parts, i);
448    if (ret) {
449        printk(KERN_ERR "Flash: add_mtd_partitions failed\n");
450        goto fail;
451    }
452#endif
453    return 0;
454
455 fail:
456    if (bcm47xx_mtd)
457        map_destroy(bcm47xx_mtd);
458    if (bcm47xx_map.virt)
459        iounmap((void *)bcm47xx_map.virt);
460    bcm47xx_map.virt = 0;
461    return ret;
462}
463
464void __exit cleanup_bcm47xx_map(void)
465{
466#ifdef CONFIG_MTD_PARTITIONS
467    del_mtd_partitions(bcm47xx_mtd);
468#endif
469    map_destroy(bcm47xx_mtd);
470    iounmap((void *)bcm47xx_map.virt);
471}
472
473module_init(init_bcm47xx_map);
474module_exit(cleanup_bcm47xx_map);
target/linux/brcm47xx/files-2.6.34/drivers/mtd/maps/bcm47xx-flash.c
1/*
2 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
3 * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
4 * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
5 *
6 * original functions for finding root filesystem from Mike Baker
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 675 Mass Ave, Cambridge, MA 02139, USA.
27 *
28 * Copyright 2001-2003, Broadcom Corporation
29 * All Rights Reserved.
30 *
31 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
32 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
33 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
34 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
35 *
36 * Flash mapping for BCM947XX boards
37 */
38
39#include <linux/init.h>
40#include <linux/module.h>
41#include <linux/types.h>
42#include <linux/kernel.h>
43#include <linux/sched.h>
44#include <linux/wait.h>
45#include <linux/mtd/mtd.h>
46#include <linux/mtd/map.h>
47#ifdef CONFIG_MTD_PARTITIONS
48#include <linux/mtd/partitions.h>
49#endif
50#include <linux/crc32.h>
51#ifdef CONFIG_SSB
52#include <linux/ssb/ssb.h>
53#endif
54#include <asm/io.h>
55
56
57#define TRX_MAGIC 0x30524448 /* "HDR0" */
58#define TRX_VERSION 1
59#define TRX_MAX_LEN 0x3A0000
60#define TRX_NO_HEADER 1 /* Do not write TRX header */
61#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */
62#define TRX_MAX_OFFSET 3
63
64struct trx_header {
65    u32 magic; /* "HDR0" */
66    u32 len; /* Length of file including header */
67    u32 crc32; /* 32-bit CRC from flag_version to end of file */
68    u32 flag_version; /* 0:15 flags, 16:31 version */
69    u32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */
70};
71
72#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
73#define NVRAM_SPACE 0x8000
74#define WINDOW_ADDR 0x1fc00000
75#define WINDOW_SIZE 0x400000
76#define BUSWIDTH 2
77
78#ifdef CONFIG_SSB
79extern struct ssb_bus ssb_bcm47xx;
80#endif
81static struct mtd_info *bcm47xx_mtd;
82
83static void bcm47xx_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
84{
85    if (len==1) {
86        memcpy_fromio(to, map->virt + from, len);
87    } else {
88        int i;
89        u16 *dest = (u16 *) to;
90        u16 *src = (u16 *) (map->virt + from);
91        for (i = 0; i < (len / 2); i++) {
92            dest[i] = src[i];
93        }
94        if (len & 1)
95            *((u8 *)dest+len-1) = src[i] & 0xff;
96    }
97}
98
99static struct map_info bcm47xx_map = {
100    name: "Physically mapped flash",
101    size: WINDOW_SIZE,
102    bankwidth: BUSWIDTH,
103    phys: WINDOW_ADDR,
104};
105
106#ifdef CONFIG_MTD_PARTITIONS
107
108static struct mtd_partition bcm47xx_parts[] = {
109    { name: "cfe", offset: 0, size: 0, mask_flags: MTD_WRITEABLE, },
110    { name: "linux", offset: 0, size: 0, },
111    { name: "rootfs", offset: 0, size: 0, },
112    { name: "nvram", offset: 0, size: 0, },
113    { name: NULL, },
114};
115
116static int __init
117find_cfe_size(struct mtd_info *mtd, size_t size)
118{
119    struct trx_header *trx;
120    unsigned char buf[512];
121    int off;
122    size_t len;
123    int blocksize;
124
125    trx = (struct trx_header *) buf;
126
127    blocksize = mtd->erasesize;
128    if (blocksize < 0x10000)
129        blocksize = 0x10000;
130
131    for (off = (128*1024); off < size; off += blocksize) {
132        memset(buf, 0xe5, sizeof(buf));
133
134        /*
135         * Read into buffer
136         */
137        if (mtd->read(mtd, off, sizeof(buf), &len, buf) ||
138            len != sizeof(buf))
139            continue;
140
141        /* found a TRX header */
142        if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
143            goto found;
144        }
145    }
146
147    printk(KERN_NOTICE
148           "%s: Couldn't find bootloader size\n",
149           mtd->name);
150    return -1;
151
152 found:
153    printk(KERN_NOTICE "bootloader size: %d\n", off);
154    return off;
155
156}
157
158/*
159 * Copied from mtdblock.c
160 *
161 * Cache stuff...
162 *
163 * Since typical flash erasable sectors are much larger than what Linux's
164 * buffer cache can handle, we must implement read-modify-write on flash
165 * sectors for each block write requests. To avoid over-erasing flash sectors
166 * and to speed things up, we locally cache a whole flash sector while it is
167 * being written to until a different sector is required.
168 */
169
170static void erase_callback(struct erase_info *done)
171{
172    wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
173    wake_up(wait_q);
174}
175
176static int erase_write (struct mtd_info *mtd, unsigned long pos,
177            int len, const char *buf)
178{
179    struct erase_info erase;
180    DECLARE_WAITQUEUE(wait, current);
181    wait_queue_head_t wait_q;
182    size_t retlen;
183    int ret;
184
185    /*
186     * First, let's erase the flash block.
187     */
188
189    init_waitqueue_head(&wait_q);
190    erase.mtd = mtd;
191    erase.callback = erase_callback;
192    erase.addr = pos;
193    erase.len = len;
194    erase.priv = (u_long)&wait_q;
195
196    set_current_state(TASK_INTERRUPTIBLE);
197    add_wait_queue(&wait_q, &wait);
198
199    ret = mtd->erase(mtd, &erase);
200    if (ret) {
201        set_current_state(TASK_RUNNING);
202        remove_wait_queue(&wait_q, &wait);
203        printk (KERN_WARNING "erase of region [0x%lx, 0x%x] "
204                     "on \"%s\" failed\n",
205            pos, len, mtd->name);
206        return ret;
207    }
208
209    schedule(); /* Wait for erase to finish. */
210    remove_wait_queue(&wait_q, &wait);
211
212    /*
213     * Next, writhe data to flash.
214     */
215
216    ret = mtd->write (mtd, pos, len, &retlen, buf);
217    if (ret)
218        return ret;
219    if (retlen != len)
220        return -EIO;
221    return 0;
222}
223
224
225static int __init
226find_dual_image_off (struct mtd_info *mtd, size_t size)
227{
228    struct trx_header trx;
229    int off, blocksize;
230    size_t len;
231
232    blocksize = mtd->erasesize;
233    if (blocksize < 0x10000)
234        blocksize = 0x10000;
235
236    for (off = (128*1024); off < size; off += blocksize) {
237        memset(&trx, 0xe5, sizeof(trx));
238        /*
239        * Read into buffer
240        */
241        if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) ||
242            len != sizeof(trx))
243            continue;
244        /* found last TRX header */
245        if (le32_to_cpu(trx.magic) == TRX_MAGIC){
246            if (le32_to_cpu(trx.flag_version >> 16)==2){
247                printk("dual image TRX header found\n");
248                return size/2;
249            } else {
250                return 0;
251            }
252        }
253    }
254    return 0;
255}
256
257
258static int __init
259find_root(struct mtd_info *mtd, size_t size, struct mtd_partition *part)
260{
261    struct trx_header trx, *trx2;
262    unsigned char buf[512], *block;
263    int off, blocksize;
264    u32 i, crc = ~0;
265    size_t len;
266
267    blocksize = mtd->erasesize;
268    if (blocksize < 0x10000)
269        blocksize = 0x10000;
270
271    for (off = (128*1024); off < size; off += blocksize) {
272        memset(&trx, 0xe5, sizeof(trx));
273
274        /*
275         * Read into buffer
276         */
277        if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) ||
278            len != sizeof(trx))
279            continue;
280
281        /* found a TRX header */
282        if (le32_to_cpu(trx.magic) == TRX_MAGIC) {
283            part->offset = le32_to_cpu(trx.offsets[2]) ? :
284                le32_to_cpu(trx.offsets[1]);
285            part->size = le32_to_cpu(trx.len);
286
287            part->size -= part->offset;
288            part->offset += off;
289
290            goto found;
291        }
292    }
293
294    printk(KERN_NOTICE
295           "%s: Couldn't find root filesystem\n",
296           mtd->name);
297    return -1;
298
299 found:
300    if (part->size == 0)
301        return 0;
302
303    if (mtd->read(mtd, part->offset, sizeof(buf), &len, buf) || len != sizeof(buf))
304        return 0;
305
306    /* Move the fs outside of the trx */
307    part->size = 0;
308
309    if (trx.len != part->offset + part->size - off) {
310        /* Update the trx offsets and length */
311        trx.len = part->offset + part->size - off;
312
313        /* Update the trx crc32 */
314        for (i = (u32) &(((struct trx_header *)NULL)->flag_version); i <= trx.len; i += sizeof(buf)) {
315            if (mtd->read(mtd, off + i, sizeof(buf), &len, buf) || len != sizeof(buf))
316                return 0;
317            crc = crc32_le(crc, buf, min(sizeof(buf), trx.len - i));
318        }
319        trx.crc32 = crc;
320
321        /* read first eraseblock from the trx */
322        block = kmalloc(mtd->erasesize, GFP_KERNEL);
323        trx2 = (struct trx_header *) block;
324        if (mtd->read(mtd, off, mtd->erasesize, &len, block) || len != mtd->erasesize) {
325            printk("Error accessing the first trx eraseblock\n");
326            return 0;
327        }
328
329        printk("Updating TRX offsets and length:\n");
330        printk("old trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx2->offsets[0], trx2->offsets[1], trx2->offsets[2], trx2->len, trx2->crc32);
331        printk("new trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx.offsets[0], trx.offsets[1], trx.offsets[2], trx.len, trx.crc32);
332
333        /* Write updated trx header to the flash */
334        memcpy(block, &trx, sizeof(trx));
335        if (mtd->unlock)
336            mtd->unlock(mtd, off, mtd->erasesize);
337        erase_write(mtd, off, mtd->erasesize, block);
338        if (mtd->sync)
339            mtd->sync(mtd);
340        kfree(block);
341        printk("Done\n");
342    }
343
344    return part->size;
345}
346
347struct mtd_partition * __init
348init_mtd_partitions(struct mtd_info *mtd, size_t size)
349{
350    int cfe_size;
351    int dual_image_offset = 0;
352
353    if ((cfe_size = find_cfe_size(mtd,size)) < 0)
354        return NULL;
355
356    /* boot loader */
357    bcm47xx_parts[0].offset = 0;
358    bcm47xx_parts[0].size = cfe_size;
359
360    /* nvram */
361    if (cfe_size != 384 * 1024) {
362        bcm47xx_parts[3].offset = size - ROUNDUP(NVRAM_SPACE, mtd->erasesize);
363        bcm47xx_parts[3].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
364    } else {
365        /* nvram (old 128kb config partition on netgear wgt634u) */
366        bcm47xx_parts[3].offset = bcm47xx_parts[0].size;
367        bcm47xx_parts[3].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
368    }
369
370    /* dual image offset*/
371    printk("Looking for dual image\n");
372    dual_image_offset=find_dual_image_off(mtd,size);
373    /* linux (kernel and rootfs) */
374    if (cfe_size != 384 * 1024) {
375        bcm47xx_parts[1].offset = bcm47xx_parts[0].size;
376        bcm47xx_parts[1].size = bcm47xx_parts[3].offset - dual_image_offset -
377            bcm47xx_parts[1].offset;
378    } else {
379        /* do not count the elf loader, which is on one block */
380        bcm47xx_parts[1].offset = bcm47xx_parts[0].size +
381            bcm47xx_parts[3].size + mtd->erasesize;
382        bcm47xx_parts[1].size = size -
383            bcm47xx_parts[0].size -
384            (2*bcm47xx_parts[3].size) -
385            mtd->erasesize;
386    }
387
388    /* find and size rootfs */
389    find_root(mtd,size,&bcm47xx_parts[2]);
390    bcm47xx_parts[2].size = size - dual_image_offset - bcm47xx_parts[2].offset - bcm47xx_parts[3].size;
391
392    return bcm47xx_parts;
393}
394#endif
395
396int __init init_bcm47xx_map(void)
397{
398#ifdef CONFIG_SSB
399    struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
400#endif
401    size_t size;
402    int ret = 0;
403#ifdef CONFIG_MTD_PARTITIONS
404    struct mtd_partition *parts;
405    int i;
406#endif
407
408#ifdef CONFIG_SSB
409    u32 window = mcore->flash_window;
410    u32 window_size = mcore->flash_window_size;
411
412    printk("flash init: 0x%08x 0x%08x\n", window, window_size);
413    bcm47xx_map.phys = window;
414    bcm47xx_map.size = window_size;
415    bcm47xx_map.bankwidth = mcore->flash_buswidth;
416    bcm47xx_map.virt = ioremap_nocache(window, window_size);
417#else
418    printk("flash init: 0x%08x 0x%08x\n", WINDOW_ADDR, WINDOW_SIZE);
419    bcm47xx_map.virt = ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
420#endif
421
422    if (!bcm47xx_map.virt) {
423        printk("Failed to ioremap\n");
424        return -EIO;
425    }
426
427    simple_map_init(&bcm47xx_map);
428
429    if (!(bcm47xx_mtd = do_map_probe("cfi_probe", &bcm47xx_map))) {
430        printk("Failed to do_map_probe\n");
431        iounmap((void *)bcm47xx_map.virt);
432        return -ENXIO;
433    }
434
435    /* override copy_from routine */
436     bcm47xx_map.copy_from = bcm47xx_map_copy_from;
437
438    bcm47xx_mtd->owner = THIS_MODULE;
439
440    size = bcm47xx_mtd->size;
441
442    printk(KERN_NOTICE "Flash device: 0x%x at 0x%x\n", size, WINDOW_ADDR);
443
444#ifdef CONFIG_MTD_PARTITIONS
445    parts = init_mtd_partitions(bcm47xx_mtd, size);
446    for (i = 0; parts[i].name; i++);
447    ret = add_mtd_partitions(bcm47xx_mtd, parts, i);
448    if (ret) {
449        printk(KERN_ERR "Flash: add_mtd_partitions failed\n");
450        goto fail;
451    }
452#endif
453    return 0;
454
455 fail:
456    if (bcm47xx_mtd)
457        map_destroy(bcm47xx_mtd);
458    if (bcm47xx_map.virt)
459        iounmap((void *)bcm47xx_map.virt);
460    bcm47xx_map.virt = 0;
461    return ret;
462}
463
464void __exit cleanup_bcm47xx_map(void)
465{
466#ifdef CONFIG_MTD_PARTITIONS
467    del_mtd_partitions(bcm47xx_mtd);
468#endif
469    map_destroy(bcm47xx_mtd);
470    iounmap((void *)bcm47xx_map.virt);
471}
472
473module_init(init_bcm47xx_map);
474module_exit(cleanup_bcm47xx_map);
target/linux/brcm47xx/files-2.6.35/drivers/mtd/maps/bcm47xx-flash.c
1/*
2 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
3 * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
4 * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
5 *
6 * original functions for finding root filesystem from Mike Baker
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 675 Mass Ave, Cambridge, MA 02139, USA.
27 *
28 * Copyright 2001-2003, Broadcom Corporation
29 * All Rights Reserved.
30 *
31 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
32 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
33 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
34 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
35 *
36 * Flash mapping for BCM947XX boards
37 */
38
39#include <linux/init.h>
40#include <linux/module.h>
41#include <linux/types.h>
42#include <linux/kernel.h>
43#include <linux/sched.h>
44#include <linux/wait.h>
45#include <linux/mtd/mtd.h>
46#include <linux/mtd/map.h>
47#ifdef CONFIG_MTD_PARTITIONS
48#include <linux/mtd/partitions.h>
49#endif
50#include <linux/crc32.h>
51#ifdef CONFIG_SSB
52#include <linux/ssb/ssb.h>
53#endif
54#include <asm/io.h>
55
56
57#define TRX_MAGIC 0x30524448 /* "HDR0" */
58#define TRX_VERSION 1
59#define TRX_MAX_LEN 0x3A0000
60#define TRX_NO_HEADER 1 /* Do not write TRX header */
61#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */
62#define TRX_MAX_OFFSET 3
63
64struct trx_header {
65    u32 magic; /* "HDR0" */
66    u32 len; /* Length of file including header */
67    u32 crc32; /* 32-bit CRC from flag_version to end of file */
68    u32 flag_version; /* 0:15 flags, 16:31 version */
69    u32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */
70};
71
72#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
73#define NVRAM_SPACE 0x8000
74#define WINDOW_ADDR 0x1fc00000
75#define WINDOW_SIZE 0x400000
76#define BUSWIDTH 2
77
78#ifdef CONFIG_SSB
79extern struct ssb_bus ssb_bcm47xx;
80#endif
81static struct mtd_info *bcm47xx_mtd;
82
83static void bcm47xx_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
84{
85    if (len==1) {
86        memcpy_fromio(to, map->virt + from, len);
87    } else {
88        int i;
89        u16 *dest = (u16 *) to;
90        u16 *src = (u16 *) (map->virt + from);
91        for (i = 0; i < (len / 2); i++) {
92            dest[i] = src[i];
93        }
94        if (len & 1)
95            *((u8 *)dest+len-1) = src[i] & 0xff;
96    }
97}
98
99static struct map_info bcm47xx_map = {
100    name: "Physically mapped flash",
101    size: WINDOW_SIZE,
102    bankwidth: BUSWIDTH,
103    phys: WINDOW_ADDR,
104};
105
106#ifdef CONFIG_MTD_PARTITIONS
107
108static struct mtd_partition bcm47xx_parts[] = {
109    { name: "cfe", offset: 0, size: 0, mask_flags: MTD_WRITEABLE, },
110    { name: "linux", offset: 0, size: 0, },
111    { name: "rootfs", offset: 0, size: 0, },
112    { name: "nvram", offset: 0, size: 0, },
113    { name: NULL, },
114};
115
116static int __init
117find_cfe_size(struct mtd_info *mtd, size_t size)
118{
119    struct trx_header *trx;
120    unsigned char buf[512];
121    int off;
122    size_t len;
123    int blocksize;
124
125    trx = (struct trx_header *) buf;
126
127    blocksize = mtd->erasesize;
128    if (blocksize < 0x10000)
129        blocksize = 0x10000;
130
131    for (off = (128*1024); off < size; off += blocksize) {
132        memset(buf, 0xe5, sizeof(buf));
133
134        /*
135         * Read into buffer
136         */
137        if (mtd->read(mtd, off, sizeof(buf), &len, buf) ||
138            len != sizeof(buf))
139            continue;
140
141        /* found a TRX header */
142        if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
143            goto found;
144        }
145    }
146
147    printk(KERN_NOTICE
148           "%s: Couldn't find bootloader size\n",
149           mtd->name);
150    return -1;
151
152 found:
153    printk(KERN_NOTICE "bootloader size: %d\n", off);
154    return off;
155
156}
157
158/*
159 * Copied from mtdblock.c
160 *
161 * Cache stuff...
162 *
163 * Since typical flash erasable sectors are much larger than what Linux's
164 * buffer cache can handle, we must implement read-modify-write on flash
165 * sectors for each block write requests. To avoid over-erasing flash sectors
166 * and to speed things up, we locally cache a whole flash sector while it is
167 * being written to until a different sector is required.
168 */
169
170static void erase_callback(struct erase_info *done)
171{
172    wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
173    wake_up(wait_q);
174}
175
176static int erase_write (struct mtd_info *mtd, unsigned long pos,
177            int len, const char *buf)
178{
179    struct erase_info erase;
180    DECLARE_WAITQUEUE(wait, current);
181    wait_queue_head_t wait_q;
182    size_t retlen;
183    int ret;
184
185    /*
186     * First, let's erase the flash block.
187     */
188
189    init_waitqueue_head(&wait_q);
190    erase.mtd = mtd;
191    erase.callback = erase_callback;
192    erase.addr = pos;
193    erase.len = len;
194    erase.priv = (u_long)&wait_q;
195
196    set_current_state(TASK_INTERRUPTIBLE);
197    add_wait_queue(&wait_q, &wait);
198
199    ret = mtd->erase(mtd, &erase);
200    if (ret) {
201        set_current_state(TASK_RUNNING);
202        remove_wait_queue(&wait_q, &wait);
203        printk (KERN_WARNING "erase of region [0x%lx, 0x%x] "
204                     "on \"%s\" failed\n",
205            pos, len, mtd->name);
206        return ret;
207    }
208
209    schedule(); /* Wait for erase to finish. */
210    remove_wait_queue(&wait_q, &wait);
211
212    /*
213     * Next, writhe data to flash.
214     */
215
216    ret = mtd->write (mtd, pos, len, &retlen, buf);
217    if (ret)
218        return ret;
219    if (retlen != len)
220        return -EIO;
221    return 0;
222}
223
224
225static int __init
226find_dual_image_off (struct mtd_info *mtd, size_t size)
227{
228    struct trx_header trx;
229    int off, blocksize;
230    size_t len;
231
232    blocksize = mtd->erasesize;
233    if (blocksize < 0x10000)
234        blocksize = 0x10000;
235
236    for (off = (128*1024); off < size; off += blocksize) {
237        memset(&trx, 0xe5, sizeof(trx));
238        /*
239        * Read into buffer
240        */
241        if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) ||
242            len != sizeof(trx))
243            continue;
244        /* found last TRX header */
245        if (le32_to_cpu(trx.magic) == TRX_MAGIC){
246            if (le32_to_cpu(trx.flag_version >> 16)==2){
247                printk("dual image TRX header found\n");
248                return size/2;
249            } else {
250                return 0;
251            }
252        }
253    }
254    return 0;
255}
256
257
258static int __init
259find_root(struct mtd_info *mtd, size_t size, struct mtd_partition *part)
260{
261    struct trx_header trx, *trx2;
262    unsigned char buf[512], *block;
263    int off, blocksize;
264    u32 i, crc = ~0;
265    size_t len;
266
267    blocksize = mtd->erasesize;
268    if (blocksize < 0x10000)
269        blocksize = 0x10000;
270
271    for (off = (128*1024); off < size; off += blocksize) {
272        memset(&trx, 0xe5, sizeof(trx));
273
274        /*
275         * Read into buffer
276         */
277        if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) ||
278            len != sizeof(trx))
279            continue;
280
281        /* found a TRX header */
282        if (le32_to_cpu(trx.magic) == TRX_MAGIC) {
283            part->offset = le32_to_cpu(trx.offsets[2]) ? :
284                le32_to_cpu(trx.offsets[1]);
285            part->size = le32_to_cpu(trx.len);
286
287            part->size -= part->offset;
288            part->offset += off;
289
290            goto found;
291        }
292    }
293
294    printk(KERN_NOTICE
295           "%s: Couldn't find root filesystem\n",
296           mtd->name);
297    return -1;
298
299 found:
300    if (part->size == 0)
301        return 0;
302
303    if (mtd->read(mtd, part->offset, sizeof(buf), &len, buf) || len != sizeof(buf))
304        return 0;
305
306    /* Move the fs outside of the trx */
307    part->size = 0;
308
309    if (trx.len != part->offset + part->size - off) {
310        /* Update the trx offsets and length */
311        trx.len = part->offset + part->size - off;
312
313        /* Update the trx crc32 */
314        for (i = (u32) &(((struct trx_header *)NULL)->flag_version); i <= trx.len; i += sizeof(buf)) {
315            if (mtd->read(mtd, off + i, sizeof(buf), &len, buf) || len != sizeof(buf))
316                return 0;
317            crc = crc32_le(crc, buf, min(sizeof(buf), trx.len - i));
318        }
319        trx.crc32 = crc;
320
321        /* read first eraseblock from the trx */
322        block = kmalloc(mtd->erasesize, GFP_KERNEL);
323        trx2 = (struct trx_header *) block;
324        if (mtd->read(mtd, off, mtd->erasesize, &len, block) || len != mtd->erasesize) {
325            printk("Error accessing the first trx eraseblock\n");
326            return 0;
327        }
328
329        printk("Updating TRX offsets and length:\n");
330        printk("old trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx2->offsets[0], trx2->offsets[1], trx2->offsets[2], trx2->len, trx2->crc32);
331        printk("new trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx.offsets[0], trx.offsets[1], trx.offsets[2], trx.len, trx.crc32);
332
333        /* Write updated trx header to the flash */
334        memcpy(block, &trx, sizeof(trx));
335        if (mtd->unlock)
336            mtd->unlock(mtd, off, mtd->erasesize);
337        erase_write(mtd, off, mtd->erasesize, block);
338        if (mtd->sync)
339            mtd->sync(mtd);
340        kfree(block);
341        printk("Done\n");
342    }
343
344    return part->size;
345}
346
347struct mtd_partition * __init
348init_mtd_partitions(struct mtd_info *mtd, size_t size)
349{
350    int cfe_size;
351    int dual_image_offset = 0;
352
353    if ((cfe_size = find_cfe_size(mtd,size)) < 0)
354        return NULL;
355
356    /* boot loader */
357    bcm47xx_parts[0].offset = 0;
358    bcm47xx_parts[0].size = cfe_size;
359
360    /* nvram */
361    if (cfe_size != 384 * 1024) {
362        bcm47xx_parts[3].offset = size - ROUNDUP(NVRAM_SPACE, mtd->erasesize);
363        bcm47xx_parts[3].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
364    } else {
365        /* nvram (old 128kb config partition on netgear wgt634u) */
366        bcm47xx_parts[3].offset = bcm47xx_parts[0].size;
367        bcm47xx_parts[3].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
368    }
369
370    /* dual image offset*/
371    printk("Looking for dual image\n");
372    dual_image_offset=find_dual_image_off(mtd,size);
373    /* linux (kernel and rootfs) */
374    if (cfe_size != 384 * 1024) {
375        bcm47xx_parts[1].offset = bcm47xx_parts[0].size;
376        bcm47xx_parts[1].size = bcm47xx_parts[3].offset - dual_image_offset -
377            bcm47xx_parts[1].offset;
378    } else {
379        /* do not count the elf loader, which is on one block */
380        bcm47xx_parts[1].offset = bcm47xx_parts[0].size +
381            bcm47xx_parts[3].size + mtd->erasesize;
382        bcm47xx_parts[1].size = size -
383            bcm47xx_parts[0].size -
384            (2*bcm47xx_parts[3].size) -
385            mtd->erasesize;
386    }
387
388    /* find and size rootfs */
389    find_root(mtd,size,&bcm47xx_parts[2]);
390    bcm47xx_parts[2].size = size - dual_image_offset - bcm47xx_parts[2].offset - bcm47xx_parts[3].size;
391
392    return bcm47xx_parts;
393}
394#endif
395
396int __init init_bcm47xx_map(void)
397{
398#ifdef CONFIG_SSB
399    struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
400#endif
401    size_t size;
402    int ret = 0;
403#ifdef CONFIG_MTD_PARTITIONS
404    struct mtd_partition *parts;
405    int i;
406#endif
407
408#ifdef CONFIG_SSB
409    u32 window = mcore->flash_window;
410    u32 window_size = mcore->flash_window_size;
411
412    printk("flash init: 0x%08x 0x%08x\n", window, window_size);
413    bcm47xx_map.phys = window;
414    bcm47xx_map.size = window_size;
415    bcm47xx_map.bankwidth = mcore->flash_buswidth;
416    bcm47xx_map.virt = ioremap_nocache(window, window_size);
417#else
418    printk("flash init: 0x%08x 0x%08x\n", WINDOW_ADDR, WINDOW_SIZE);
419    bcm47xx_map.virt = ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
420#endif
421
422    if (!bcm47xx_map.virt) {
423        printk("Failed to ioremap\n");
424        return -EIO;
425    }
426
427    simple_map_init(&bcm47xx_map);
428
429    if (!(bcm47xx_mtd = do_map_probe("cfi_probe", &bcm47xx_map))) {
430        printk("Failed to do_map_probe\n");
431        iounmap((void *)bcm47xx_map.virt);
432        return -ENXIO;
433    }
434
435    /* override copy_from routine */
436     bcm47xx_map.copy_from = bcm47xx_map_copy_from;
437
438    bcm47xx_mtd->owner = THIS_MODULE;
439
440    size = bcm47xx_mtd->size;
441
442    printk(KERN_NOTICE "Flash device: 0x%x at 0x%x\n", size, WINDOW_ADDR);
443
444#ifdef CONFIG_MTD_PARTITIONS
445    parts = init_mtd_partitions(bcm47xx_mtd, size);
446    for (i = 0; parts[i].name; i++);
447    ret = add_mtd_partitions(bcm47xx_mtd, parts, i);
448    if (ret) {
449        printk(KERN_ERR "Flash: add_mtd_partitions failed\n");
450        goto fail;
451    }
452#endif
453    return 0;
454
455 fail:
456    if (bcm47xx_mtd)
457        map_destroy(bcm47xx_mtd);
458    if (bcm47xx_map.virt)
459        iounmap((void *)bcm47xx_map.virt);
460    bcm47xx_map.virt = 0;
461    return ret;
462}
463
464void __exit cleanup_bcm47xx_map(void)
465{
466#ifdef CONFIG_MTD_PARTITIONS
467    del_mtd_partitions(bcm47xx_mtd);
468#endif
469    map_destroy(bcm47xx_mtd);
470    iounmap((void *)bcm47xx_map.virt);
471}
472
473module_init(init_bcm47xx_map);
474module_exit(cleanup_bcm47xx_map);
target/linux/brcm47xx/files/arch/mips/bcm47xx/cfe_env.c
1/*
2 * CFE environment variable access
3 *
4 * Copyright 2001-2003, Broadcom Corporation
5 * Copyright 2006, Felix Fietkau <nbd@openwrt.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/string.h>
17#include <asm/io.h>
18#include <asm/uaccess.h>
19
20#define NVRAM_SIZE (0x1ff0)
21static char _nvdata[NVRAM_SIZE];
22static char _valuestr[256];
23
24/*
25 * TLV types. These codes are used in the "type-length-value"
26 * encoding of the items stored in the NVRAM device (flash or EEPROM)
27 *
28 * The layout of the flash/nvram is as follows:
29 *
30 * <type> <length> <data ...> <type> <length> <data ...> <type_end>
31 *
32 * The type code of "ENV_TLV_TYPE_END" marks the end of the list.
33 * The "length" field marks the length of the data section, not
34 * including the type and length fields.
35 *
36 * Environment variables are stored as follows:
37 *
38 * <type_env> <length> <flags> <name> = <value>
39 *
40 * If bit 0 (low bit) is set, the length is an 8-bit value.
41 * If bit 0 (low bit) is clear, the length is a 16-bit value
42 *
43 * Bit 7 set indicates "user" TLVs. In this case, bit 0 still
44 * indicates the size of the length field.
45 *
46 * Flags are from the constants below:
47 *
48 */
49#define ENV_LENGTH_16BITS 0x00 /* for low bit */
50#define ENV_LENGTH_8BITS 0x01
51
52#define ENV_TYPE_USER 0x80
53
54#define ENV_CODE_SYS(n,l) (((n)<<1)|(l))
55#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER)
56
57/*
58 * The actual TLV types we support
59 */
60
61#define ENV_TLV_TYPE_END 0x00
62#define ENV_TLV_TYPE_ENV ENV_CODE_SYS(0,ENV_LENGTH_8BITS)
63
64/*
65 * Environment variable flags
66 */
67
68#define ENV_FLG_NORMAL 0x00 /* normal read/write */
69#define ENV_FLG_BUILTIN 0x01 /* builtin - not stored in flash */
70#define ENV_FLG_READONLY 0x02 /* read-only - cannot be changed */
71
72#define ENV_FLG_MASK 0xFF /* mask of attributes we keep */
73#define ENV_FLG_ADMIN 0x100 /* lets us internally override permissions */
74
75
76/* *********************************************************************
77    * _nvram_read(buffer,offset,length)
78    *
79    * Read data from the NVRAM device
80    *
81    * Input parameters:
82    * buffer - destination buffer
83    * offset - offset of data to read
84    * length - number of bytes to read
85    *
86    * Return value:
87    * number of bytes read, or <0 if error occured
88    ********************************************************************* */
89static int
90_nvram_read(unsigned char *nv_buf, unsigned char *buffer, int offset, int length)
91{
92    int i;
93    if (offset > NVRAM_SIZE)
94    return -1;
95
96    for ( i = 0; i < length; i++) {
97    buffer[i] = ((volatile unsigned char*)nv_buf)[offset + i];
98    }
99    return length;
100}
101
102
103static char*
104_strnchr(const char *dest,int c,size_t cnt)
105{
106    while (*dest && (cnt > 0)) {
107    if (*dest == c) return (char *) dest;
108    dest++;
109    cnt--;
110    }
111    return NULL;
112}
113
114
115
116/*
117 * Core support API: Externally visible.
118 */
119
120/*
121 * Get the value of an NVRAM variable
122 * @param name name of variable to get
123 * @return value of variable or NULL if undefined
124 */
125
126char*
127cfe_env_get(unsigned char *nv_buf, char* name)
128{
129    int size;
130    unsigned char *buffer;
131    unsigned char *ptr;
132    unsigned char *envval;
133    unsigned int reclen;
134    unsigned int rectype;
135    int offset;
136    int flg;
137
138    if (!strcmp(name, "nvram_type"))
139        return "cfe";
140
141    size = NVRAM_SIZE;
142    buffer = &_nvdata[0];
143
144    ptr = buffer;
145    offset = 0;
146
147    /* Read the record type and length */
148    if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
149    goto error;
150    }
151
152    while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) {
153
154    /* Adjust pointer for TLV type */
155    rectype = *(ptr);
156    offset++;
157    size--;
158
159    /*
160     * Read the length. It can be either 1 or 2 bytes
161     * depending on the code
162     */
163    if (rectype & ENV_LENGTH_8BITS) {
164        /* Read the record type and length - 8 bits */
165        if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
166        goto error;
167        }
168        reclen = *(ptr);
169        size--;
170        offset++;
171    }
172    else {
173        /* Read the record type and length - 16 bits, MSB first */
174        if (_nvram_read(nv_buf, ptr,offset,2) != 2) {
175        goto error;
176        }
177        reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1);
178        size -= 2;
179        offset += 2;
180    }
181
182    if (reclen > size)
183        break; /* should not happen, bad NVRAM */
184
185    switch (rectype) {
186        case ENV_TLV_TYPE_ENV:
187        /* Read the TLV data */
188        if (_nvram_read(nv_buf, ptr,offset,reclen) != reclen)
189            goto error;
190        flg = *ptr++;
191        envval = (unsigned char *) _strnchr(ptr,'=',(reclen-1));
192        if (envval) {
193            *envval++ = '\0';
194            memcpy(_valuestr,envval,(reclen-1)-(envval-ptr));
195            _valuestr[(reclen-1)-(envval-ptr)] = '\0';
196#if 0
197            printk(KERN_INFO "NVRAM:%s=%s\n", ptr, _valuestr);
198#endif
199            if(!strcmp(ptr, name)){
200            return _valuestr;
201            }
202            if((strlen(ptr) > 1) && !strcmp(&ptr[1], name))
203            return _valuestr;
204        }
205        break;
206
207        default:
208        /* Unknown TLV type, skip it. */
209        break;
210        }
211
212    /*
213     * Advance to next TLV
214     */
215
216    size -= (int)reclen;
217    offset += reclen;
218
219    /* Read the next record type */
220    ptr = buffer;
221    if (_nvram_read(nv_buf, ptr,offset,1) != 1)
222        goto error;
223    }
224
225error:
226    return NULL;
227
228}
229
target/linux/brcm47xx/files/arch/mips/bcm47xx/include/nvram.h
1/*
2 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 */
9
10#ifndef __NVRAM_H
11#define __NVRAM_H
12
13struct nvram_header {
14    u32 magic;
15    u32 len;
16    u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
17    u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */
18    u32 config_ncdl; /* ncdl values for memc */
19};
20
21struct nvram_tuple {
22    char *name;
23    char *value;
24    struct nvram_tuple *next;
25};
26
27#define NVRAM_HEADER 0x48534C46 /* 'FLSH' */
28#define NVRAM_VERSION 1
29#define NVRAM_HEADER_SIZE 20
30#define NVRAM_SPACE 0x8000
31
32#define NVRAM_MAX_VALUE_LEN 255
33#define NVRAM_MAX_PARAM_LEN 64
34
35char *nvram_get(const char *name);
36
37#endif
target/linux/brcm47xx/files/arch/mips/bcm47xx/nvram.c
1/*
2 * BCM947xx nvram variable access
3 *
4 * Copyright 2005, Broadcom Corporation
5 * Copyright 2006, Felix Fietkau <nbd@openwrt.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/ssb/ssb.h>
16#include <linux/kernel.h>
17#include <linux/string.h>
18#include <linux/interrupt.h>
19#include <linux/spinlock.h>
20#include <linux/slab.h>
21#include <asm/byteorder.h>
22#include <asm/bootinfo.h>
23#include <asm/addrspace.h>
24#include <asm/io.h>
25#include <asm/uaccess.h>
26
27#include <nvram.h>
28
29#define MB * 1048576
30extern struct ssb_bus ssb;
31
32static char nvram_buf[NVRAM_SPACE];
33static int cfe_env;
34extern char *cfe_env_get(char *nv_buf, const char *name);
35
36/* Probe for NVRAM header */
37static void __init early_nvram_init(void)
38{
39    struct ssb_mipscore *mcore = &ssb.mipscore;
40    struct nvram_header *header;
41    int i;
42    u32 base, lim, off;
43    u32 *src, *dst;
44
45    base = mcore->flash_window;
46    lim = mcore->flash_window_size;
47    cfe_env = 0;
48
49
50    /* XXX: hack for supporting the CFE environment stuff on WGT634U */
51    if (lim >= 8 MB) {
52        src = (u32 *) KSEG1ADDR(base + 8 MB - 0x2000);
53        dst = (u32 *) nvram_buf;
54
55        if ((*src & 0xff00ff) == 0x000001) {
56            printk("early_nvram_init: WGT634U NVRAM found.\n");
57
58            for (i = 0; i < 0x1ff0; i++) {
59                if (*src == 0xFFFFFFFF)
60                    break;
61                *dst++ = *src++;
62            }
63            cfe_env = 1;
64            return;
65        }
66    }
67
68    off = 0x20000;
69    while (off <= lim) {
70        /* Windowed flash access */
71        header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE);
72        if (header->magic == NVRAM_HEADER)
73            goto found;
74        off <<= 1;
75    }
76
77    /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
78    header = (struct nvram_header *) KSEG1ADDR(base + 4096);
79    if (header->magic == NVRAM_HEADER)
80        goto found;
81
82    header = (struct nvram_header *) KSEG1ADDR(base + 1024);
83    if (header->magic == NVRAM_HEADER)
84        goto found;
85
86    return;
87
88found:
89    src = (u32 *) header;
90    dst = (u32 *) nvram_buf;
91    for (i = 0; i < sizeof(struct nvram_header); i += 4)
92        *dst++ = *src++;
93    for (; i < header->len && i < NVRAM_SPACE; i += 4)
94        *dst++ = le32_to_cpu(*src++);
95}
96
97char *nvram_get(const char *name)
98{
99    char *var, *value, *end, *eq;
100
101    if (!name)
102        return NULL;
103
104    if (!nvram_buf[0])
105        early_nvram_init();
106
107    if (cfe_env)
108        return cfe_env_get(nvram_buf, name);
109
110    /* Look for name=value and return value */
111    var = &nvram_buf[sizeof(struct nvram_header)];
112    end = nvram_buf + sizeof(nvram_buf) - 2;
113    end[0] = end[1] = '\0';
114    for (; *var; var = value + strlen(value) + 1) {
115        if (!(eq = strchr(var, '=')))
116            break;
117        value = eq + 1;
118        if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0)
119            return value;
120    }
121
122    return NULL;
123}
124
125EXPORT_SYMBOL(nvram_get);
target/linux/brcm47xx/files/arch/mips/include/asm/mach-bcm47xx/kernel-entry-init.h
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2005 Embedded Alley Solutions, Inc
7 * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
8 * Copyright (C) 2006 Michael Buesch
9 */
10#ifndef __ASM_MACH_GENERIC_KERNEL_ENTRY_H
11#define __ASM_MACH_GENERIC_KERNEL_ENTRY_H
12
13/* Intentionally empty macro, used in head.S. Override in
14 * arch/mips/mach-xxx/kernel-entry-init.h when necessary.
15 */
16    .macro kernel_entry_setup
17    .endm
18
19/*
20 * Do SMP slave processor setup necessary before we can savely execute C code.
21 */
22    .macro smp_slave_setup
23    .endm
24
25
26#endif /* __ASM_MACH_GENERIC_KERNEL_ENTRY_H */
target/linux/brcm47xx/files/drivers/mtd/maps/bcm47xx-flash.c
1/*
2 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
3 * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
4 * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
5 *
6 * original functions for finding root filesystem from Mike Baker
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 675 Mass Ave, Cambridge, MA 02139, USA.
27 *
28 * Copyright 2001-2003, Broadcom Corporation
29 * All Rights Reserved.
30 *
31 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
32 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
33 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
34 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
35 *
36 * Flash mapping for BCM947XX boards
37 */
38
39#include <linux/init.h>
40#include <linux/module.h>
41#include <linux/types.h>
42#include <linux/kernel.h>
43#include <linux/sched.h>
44#include <linux/wait.h>
45#include <linux/mtd/mtd.h>
46#include <linux/mtd/map.h>
47#ifdef CONFIG_MTD_PARTITIONS
48#include <linux/mtd/partitions.h>
49#endif
50#include <linux/crc32.h>
51#ifdef CONFIG_SSB
52#include <linux/ssb/ssb.h>
53#endif
54#include <asm/io.h>
55
56
57#define TRX_MAGIC 0x30524448 /* "HDR0" */
58#define TRX_VERSION 1
59#define TRX_MAX_LEN 0x3A0000
60#define TRX_NO_HEADER 1 /* Do not write TRX header */
61#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */
62#define TRX_MAX_OFFSET 3
63
64struct trx_header {
65    u32 magic; /* "HDR0" */
66    u32 len; /* Length of file including header */
67    u32 crc32; /* 32-bit CRC from flag_version to end of file */
68    u32 flag_version; /* 0:15 flags, 16:31 version */
69    u32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */
70};
71
72#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
73#define NVRAM_SPACE 0x8000
74#define WINDOW_ADDR 0x1fc00000
75#define WINDOW_SIZE 0x400000
76#define BUSWIDTH 2
77
78#ifdef CONFIG_SSB
79extern struct ssb_bus ssb_bcm47xx;
80#endif
81static struct mtd_info *bcm47xx_mtd;
82
83static void bcm47xx_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
84{
85    if (len==1) {
86        memcpy_fromio(to, map->virt + from, len);
87    } else {
88        int i;
89        u16 *dest = (u16 *) to;
90        u16 *src = (u16 *) (map->virt + from);
91        for (i = 0; i < (len / 2); i++) {
92            dest[i] = src[i];
93        }
94        if (len & 1)
95            *((u8 *)dest+len-1) = src[i] & 0xff;
96    }
97}
98
99static struct map_info bcm47xx_map = {
100    name: "Physically mapped flash",
101    size: WINDOW_SIZE,
102    bankwidth: BUSWIDTH,
103    phys: WINDOW_ADDR,
104};
105
106#ifdef CONFIG_MTD_PARTITIONS
107
108static struct mtd_partition bcm47xx_parts[] = {
109    { name: "cfe", offset: 0, size: 0, mask_flags: MTD_WRITEABLE, },
110    { name: "linux", offset: 0, size: 0, },
111    { name: "rootfs", offset: 0, size: 0, },
112    { name: "nvram", offset: 0, size: 0, },
113    { name: NULL, },
114};
115
116static int __init
117find_cfe_size(struct mtd_info *mtd, size_t size)
118{
119    struct trx_header *trx;
120    unsigned char buf[512];
121    int off;
122    size_t len;
123    int blocksize;
124
125    trx = (struct trx_header *) buf;
126
127    blocksize = mtd->erasesize;
128    if (blocksize < 0x10000)
129        blocksize = 0x10000;
130
131    for (off = (128*1024); off < size; off += blocksize) {
132        memset(buf, 0xe5, sizeof(buf));
133
134        /*
135         * Read into buffer
136         */
137        if (mtd->read(mtd, off, sizeof(buf), &len, buf) ||
138            len != sizeof(buf))
139            continue;
140
141        /* found a TRX header */
142        if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
143            goto found;
144        }
145    }
146
147    printk(KERN_NOTICE
148           "%s: Couldn't find bootloader size\n",
149           mtd->name);
150    return -1;
151
152 found:
153    printk(KERN_NOTICE "bootloader size: %d\n", off);
154    return off;
155
156}
157
158/*
159 * Copied from mtdblock.c
160 *
161 * Cache stuff...
162 *
163 * Since typical flash erasable sectors are much larger than what Linux's
164 * buffer cache can handle, we must implement read-modify-write on flash
165 * sectors for each block write requests. To avoid over-erasing flash sectors
166 * and to speed things up, we locally cache a whole flash sector while it is
167 * being written to until a different sector is required.
168 */
169
170static void erase_callback(struct erase_info *done)
171{
172    wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
173    wake_up(wait_q);
174}
175
176static int erase_write (struct mtd_info *mtd, unsigned long pos,
177            int len, const char *buf)
178{
179    struct erase_info erase;
180    DECLARE_WAITQUEUE(wait, current);
181    wait_queue_head_t wait_q;
182    size_t retlen;
183    int ret;
184
185    /*
186     * First, let's erase the flash block.
187     */
188
189    init_waitqueue_head(&wait_q);
190    erase.mtd = mtd;
191    erase.callback = erase_callback;
192    erase.addr = pos;
193    erase.len = len;
194    erase.priv = (u_long)&wait_q;
195
196    set_current_state(TASK_INTERRUPTIBLE);
197    add_wait_queue(&wait_q, &wait);
198
199    ret = mtd->erase(mtd, &erase);
200    if (ret) {
201        set_current_state(TASK_RUNNING);
202        remove_wait_queue(&wait_q, &wait);
203        printk (KERN_WARNING "erase of region [0x%lx, 0x%x] "
204                     "on \"%s\" failed\n",
205            pos, len, mtd->name);
206        return ret;
207    }
208
209    schedule(); /* Wait for erase to finish. */
210    remove_wait_queue(&wait_q, &wait);
211
212    /*
213     * Next, writhe data to flash.
214     */
215
216    ret = mtd->write (mtd, pos, len, &retlen, buf);
217    if (ret)
218        return ret;
219    if (retlen != len)
220        return -EIO;
221    return 0;
222}
223
224
225static int __init
226find_dual_image_off (struct mtd_info *mtd, size_t size)
227{
228    struct trx_header trx;
229    int off, blocksize;
230    size_t len;
231
232    blocksize = mtd->erasesize;
233    if (blocksize < 0x10000)
234        blocksize = 0x10000;
235
236    for (off = (128*1024); off < size; off += blocksize) {
237        memset(&trx, 0xe5, sizeof(trx));
238        /*
239        * Read into buffer
240        */
241        if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) ||
242            len != sizeof(trx))
243            continue;
244        /* found last TRX header */
245        if (le32_to_cpu(trx.magic) == TRX_MAGIC){
246            if (le32_to_cpu(trx.flag_version >> 16)==2){
247                printk("dual image TRX header found\n");
248                return size/2;
249            } else {
250                return 0;
251            }
252        }
253    }
254    return 0;
255}
256
257
258static int __init
259find_root(struct mtd_info *mtd, size_t size, struct mtd_partition *part)
260{
261    struct trx_header trx, *trx2;
262    unsigned char buf[512], *block;
263    int off, blocksize;
264    u32 i, crc = ~0;
265    size_t len;
266
267    blocksize = mtd->erasesize;
268    if (blocksize < 0x10000)
269        blocksize = 0x10000;
270
271    for (off = (128*1024); off < size; off += blocksize) {
272        memset(&trx, 0xe5, sizeof(trx));
273
274        /*
275         * Read into buffer
276         */
277        if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) ||
278            len != sizeof(trx))
279            continue;
280
281        /* found a TRX header */
282        if (le32_to_cpu(trx.magic) == TRX_MAGIC) {
283            part->offset = le32_to_cpu(trx.offsets[2]) ? :
284                le32_to_cpu(trx.offsets[1]);
285            part->size = le32_to_cpu(trx.len);
286
287            part->size -= part->offset;
288            part->offset += off;
289
290            goto found;
291        }
292    }
293
294    printk(KERN_NOTICE
295           "%s: Couldn't find root filesystem\n",
296           mtd->name);
297    return -1;
298
299 found:
300    if (part->size == 0)
301        return 0;
302
303    if (mtd->read(mtd, part->offset, sizeof(buf), &len, buf) || len != sizeof(buf))
304        return 0;
305
306    /* Move the fs outside of the trx */
307    part->size = 0;
308
309    if (trx.len != part->offset + part->size - off) {
310        /* Update the trx offsets and length */
311        trx.len = part->offset + part->size - off;
312
313        /* Update the trx crc32 */
314        for (i = (u32) &(((struct trx_header *)NULL)->flag_version); i <= trx.len; i += sizeof(buf)) {
315            if (mtd->read(mtd, off + i, sizeof(buf), &len, buf) || len != sizeof(buf))
316                return 0;
317            crc = crc32_le(crc, buf, min(sizeof(buf), trx.len - i));
318        }
319        trx.crc32 = crc;
320
321        /* read first eraseblock from the trx */
322        block = kmalloc(mtd->erasesize, GFP_KERNEL);
323        trx2 = (struct trx_header *) block;
324        if (mtd->read(mtd, off, mtd->erasesize, &len, block) || len != mtd->erasesize) {
325            printk("Error accessing the first trx eraseblock\n");
326            return 0;
327        }
328
329        printk("Updating TRX offsets and length:\n");
330        printk("old trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx2->offsets[0], trx2->offsets[1], trx2->offsets[2], trx2->len, trx2->crc32);
331        printk("new trx = [0x%08x, 0x%08x, 0x%08x], len=0x%08x crc32=0x%08x\n", trx.offsets[0], trx.offsets[1], trx.offsets[2], trx.len, trx.crc32);
332
333        /* Write updated trx header to the flash */
334        memcpy(block, &trx, sizeof(trx));
335        if (mtd->unlock)
336            mtd->unlock(mtd, off, mtd->erasesize);
337        erase_write(mtd, off, mtd->erasesize, block);
338        if (mtd->sync)
339            mtd->sync(mtd);
340        kfree(block);
341        printk("Done\n");
342    }
343
344    return part->size;
345}
346
347struct mtd_partition * __init
348init_mtd_partitions(struct mtd_info *mtd, size_t size)
349{
350    int cfe_size;
351    int dual_image_offset = 0;
352
353    if ((cfe_size = find_cfe_size(mtd,size)) < 0)
354        return NULL;
355
356    /* boot loader */
357    bcm47xx_parts[0].offset = 0;
358    bcm47xx_parts[0].size = cfe_size;
359
360    /* nvram */
361    if (cfe_size != 384 * 1024) {
362        bcm47xx_parts[3].offset = size - ROUNDUP(NVRAM_SPACE, mtd->erasesize);
363        bcm47xx_parts[3].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
364    } else {
365        /* nvram (old 128kb config partition on netgear wgt634u) */
366        bcm47xx_parts[3].offset = bcm47xx_parts[0].size;
367        bcm47xx_parts[3].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
368    }
369
370    /* dual image offset*/
371    printk("Looking for dual image\n");
372    dual_image_offset=find_dual_image_off(mtd,size);
373    /* linux (kernel and rootfs) */
374    if (cfe_size != 384 * 1024) {
375        bcm47xx_parts[1].offset = bcm47xx_parts[0].size;
376        bcm47xx_parts[1].size = bcm47xx_parts[3].offset - dual_image_offset -
377            bcm47xx_parts[1].offset;
378    } else {
379        /* do not count the elf loader, which is on one block */
380        bcm47xx_parts[1].offset = bcm47xx_parts[0].size +
381            bcm47xx_parts[3].size + mtd->erasesize;
382        bcm47xx_parts[1].size = size -
383            bcm47xx_parts[0].size -
384            (2*bcm47xx_parts[3].size) -
385            mtd->erasesize;
386    }
387
388    /* find and size rootfs */
389    find_root(mtd,size,&bcm47xx_parts[2]);
390    bcm47xx_parts[2].size = size - dual_image_offset - bcm47xx_parts[2].offset - bcm47xx_parts[3].size;
391
392    return bcm47xx_parts;
393}
394#endif
395
396int __init init_bcm47xx_map(void)
397{
398#ifdef CONFIG_SSB
399    struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
400#endif
401    size_t size;
402    int ret = 0;
403#ifdef CONFIG_MTD_PARTITIONS
404    struct mtd_partition *parts;
405    int i;
406#endif
407
408#ifdef CONFIG_SSB
409    u32 window = mcore->flash_window;
410    u32 window_size = mcore->flash_window_size;
411
412    printk("flash init: 0x%08x 0x%08x\n", window, window_size);
413    bcm47xx_map.phys = window;
414    bcm47xx_map.size = window_size;
415    bcm47xx_map.bankwidth = mcore->flash_buswidth;
416    bcm47xx_map.virt = ioremap_nocache(window, window_size);
417#else
418    printk("flash init: 0x%08x 0x%08x\n", WINDOW_ADDR, WINDOW_SIZE);
419    bcm47xx_map.virt = ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
420#endif
421
422    if (!bcm47xx_map.virt) {
423        printk("Failed to ioremap\n");
424        return -EIO;
425    }
426
427    simple_map_init(&bcm47xx_map);
428
429    if (!(bcm47xx_mtd = do_map_probe("cfi_probe", &bcm47xx_map))) {
430        printk("Failed to do_map_probe\n");
431        iounmap((void *)bcm47xx_map.virt);
432        return -ENXIO;
433    }
434
435    /* override copy_from routine */
436     bcm47xx_map.copy_from = bcm47xx_map_copy_from;
437
438    bcm47xx_mtd->owner = THIS_MODULE;
439
440    size = bcm47xx_mtd->size;
441
442    printk(KERN_NOTICE "Flash device: 0x%x at 0x%x\n", size, WINDOW_ADDR);
443
444#ifdef CONFIG_MTD_PARTITIONS
445    parts = init_mtd_partitions(bcm47xx_mtd, size);
446    for (i = 0; parts[i].name; i++);
447    ret = add_mtd_partitions(bcm47xx_mtd, parts, i);
448    if (ret) {
449        printk(KERN_ERR "Flash: add_mtd_partitions failed\n");
450        goto fail;
451    }
452#endif
453    return 0;
454
455 fail:
456    if (bcm47xx_mtd)
457        map_destroy(bcm47xx_mtd);
458    if (bcm47xx_map.virt)
459        iounmap((void *)bcm47xx_map.virt);
460    bcm47xx_map.virt = 0;
461    return ret;
462}
463
464void __exit cleanup_bcm47xx_map(void)
465{
466#ifdef CONFIG_MTD_PARTITIONS
467    del_mtd_partitions(bcm47xx_mtd);
468#endif
469    map_destroy(bcm47xx_mtd);
470    iounmap((void *)bcm47xx_map.virt);
471}
472
473module_init(init_bcm47xx_map);
474module_exit(cleanup_bcm47xx_map);
target/linux/brcm47xx/patches-2.6.34/001-backport.patch
1commit 121915c4ee0812a14bc8d752bc210d0238d755c1
2Author: Waldemar Brodkorb <mips@waldemar-brodkorb.de>
3Date: Tue Jun 8 19:06:01 2010 +0200
4
5    MIPS: BCM47xx: Add NVRAM support devices
6
7    When trying to netboot a Linksys WRT54GS WLAN router, the bootup fails,
8    because of following error message:
9
10    ...
11    [ 0.424000] b44: b44.c:v2.0
12    [ 0.424000] b44: Invalid MAC address found in EEPROM
13    [ 0.432000] b44 ssb0:1: Problem fetching invariants of chip,aborting
14    [ 0.436000] b44: probe of ssb0:1 failed with error -22
15    ...
16
17    The router uses a CFE bootloader, but most of the needed environment
18    variables for network card initialization, are not available from CFE
19    via printenv and even though not via cfe_getenv().
20    The required environment variables are saved in a special partition
21    in flash memory. The attached patch implement nvram_getenv and enables
22    bootup via NFS root on my router.
23
24    Most of the patch is extracted from the OpenWrt subversion repository and
25    stripped down and cleaned up to just fix this issue.
26
27    [Ralf: sorted out header file inclusions. Lots of unneded headers and such
28    that should have been included.]
29
30    Signed-off-by: Waldemar Brodkorb <wbx@openadk.org>
31    Reviewed-by: Phil Sutter <phil@nwl.cc>
32    To: linux-mips@linux-mips.org
33    Cc: Hauke Mehrtens <hauke@hauke-m.de>
34    Patchwork: http://patchwork.linux-mips.org/patch/1359/
35    Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
36
37--- a/arch/mips/bcm47xx/Makefile
38@@ -3,4 +3,4 @@
39 # under Linux.
40 #
41
42-obj-y := gpio.o irq.o prom.o serial.o setup.o time.o wgt634u.o
43+obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
44--- /dev/null
45@@ -0,0 +1,94 @@
46+/*
47+ * BCM947xx nvram variable access
48+ *
49+ * Copyright (C) 2005 Broadcom Corporation
50+ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
51+ *
52+ * This program is free software; you can redistribute it and/or modify it
53+ * under the terms of the GNU General Public License as published by the
54+ * Free Software Foundation; either version 2 of the License, or (at your
55+ * option) any later version.
56+ */
57+
58+#include <linux/init.h>
59+#include <linux/types.h>
60+#include <linux/module.h>
61+#include <linux/ssb/ssb.h>
62+#include <linux/kernel.h>
63+#include <linux/string.h>
64+#include <asm/addrspace.h>
65+#include <asm/mach-bcm47xx/nvram.h>
66+#include <asm/mach-bcm47xx/bcm47xx.h>
67+
68+static char nvram_buf[NVRAM_SPACE];
69+
70+/* Probe for NVRAM header */
71+static void __init early_nvram_init(void)
72+{
73+ struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
74+ struct nvram_header *header;
75+ int i;
76+ u32 base, lim, off;
77+ u32 *src, *dst;
78+
79+ base = mcore->flash_window;
80+ lim = mcore->flash_window_size;
81+
82+ off = FLASH_MIN;
83+ while (off <= lim) {
84+ /* Windowed flash access */
85+ header = (struct nvram_header *)
86+ KSEG1ADDR(base + off - NVRAM_SPACE);
87+ if (header->magic == NVRAM_HEADER)
88+ goto found;
89+ off <<= 1;
90+ }
91+
92+ /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
93+ header = (struct nvram_header *) KSEG1ADDR(base + 4096);
94+ if (header->magic == NVRAM_HEADER)
95+ goto found;
96+
97+ header = (struct nvram_header *) KSEG1ADDR(base + 1024);
98+ if (header->magic == NVRAM_HEADER)
99+ goto found;
100+
101+ return;
102+
103+found:
104+ src = (u32 *) header;
105+ dst = (u32 *) nvram_buf;
106+ for (i = 0; i < sizeof(struct nvram_header); i += 4)
107+ *dst++ = *src++;
108+ for (; i < header->len && i < NVRAM_SPACE; i += 4)
109+ *dst++ = le32_to_cpu(*src++);
110+}
111+
112+int nvram_getenv(char *name, char *val, size_t val_len)
113+{
114+ char *var, *value, *end, *eq;
115+
116+ if (!name)
117+ return 1;
118+
119+ if (!nvram_buf[0])
120+ early_nvram_init();
121+
122+ /* Look for name=value and return value */
123+ var = &nvram_buf[sizeof(struct nvram_header)];
124+ end = nvram_buf + sizeof(nvram_buf) - 2;
125+ end[0] = end[1] = '\0';
126+ for (; *var; var = value + strlen(value) + 1) {
127+ eq = strchr(var, '=');
128+ if (!eq)
129+ break;
130+ value = eq + 1;
131+ if ((eq - var) == strlen(name) &&
132+ strncmp(var, name, (eq - var)) == 0) {
133+ snprintf(val, val_len, "%s", value);
134+ return 0;
135+ }
136+ }
137+ return 1;
138+}
139+EXPORT_SYMBOL(nvram_getenv);
140--- a/arch/mips/bcm47xx/setup.c
141@@ -1,8 +1,8 @@
142 /*
143  * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
144- * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
145  * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
146  * Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
147+ * Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
148  *
149  * This program is free software; you can redistribute it and/or modify it
150  * under the terms of the GNU General Public License as published by the
151@@ -33,6 +33,7 @@
152 #include <asm/time.h>
153 #include <bcm47xx.h>
154 #include <asm/fw/cfe/cfe_api.h>
155+#include <asm/mach-bcm47xx/nvram.h>
156
157 struct ssb_bus ssb_bcm47xx;
158 EXPORT_SYMBOL(ssb_bcm47xx);
159@@ -81,28 +82,42 @@ static int bcm47xx_get_invariants(struct
160     /* Fill boardinfo structure */
161     memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
162
163- if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0)
164+ if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 ||
165+ nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
166         iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
167- if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0)
168+ if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 ||
169+ nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
170         iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
171- if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0)
172+ if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 ||
173+ nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
174         iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
175
176     /* Fill sprom structure */
177     memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
178     iv->sprom.revision = 3;
179
180- if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
181+ if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 ||
182+ nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
183         str2eaddr(buf, iv->sprom.et0mac);
184- if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
185+
186+ if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 ||
187+ nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
188         str2eaddr(buf, iv->sprom.et1mac);
189- if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
190- iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 10);
191- if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
192- iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 10);
193- if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
194+
195+ if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ||
196+ nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
197+ iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0);
198+
199+ if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ||
200+ nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
201+ iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0);
202+
203+ if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 ||
204+ nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
205         iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
206- if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
207+
208+ if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 ||
209+ nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
210         iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
211
212     return 0;
213--- /dev/null
214@@ -0,0 +1,36 @@
215+/*
216+ * Copyright (C) 2005, Broadcom Corporation
217+ * Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org>
218+ *
219+ * This program is free software; you can redistribute it and/or modify it
220+ * under the terms of the GNU General Public License as published by the
221+ * Free Software Foundation; either version 2 of the License, or (at your
222+ * option) any later version.
223+ */
224+
225+#ifndef __NVRAM_H
226+#define __NVRAM_H
227+
228+#include <linux/types.h>
229+
230+struct nvram_header {
231+ u32 magic;
232+ u32 len;
233+ u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
234+ u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */
235+ u32 config_ncdl; /* ncdl values for memc */
236+};
237+
238+#define NVRAM_HEADER 0x48534C46 /* 'FLSH' */
239+#define NVRAM_VERSION 1
240+#define NVRAM_HEADER_SIZE 20
241+#define NVRAM_SPACE 0x8000
242+
243+#define FLASH_MIN 0x00020000 /* Minimum flash size */
244+
245+#define NVRAM_MAX_VALUE_LEN 255
246+#define NVRAM_MAX_PARAM_LEN 64
247+
248+extern int nvram_getenv(char *name, char *val, size_t val_len);
249+
250+#endif
target/linux/brcm47xx/patches-2.6.34/011-MIPS-BCM47xx-Really-fix-128MB-RAM-problem.patch
1From b6d850fe4035d6bee7199119358e06f802aa19ed Mon Sep 17 00:00:00 2001
2From: Hauke Mehrtens <hauke@hauke-m.de>
3Date: Sun, 18 Jul 2010 12:49:41 +0200
4Subject: [PATCH 1/5] MIPS: BCM47xx: Really fix 128MB RAM problem
5
6The previews patch 84a6fcb368a080620d12fc4d79e07902dbee7335 was wrong,
7I got wrong success reports.
8
9The bcm47xx architecture maps the ram into a 128MB address space. It
10will be paced there as often as goes into the 128MB. The detection
11tries to find the position where the same memory is found. When reading
12over 128MB the processor will throw an exception. If 128MB ram is
13installed, it will not find the same memory because it tries to read
14over the 128MB boarder. Now it just assumes 128MB installed ram if it
15can not find that the ram is repeating.
16
17Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
18---
19 arch/mips/bcm47xx/prom.c | 22 ++++++++++++++--------
20 1 files changed, 14 insertions(+), 8 deletions(-)
21
22--- a/arch/mips/bcm47xx/prom.c
23@@ -126,6 +126,7 @@ static __init void prom_init_cmdline(voi
24 static __init void prom_init_mem(void)
25 {
26     unsigned long mem;
27+ unsigned long max;
28
29     /* Figure out memory size by finding aliases.
30      *
31@@ -134,21 +135,26 @@ static __init void prom_init_mem(void)
32      * want to reuse the memory used by CFE (around 4MB). That means cfe_*
33      * functions stop to work at some point during the boot, we should only
34      * call them at the beginning of the boot.
35+ *
36+ * BCM47XX uses 128MB for addressing the ram, if the system contains
37+ * less that that amount of ram it remaps the ram more often into the
38+ * available space.
39+ * Accessing memory after 128MB will cause an exception.
40+ * max contains the biggest possible address supported by the platform.
41+ * If the method wants to try something above we assume 128MB ram.
42      */
43+ max = ((unsigned long)(prom_init) | ((128 << 20) - 1));
44     for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) {
45+ if (((unsigned long)(prom_init) + mem) > max) {
46+ mem = (128 << 20);
47+ printk("assume 128MB RAM\n");
48+ break;
49+ }
50         if (*(unsigned long *)((unsigned long)(prom_init) + mem) ==
51             *(unsigned long *)(prom_init))
52             break;
53     }
54
55- /* Ignoring the last page when ddr size is 128M. Cached
56- * accesses to last page is causing the processor to prefetch
57- * using address above 128M stepping out of the ddr address
58- * space.
59- */
60- if (mem == 0x8000000)
61- mem -= 0x1000;
62-
63     add_memory_region(0, mem, BOOT_MEM_RAM);
64 }
65
target/linux/brcm47xx/patches-2.6.34/012-MIPS-BCM47xx-Fill-more-values-into-ssb-sprom.patch
1From d6c049e08568aac29fff854ea0385e63c7150e09 Mon Sep 17 00:00:00 2001
2From: Hauke Mehrtens <hauke@hauke-m.de>
3Date: Sun, 18 Jul 2010 13:34:32 +0200
4Subject: [PATCH 2/5] MIPS: BCM47xx: Fill more values into ssb sprom
5
6Most of the values are stored in the nvram and not in the CFE. At first
7the nvram should be read and if there is no value it should look into
8the CFE. Now more values are read out because the b43 and b43legacy
9drivers needs them.
10
11Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
12---
13 arch/mips/bcm47xx/setup.c | 122 +++++++++++++++++++++++++++++++++------------
14 1 files changed, 89 insertions(+), 33 deletions(-)
15
16--- a/arch/mips/bcm47xx/setup.c
17@@ -74,6 +74,86 @@ static void str2eaddr(char *str, char *d
18     }
19 }
20
21+static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
22+{
23+ char buf[100];
24+
25+ memset(sprom, 0, sizeof(struct ssb_sprom));
26+
27+ sprom->revision = 3;
28+ if (nvram_getenv("il0macaddr", buf, sizeof(buf)) >= 0 ||
29+ cfe_getenv("il0macaddr", buf, sizeof(buf)) >= 0)
30+ str2eaddr(buf, sprom->il0mac);
31+ if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0 ||
32+ cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
33+ str2eaddr(buf, sprom->et0mac);
34+ if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0 ||
35+ cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
36+ str2eaddr(buf, sprom->et1mac);
37+ if (nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ||
38+ cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
39+ sprom->et0phyaddr = simple_strtoul(buf, NULL, 0);
40+ if (nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ||
41+ cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
42+ sprom->et1phyaddr = simple_strtoul(buf, NULL, 0);
43+ if (nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0 ||
44+ cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
45+ sprom->et0mdcport = !!simple_strtoul(buf, NULL, 10);
46+ if (nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0 ||
47+ cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
48+ sprom->et1mdcport = !!simple_strtoul(buf, NULL, 10);
49+ if (nvram_getenv("pa0b0", buf, sizeof(buf)) >= 0 ||
50+ cfe_getenv("pa0b0", buf, sizeof(buf)) >= 0)
51+ sprom->pa0b0 = simple_strtoul(buf, NULL, 0);
52+ if (nvram_getenv("pa0b1", buf, sizeof(buf)) >= 0 ||
53+ cfe_getenv("pa0b1", buf, sizeof(buf)) >= 0)
54+ sprom->pa0b1 = simple_strtoul(buf, NULL, 0);
55+ if (nvram_getenv("pa0b2", buf, sizeof(buf)) >= 0 ||
56+ cfe_getenv("pa0b2", buf, sizeof(buf)) >= 0)
57+ sprom->pa0b2 = simple_strtoul(buf, NULL, 0);
58+ if (nvram_getenv("pa1b0", buf, sizeof(buf)) >= 0 ||
59+ cfe_getenv("pa1b0", buf, sizeof(buf)) >= 0)
60+ sprom->pa1b0 = simple_strtoul(buf, NULL, 0);
61+ if (nvram_getenv("pa1b1", buf, sizeof(buf)) >= 0 ||
62+ cfe_getenv("pa1b1", buf, sizeof(buf)) >= 0)
63+ sprom->pa1b1 = simple_strtoul(buf, NULL, 0);
64+ if (nvram_getenv("pa1b2", buf, sizeof(buf)) >= 0 ||
65+ cfe_getenv("pa1b2", buf, sizeof(buf)) >= 0)
66+ sprom->pa1b2 = simple_strtoul(buf, NULL, 0);
67+ if (nvram_getenv("wl0gpio0", buf, sizeof(buf)) >= 0 ||
68+ cfe_getenv("wl0gpio0", buf, sizeof(buf)) >= 0)
69+ sprom->gpio0 = simple_strtoul(buf, NULL, 0);
70+ if (nvram_getenv("wl0gpio1", buf, sizeof(buf)) >= 0 ||
71+ cfe_getenv("wl0gpio1", buf, sizeof(buf)) >= 0)
72+ sprom->gpio1 = simple_strtoul(buf, NULL, 0);
73+ if (nvram_getenv("wl0gpio2", buf, sizeof(buf)) >= 0 ||
74+ cfe_getenv("wl0gpio2", buf, sizeof(buf)) >= 0)
75+ sprom->gpio2 = simple_strtoul(buf, NULL, 0);
76+ if (nvram_getenv("wl0gpio3", buf, sizeof(buf)) >= 0 ||
77+ cfe_getenv("wl0gpio3", buf, sizeof(buf)) >= 0)
78+ sprom->gpio3 = simple_strtoul(buf, NULL, 0);
79+ if (nvram_getenv("pa0maxpwr", buf, sizeof(buf)) >= 0 ||
80+ cfe_getenv("pa0maxpwr", buf, sizeof(buf)) >= 0)
81+ sprom->maxpwr_bg = simple_strtoul(buf, NULL, 0);
82+ if (nvram_getenv("pa1maxpwr", buf, sizeof(buf)) >= 0 ||
83+ cfe_getenv("pa1maxpwr", buf, sizeof(buf)) >= 0)
84+ sprom->maxpwr_a = simple_strtoul(buf, NULL, 0);
85+ if (nvram_getenv("pa0itssit", buf, sizeof(buf)) >= 0 ||
86+ cfe_getenv("pa0itssit", buf, sizeof(buf)) >= 0)
87+ sprom->itssi_bg = simple_strtoul(buf, NULL, 0);
88+ if (nvram_getenv("pa1itssit", buf, sizeof(buf)) >= 0 ||
89+ cfe_getenv("pa1itssit", buf, sizeof(buf)) >= 0)
90+ sprom->itssi_a = simple_strtoul(buf, NULL, 0);
91+ sprom->boardflags_lo = 0;
92+ if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0 ||
93+ cfe_getenv("boardflags", buf, sizeof(buf)) >= 0)
94+ sprom->boardflags_lo = simple_strtoul(buf, NULL, 0);
95+ sprom->boardflags_hi = 0;
96+ if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0 ||
97+ cfe_getenv("boardflags", buf, sizeof(buf)) >= 0)
98+ sprom->boardflags_hi = simple_strtoul(buf, NULL, 0);
99+}
100+
101 static int bcm47xx_get_invariants(struct ssb_bus *bus,
102                    struct ssb_init_invariants *iv)
103 {
104@@ -82,43 +162,19 @@ static int bcm47xx_get_invariants(struct
105     /* Fill boardinfo structure */
106     memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
107
108- if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 ||
109- nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
110+ iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
111+ if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0 ||
112+ cfe_getenv("boardtype", buf, sizeof(buf)) >= 0)
113         iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
114- if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 ||
115- nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
116- iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
117- if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 ||
118- nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
119+ if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0 ||
120+ cfe_getenv("boardrev", buf, sizeof(buf)) >= 0)
121         iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
122
123- /* Fill sprom structure */
124- memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
125- iv->sprom.revision = 3;
126-
127- if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 ||
128- nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
129- str2eaddr(buf, iv->sprom.et0mac);
130-
131- if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 ||
132- nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
133- str2eaddr(buf, iv->sprom.et1mac);
134-
135- if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ||
136- nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
137- iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0);
138-
139- if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ||
140- nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
141- iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0);
142-
143- if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 ||
144- nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
145- iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
146-
147- if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 ||
148- nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
149- iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
150+ bcm47xx_fill_sprom(&iv->sprom);
151+
152+ if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0 ||
153+ cfe_getenv("cardbus", buf, sizeof(buf)) >= 0)
154+ iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
155
156     return 0;
157 }
target/linux/brcm47xx/patches-2.6.34/013-MIPS-BCM47xx-Activate-SSB_B43_PCI_BRIDGE-by-default.patch
1From b1a0abc936bf61689d1e8a56c423b232cff24da5 Mon Sep 17 00:00:00 2001
2From: Hauke Mehrtens <hauke@hauke-m.de>
3Date: Sun, 18 Jul 2010 13:58:09 +0200
4Subject: [PATCH 3/5] MIPS: BCM47xx: Activate SSB_B43_PCI_BRIDGE by default
5
6The b43_pci_bridge is needed to use the b43 driver with brcm47xx.
7Activate it by default if pci is available.
8
9Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
10---
11 arch/mips/Kconfig | 1 +
12 1 files changed, 1 insertions(+), 0 deletions(-)
13
14--- a/arch/mips/Kconfig
15@@ -62,6 +62,7 @@ config BCM47XX
16     select SSB_DRIVER_MIPS
17     select SSB_DRIVER_EXTIF
18     select SSB_EMBEDDED
19+ select SSB_B43_PCI_BRIDGE if PCI
20     select SSB_PCICORE_HOSTMODE if PCI
21     select GENERIC_GPIO
22     select SYS_HAS_EARLY_PRINTK
target/linux/brcm47xx/patches-2.6.34/014-MIPS-BCM47xx-Setup-and-register-serial-early.patch
1From 4c6a515310f29c89f25a54a115cde905f97330f8 Mon Sep 17 00:00:00 2001
2From: Hauke Mehrtens <hauke@hauke-m.de>
3Date: Sun, 18 Jul 2010 14:59:24 +0200
4Subject: [PATCH 4/5] MIPS: BCM47xx: Setup and register serial early
5
6Swap the first and second serial if console=ttyS1 was set.
7Set it up and register it for early serial support.
8
9Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
10---
11 arch/mips/Kconfig | 1 -
12 arch/mips/bcm47xx/setup.c | 36 +++++++++++++++++++++++++++++++++++-
13 2 files changed, 35 insertions(+), 2 deletions(-)
14
15--- a/arch/mips/Kconfig
16@@ -65,7 +65,6 @@ config BCM47XX
17     select SSB_B43_PCI_BRIDGE if PCI
18     select SSB_PCICORE_HOSTMODE if PCI
19     select GENERIC_GPIO
20- select SYS_HAS_EARLY_PRINTK
21     select CFE
22     help
23      Support for BCM47XX based boards
24--- a/arch/mips/bcm47xx/setup.c
25@@ -28,6 +28,8 @@
26 #include <linux/types.h>
27 #include <linux/ssb/ssb.h>
28 #include <linux/ssb/ssb_embedded.h>
29+#include <linux/serial.h>
30+#include <linux/serial_8250.h>
31 #include <asm/bootinfo.h>
32 #include <asm/reboot.h>
33 #include <asm/time.h>
34@@ -181,12 +183,44 @@ static int bcm47xx_get_invariants(struct
35
36 void __init plat_mem_setup(void)
37 {
38- int err;
39+ int i, err;
40+ char buf[100];
41+ struct ssb_mipscore *mcore;
42
43     err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
44                       bcm47xx_get_invariants);
45     if (err)
46         panic("Failed to initialize SSB bus (err %d)\n", err);
47+ mcore = &ssb_bcm47xx.mipscore;
48+
49+ nvram_getenv("kernel_args", buf, sizeof(buf));
50+ if (!strncmp(buf, "console=ttyS1", 13)) {
51+ struct ssb_serial_port port;
52+
53+ printk("Swapping serial ports!\n");
54+ /* swap serial ports */
55+ memcpy(&port, &mcore->serial_ports[0], sizeof(port));
56+ memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1], sizeof(port));
57+ memcpy(&mcore->serial_ports[1], &port, sizeof(port));
58+ }
59+
60+ for (i = 0; i < mcore->nr_serial_ports; i++) {
61+ struct ssb_serial_port *port = &(mcore->serial_ports[i]);
62+ struct uart_port s;
63+
64+ memset(&s, 0, sizeof(s));
65+ s.line = i;
66+ s.mapbase = (unsigned int) port->regs;
67+ s.membase = port->regs;
68+ s.irq = port->irq + 2;
69+ s.uartclk = port->baud_base;
70+ s.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
71+ s.iotype = SERIAL_IO_MEM;
72+ s.regshift = port->reg_shift;
73+
74+ early_serial_setup(&s);
75+ }
76+ printk("Serial init done.\n");
77
78     _machine_restart = bcm47xx_machine_restart;
79     _machine_halt = bcm47xx_machine_halt;
target/linux/brcm47xx/patches-2.6.34/015-MIPS-BCM47xx-Remove-CFE-console.patch
1From 6bd2c73ed31a2dfe7eab04d32c17318a5c62f9d4 Mon Sep 17 00:00:00 2001
2From: Hauke Mehrtens <hauke@hauke-m.de>
3Date: Sun, 18 Jul 2010 15:11:26 +0200
4Subject: [PATCH 5/5] MIPS: BCM47xx: Remove CFE console
5
6Do not use the CFE console. It causes hangs on some devices like the
7Buffalo WHR-HP-G54.
8This was reported in https://dev.openwrt.org/ticket/4061 and
9https://forum.openwrt.org/viewtopic.php?id=17063
10
11Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
12---
13 arch/mips/bcm47xx/prom.c | 82 +++------------------------------------------
14 1 files changed, 6 insertions(+), 76 deletions(-)
15
16--- a/arch/mips/bcm47xx/prom.c
17@@ -31,96 +31,28 @@
18 #include <asm/fw/cfe/cfe_api.h>
19 #include <asm/fw/cfe/cfe_error.h>
20
21-static int cfe_cons_handle;
22-
23 const char *get_system_type(void)
24 {
25     return "Broadcom BCM47XX";
26 }
27
28-void prom_putchar(char c)
29-{
30- while (cfe_write(cfe_cons_handle, &c, 1) == 0)
31- ;
32-}
33-
34-static __init void prom_init_cfe(void)
35+static __init int prom_init_cfe(void)
36 {
37     uint32_t cfe_ept;
38     uint32_t cfe_handle;
39     uint32_t cfe_eptseal;
40- int argc = fw_arg0;
41- char **envp = (char **) fw_arg2;
42- int *prom_vec = (int *) fw_arg3;
43-
44- /*
45- * Check if a loader was used; if NOT, the 4 arguments are
46- * what CFE gives us (handle, 0, EPT and EPTSEAL)
47- */
48- if (argc < 0) {
49- cfe_handle = (uint32_t)argc;
50- cfe_ept = (uint32_t)envp;
51- cfe_eptseal = (uint32_t)prom_vec;
52- } else {
53- if ((int)prom_vec < 0) {
54- /*
55- * Old loader; all it gives us is the handle,
56- * so use the "known" entrypoint and assume
57- * the seal.
58- */
59- cfe_handle = (uint32_t)prom_vec;
60- cfe_ept = 0xBFC00500;
61- cfe_eptseal = CFE_EPTSEAL;
62- } else {
63- /*
64- * Newer loaders bundle the handle/ept/eptseal
65- * Note: prom_vec is in the loader's useg
66- * which is still alive in the TLB.
67- */
68- cfe_handle = prom_vec[0];
69- cfe_ept = prom_vec[2];
70- cfe_eptseal = prom_vec[3];
71- }
72- }
73+
74+ cfe_eptseal = (uint32_t) fw_arg3;
75+ cfe_handle = (uint32_t) fw_arg0;
76+ cfe_ept = (uint32_t) fw_arg2;
77
78     if (cfe_eptseal != CFE_EPTSEAL) {
79- /* too early for panic to do any good */
80         printk(KERN_ERR "CFE's entrypoint seal doesn't match.");
81- while (1) ;
82+ return -1;
83     }
84
85     cfe_init(cfe_handle, cfe_ept);
86-}
87-
88-static __init void prom_init_console(void)
89-{
90- /* Initialize CFE console */
91- cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
92-}
93-
94-static __init void prom_init_cmdline(void)
95-{
96- static char buf[COMMAND_LINE_SIZE] __initdata;
97-
98- /* Get the kernel command line from CFE */
99- if (cfe_getenv("LINUX_CMDLINE", buf, COMMAND_LINE_SIZE) >= 0) {
100- buf[COMMAND_LINE_SIZE - 1] = 0;
101- strcpy(arcs_cmdline, buf);
102- }
103-
104- /* Force a console handover by adding a console= argument if needed,
105- * as CFE is not available anymore later in the boot process. */
106- if ((strstr(arcs_cmdline, "console=")) == NULL) {
107- /* Try to read the default serial port used by CFE */
108- if ((cfe_getenv("BOOT_CONSOLE", buf, COMMAND_LINE_SIZE) < 0)
109- || (strncmp("uart", buf, 4)))
110- /* Default to uart0 */
111- strcpy(buf, "uart0");
112-
113- /* Compute the new command line */
114- snprintf(arcs_cmdline, COMMAND_LINE_SIZE, "%s console=ttyS%c,115200",
115- arcs_cmdline, buf[4]);
116- }
117+ return 0;
118 }
119
120 static __init void prom_init_mem(void)
121@@ -161,8 +93,6 @@ static __init void prom_init_mem(void)
122 void __init prom_init(void)
123 {
124     prom_init_cfe();
125- prom_init_console();
126- prom_init_cmdline();
127     prom_init_mem();
128 }
129
target/linux/brcm47xx/patches-2.6.34/021-USB-Add-USB-2.0-to-ssb-ohci-driver.patch
1From cb33ffbdd8491c58b35958ec74c39b3a5c7fabe8 Mon Sep 17 00:00:00 2001
2From: Hauke Mehrtens <hauke@hauke-m.de>
3Date: Sun, 18 Jul 2010 21:25:03 +0200
4Subject: [PATCH 1/2] USB: Add USB 2.0 to ssb ohci driver
5
6This adds USB 2.0 support to ssb ohci driver.
7This work was done based on Braodcom source code in the OpenWRT project.
8
9Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
10---
11 drivers/usb/host/ohci-ssb.c | 55 ++++++++++++++++++++++++++++++++++++++++--
12 1 files changed, 52 insertions(+), 3 deletions(-)
13
14--- a/drivers/usb/host/ohci-ssb.c
15@@ -92,9 +92,12 @@ static const struct hc_driver ssb_ohci_h
16 static void ssb_ohci_detach(struct ssb_device *dev)
17 {
18     struct usb_hcd *hcd = ssb_get_drvdata(dev);
19+ if (hcd->driver->shutdown)
20+ hcd->driver->shutdown(hcd);
21
22     usb_remove_hcd(hcd);
23     iounmap(hcd->regs);
24+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
25     usb_put_hcd(hcd);
26     ssb_device_disable(dev, 0);
27 }
28@@ -106,10 +109,55 @@ static int ssb_ohci_attach(struct ssb_de
29     int err = -ENOMEM;
30     u32 tmp, flags = 0;
31
32- if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV)
33- flags |= SSB_OHCI_TMSLOW_HOSTMODE;
34+ if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
35+ dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
36+ return -EOPNOTSUPP;
37
38- ssb_device_enable(dev, flags);
39+ if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
40+ /* Put the device into host-mode. */
41+ flags |= SSB_OHCI_TMSLOW_HOSTMODE;
42+ ssb_device_enable(dev, flags);
43+ } else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
44+ /*
45+ * USB 2.0 special considerations:
46+ *
47+ * 1. Since the core supports both ehci and EHCI functions, it must
48+ * only be reset once.
49+ *
50+ * 2. In addition to the standard SSB reset sequence, the Host Control
51+ * Register must be programmed to bring the USB core and various
52+ * phy components out of reset.
53+ */
54+ ssb_device_enable(dev, 0);
55+ ssb_write32(dev, 0x200, 0x7ff);
56+
57+ /* Change Flush control reg */
58+ tmp = ssb_read32(dev, 0x400);
59+ tmp &= ~8;
60+ ssb_write32(dev, 0x400, tmp);
61+ tmp = ssb_read32(dev, 0x400);
62+
63+ /* Change Shim control reg */
64+ tmp = ssb_read32(dev, 0x304);
65+ tmp &= ~0x100;
66+ ssb_write32(dev, 0x304, tmp);
67+ tmp = ssb_read32(dev, 0x304);
68+
69+ udelay(1);
70+
71+ /* Work around for 5354 failures */
72+ if ((dev->id.revision == 2) && (dev->bus->chip_id == 0x5354)) {
73+ /* Change syn01 reg */
74+ tmp = 0x00fe00fe;
75+ ssb_write32(dev, 0x894, tmp);
76+
77+ /* Change syn03 reg */
78+ tmp = ssb_read32(dev, 0x89c);
79+ tmp |= 0x1;
80+ ssb_write32(dev, 0x89c, tmp);
81+ }
82+ } else
83+ ssb_device_enable(dev, 0);
84
85     hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
86             dev_name(dev->dev));
87@@ -200,6 +248,7 @@ static int ssb_ohci_resume(struct ssb_de
88 static const struct ssb_device_id ssb_ohci_table[] = {
89     SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
90     SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
91+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
92     SSB_DEVTABLE_END
93 };
94 MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);
target/linux/brcm47xx/patches-2.6.34/022-USB-Add-ehci-ssb-driver.patch
1From cb269cf1f97c316a5184080814a751687c72b718 Mon Sep 17 00:00:00 2001
2From: Hauke Mehrtens <hauke@hauke-m.de>
3Date: Sun, 18 Jul 2010 21:29:40 +0200
4Subject: [PATCH 2/2] USB: Add ehci ssb driver
5
6Support for the Sonics Silicon Backplane (SSB) attached Broadcom USB EHCI core.
7
8Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
9---
10 drivers/usb/host/Kconfig | 13 ++
11 drivers/usb/host/ehci-hcd.c | 23 ++++-
12 drivers/usb/host/ehci-ssb.c | 258 +++++++++++++++++++++++++++++++++++++++++++
13 3 files changed, 292 insertions(+), 2 deletions(-)
14 create mode 100644 drivers/usb/host/ehci-ssb.c
15
16--- a/drivers/usb/host/Kconfig
17@@ -150,6 +150,19 @@ config USB_OXU210HP_HCD
18       To compile this driver as a module, choose M here: the
19       module will be called oxu210hp-hcd.
20
21+config USB_EHCI_HCD_SSB
22+ bool "EHCI support for Broadcom SSB EHCI core"
23+ depends on USB_EHCI_HCD && (SSB = y || SSB = USB_EHCI_HCD) && EXPERIMENTAL
24+ default n
25+ ---help---
26+ Support for the Sonics Silicon Backplane (SSB) attached
27+ Broadcom USB EHCI core.
28+
29+ This device is present in some embedded devices with
30+ Broadcom based SSB bus.
31+
32+ If unsure, say N.
33+
34 config USB_ISP116X_HCD
35     tristate "ISP116X HCD support"
36     depends on USB
37--- a/drivers/usb/host/ehci-hcd.c
38@@ -1159,8 +1159,14 @@ MODULE_LICENSE ("GPL");
39 #define PLATFORM_DRIVER ehci_atmel_driver
40 #endif
41
42+#ifdef CONFIG_USB_EHCI_HCD_SSB
43+#include "ehci-ssb.c"
44+#define SSB_EHCI_DRIVER ssb_ehci_driver
45+#endif
46+
47 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
48- !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER)
49+ !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
50+ !defined(SSB_EHCI_DRIVER)
51 #error "missing bus glue for ehci-hcd"
52 #endif
53
54@@ -1214,10 +1220,20 @@ static int __init ehci_hcd_init(void)
55     if (retval < 0)
56         goto clean3;
57 #endif
58+
59+#ifdef SSB_EHCI_DRIVER
60+ retval = ssb_driver_register(&SSB_EHCI_DRIVER);
61+ if (retval < 0)
62+ goto clean4;
63+#endif
64     return retval;
65
66+#ifdef SSB_EHCI_DRIVER
67+ /* ssb_driver_unregister(&SSB_EHCI_DRIVER); */
68+clean4:
69+#endif
70 #ifdef OF_PLATFORM_DRIVER
71- /* of_unregister_platform_driver(&OF_PLATFORM_DRIVER); */
72+ of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
73 clean3:
74 #endif
75 #ifdef PS3_SYSTEM_BUS_DRIVER
76@@ -1256,6 +1272,9 @@ static void __exit ehci_hcd_cleanup(void
77 #ifdef PS3_SYSTEM_BUS_DRIVER
78     ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
79 #endif
80+#ifdef SSB_EHCI_DRIVER
81+ ssb_driver_unregister(&SSB_EHCI_DRIVER);
82+#endif
83 #ifdef DEBUG
84     debugfs_remove(ehci_debug_root);
85 #endif
86--- /dev/null
87@@ -0,0 +1,258 @@
88+/*
89+ * Sonics Silicon Backplane
90+ * Broadcom USB-core EHCI driver (SSB bus glue)
91+ *
92+ * Copyright 2007 Steven Brown <sbrown@cortland.com>
93+ * Copyright 2010 Hauke Mehrtens <hauke@hauke-m.de>
94+ *
95+ * Derived from the OHCI-SSB driver
96+ * Copyright 2007 Michael Buesch <mb@bu3sch.de>
97+ *
98+ * Derived from the EHCI-PCI driver
99+ * Copyright (c) 2000-2004 by David Brownell
100+ *
101+ * Derived from the OHCI-PCI driver
102+ * Copyright 1999 Roman Weissgaerber
103+ * Copyright 2000-2002 David Brownell
104+ * Copyright 1999 Linus Torvalds
105+ * Copyright 1999 Gregory P. Smith
106+ *
107+ * Derived from the USBcore related parts of Broadcom-SB
108+ * Copyright 2005 Broadcom Corporation
109+ *
110+ * Licensed under the GNU/GPL. See COPYING for details.
111+ */
112+#include <linux/ssb/ssb.h>
113+
114+
115+struct ssb_ehci_device {
116+ struct ehci_hcd ehci; /* _must_ be at the beginning. */
117+};
118+
119+static inline
120+struct ssb_ehci_device *hcd_to_ssb_ehci(struct usb_hcd *hcd)
121+{
122+ return (struct ssb_ehci_device *)(hcd->hcd_priv);
123+}
124+
125+static int ssb_ehci_reset(struct usb_hcd *hcd)
126+{
127+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
128+ int err;
129+
130+ ehci->caps = hcd->regs;
131+ ehci->regs = hcd->regs +
132+ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
133+
134+ dbg_hcs_params(ehci, "reset");
135+ dbg_hcc_params(ehci, "reset");
136+
137+ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
138+
139+ err = ehci_halt(ehci);
140+
141+ if (err)
142+ return err;
143+
144+ err = ehci_init(hcd);
145+
146+ if (err)
147+ return err;
148+
149+ ehci_reset(ehci);
150+
151+ return err;
152+}
153+
154+static const struct hc_driver ssb_ehci_hc_driver = {
155+ .description = "ssb-usb-ehci",
156+ .product_desc = "SSB EHCI Controller",
157+ .hcd_priv_size = sizeof(struct ssb_ehci_device),
158+
159+ .irq = ehci_irq,
160+ .flags = HCD_MEMORY | HCD_USB2,
161+
162+ .reset = ssb_ehci_reset,
163+ .start = ehci_run,
164+ .stop = ehci_stop,
165+ .shutdown = ehci_shutdown,
166+
167+ .urb_enqueue = ehci_urb_enqueue,
168+ .urb_dequeue = ehci_urb_dequeue,
169+ .endpoint_disable = ehci_endpoint_disable,
170+ .endpoint_reset = ehci_endpoint_reset,
171+
172+ .get_frame_number = ehci_get_frame,
173+
174+ .hub_status_data = ehci_hub_status_data,
175+ .hub_control = ehci_hub_control,
176+#if defined(CONFIG_PM)
177+ .bus_suspend = ehci_bus_suspend,
178+ .bus_resume = ehci_bus_resume,
179+#endif
180+ .relinquish_port = ehci_relinquish_port,
181+ .port_handed_over = ehci_port_handed_over,
182+
183+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
184+};
185+
186+static void ssb_ehci_detach(struct ssb_device *dev)
187+{
188+ struct usb_hcd *hcd = ssb_get_drvdata(dev);
189+ if (hcd->driver->shutdown)
190+ hcd->driver->shutdown(hcd);
191+
192+ usb_remove_hcd(hcd);
193+ iounmap(hcd->regs);
194+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
195+ usb_put_hcd(hcd);
196+ ssb_device_disable(dev, 0);
197+}
198+
199+static int ssb_ehci_attach(struct ssb_device *dev)
200+{
201+ struct ssb_ehci_device *ehcidev;
202+ struct usb_hcd *hcd;
203+ int err = -ENOMEM;
204+ u32 tmp;
205+
206+ if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
207+ dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
208+ return -EOPNOTSUPP;
209+
210+ /*
211+ * USB 2.0 special considerations:
212+ *
213+ * 1. Since the core supports both ehci and EHCI functions, it must
214+ * only be reset once.
215+ *
216+ * 2. In addition to the standard SSB reset sequence, the Host Control
217+ * Register must be programmed to bring the USB core and various
218+ * phy components out of reset.
219+ */
220+ ssb_device_enable(dev, 0);
221+ ssb_write32(dev, 0x200, 0x7ff);
222+
223+ /* Change Flush control reg */
224+ tmp = ssb_read32(dev, 0x400);
225+ tmp &= ~8;
226+ ssb_write32(dev, 0x400, tmp);
227+ tmp = ssb_read32(dev, 0x400);
228+
229+ /* Change Shim control reg */
230+ tmp = ssb_read32(dev, 0x304);
231+ tmp &= ~0x100;
232+ ssb_write32(dev, 0x304, tmp);
233+ tmp = ssb_read32(dev, 0x304);
234+
235+ udelay(1);
236+
237+ /* Work around for 5354 failures */
238+ if ((dev->id.revision == 2) && (dev->bus->chip_id == 0x5354)) {
239+ /* Change syn01 reg */
240+ tmp = 0x00fe00fe;
241+ ssb_write32(dev, 0x894, tmp);
242+
243+ /* Change syn03 reg */
244+ tmp = ssb_read32(dev, 0x89c);
245+ tmp |= 0x1;
246+ ssb_write32(dev, 0x89c, tmp);
247+ }
248+
249+ hcd = usb_create_hcd(&ssb_ehci_hc_driver, dev->dev,
250+ dev_name(dev->dev));
251+ if (!hcd)
252+ goto err_dev_disable;
253+
254+ ehcidev = hcd_to_ssb_ehci(hcd);
255+ tmp = ssb_read32(dev, SSB_ADMATCH0);
256+ hcd->rsrc_start = ssb_admatch_base(tmp) + 0x800; /* ehci core offset */
257+ hcd->rsrc_len = 0x100; /* ehci reg block size */
258+ /*
259+ * start & size modified per sbutils.c
260+ */
261+ hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
262+ if (!hcd->regs)
263+ goto err_put_hcd;
264+ err = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED);
265+ if (err)
266+ goto err_iounmap;
267+
268+ ssb_set_drvdata(dev, hcd);
269+
270+ return err;
271+
272+err_iounmap:
273+ iounmap(hcd->regs);
274+err_put_hcd:
275+ usb_put_hcd(hcd);
276+err_dev_disable:
277+ ssb_device_disable(dev, 0);
278+ return err;
279+}
280+
281+static int ssb_ehci_probe(struct ssb_device *dev,
282+ const struct ssb_device_id *id)
283+{
284+ int err;
285+ u16 chipid_top;
286+
287+ /* USBcores are only connected on embedded devices. */
288+ chipid_top = (dev->bus->chip_id & 0xFF00);
289+ if (chipid_top != 0x4700 && chipid_top != 0x5300)
290+ return -ENODEV;
291+
292+ /* TODO: Probably need checks here; is the core connected? */
293+
294+ if (usb_disabled())
295+ return -ENODEV;
296+
297+ err = ssb_ehci_attach(dev);
298+
299+ return err;
300+}
301+
302+static void ssb_ehci_remove(struct ssb_device *dev)
303+{
304+ ssb_ehci_detach(dev);
305+}
306+
307+#ifdef CONFIG_PM
308+
309+static int ssb_ehci_suspend(struct ssb_device *dev, pm_message_t state)
310+{
311+ ssb_device_disable(dev, 0);
312+
313+ return 0;
314+}
315+
316+static int ssb_ehci_resume(struct ssb_device *dev)
317+{
318+ struct usb_hcd *hcd = ssb_get_drvdata(dev);
319+ struct ssb_ehci_device *ehcidev = hcd_to_ssb_ehci(hcd);
320+
321+ ssb_device_enable(dev, 0);
322+
323+ ehci_finish_controller_resume(hcd);
324+ return 0;
325+}
326+
327+#else /* !CONFIG_PM */
328+#define ssb_ehci_suspend NULL
329+#define ssb_ehci_resume NULL
330+#endif /* CONFIG_PM */
331+
332+static const struct ssb_device_id ssb_ehci_table[] = {
333+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
334+ SSB_DEVTABLE_END
335+};
336+MODULE_DEVICE_TABLE(ssb, ssb_ehci_table);
337+
338+static struct ssb_driver ssb_ehci_driver = {
339+ .name = KBUILD_MODNAME,
340+ .id_table = ssb_ehci_table,
341+ .probe = ssb_ehci_probe,
342+ .remove = ssb_ehci_remove,
343+ .suspend = ssb_ehci_suspend,
344+ .resume = ssb_ehci_resume,
345+};
target/linux/brcm47xx/patches-2.6.34/130-remove_scache.patch
1+++ b/arch/mips/Kconfig
2@@ -205,7 +205,6 @@ config MIPS_MALTA
3     select I8259
4     select MIPS_BOARDS_GEN
5     select MIPS_BONITO64
6- select MIPS_CPU_SCACHE
7     select PCI_GT64XXX_PCI0
8     select MIPS_MSC
9     select SWAP_IO_SPACE
10@@ -1589,13 +1588,6 @@ config IP22_CPU_SCACHE
11     bool
12     select BOARD_SCACHE
13
14-#
15-# Support for a MIPS32 / MIPS64 style S-caches
16-#
17-config MIPS_CPU_SCACHE
18- bool
19- select BOARD_SCACHE
20-
21 config R5000_CPU_SCACHE
22     bool
23     select BOARD_SCACHE
24+++ b/arch/mips/kernel/cpu-probe.c
25@@ -772,6 +772,8 @@ static inline void cpu_probe_mips(struct
26     case PRID_IMP_25KF:
27         c->cputype = CPU_25KF;
28         __cpu_name[cpu] = "MIPS 25Kc";
29+ /* Probe for L2 cache */
30+ c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
31         break;
32     case PRID_IMP_34K:
33         c->cputype = CPU_34K;
34+++ b/arch/mips/mm/Makefile
35@@ -33,6 +33,5 @@ obj-$(CONFIG_CPU_CAVIUM_OCTEON) += c-oct
36 obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o
37 obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o
38 obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
39-obj-$(CONFIG_MIPS_CPU_SCACHE) += sc-mips.o
40
41 EXTRA_CFLAGS += -Werror
42+++ b/arch/mips/mm/c-r4k.c
43@@ -1148,7 +1148,6 @@ static void __init loongson2_sc_init(voi
44
45 extern int r5k_sc_init(void);
46 extern int rm7k_sc_init(void);
47-extern int mips_sc_init(void);
48
49 static void __cpuinit setup_scache(void)
50 {
51@@ -1202,29 +1201,17 @@ static void __cpuinit setup_scache(void)
52 #endif
53
54     default:
55- if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
56- c->isa_level == MIPS_CPU_ISA_M32R2 ||
57- c->isa_level == MIPS_CPU_ISA_M64R1 ||
58- c->isa_level == MIPS_CPU_ISA_M64R2) {
59-#ifdef CONFIG_MIPS_CPU_SCACHE
60- if (mips_sc_init ()) {
61- scache_size = c->scache.ways * c->scache.sets * c->scache.linesz;
62- printk("MIPS secondary cache %ldkB, %s, linesize %d bytes.\n",
63- scache_size >> 10,
64- way_string[c->scache.ways], c->scache.linesz);
65- }
66-#else
67- if (!(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
68- panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
69-#endif
70- return;
71- }
72         sc_present = 0;
73     }
74
75     if (!sc_present)
76         return;
77
78+ if ((c->isa_level == MIPS_CPU_ISA_M32R1 ||
79+ c->isa_level == MIPS_CPU_ISA_M64R1) &&
80+ !(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
81+ panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
82+
83     /* compute a couple of other cache variables */
84     c->scache.waysize = scache_size / c->scache.ways;
85
target/linux/brcm47xx/patches-2.6.34/150-cpu_fixes.patch
295295     if (dc_lsize)
296296         protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
297297     if (!cpu_icache_snoops_remote_store && scache_size)
298@@ -1298,6 +1312,17 @@ static void __cpuinit coherency_setup(vo
298@@ -1311,6 +1325,17 @@ static void __cpuinit coherency_setup(vo
299299      * silly idea of putting something else there ...
300300      */
301301     switch (current_cpu_type()) {
...... 
313313     case CPU_R4000PC:
314314     case CPU_R4000SC:
315315     case CPU_R4000MC:
316@@ -1354,6 +1379,15 @@ void __cpuinit r4k_cache_init(void)
316@@ -1367,6 +1392,15 @@ void __cpuinit r4k_cache_init(void)
317317         break;
318318     }
319319
...... 
329329     probe_pcache();
330330     setup_scache();
331331
332@@ -1412,5 +1446,13 @@ void __cpuinit r4k_cache_init(void)
332@@ -1425,5 +1459,13 @@ void __cpuinit r4k_cache_init(void)
333333 #if !defined(CONFIG_MIPS_CMP)
334334     local_r4k___flush_cache_all(NULL);
335335 #endif
target/linux/brcm47xx/patches-2.6.34/170-128MB_ram_bugfix.patch
1+++ b/arch/mips/bcm47xx/prom.c
2@@ -126,6 +126,7 @@ static __init void prom_init_cmdline(voi
3 static __init void prom_init_mem(void)
4 {
5     unsigned long mem;
6+ unsigned long max;
7
8     /* Figure out memory size by finding aliases.
9      *
10@@ -134,21 +135,26 @@ static __init void prom_init_mem(void)
11      * want to reuse the memory used by CFE (around 4MB). That means cfe_*
12      * functions stop to work at some point during the boot, we should only
13      * call them at the beginning of the boot.
14+ *
15+ * BCM47XX uses 128MB for addressing the ram, if the system contains
16+ * less that that amount of ram it remaps the ram more often into the
17+ * available space.
18+ * Accessing memory after 128MB will cause an exception.
19+ * max contains the biggest possible address supported by the platform.
20+ * If the method wants to try something above we assume 128MB ram.
21      */
22+ max = ((unsigned long)(prom_init) | ((128 << 20) - 1));
23     for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) {
24+ if (((unsigned long)(prom_init) + mem) > max) {
25+ mem = (128 << 20);
26+ printk("assume 128MB RAM\n");
27+ break;
28+ }
29         if (*(unsigned long *)((unsigned long)(prom_init) + mem) ==
30             *(unsigned long *)(prom_init))
31             break;
32     }
33
34- /* Ignoring the last page when ddr size is 128M. Cached
35- * accesses to last page is causing the processor to prefetch
36- * using address above 128M stepping out of the ddr address
37- * space.
38- */
39- if (mem == 0x8000000)
40- mem -= 0x1000;
41-
42     add_memory_region(0, mem, BOOT_MEM_RAM);
43 }
44
target/linux/brcm47xx/patches-2.6.34/210-b44_phy_fix.patch
11--- a/drivers/net/b44.c
22+++ b/drivers/net/b44.c
3@@ -384,7 +384,7 @@ static void b44_set_flow_ctrl(struct b44
3@@ -381,11 +381,12 @@ static void b44_set_flow_ctrl(struct b44
44     __b44_set_flow_ctrl(bp, pause_enab);
55 }
66
77-#ifdef SSB_DRIVER_MIPS
8+#ifdef CONFIG_SSB_DRIVER_MIPS
9 extern char *nvram_get(char *name);
8-extern char *nvram_get(char *name);
9+#ifdef CONFIG_BCM47XX
10+
11+#include <asm/mach-bcm47xx/nvram.h>
1012 static void b44_wap54g10_workaround(struct b44 *bp)
1113 {
12@@ -421,12 +421,45 @@ static inline void b44_wap54g10_workarou
13 }
14 #endif
14- const char *str;
15+ char buf[20];
16     u32 val;
17     int err;
1518
16+#ifdef CONFIG_SSB_DRIVER_MIPS
19@@ -394,10 +395,9 @@ static void b44_wap54g10_workaround(stru
20      * see https://dev.openwrt.org/ticket/146
21      * check and reset bit "isolate"
22      */
23- str = nvram_get("boardnum");
24- if (!str)
25+ if (nvram_getenv("boardnum", buf, sizeof(buf)) > 0)
26         return;
27- if (simple_strtoul(str, NULL, 0) == 2) {
28+ if (simple_strtoul(buf, NULL, 0) == 2) {
29         err = __b44_readphy(bp, 0, MII_BMCR, &val);
30         if (err)
31             goto error;
32@@ -412,10 +412,43 @@ static void b44_wap54g10_workaround(stru
33 error:
34     pr_warning("PHY: cannot reset MII transceiver isolate bit\n");
35 }
36+
1737+static inline int startswith (const char *source, const char *cmp)
1838+{
1939+ return !strncmp(source,cmp,strlen(cmp));
2040+}
2141+
22+#define getvar(str) (nvram_get(str) ? : "")
23+
2442+static inline void b44_bcm47xx_workarounds(struct b44 *bp)
2543+{
44+ char buf[20];
2645+ /* Toshiba WRC-1000, Siemens SE505 v1, Askey RT-210W, RT-220W */
27+ if (simple_strtoul(getvar("boardnum"), NULL, 0) == 100) {
46+ if (nvram_getenv("boardnum", buf, sizeof(buf)) > 0)
47+ return;
48+ if (simple_strtoul(buf, NULL, 0) == 100) {
2849+ bp->phy_addr = B44_PHY_ADDR_NO_PHY;
2950+ } else {
3051+ /* WL-HDD */
3152+ struct ssb_device *sdev = bp->sdev;
32+ if (startswith(getvar("hardware_version"), "WL300-"))
33+ {
53+ if (nvram_getenv("hardware_version", buf, sizeof(buf)) > 0)
54+ return;
55+ if (startswith(buf, "WL300-")) {
3456+ if (sdev->bus->sprom.et0phyaddr == 0 &&
3557+ sdev->bus->sprom.et1phyaddr == 1)
3658+ bp->phy_addr = B44_PHY_ADDR_NO_PHY;
...... 
3961+ return;
4062+}
4163+
42+#else
64 #else
65+
66 static inline void b44_wap54g10_workaround(struct b44 *bp)
67 {
68 }
69+
4370+static inline void b44_bcm47xx_workarounds(struct b44 *bp)
4471+{
4572+}
46+#endif
47+
73 #endif
74
4875 static int b44_setup_phy(struct b44 *bp)
49 {
50     u32 val;
76@@ -424,6 +457,7 @@ static int b44_setup_phy(struct b44 *bp)
5177     int err;
5278
5379     b44_wap54g10_workaround(bp);
...... 
5581
5682     if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
5783         return 0;
58@@ -2089,6 +2122,8 @@ static int __devinit b44_get_invariants(
84@@ -2080,6 +2114,8 @@ static int __devinit b44_get_invariants(
5985      * valid PHY address. */
6086     bp->phy_addr &= 0x1F;
6187
target/linux/brcm47xx/patches-2.6.34/211-b44_timeout_spam.patch
11--- a/drivers/net/b44.c
22+++ b/drivers/net/b44.c
3@@ -191,10 +190,11 @@ static int b44_wait_bit(struct b44 *bp,
3@@ -188,10 +188,11 @@ static int b44_wait_bit(struct b44 *bp,
44         udelay(10);
55     }
66     if (i == timeout) {
target/linux/brcm47xx/patches-2.6.34/220-bcm5354.patch
11--- a/drivers/ssb/driver_chipcommon.c
22+++ b/drivers/ssb/driver_chipcommon.c
3@@ -260,6 +260,8 @@ void ssb_chipco_resume(struct ssb_chipco
3@@ -285,6 +285,8 @@ void ssb_chipco_resume(struct ssb_chipco
44 void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
55                              u32 *plltype, u32 *n, u32 *m)
66 {
...... 
99     *n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N);
1010     *plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
1111     switch (*plltype) {
12@@ -283,6 +285,8 @@ void ssb_chipco_get_clockcpu(struct ssb_
12@@ -308,6 +310,8 @@ void ssb_chipco_get_clockcpu(struct ssb_
1313 void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,
1414                  u32 *plltype, u32 *n, u32 *m)
1515 {
...... 
3131     }
3232--- a/drivers/ssb/main.c
3333+++ b/drivers/ssb/main.c
34@@ -1073,6 +1073,8 @@ u32 ssb_clockspeed(struct ssb_bus *bus)
34@@ -1075,6 +1075,8 @@ u32 ssb_clockspeed(struct ssb_bus *bus)
3535
3636     if (bus->chip_id == 0x5365) {
3737         rate = 100000000;
target/linux/brcm47xx/patches-2.6.34/250-ohci-ssb-usb2.patch
1 drivers/usb/host/ohci-ssb.c | 39 ++++++++++++++++++++++++++++++++++++---
2 1 file changed, 36 insertions(+), 3 deletions(-)
3
4+++ b/drivers/usb/host/ohci-ssb.c
5@@ -106,10 +106,42 @@ static int ssb_ohci_attach(struct ssb_de
6     int err = -ENOMEM;
7     u32 tmp, flags = 0;
8
9- if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV)
10+ if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
11+ /* Put the device into host-mode. */
12         flags |= SSB_OHCI_TMSLOW_HOSTMODE;
13-
14- ssb_device_enable(dev, flags);
15+ ssb_device_enable(dev, flags);
16+ } else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
17+ /*
18+ * USB 2.0 special considerations:
19+ *
20+ * 1. Since the core supports both OHCI and EHCI functions, it must
21+ * only be reset once.
22+ *
23+ * 2. In addition to the standard SSB reset sequence, the Host Control
24+ * Register must be programmed to bring the USB core and various
25+ * phy components out of reset.
26+ */
27+ ssb_device_enable(dev, 0);
28+ ssb_write32(dev, 0x200, 0x7ff);
29+ udelay(1);
30+ if (dev->id.revision == 1) { // bug in rev 1
31+
32+ /* Change Flush control reg */
33+ tmp = ssb_read32(dev, 0x400);
34+ tmp &= ~8;
35+ ssb_write32(dev, 0x400, tmp);
36+ tmp = ssb_read32(dev, 0x400);
37+ printk("USB20H fcr: 0x%0x\n", tmp);
38+
39+ /* Change Shim control reg */
40+ tmp = ssb_read32(dev, 0x304);
41+ tmp &= ~0x100;
42+ ssb_write32(dev, 0x304, tmp);
43+ tmp = ssb_read32(dev, 0x304);
44+ printk("USB20H shim: 0x%0x\n", tmp);
45+ }
46+ } else
47+ ssb_device_enable(dev, 0);
48
49     hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
50             dev_name(dev->dev));
51@@ -200,6 +232,7 @@ static int ssb_ohci_resume(struct ssb_de
52 static const struct ssb_device_id ssb_ohci_table[] = {
53     SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
54     SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
55+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
56     SSB_DEVTABLE_END
57 };
58 MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);
target/linux/brcm47xx/patches-2.6.34/260-ohci-set-dma-mask.patch
1 drivers/usb/host/ohci-ssb.c | 3 +++
2 1 file changed, 3 insertions(+)
3
4+++ b/drivers/usb/host/ohci-ssb.c
5@@ -106,6 +106,9 @@ static int ssb_ohci_attach(struct ssb_de
6     int err = -ENOMEM;
7     u32 tmp, flags = 0;
8
9+ if (ssb_dma_set_mask(dev, DMA_BIT_MASK(32)))
10+ return -EOPNOTSUPP;
11+
12     if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
13         /* Put the device into host-mode. */
14         flags |= SSB_OHCI_TMSLOW_HOSTMODE;
target/linux/brcm47xx/patches-2.6.34/270-ehci-ssb.patch
1 drivers/usb/host/Kconfig | 13 ++
2 drivers/usb/host/ehci-hcd.c | 12 ++
3 drivers/usb/host/ehci-ssb.c | 201 ++++++++++++++++++++++++++++++++++++++++++++
4 drivers/usb/host/ohci-ssb.c | 23 +++++
5 4 files changed, 247 insertions(+), 2 deletions(-)
6
7+++ b/drivers/usb/host/Kconfig
8@@ -150,6 +150,19 @@ config USB_OXU210HP_HCD
9       To compile this driver as a module, choose M here: the
10       module will be called oxu210hp-hcd.
11
12+config USB_EHCI_HCD_SSB
13+ bool "EHCI support for Broadcom SSB EHCI core"
14+ depends on USB_EHCI_HCD && SSB && EXPERIMENTAL
15+ default n
16+ ---help---
17+ Support for the Sonics Silicon Backplane (SSB) attached
18+ Broadcom USB EHCI core.
19+
20+ This device is present in some embedded devices with
21+ Broadcom based SSB bus.
22+
23+ If unsure, say N.
24+
25 config USB_ISP116X_HCD
26     tristate "ISP116X HCD support"
27     depends on USB
28+++ b/drivers/usb/host/ehci-hcd.c
29@@ -1159,8 +1159,16 @@ MODULE_LICENSE ("GPL");
30 #define PLATFORM_DRIVER ehci_atmel_driver
31 #endif
32
33-#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
34- !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER)
35+#ifdef CONFIG_USB_EHCI_HCD_SSB
36+#include "ehci-ssb.c"
37+#define SSB_EHCI_DRIVER ssb_ehci_driver
38+#endif
39+
40+#if !defined(PCI_DRIVER) && \
41+ !defined(PLATFORM_DRIVER) && \
42+ !defined(PS3_SYSTEM_BUS_DRIVER) && \
43+ !defined(OF_PLATFORM_DRIVER) && \
44+ !defined(SSB_EHCI_DRIVER)
45 #error "missing bus glue for ehci-hcd"
46 #endif
47
48+++ b/drivers/usb/host/ehci-ssb.c
49@@ -0,0 +1,158 @@
50+/*
51+ * Sonics Silicon Backplane
52+ * Broadcom USB-core EHCI driver (SSB bus glue)
53+ *
54+ * Copyright 2007 Steven Brown <sbrown@cortland.com>
55+ *
56+ * Derived from the OHCI-SSB driver
57+ * Copyright 2007 Michael Buesch <mb@bu3sch.de>
58+ *
59+ * Derived from the EHCI-PCI driver
60+ * Copyright (c) 2000-2004 by David Brownell
61+ *
62+ * Derived from the OHCI-PCI driver
63+ * Copyright 1999 Roman Weissgaerber
64+ * Copyright 2000-2002 David Brownell
65+ * Copyright 1999 Linus Torvalds
66+ * Copyright 1999 Gregory P. Smith
67+ *
68+ * Derived from the USBcore related parts of Broadcom-SB
69+ * Copyright 2005 Broadcom Corporation
70+ *
71+ * Licensed under the GNU/GPL. See COPYING for details.
72+ */
73+#include <linux/ssb/ssb.h>
74+
75+#define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29)
76+
77+struct ssb_ehci_device {
78+ struct ehci_hcd ehci; /* _must_ be at the beginning. */
79+
80+ u32 enable_flags;
81+};
82+
83+static inline
84+struct ssb_ehci_device *hcd_to_ssb_ehci(struct usb_hcd *hcd)
85+{
86+ return (struct ssb_ehci_device *)(hcd->hcd_priv);
87+}
88+
89+static int ssb_ehci_reset(struct usb_hcd *hcd)
90+{
91+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
92+ int err;
93+
94+ ehci->caps = hcd->regs;
95+ ehci->regs = hcd->regs +
96+ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
97+
98+ dbg_hcs_params(ehci, "reset");
99+ dbg_hcc_params(ehci, "reset");
100+
101+ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
102+
103+ err = ehci_halt(ehci);
104+
105+ if (err)
106+ return err;
107+
108+ err = ehci_init(hcd);
109+
110+ if (err)
111+ return err;
112+
113+ ehci_reset(ehci);
114+
115+ return err;
116+}
117+
118+static const struct hc_driver ssb_ehci_hc_driver = {
119+ .description = "ssb-usb-ehci",
120+ .product_desc = "SSB EHCI Controller",
121+ .hcd_priv_size = sizeof(struct ssb_ehci_device),
122+
123+ .irq = ehci_irq,
124+ .flags = HCD_MEMORY | HCD_USB2,
125+
126+ .reset = ssb_ehci_reset,
127+ .start = ehci_run,
128+ .stop = ehci_stop,
129+ .shutdown = ehci_shutdown,
130+
131+ .urb_enqueue = ehci_urb_enqueue,
132+ .urb_dequeue = ehci_urb_dequeue,
133+ .endpoint_disable = ehci_endpoint_disable,
134+ .endpoint_reset = ehci_endpoint_reset,
135+
136+ .get_frame_number = ehci_get_frame,
137+
138+ .hub_status_data = ehci_hub_status_data,
139+ .hub_control = ehci_hub_control,
140+ .bus_suspend = ehci_bus_suspend,
141+ .bus_resume = ehci_bus_resume,
142+ .relinquish_port = ehci_relinquish_port,
143+ .port_handed_over = ehci_port_handed_over,
144+
145+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
146+};
147+
148+static void ssb_ehci_detach(struct ssb_device *dev, struct usb_hcd *hcd)
149+{
150+ if (hcd->driver->shutdown)
151+ hcd->driver->shutdown(hcd);
152+
153+ usb_remove_hcd(hcd);
154+
155+ iounmap(hcd->regs);
156+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
157+
158+ usb_put_hcd(hcd);
159+}
160+EXPORT_SYMBOL_GPL(ssb_ehci_detach);
161+
162+static int ssb_ehci_attach(struct ssb_device *dev, struct usb_hcd **ehci_hcd)
163+{
164+ struct ssb_ehci_device *ehcidev;
165+ struct usb_hcd *hcd;
166+ int err = -ENOMEM;
167+ u32 tmp, flags = 0;
168+
169+ hcd = usb_create_hcd(&ssb_ehci_hc_driver, dev->dev,
170+ dev_name(dev->dev));
171+ if (!hcd)
172+ goto err_dev_disable;
173+
174+ ehcidev = hcd_to_ssb_ehci(hcd);
175+ ehcidev->enable_flags = flags;
176+ tmp = ssb_read32(dev, SSB_ADMATCH0);
177+ hcd->rsrc_start = ssb_admatch_base(tmp) + 0x800; /* ehci core offset */
178+ hcd->rsrc_len = 0x100; /* ehci reg block size */
179+ /*
180+ * start & size modified per sbutils.c
181+ */
182+ hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
183+ if (!hcd->regs)
184+ goto err_put_hcd;
185+ err = usb_add_hcd(hcd, dev->irq, IRQF_SHARED | IRQF_DISABLED);
186+ if (err)
187+ goto err_iounmap;
188+
189+ *ehci_hcd = hcd;
190+
191+ return err;
192+
193+err_iounmap:
194+ iounmap(hcd->regs);
195+err_put_hcd:
196+ usb_put_hcd(hcd);
197+err_dev_disable:
198+ ssb_device_disable(dev, flags);
199+ return err;
200+}
201+EXPORT_SYMBOL_GPL(ssb_ehci_attach);
202+
203+static const struct ssb_device_id ssb_ehci_table[] = {
204+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
205+ SSB_DEVTABLE_END
206+};
207+MODULE_DEVICE_TABLE(ssb, ssb_ehci_table);
208+++ b/drivers/usb/host/ohci-ssb.c
209@@ -17,6 +17,8 @@
210  */
211 #include <linux/ssb/ssb.h>
212
213+extern int ssb_ehci_attach(struct ssb_device *dev, struct usb_hcd **hcd);
214+extern void ssb_ehci_detach(struct ssb_device *dev, struct usb_hcd *hcd);
215
216 #define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29)
217
218@@ -24,6 +26,7 @@ struct ssb_ohci_device {
219     struct ohci_hcd ohci; /* _must_ be at the beginning. */
220
221     u32 enable_flags;
222+ struct usb_hcd *ehci_hcd;
223 };
224
225 static inline
226@@ -92,13 +95,25 @@ static const struct hc_driver ssb_ohci_h
227 static void ssb_ohci_detach(struct ssb_device *dev)
228 {
229     struct usb_hcd *hcd = ssb_get_drvdata(dev);
230+#ifdef CONFIG_USB_EHCI_HCD_SSB
231+ struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
232+#endif
233
234     usb_remove_hcd(hcd);
235     iounmap(hcd->regs);
236     usb_put_hcd(hcd);
237+
238+#ifdef CONFIG_USB_EHCI_HCD_SSB
239+ /*
240+ * Also detach ehci function
241+ */
242+ if (dev->id.coreid == SSB_DEV_USB20_HOST)
243+ ssb_ehci_detach(dev, ohcidev->ehci_hcd);
244+#endif
245     ssb_device_disable(dev, 0);
246 }
247
248+
249 static int ssb_ohci_attach(struct ssb_device *dev)
250 {
251     struct ssb_ohci_device *ohcidev;
252@@ -165,6 +180,14 @@ static int ssb_ohci_attach(struct ssb_de
253
254     ssb_set_drvdata(dev, hcd);
255
256+#ifdef CONFIG_USB_EHCI_HCD_SSB
257+ /*
258+ * attach ehci function in this core
259+ */
260+ if (dev->id.coreid == SSB_DEV_USB20_HOST)
261+ err = ssb_ehci_attach(dev, &(ohcidev->ehci_hcd));
262+#endif
263+
264     return err;
265
266 err_iounmap:
target/linux/brcm47xx/patches-2.6.34/275-usb2-bcm5354-init.patch
1This patch significantly improves the reliability of high speed
2usb writes on the bcm5354. It implements a work around for version 2
3of the usb20 core that was cribbed from the GPL sources for the
4Asus wl500gpv2 and verified against the wl520gu sources.
5
6Reference:
7GPL/WL-520gu-NewUI/src/linux/linux/arch/mips/brcm-boards/bcm947xx/pcibios.c
8GPL/WL-500gPV2-NewUI/src/linux/linux/arch/mips/brcm-boards/bcm947xx/pcibios.c
9
10Signed-off-by: Steve Brown <sbrown@cortland.com>
11
12 drivers/usb/host/ohci-ssb.c | 37 +++++++++++++++++++++++--------------
13 1 file changed, 23 insertions(+), 14 deletions(-)
14
15+++ b/drivers/usb/host/ohci-ssb.c
16@@ -141,22 +141,31 @@ static int ssb_ohci_attach(struct ssb_de
17          */
18         ssb_device_enable(dev, 0);
19         ssb_write32(dev, 0x200, 0x7ff);
20+
21+ /* Change Flush control reg */
22+ tmp = ssb_read32(dev, 0x400);
23+ tmp &= ~8;
24+ ssb_write32(dev, 0x400, tmp);
25+ tmp = ssb_read32(dev, 0x400);
26+
27+ /* Change Shim control reg */
28+ tmp = ssb_read32(dev, 0x304);
29+ tmp &= ~0x100;
30+ ssb_write32(dev, 0x304, tmp);
31+ tmp = ssb_read32(dev, 0x304);
32+
33         udelay(1);
34- if (dev->id.revision == 1) { // bug in rev 1
35
36- /* Change Flush control reg */
37- tmp = ssb_read32(dev, 0x400);
38- tmp &= ~8;
39- ssb_write32(dev, 0x400, tmp);
40- tmp = ssb_read32(dev, 0x400);
41- printk("USB20H fcr: 0x%0x\n", tmp);
42-
43- /* Change Shim control reg */
44- tmp = ssb_read32(dev, 0x304);
45- tmp &= ~0x100;
46- ssb_write32(dev, 0x304, tmp);
47- tmp = ssb_read32(dev, 0x304);
48- printk("USB20H shim: 0x%0x\n", tmp);
49+ /* Work around for 5354 failures */
50+ if ((dev->id.revision == 2) && (dev->bus->chip_id == 0x5354)) {
51+ /* Change syn01 reg */
52+ tmp = 0x00fe00fe;
53+ ssb_write32(dev, 0x894, tmp);
54+
55+ /* Change syn03 reg */
56+ tmp = ssb_read32(dev, 0x89c);
57+ tmp |= 0x1;
58+ ssb_write32(dev, 0x89c, tmp);
59         }
60     } else
61         ssb_device_enable(dev, 0);
target/linux/brcm47xx/patches-2.6.34/301-kmod-fuse-dcache-bug-r4k.patch
1818     unsigned long addr, unsigned long pfn)
1919 {
2020     struct flush_cache_page_args args;
21@@ -1456,3 +1456,10 @@ void __cpuinit r4k_cache_init(void)
21@@ -1469,3 +1469,10 @@ void __cpuinit r4k_cache_init(void)
2222     coherency_setup();
2323 #endif
2424 }
target/linux/brcm47xx/patches-2.6.34/400-arch-bcm47xx.patch
1+++ b/arch/mips/Kconfig
2@@ -62,6 +62,7 @@ config BCM47XX
3     select SSB_DRIVER_MIPS
4     select SSB_DRIVER_EXTIF
5     select SSB_EMBEDDED
6+ select SSB_B43_PCI_BRIDGE if PCI
7     select SSB_PCICORE_HOSTMODE if PCI
8     select GENERIC_GPIO
9     select SYS_HAS_EARLY_PRINTK
10+++ b/arch/mips/bcm47xx/Makefile
11@@ -3,4 +3,4 @@
12 # under Linux.
13 #
14
15-obj-y := gpio.o irq.o prom.o serial.o setup.o time.o wgt634u.o
16+obj-y := cfe_env.o gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
17+++ b/arch/mips/bcm47xx/irq.c
18@@ -1,5 +1,6 @@
19 /*
20  * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
21+ * Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
22  *
23  * This program is free software; you can redistribute it and/or modify it
24  * under the terms of the GNU General Public License as published by the
25@@ -23,10 +24,19 @@
26  */
27
28 #include <linux/types.h>
29+#include <linux/errno.h>
30+#include <linux/init.h>
31 #include <linux/interrupt.h>
32 #include <linux/irq.h>
33+#include <linux/pci.h>
34+#include <linux/ssb/ssb.h>
35+
36 #include <asm/irq_cpu.h>
37
38+
39+extern struct ssb_bus ssb_bcm47xx;
40+
41+
42 void plat_irq_dispatch(void)
43 {
44     u32 cause;
451--- a/arch/mips/bcm47xx/nvram.c
462+++ b/arch/mips/bcm47xx/nvram.c
47@@ -24,10 +24,10 @@
48 #include <asm/io.h>
49 #include <asm/uaccess.h>
50
51-#include <nvram.h>
52+#include "include/nvram.h"
53
54 #define MB * 1048576
55-extern struct ssb_bus ssb;
56+extern struct ssb_bus ssb_bcm47xx;
57
58 static char nvram_buf[NVRAM_SPACE];
59 static int cfe_env;
60@@ -36,7 +36,7 @@ extern char *cfe_env_get(char *nv_buf, c
61 /* Probe for NVRAM header */
62 static void __init early_nvram_init(void)
63 {
64- struct ssb_mipscore *mcore = &ssb.mipscore;
65+ struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
66     struct nvram_header *header;
67     int i;
68     u32 base, lim, off;
69+++ b/arch/mips/bcm47xx/setup.c
70@@ -2,7 +2,7 @@
71  * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
72  * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
73  * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
74- * Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
75+ * Copyright (C) 2006-2008 Michael Buesch <mb@bu3sch.de>
76  *
77  * This program is free software; you can redistribute it and/or modify it
78  * under the terms of the GNU General Public License as published by the
79@@ -25,18 +25,28 @@
80  * 675 Mass Ave, Cambridge, MA 02139, USA.
81  */
82
83+#include <linux/init.h>
84 #include <linux/types.h>
85 #include <linux/ssb/ssb.h>
86 #include <linux/ssb/ssb_embedded.h>
87+#include <linux/tty.h>
88+#include <linux/serial.h>
89+#include <linux/serial_core.h>
90+#include <linux/serial_reg.h>
91+#include <linux/serial_8250.h>
92 #include <asm/bootinfo.h>
93 #include <asm/reboot.h>
94 #include <asm/time.h>
95-#include <bcm47xx.h>
96 #include <asm/fw/cfe/cfe_api.h>
97+#include <linux/pm.h>
98+
99+#include "include/nvram.h"
100
101 struct ssb_bus ssb_bcm47xx;
102 EXPORT_SYMBOL(ssb_bcm47xx);
103
104+extern void bcm47xx_pci_init(void);
105+
106 static void bcm47xx_machine_restart(char *command)
107 {
108     printk(KERN_ALERT "Please stand by while rebooting the system...\n");
109@@ -56,7 +66,7 @@ static void bcm47xx_machine_halt(void)
110         cpu_relax();
111 }
112
113-static void str2eaddr(char *str, char *dest)
114+static void e_aton(char *str, char *dest)
115 {
116     int i = 0;
117
118@@ -73,51 +83,142 @@ static void str2eaddr(char *str, char *d
119     }
3@@ -92,3 +92,30 @@ int nvram_getenv(char *name, char *val,
4     return 1;
1205 }
121
122-static int bcm47xx_get_invariants(struct ssb_bus *bus,
123- struct ssb_init_invariants *iv)
124+static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
125+{
126+ char *s;
127+
128+ memset(sprom, 0xFF, sizeof(struct ssb_sprom));
129+
130+ sprom->revision = 1;
131+ if ((s = nvram_get("il0macaddr")))
132+ e_aton(s, sprom->il0mac);
133+ if ((s = nvram_get("et0macaddr")))
134+ e_aton(s, sprom->et0mac);
135+ if ((s = nvram_get("et1macaddr")))
136+ e_aton(s, sprom->et1mac);
137+ if ((s = nvram_get("et0phyaddr")))
138+ sprom->et0phyaddr = simple_strtoul(s, NULL, 0);
139+ if ((s = nvram_get("et1phyaddr")))
140+ sprom->et1phyaddr = simple_strtoul(s, NULL, 0);
141+ if ((s = nvram_get("et0mdcport")))
142+ sprom->et0mdcport = !!simple_strtoul(s, NULL, 10);
143+ if ((s = nvram_get("et1mdcport")))
144+ sprom->et1mdcport = !!simple_strtoul(s, NULL, 10);
145+ if ((s = nvram_get("pa0b0")))
146+ sprom->pa0b0 = simple_strtoul(s, NULL, 0);
147+ if ((s = nvram_get("pa0b1")))
148+ sprom->pa0b1 = simple_strtoul(s, NULL, 0);
149+ if ((s = nvram_get("pa0b2")))
150+ sprom->pa0b2 = simple_strtoul(s, NULL, 0);
151+ if ((s = nvram_get("pa1b0")))
152+ sprom->pa1b0 = simple_strtoul(s, NULL, 0);
153+ if ((s = nvram_get("pa1b1")))
154+ sprom->pa1b1 = simple_strtoul(s, NULL, 0);
155+ if ((s = nvram_get("pa1b2")))
156+ sprom->pa1b2 = simple_strtoul(s, NULL, 0);
157+ if ((s = nvram_get("wl0gpio0")))
158+ sprom->gpio0 = simple_strtoul(s, NULL, 0);
159+ if ((s = nvram_get("wl0gpio1")))
160+ sprom->gpio1 = simple_strtoul(s, NULL, 0);
161+ if ((s = nvram_get("wl0gpio2")))
162+ sprom->gpio2 = simple_strtoul(s, NULL, 0);
163+ if ((s = nvram_get("wl0gpio3")))
164+ sprom->gpio3 = simple_strtoul(s, NULL, 0);
165+ if ((s = nvram_get("pa0maxpwr")))
166+ sprom->maxpwr_bg = simple_strtoul(s, NULL, 0);
167+ if ((s = nvram_get("pa1maxpwr")))
168+ sprom->maxpwr_a = simple_strtoul(s, NULL, 0);
169+ if ((s = nvram_get("pa0itssit")))
170+ sprom->itssi_bg = simple_strtoul(s, NULL, 0);
171+ if ((s = nvram_get("pa1itssit")))
172+ sprom->itssi_a = simple_strtoul(s, NULL, 0);
173+ sprom->boardflags_lo = 0;
174+ if ((s = nvram_get("boardflags")))
175+ sprom->boardflags_lo = simple_strtoul(s, NULL, 0);
176+ sprom->boardflags_hi = 0;
177+ if ((s = nvram_get("boardflags2")))
178+ sprom->boardflags_hi = simple_strtoul(s, NULL, 0);
179+}
6 EXPORT_SYMBOL(nvram_getenv);
1807+
181+static int bcm47xx_get_invariants(struct ssb_bus *bus, struct ssb_init_invariants *iv)
182 {
183- char buf[100];
184+ char *s;
185+
186+ iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
187+ if ((s = nvram_get("boardtype")))
188+ iv->boardinfo.type = (u16)simple_strtoul(s, NULL, 0);
189+ if ((s = nvram_get("boardrev")))
190+ iv->boardinfo.rev = (u16)simple_strtoul(s, NULL, 0);
191
192- /* Fill boardinfo structure */
193- memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
194+ bcm47xx_fill_sprom(&iv->sprom);
195
196- if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0)
197- iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
198- if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0)
199- iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
200- if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0)
201- iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
202-
203- /* Fill sprom structure */
204- memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
205- iv->sprom.revision = 3;
206-
207- if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
208- str2eaddr(buf, iv->sprom.et0mac);
209- if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
210- str2eaddr(buf, iv->sprom.et1mac);
211- if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
212- iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 10);
213- if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
214- iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 10);
215- if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
216- iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
217- if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
218- iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
219+ if ((s = nvram_get("cardbus")))
220+ iv->has_cardbus_slot = !!simple_strtoul(s, NULL, 10);
221
222     return 0;
223 }
224
225 void __init plat_mem_setup(void)
226 {
227- int err;
228+ int i, err;
229+ char *s;
230+ struct ssb_mipscore *mcore;
231+
232+ err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE, bcm47xx_get_invariants);
233+ if (err) {
234+ const char *msg = "Failed to initialize SSB bus (err %d)\n";
235+ printk(msg, err); /* Make sure the message gets out of the box. */
236+ panic(msg, err);
237+ }
238+ mcore = &ssb_bcm47xx.mipscore;
239
240- err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
241- bcm47xx_get_invariants);
242- if (err)
243- panic("Failed to initialize SSB bus (err %d)\n", err);
244+ s = nvram_get("kernel_args");
245+ if (s && !strncmp(s, "console=ttyS1", 13)) {
246+ struct ssb_serial_port port;
247+
248+ printk("Swapping serial ports!\n");
249+ /* swap serial ports */
250+ memcpy(&port, &mcore->serial_ports[0], sizeof(port));
251+ memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1], sizeof(port));
252+ memcpy(&mcore->serial_ports[1], &port, sizeof(port));
8+char *nvram_get(const char *name)
9+{
10+ char *var, *value, *end, *eq;
11+
12+ if (!name)
13+ return NULL;
14+
15+ if (!nvram_buf[0])
16+ early_nvram_init();
17+
18+ /* Look for name=value and return value */
19+ var = &nvram_buf[sizeof(struct nvram_header)];
20+ end = nvram_buf + sizeof(nvram_buf) - 2;
21+ end[0] = end[1] = '\0';
22+ for (; *var; var = value + strlen(value) + 1) {
23+ if (!(eq = strchr(var, '=')))
24+ break;
25+ value = eq + 1;
26+ if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0)
27+ return value;
25328+ }
25429+
255+ for (i = 0; i < mcore->nr_serial_ports; i++) {
256+ struct ssb_serial_port *port = &(mcore->serial_ports[i]);
257+ struct uart_port s;
258+
259+ memset(&s, 0, sizeof(s));
260+ s.line = i;
261+ s.mapbase = (unsigned int) port->regs;
262+ s.membase = port->regs;
263+ s.irq = port->irq + 2;
264+ s.uartclk = port->baud_base;
265+ s.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
266+ s.iotype = SERIAL_IO_MEM;
267+ s.regshift = port->reg_shift;
30+ return NULL;
31+}
26832+
269+ early_serial_setup(&s);
270+ }
271+ printk("Serial init done.\n");
272
273     _machine_restart = bcm47xx_machine_restart;
33+EXPORT_SYMBOL(nvram_get);
34--- a/arch/mips/bcm47xx/setup.c
35@@ -226,3 +226,20 @@ void __init plat_mem_setup(void)
27436     _machine_halt = bcm47xx_machine_halt;
27537     pm_power_off = bcm47xx_machine_halt;
27638 }
...... 
29554+ return 0;
29655+}
29756+device_initcall(bcm47xx_register_gpiodev);
298+++ b/arch/mips/bcm47xx/time.c
299@@ -22,11 +22,17 @@
300  * 675 Mass Ave, Cambridge, MA 02139, USA.
301  */
302
303-
304 #include <linux/init.h>
305+#include <linux/kernel.h>
306+#include <linux/sched.h>
307+#include <linux/serial_reg.h>
308+#include <linux/interrupt.h>
309 #include <linux/ssb/ssb.h>
310+#include <asm/addrspace.h>
311+#include <asm/io.h>
312 #include <asm/time.h>
313-#include <bcm47xx.h>
314+
315+extern struct ssb_bus ssb_bcm47xx;
316
317 void __init plat_time_init(void)
318 {
target/linux/brcm47xx/patches-2.6.34/800-fix_cfe_detection.patch
1+++ b/arch/mips/bcm47xx/prom.c
2@@ -32,6 +32,7 @@
3 #include <asm/fw/cfe/cfe_error.h>
4
5 static int cfe_cons_handle;
6+static void (* __prom_putchar)(char c);
7
8 const char *get_system_type(void)
9 {
10@@ -40,65 +41,40 @@ const char *get_system_type(void)
11
12 void prom_putchar(char c)
13 {
14+ if (__prom_putchar)
15+ __prom_putchar(c);
16+}
17+
18+void prom_putchar_cfe(char c)
19+{
20     while (cfe_write(cfe_cons_handle, &c, 1) == 0)
21         ;
22 }
23
24-static __init void prom_init_cfe(void)
25+static __init int prom_init_cfe(void)
26 {
27     uint32_t cfe_ept;
28     uint32_t cfe_handle;
29     uint32_t cfe_eptseal;
30- int argc = fw_arg0;
31- char **envp = (char **) fw_arg2;
32- int *prom_vec = (int *) fw_arg3;
33-
34- /*
35- * Check if a loader was used; if NOT, the 4 arguments are
36- * what CFE gives us (handle, 0, EPT and EPTSEAL)
37- */
38- if (argc < 0) {
39- cfe_handle = (uint32_t)argc;
40- cfe_ept = (uint32_t)envp;
41- cfe_eptseal = (uint32_t)prom_vec;
42- } else {
43- if ((int)prom_vec < 0) {
44- /*
45- * Old loader; all it gives us is the handle,
46- * so use the "known" entrypoint and assume
47- * the seal.
48- */
49- cfe_handle = (uint32_t)prom_vec;
50- cfe_ept = 0xBFC00500;
51- cfe_eptseal = CFE_EPTSEAL;
52- } else {
53- /*
54- * Newer loaders bundle the handle/ept/eptseal
55- * Note: prom_vec is in the loader's useg
56- * which is still alive in the TLB.
57- */
58- cfe_handle = prom_vec[0];
59- cfe_ept = prom_vec[2];
60- cfe_eptseal = prom_vec[3];
61- }
62- }
63
64- if (cfe_eptseal != CFE_EPTSEAL) {
65- /* too early for panic to do any good */
66- printk(KERN_ERR "CFE's entrypoint seal doesn't match.");
67- while (1) ;
68- }
69+ cfe_eptseal = (uint32_t) fw_arg3;
70+ cfe_handle = (uint32_t) fw_arg0;
71+ cfe_ept = (uint32_t) fw_arg2;
72+
73+ if (cfe_eptseal != CFE_EPTSEAL)
74+ return -1;
75
76     cfe_init(cfe_handle, cfe_ept);
77+ return 0;
78 }
79
80-static __init void prom_init_console(void)
81+static __init void prom_init_console_cfe(void)
82 {
83     /* Initialize CFE console */
84     cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
85 }
86
87-static __init void prom_init_cmdline(void)
88+static __init void prom_init_cmdline_cfe(void)
89 {
90     static char buf[COMMAND_LINE_SIZE] __initdata;
91
92@@ -160,9 +136,12 @@ static __init void prom_init_mem(void)
93
94 void __init prom_init(void)
95 {
96- prom_init_cfe();
97- prom_init_console();
98- prom_init_cmdline();
99+ if (prom_init_cfe() == 0) {
100+ //prom_init_console_cfe();
101+ //prom_init_cmdline_cfe();
102+ __prom_putchar = prom_putchar_cfe;
103+ }
104+
105     prom_init_mem();
106 }
107
target/linux/brcm47xx/patches-2.6.34/812-disable_wgt634u_crap.patch
44 # under Linux.
55 #
66
7-obj-y := cfe_env.o gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
8+obj-y := cfe_env.o gpio.o irq.o nvram.o prom.o serial.o setup.o time.o
7-obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
8+obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o
99--- a/arch/mips/bcm47xx/wgt634u.c
1010+++ /dev/null
1111@@ -1,166 +0,0 @@
target/linux/brcm47xx/patches-2.6.34/900-disable_early_printk.patch
1+++ b/arch/mips/Kconfig
2@@ -65,7 +65,6 @@ config BCM47XX
3     select SSB_B43_PCI_BRIDGE if PCI
4     select SSB_PCICORE_HOSTMODE if PCI
5     select GENERIC_GPIO
6- select SYS_HAS_EARLY_PRINTK
7     select CFE
8     help
9      Support for BCM47XX based boards
target/linux/brcm47xx/patches-2.6.34/940-bcm47xx-yenta.patch
1717
1818     mask = probe_irq_mask(val) & 0xffff;
1919
20@@ -1022,6 +1025,10 @@ static void yenta_get_socket_capabilitie
20@@ -1023,6 +1026,10 @@ static void yenta_get_socket_capabilitie
2121     else
2222         socket->socket.irq_mask = 0;
2323
...... 
2828     dev_printk(KERN_INFO, &socket->dev->dev,
2929            "ISA IRQ mask 0x%04x, PCI irq %d\n",
3030            socket->socket.irq_mask, socket->cb_irq);
31@@ -1260,6 +1267,15 @@ static int __devinit yenta_probe(struct
31@@ -1261,6 +1268,15 @@ static int __devinit yenta_probe(struct
3232     dev_printk(KERN_INFO, &dev->dev,
3333            "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
3434
target/linux/brcm47xx/patches-2.6.34/999-wl_exports.patch
11--- a/arch/mips/bcm47xx/nvram.c
22+++ b/arch/mips/bcm47xx/nvram.c
3@@ -29,7 +29,9 @@
4 #define MB * 1048576
5 extern struct ssb_bus ssb_bcm47xx;
3@@ -20,7 +20,8 @@
4 #include <asm/mach-bcm47xx/nvram.h>
5 #include <asm/mach-bcm47xx/bcm47xx.h>
66
77-static char nvram_buf[NVRAM_SPACE];
88+char nvram_buf[NVRAM_SPACE];
99+EXPORT_SYMBOL(nvram_buf);
10+
11 static int cfe_env;
12 extern char *cfe_env_get(char *nv_buf, const char *name);
13
10
11 /* Probe for NVRAM header */
12 static void __init early_nvram_init(void)
1413--- a/arch/mips/mm/cache.c
1514+++ b/arch/mips/mm/cache.c
1615@@ -52,6 +52,7 @@ void (*_dma_cache_wback)(unsigned long s
target/linux/brcm47xx/patches-2.6.35/011-MIPS-BCM47xx-Really-fix-128MB-RAM-problem.patch
1From b6d850fe4035d6bee7199119358e06f802aa19ed Mon Sep 17 00:00:00 2001
2From: Hauke Mehrtens <hauke@hauke-m.de>
3Date: Sun, 18 Jul 2010 12:49:41 +0200
4Subject: [PATCH 1/5] MIPS: BCM47xx: Really fix 128MB RAM problem
5
6The previews patch 84a6fcb368a080620d12fc4d79e07902dbee7335 was wrong,
7I got wrong success reports.
8
9The bcm47xx architecture maps the ram into a 128MB address space. It
10will be paced there as often as goes into the 128MB. The detection
11tries to find the position where the same memory is found. When reading
12over 128MB the processor will throw an exception. If 128MB ram is
13installed, it will not find the same memory because it tries to read
14over the 128MB boarder. Now it just assumes 128MB installed ram if it
15can not find that the ram is repeating.
16
17Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
18---
19 arch/mips/bcm47xx/prom.c | 22 ++++++++++++++--------
20 1 files changed, 14 insertions(+), 8 deletions(-)
21
22--- a/arch/mips/bcm47xx/prom.c
23@@ -126,6 +126,7 @@ static __init void prom_init_cmdline(voi
24 static __init void prom_init_mem(void)
25 {
26     unsigned long mem;
27+ unsigned long max;
28
29     /* Figure out memory size by finding aliases.
30      *
31@@ -134,21 +135,26 @@ static __init void prom_init_mem(void)
32      * want to reuse the memory used by CFE (around 4MB). That means cfe_*
33      * functions stop to work at some point during the boot, we should only
34      * call them at the beginning of the boot.
35+ *
36+ * BCM47XX uses 128MB for addressing the ram, if the system contains
37+ * less that that amount of ram it remaps the ram more often into the
38+ * available space.
39+ * Accessing memory after 128MB will cause an exception.
40+ * max contains the biggest possible address supported by the platform.
41+ * If the method wants to try something above we assume 128MB ram.
42      */
43+ max = ((unsigned long)(prom_init) | ((128 << 20) - 1));
44     for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) {
45+ if (((unsigned long)(prom_init) + mem) > max) {
46+ mem = (128 << 20);
47+ printk("assume 128MB RAM\n");
48+ break;
49+ }
50         if (*(unsigned long *)((unsigned long)(prom_init) + mem) ==
51             *(unsigned long *)(prom_init))
52             break;
53     }
54
55- /* Ignoring the last page when ddr size is 128M. Cached
56- * accesses to last page is causing the processor to prefetch
57- * using address above 128M stepping out of the ddr address
58- * space.
59- */
60- if (mem == 0x8000000)
61- mem -= 0x1000;
62-
63     add_memory_region(0, mem, BOOT_MEM_RAM);
64 }
65
target/linux/brcm47xx/patches-2.6.35/012-MIPS-BCM47xx-Fill-more-values-into-ssb-sprom.patch
1From d6c049e08568aac29fff854ea0385e63c7150e09 Mon Sep 17 00:00:00 2001
2From: Hauke Mehrtens <hauke@hauke-m.de>
3Date: Sun, 18 Jul 2010 13:34:32 +0200
4Subject: [PATCH 2/5] MIPS: BCM47xx: Fill more values into ssb sprom
5
6Most of the values are stored in the nvram and not in the CFE. At first
7the nvram should be read and if there is no value it should look into
8the CFE. Now more values are read out because the b43 and b43legacy
9drivers needs them.
10
11Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
12---
13 arch/mips/bcm47xx/setup.c | 122 +++++++++++++++++++++++++++++++++------------
14 1 files changed, 89 insertions(+), 33 deletions(-)
15
16--- a/arch/mips/bcm47xx/setup.c
17@@ -74,6 +74,86 @@ static void str2eaddr(char *str, char *d
18     }
19 }
20
21+static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
22+{
23+ char buf[100];
24+
25+ memset(sprom, 0, sizeof(struct ssb_sprom));
26+
27+ sprom->revision = 3;
28+ if (nvram_getenv("il0macaddr", buf, sizeof(buf)) >= 0 ||
29+ cfe_getenv("il0macaddr", buf, sizeof(buf)) >= 0)
30+ str2eaddr(buf, sprom->il0mac);
31+ if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0 ||
32+ cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
33+ str2eaddr(buf, sprom->et0mac);
34+ if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0 ||
35+ cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
36+ str2eaddr(buf, sprom->et1mac);
37+ if (nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ||
38+ cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
39+ sprom->et0phyaddr = simple_strtoul(buf, NULL, 0);
40+ if (nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ||
41+ cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
42+ sprom->et1phyaddr = simple_strtoul(buf, NULL, 0);
43+ if (nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0 ||
44+ cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
45+ sprom->et0mdcport = !!simple_strtoul(buf, NULL, 10);
46+ if (nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0 ||
47+ cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
48+ sprom->et1mdcport = !!simple_strtoul(buf, NULL, 10);
49+ if (nvram_getenv("pa0b0", buf, sizeof(buf)) >= 0 ||
50+ cfe_getenv("pa0b0", buf, sizeof(buf)) >= 0)
51+ sprom->pa0b0 = simple_strtoul(buf, NULL, 0);
52+ if (nvram_getenv("pa0b1", buf, sizeof(buf)) >= 0 ||
53+ cfe_getenv("pa0b1", buf, sizeof(buf)) >= 0)
54+ sprom->pa0b1 = simple_strtoul(buf, NULL, 0);
55+ if (nvram_getenv("pa0b2", buf, sizeof(buf)) >= 0 ||
56+ cfe_getenv("pa0b2", buf, sizeof(buf)) >= 0)
57+ sprom->pa0b2 = simple_strtoul(buf, NULL, 0);
58+ if (nvram_getenv("pa1b0", buf, sizeof(buf)) >= 0 ||
59+ cfe_getenv("pa1b0", buf, sizeof(buf)) >= 0)
60+ sprom->pa1b0 = simple_strtoul(buf, NULL, 0);
61+ if (nvram_getenv("pa1b1", buf, sizeof(buf)) >= 0 ||
62+ cfe_getenv("pa1b1", buf, sizeof(buf)) >= 0)
63+ sprom->pa1b1 = simple_strtoul(buf, NULL, 0);
64+ if (nvram_getenv("pa1b2", buf, sizeof(buf)) >= 0 ||
65+ cfe_getenv("pa1b2", buf, sizeof(buf)) >= 0)
66+ sprom->pa1b2 = simple_strtoul(buf, NULL, 0);
67+ if (nvram_getenv("wl0gpio0", buf, sizeof(buf)) >= 0 ||
68+ cfe_getenv("wl0gpio0", buf, sizeof(buf)) >= 0)
69+ sprom->gpio0 = simple_strtoul(buf, NULL, 0);
70+ if (nvram_getenv("wl0gpio1", buf, sizeof(buf)) >= 0 ||
71+ cfe_getenv("wl0gpio1", buf, sizeof(buf)) >= 0)
72+ sprom->gpio1 = simple_strtoul(buf, NULL, 0);
73+ if (nvram_getenv("wl0gpio2", buf, sizeof(buf)) >= 0 ||
74+ cfe_getenv("wl0gpio2", buf, sizeof(buf)) >= 0)
75+ sprom->gpio2 = simple_strtoul(buf, NULL, 0);
76+ if (nvram_getenv("wl0gpio3", buf, sizeof(buf)) >= 0 ||
77+ cfe_getenv("wl0gpio3", buf, sizeof(buf)) >= 0)
78+ sprom->gpio3 = simple_strtoul(buf, NULL, 0);
79+ if (nvram_getenv("pa0maxpwr", buf, sizeof(buf)) >= 0 ||
80+ cfe_getenv("pa0maxpwr", buf, sizeof(buf)) >= 0)
81+ sprom->maxpwr_bg = simple_strtoul(buf, NULL, 0);
82+ if (nvram_getenv("pa1maxpwr", buf, sizeof(buf)) >= 0 ||
83+ cfe_getenv("pa1maxpwr", buf, sizeof(buf)) >= 0)
84+ sprom->maxpwr_a = simple_strtoul(buf, NULL, 0);
85+ if (nvram_getenv("pa0itssit", buf, sizeof(buf)) >= 0 ||
86+ cfe_getenv("pa0itssit", buf, sizeof(buf)) >= 0)
87+ sprom->itssi_bg = simple_strtoul(buf, NULL, 0);
88+ if (nvram_getenv("pa1itssit", buf, sizeof(buf)) >= 0 ||
89+ cfe_getenv("pa1itssit", buf, sizeof(buf)) >= 0)
90+ sprom->itssi_a = simple_strtoul(buf, NULL, 0);
91+ sprom->boardflags_lo = 0;
92+ if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0 ||
93+ cfe_getenv("boardflags", buf, sizeof(buf)) >= 0)
94+ sprom->boardflags_lo = simple_strtoul(buf, NULL, 0);
95+ sprom->boardflags_hi = 0;
96+ if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0 ||
97+ cfe_getenv("boardflags", buf, sizeof(buf)) >= 0)
98+ sprom->boardflags_hi = simple_strtoul(buf, NULL, 0);
99+}
100+
101 static int bcm47xx_get_invariants(struct ssb_bus *bus,
102                    struct ssb_init_invariants *iv)
103 {
104@@ -82,43 +162,19 @@ static int bcm47xx_get_invariants(struct
105     /* Fill boardinfo structure */
106     memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
107
108- if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 ||
109- nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
110+ iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
111+ if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0 ||
112+ cfe_getenv("boardtype", buf, sizeof(buf)) >= 0)
113         iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
114- if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 ||
115- nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
116- iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
117- if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 ||
118- nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
119+ if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0 ||
120+ cfe_getenv("boardrev", buf, sizeof(buf)) >= 0)
121         iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
122
123- /* Fill sprom structure */
124- memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
125- iv->sprom.revision = 3;
126-
127- if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 ||
128- nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
129- str2eaddr(buf, iv->sprom.et0mac);
130-
131- if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 ||
132- nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
133- str2eaddr(buf, iv->sprom.et1mac);
134-
135- if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ||
136- nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
137- iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0);
138-
139- if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ||
140- nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
141- iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0);
142-
143- if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 ||
144- nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
145- iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
146-
147- if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 ||
148- nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
149- iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
150+ bcm47xx_fill_sprom(&iv->sprom);
151+
152+ if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0 ||
153+ cfe_getenv("cardbus", buf, sizeof(buf)) >= 0)
154+ iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
155
156     return 0;
157 }
target/linux/brcm47xx/patches-2.6.35/013-MIPS-BCM47xx-Activate-SSB_B43_PCI_BRIDGE-by-default.patch
1From b1a0abc936bf61689d1e8a56c423b232cff24da5 Mon Sep 17 00:00:00 2001
2From: Hauke Mehrtens <hauke@hauke-m.de>
3Date: Sun, 18 Jul 2010 13:58:09 +0200
4Subject: [PATCH 3/5] MIPS: BCM47xx: Activate SSB_B43_PCI_BRIDGE by default
5
6The b43_pci_bridge is needed to use the b43 driver with brcm47xx.
7Activate it by default if pci is available.
8
9Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
10---
11 arch/mips/Kconfig | 1 +
12 1 files changed, 1 insertions(+), 0 deletions(-)
13
14--- a/arch/mips/Kconfig
15@@ -62,6 +62,7 @@ config BCM47XX
16     select SSB_DRIVER_MIPS
17     select SSB_DRIVER_EXTIF
18     select SSB_EMBEDDED
19+ select SSB_B43_PCI_BRIDGE if PCI
20     select SSB_PCICORE_HOSTMODE if PCI
21     select GENERIC_GPIO
22     select SYS_HAS_EARLY_PRINTK
target/linux/brcm47xx/patches-2.6.35/014-MIPS-BCM47xx-Setup-and-register-serial-early.patch
1From 4c6a515310f29c89f25a54a115cde905f97330f8 Mon Sep 17 00:00:00 2001
2From: Hauke Mehrtens <hauke@hauke-m.de>
3Date: Sun, 18 Jul 2010 14:59:24 +0200
4Subject: [PATCH 4/5] MIPS: BCM47xx: Setup and register serial early
5
6Swap the first and second serial if console=ttyS1 was set.
7Set it up and register it for early serial support.
8
9Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
10---
11 arch/mips/Kconfig | 1 -
12 arch/mips/bcm47xx/setup.c | 36 +++++++++++++++++++++++++++++++++++-
13 2 files changed, 35 insertions(+), 2 deletions(-)
14
15--- a/arch/mips/Kconfig
16@@ -65,7 +65,6 @@ config BCM47XX
17     select SSB_B43_PCI_BRIDGE if PCI
18     select SSB_PCICORE_HOSTMODE if PCI
19     select GENERIC_GPIO
20- select SYS_HAS_EARLY_PRINTK
21     select CFE
22     help
23      Support for BCM47XX based boards
24--- a/arch/mips/bcm47xx/setup.c
25@@ -28,6 +28,8 @@
26 #include <linux/types.h>
27 #include <linux/ssb/ssb.h>
28 #include <linux/ssb/ssb_embedded.h>
29+#include <linux/serial.h>
30+#include <linux/serial_8250.h>
31 #include <asm/bootinfo.h>
32 #include <asm/reboot.h>
33 #include <asm/time.h>
34@@ -181,12 +183,44 @@ static int bcm47xx_get_invariants(struct
35
36 void __init plat_mem_setup(void)
37 {
38- int err;
39+ int i, err;
40+ char buf[100];
41+ struct ssb_mipscore *mcore;
42
43     err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
44                       bcm47xx_get_invariants);
45     if (err)
46         panic("Failed to initialize SSB bus (err %d)\n", err);
47+ mcore = &ssb_bcm47xx.mipscore;
48+
49+ nvram_getenv("kernel_args", buf, sizeof(buf));
50+ if (!strncmp(buf, "console=ttyS1", 13)) {
51+ struct ssb_serial_port port;
52+
53+ printk("Swapping serial ports!\n");
54+ /* swap serial ports */
55+ memcpy(&port, &mcore->serial_ports[0], sizeof(port));
56+ memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1], sizeof(port));
57+ memcpy(&mcore->serial_ports[1], &port, sizeof(port));
58+ }
59+
60+ for (i = 0; i < mcore->nr_serial_ports; i++) {
61+ struct ssb_serial_port *port = &(mcore->serial_ports[i]);
62+ struct uart_port s;
63+
64+ memset(&s, 0, sizeof(s));
65+ s.line = i;
66+ s.mapbase = (unsigned int) port->regs;
67+ s.membase = port->regs;
68+ s.irq = port->irq + 2;
69+ s.uartclk = port->baud_base;
70+ s.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
71+ s.iotype = SERIAL_IO_MEM;
72+ s.regshift = port->reg_shift;
73+
74+ early_serial_setup(&s);
75+ }
76+ printk("Serial init done.\n");
77
78     _machine_restart = bcm47xx_machine_restart;
79     _machine_halt = bcm47xx_machine_halt;
target/linux/brcm47xx/patches-2.6.35/015-MIPS-BCM47xx-Remove-CFE-console.patch
1From 6bd2c73ed31a2dfe7eab04d32c17318a5c62f9d4 Mon Sep 17 00:00:00 2001
2From: Hauke Mehrtens <hauke@hauke-m.de>
3Date: Sun, 18 Jul 2010 15:11:26 +0200
4Subject: [PATCH 5/5] MIPS: BCM47xx: Remove CFE console
5
6Do not use the CFE console. It causes hangs on some devices like the
7Buffalo WHR-HP-G54.
8This was reported in https://dev.openwrt.org/ticket/4061 and
9https://forum.openwrt.org/viewtopic.php?id=17063
10
11Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
12---
13 arch/mips/bcm47xx/prom.c | 82 +++------------------------------------------
14 1 files changed, 6 insertions(+), 76 deletions(-)
15
16--- a/arch/mips/bcm47xx/prom.c
17@@ -31,96 +31,28 @@
18 #include <asm/fw/cfe/cfe_api.h>
19 #include <asm/fw/cfe/cfe_error.h>
20
21-static int cfe_cons_handle;
22-
23 const char *get_system_type(void)
24 {
25     return "Broadcom BCM47XX";
26 }
27
28-void prom_putchar(char c)
29-{
30- while (cfe_write(cfe_cons_handle, &c, 1) == 0)
31- ;
32-}
33-
34-static __init void prom_init_cfe(void)
35+static __init int prom_init_cfe(void)
36 {
37     uint32_t cfe_ept;
38     uint32_t cfe_handle;
39     uint32_t cfe_eptseal;
40- int argc = fw_arg0;
41- char **envp = (char **) fw_arg2;
42- int *prom_vec = (int *) fw_arg3;
43-
44- /*
45- * Check if a loader was used; if NOT, the 4 arguments are
46- * what CFE gives us (handle, 0, EPT and EPTSEAL)
47- */
48- if (argc < 0) {
49- cfe_handle = (uint32_t)argc;
50- cfe_ept = (uint32_t)envp;
51- cfe_eptseal = (uint32_t)prom_vec;
52- } else {
53- if ((int)prom_vec < 0) {
54- /*
55- * Old loader; all it gives us is the handle,
56- * so use the "known" entrypoint and assume
57- * the seal.
58- */
59- cfe_handle = (uint32_t)prom_vec;
60- cfe_ept = 0xBFC00500;
61- cfe_eptseal = CFE_EPTSEAL;
62- } else {
63- /*
64- * Newer loaders bundle the handle/ept/eptseal
65- * Note: prom_vec is in the loader's useg
66- * which is still alive in the TLB.
67- */
68- cfe_handle = prom_vec[0];
69- cfe_ept = prom_vec[2];
70- cfe_eptseal = prom_vec[3];
71- }
72- }
73+
74+ cfe_eptseal = (uint32_t) fw_arg3;
75+ cfe_handle = (uint32_t) fw_arg0;
76+ cfe_ept = (uint32_t) fw_arg2;
77
78     if (cfe_eptseal != CFE_EPTSEAL) {
79- /* too early for panic to do any good */
80         printk(KERN_ERR "CFE's entrypoint seal doesn't match.");
81- while (1) ;
82+ return -1;
83     }
84
85     cfe_init(cfe_handle, cfe_ept);
86-}
87-
88-static __init void prom_init_console(void)
89-{
90- /* Initialize CFE console */
91- cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
92-}
93-
94-static __init void prom_init_cmdline(void)
95-{
96- static char buf[COMMAND_LINE_SIZE] __initdata;
97-
98- /* Get the kernel command line from CFE */
99- if (cfe_getenv("LINUX_CMDLINE", buf, COMMAND_LINE_SIZE) >= 0) {
100- buf[COMMAND_LINE_SIZE - 1] = 0;
101- strcpy(arcs_cmdline, buf);
102- }
103-
104- /* Force a console handover by adding a console= argument if needed,
105- * as CFE is not available anymore later in the boot process. */
106- if ((strstr(arcs_cmdline, "console=")) == NULL) {
107- /* Try to read the default serial port used by CFE */
108- if ((cfe_getenv("BOOT_CONSOLE", buf, COMMAND_LINE_SIZE) < 0)
109- || (strncmp("uart", buf, 4)))
110- /* Default to uart0 */
111- strcpy(buf, "uart0");
112-
113- /* Compute the new command line */
114- snprintf(arcs_cmdline, COMMAND_LINE_SIZE, "%s console=ttyS%c,115200",
115- arcs_cmdline, buf[4]);
116- }
117+ return 0;
118 }
119
120 static __init void prom_init_mem(void)
121@@ -161,8 +93,6 @@ static __init void prom_init_mem(void)
122 void __init prom_init(void)
123 {
124     prom_init_cfe();
125- prom_init_console();
126- prom_init_cmdline();
127     prom_init_mem();
128 }
129
target/linux/brcm47xx/patches-2.6.35/021-USB-Add-USB-2.0-to-ssb-ohci-driver.patch
1From cb33ffbdd8491c58b35958ec74c39b3a5c7fabe8 Mon Sep 17 00:00:00 2001
2From: Hauke Mehrtens <hauke@hauke-m.de>
3Date: Sun, 18 Jul 2010 21:25:03 +0200
4Subject: [PATCH 1/2] USB: Add USB 2.0 to ssb ohci driver
5
6This adds USB 2.0 support to ssb ohci driver.
7This work was done based on Braodcom source code in the OpenWRT project.
8
9Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
10---
11 drivers/usb/host/ohci-ssb.c | 55 ++++++++++++++++++++++++++++++++++++++++--
12 1 files changed, 52 insertions(+), 3 deletions(-)
13
14--- a/drivers/usb/host/ohci-ssb.c
15@@ -92,9 +92,12 @@ static const struct hc_driver ssb_ohci_h
16 static void ssb_ohci_detach(struct ssb_device *dev)
17 {
18     struct usb_hcd *hcd = ssb_get_drvdata(dev);
19+ if (hcd->driver->shutdown)
20+ hcd->driver->shutdown(hcd);
21
22     usb_remove_hcd(hcd);
23     iounmap(hcd->regs);
24+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
25     usb_put_hcd(hcd);
26     ssb_device_disable(dev, 0);
27 }
28@@ -106,10 +109,55 @@ static int ssb_ohci_attach(struct ssb_de
29     int err = -ENOMEM;
30     u32 tmp, flags = 0;
31
32- if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV)
33- flags |= SSB_OHCI_TMSLOW_HOSTMODE;
34+ if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
35+ dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
36+ return -EOPNOTSUPP;
37
38- ssb_device_enable(dev, flags);
39+ if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
40+ /* Put the device into host-mode. */
41+ flags |= SSB_OHCI_TMSLOW_HOSTMODE;
42+ ssb_device_enable(dev, flags);
43+ } else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
44+ /*
45+ * USB 2.0 special considerations:
46+ *
47+ * 1. Since the core supports both ehci and EHCI functions, it must
48+ * only be reset once.
49+ *
50+ * 2. In addition to the standard SSB reset sequence, the Host Control
51+ * Register must be programmed to bring the USB core and various
52+ * phy components out of reset.
53+ */
54+ ssb_device_enable(dev, 0);
55+ ssb_write32(dev, 0x200, 0x7ff);
56+
57+ /* Change Flush control reg */
58+ tmp = ssb_read32(dev, 0x400);
59+ tmp &= ~8;
60+ ssb_write32(dev, 0x400, tmp);
61+ tmp = ssb_read32(dev, 0x400);
62+
63+ /* Change Shim control reg */
64+ tmp = ssb_read32(dev, 0x304);
65+ tmp &= ~0x100;
66+ ssb_write32(dev, 0x304, tmp);
67+ tmp = ssb_read32(dev, 0x304);
68+
69+ udelay(1);
70+
71+ /* Work around for 5354 failures */
72+ if ((dev->id.revision == 2) && (dev->bus->chip_id == 0x5354)) {
73+ /* Change syn01 reg */
74+ tmp = 0x00fe00fe;
75+ ssb_write32(dev, 0x894, tmp);
76+
77+ /* Change syn03 reg */
78+ tmp = ssb_read32(dev, 0x89c);
79+ tmp |= 0x1;
80+ ssb_write32(dev, 0x89c, tmp);
81+ }
82+ } else
83+ ssb_device_enable(dev, 0);
84
85     hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
86             dev_name(dev->dev));
87@@ -200,6 +248,7 @@ static int ssb_ohci_resume(struct ssb_de
88 static const struct ssb_device_id ssb_ohci_table[] = {
89     SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
90     SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
91+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
92     SSB_DEVTABLE_END
93 };
94 MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);
target/linux/brcm47xx/patches-2.6.35/022-USB-Add-ehci-ssb-driver.patch
1From cb269cf1f97c316a5184080814a751687c72b718 Mon Sep 17 00:00:00 2001
2From: Hauke Mehrtens <hauke@hauke-m.de>
3Date: Sun, 18 Jul 2010 21:29:40 +0200
4Subject: [PATCH 2/2] USB: Add ehci ssb driver
5
6Support for the Sonics Silicon Backplane (SSB) attached Broadcom USB EHCI core.
7
8Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
9---
10 drivers/usb/host/Kconfig | 13 ++
11 drivers/usb/host/ehci-hcd.c | 23 ++++-
12 drivers/usb/host/ehci-ssb.c | 258 +++++++++++++++++++++++++++++++++++++++++++
13 3 files changed, 292 insertions(+), 2 deletions(-)
14 create mode 100644 drivers/usb/host/ehci-ssb.c
15
16--- a/drivers/usb/host/Kconfig
17@@ -150,6 +150,19 @@ config USB_OXU210HP_HCD
18       To compile this driver as a module, choose M here: the
19       module will be called oxu210hp-hcd.
20
21+config USB_EHCI_HCD_SSB
22+ bool "EHCI support for Broadcom SSB EHCI core"
23+ depends on USB_EHCI_HCD && (SSB = y || SSB = USB_EHCI_HCD) && EXPERIMENTAL
24+ default n
25+ ---help---
26+ Support for the Sonics Silicon Backplane (SSB) attached
27+ Broadcom USB EHCI core.
28+
29+ This device is present in some embedded devices with
30+ Broadcom based SSB bus.
31+
32+ If unsure, say N.
33+
34 config USB_ISP116X_HCD
35     tristate "ISP116X HCD support"
36     depends on USB
37--- a/drivers/usb/host/ehci-hcd.c
38@@ -1158,9 +1158,14 @@ MODULE_LICENSE ("GPL");
39 #define PLATFORM_DRIVER ehci_atmel_driver
40 #endif
41
42+#ifdef CONFIG_USB_EHCI_HCD_SSB
43+#include "ehci-ssb.c"
44+#define SSB_EHCI_DRIVER ssb_ehci_driver
45+#endif
46+
47 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
48     !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
49- !defined(XILINX_OF_PLATFORM_DRIVER)
50+ !defined(XILINX_OF_PLATFORM_DRIVER) && !defined(SSB_EHCI_DRIVER)
51 #error "missing bus glue for ehci-hcd"
52 #endif
53
54@@ -1220,10 +1225,21 @@ static int __init ehci_hcd_init(void)
55     if (retval < 0)
56         goto clean4;
57 #endif
58+
59+#ifdef SSB_EHCI_DRIVER
60+ retval = ssb_driver_register(&SSB_EHCI_DRIVER);
61+ if (retval < 0)
62+ goto clean5;
63+#endif
64+
65     return retval;
66
67+#ifdef SSB_EHCI_DRIVER
68+ /* ssb_driver_unregister(&SSB_EHCI_DRIVER); */
69+clean5:
70+#endif
71 #ifdef XILINX_OF_PLATFORM_DRIVER
72- /* of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); */
73+ of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER);
74 clean4:
75 #endif
76 #ifdef OF_PLATFORM_DRIVER
77@@ -1254,6 +1270,9 @@ module_init(ehci_hcd_init);
78
79 static void __exit ehci_hcd_cleanup(void)
80 {
81+#ifdef SSB_EHCI_DRIVER
82+ ssb_driver_unregister(&SSB_EHCI_DRIVER);
83+#endif
84 #ifdef XILINX_OF_PLATFORM_DRIVER
85     of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER);
86 #endif
87--- /dev/null
88@@ -0,0 +1,258 @@
89+/*
90+ * Sonics Silicon Backplane
91+ * Broadcom USB-core EHCI driver (SSB bus glue)
92+ *
93+ * Copyright 2007 Steven Brown <sbrown@cortland.com>
94+ * Copyright 2010 Hauke Mehrtens <hauke@hauke-m.de>
95+ *
96+ * Derived from the OHCI-SSB driver
97+ * Copyright 2007 Michael Buesch <mb@bu3sch.de>
98+ *
99+ * Derived from the EHCI-PCI driver
100+ * Copyright (c) 2000-2004 by David Brownell
101+ *
102+ * Derived from the OHCI-PCI driver
103+ * Copyright 1999 Roman Weissgaerber
104+ * Copyright 2000-2002 David Brownell
105+ * Copyright 1999 Linus Torvalds
106+ * Copyright 1999 Gregory P. Smith
107+ *
108+ * Derived from the USBcore related parts of Broadcom-SB
109+ * Copyright 2005 Broadcom Corporation
110+ *
111+ * Licensed under the GNU/GPL. See COPYING for details.
112+ */
113+#include <linux/ssb/ssb.h>
114+
115+
116+struct ssb_ehci_device {
117+ struct ehci_hcd ehci; /* _must_ be at the beginning. */
118+};
119+
120+static inline
121+struct ssb_ehci_device *hcd_to_ssb_ehci(struct usb_hcd *hcd)
122+{
123+ return (struct ssb_ehci_device *)(hcd->hcd_priv);
124+}
125+
126+static int ssb_ehci_reset(struct usb_hcd *hcd)
127+{
128+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
129+ int err;
130+
131+ ehci->caps = hcd->regs;
132+ ehci->regs = hcd->regs +
133+ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
134+
135+ dbg_hcs_params(ehci, "reset");
136+ dbg_hcc_params(ehci, "reset");
137+
138+ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
139+
140+ err = ehci_halt(ehci);
141+
142+ if (err)
143+ return err;
144+
145+ err = ehci_init(hcd);
146+
147+ if (err)
148+ return err;
149+
150+ ehci_reset(ehci);
151+
152+ return err;
153+}
154+
155+static const struct hc_driver ssb_ehci_hc_driver = {
156+ .description = "ssb-usb-ehci",
157+ .product_desc = "SSB EHCI Controller",
158+ .hcd_priv_size = sizeof(struct ssb_ehci_device),
159+
160+ .irq = ehci_irq,
161+ .flags = HCD_MEMORY | HCD_USB2,
162+
163+ .reset = ssb_ehci_reset,
164+ .start = ehci_run,
165+ .stop = ehci_stop,
166+ .shutdown = ehci_shutdown,
167+
168+ .urb_enqueue = ehci_urb_enqueue,
169+ .urb_dequeue = ehci_urb_dequeue,
170+ .endpoint_disable = ehci_endpoint_disable,
171+ .endpoint_reset = ehci_endpoint_reset,
172+
173+ .get_frame_number = ehci_get_frame,
174+
175+ .hub_status_data = ehci_hub_status_data,
176+ .hub_control = ehci_hub_control,
177+#if defined(CONFIG_PM)
178+ .bus_suspend = ehci_bus_suspend,
179+ .bus_resume = ehci_bus_resume,
180+#endif
181+ .relinquish_port = ehci_relinquish_port,
182+ .port_handed_over = ehci_port_handed_over,
183+
184+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
185+};
186+
187+static void ssb_ehci_detach(struct ssb_device *dev)
188+{
189+ struct usb_hcd *hcd = ssb_get_drvdata(dev);
190+ if (hcd->driver->shutdown)
191+ hcd->driver->shutdown(hcd);
192+
193+ usb_remove_hcd(hcd);
194+ iounmap(hcd->regs);
195+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
196+ usb_put_hcd(hcd);
197+ ssb_device_disable(dev, 0);
198+}
199+
200+static int ssb_ehci_attach(struct ssb_device *dev)
201+{
202+ struct ssb_ehci_device *ehcidev;
203+ struct usb_hcd *hcd;
204+ int err = -ENOMEM;
205+ u32 tmp;
206+
207+ if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
208+ dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
209+ return -EOPNOTSUPP;
210+
211+ /*
212+ * USB 2.0 special considerations:
213+ *
214+ * 1. Since the core supports both ehci and EHCI functions, it must
215+ * only be reset once.
216+ *
217+ * 2. In addition to the standard SSB reset sequence, the Host Control
218+ * Register must be programmed to bring the USB core and various
219+ * phy components out of reset.
220+ */
221+ ssb_device_enable(dev, 0);
222+ ssb_write32(dev, 0x200, 0x7ff);
223+
224+ /* Change Flush control reg */
225+ tmp = ssb_read32(dev, 0x400);
226+ tmp &= ~8;
227+ ssb_write32(dev, 0x400, tmp);
228+ tmp = ssb_read32(dev, 0x400);
229+
230+ /* Change Shim control reg */
231+ tmp = ssb_read32(dev, 0x304);
232+ tmp &= ~0x100;
233+ ssb_write32(dev, 0x304, tmp);
234+ tmp = ssb_read32(dev, 0x304);
235+
236+ udelay(1);
237+
238+ /* Work around for 5354 failures */
239+ if ((dev->id.revision == 2) && (dev->bus->chip_id == 0x5354)) {
240+ /* Change syn01 reg */
241+ tmp = 0x00fe00fe;
242+ ssb_write32(dev, 0x894, tmp);
243+
244+ /* Change syn03 reg */
245+ tmp = ssb_read32(dev, 0x89c);
246+ tmp |= 0x1;
247+ ssb_write32(dev, 0x89c, tmp);
248+ }
249+
250+ hcd = usb_create_hcd(&ssb_ehci_hc_driver, dev->dev,
251+ dev_name(dev->dev));
252+ if (!hcd)
253+ goto err_dev_disable;
254+
255+ ehcidev = hcd_to_ssb_ehci(hcd);
256+ tmp = ssb_read32(dev, SSB_ADMATCH0);
257+ hcd->rsrc_start = ssb_admatch_base(tmp) + 0x800; /* ehci core offset */
258+ hcd->rsrc_len = 0x100; /* ehci reg block size */
259+ /*
260+ * start & size modified per sbutils.c
261+ */
262+ hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
263+ if (!hcd->regs)
264+ goto err_put_hcd;
265+ err = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED);
266+ if (err)
267+ goto err_iounmap;
268+
269+ ssb_set_drvdata(dev, hcd);
270+
271+ return err;
272+
273+err_iounmap:
274+ iounmap(hcd->regs);
275+err_put_hcd:
276+ usb_put_hcd(hcd);
277+err_dev_disable:
278+ ssb_device_disable(dev, 0);
279+ return err;
280+}
281+
282+static int ssb_ehci_probe(struct ssb_device *dev,
283+ const struct ssb_device_id *id)
284+{
285+ int err;
286+ u16 chipid_top;
287+
288+ /* USBcores are only connected on embedded devices. */
289+ chipid_top = (dev->bus->chip_id & 0xFF00);
290+ if (chipid_top != 0x4700 && chipid_top != 0x5300)
291+ return -ENODEV;
292+
293+ /* TODO: Probably need checks here; is the core connected? */
294+
295+ if (usb_disabled())
296+ return -ENODEV;
297+
298+ err = ssb_ehci_attach(dev);
299+
300+ return err;
301+}
302+
303+static void ssb_ehci_remove(struct ssb_device *dev)
304+{
305+ ssb_ehci_detach(dev);
306+}
307+
308+#ifdef CONFIG_PM
309+
310+static int ssb_ehci_suspend(struct ssb_device *dev, pm_message_t state)
311+{
312+ ssb_device_disable(dev, 0);
313+
314+ return 0;
315+}
316+
317+static int ssb_ehci_resume(struct ssb_device *dev)
318+{
319+ struct usb_hcd *hcd = ssb_get_drvdata(dev);
320+ struct ssb_ehci_device *ehcidev = hcd_to_ssb_ehci(hcd);
321+
322+ ssb_device_enable(dev, 0);
323+
324+ ehci_finish_controller_resume(hcd);
325+ return 0;
326+}
327+
328+#else /* !CONFIG_PM */
329+#define ssb_ehci_suspend NULL
330+#define ssb_ehci_resume NULL
331+#endif /* CONFIG_PM */
332+
333+static const struct ssb_device_id ssb_ehci_table[] = {
334+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
335+ SSB_DEVTABLE_END
336+};
337+MODULE_DEVICE_TABLE(ssb, ssb_ehci_table);
338+
339+static struct ssb_driver ssb_ehci_driver = {
340+ .name = KBUILD_MODNAME,
341+ .id_table = ssb_ehci_table,
342+ .probe = ssb_ehci_probe,
343+ .remove = ssb_ehci_remove,
344+ .suspend = ssb_ehci_suspend,
345+ .resume = ssb_ehci_resume,
346+};
target/linux/brcm47xx/patches-2.6.35/130-remove_scache.patch
1+++ b/arch/mips/Kconfig
2@@ -205,7 +205,6 @@ config MIPS_MALTA
3     select I8259
4     select MIPS_BOARDS_GEN
5     select MIPS_BONITO64
6- select MIPS_CPU_SCACHE
7     select PCI_GT64XXX_PCI0
8     select MIPS_MSC
9     select SWAP_IO_SPACE
10@@ -1589,13 +1588,6 @@ config IP22_CPU_SCACHE
11     bool
12     select BOARD_SCACHE
13
14-#
15-# Support for a MIPS32 / MIPS64 style S-caches
16-#
17-config MIPS_CPU_SCACHE
18- bool
19- select BOARD_SCACHE
20-
21 config R5000_CPU_SCACHE
22     bool
23     select BOARD_SCACHE
24+++ b/arch/mips/kernel/cpu-probe.c
25@@ -772,6 +772,8 @@ static inline void cpu_probe_mips(struct
26     case PRID_IMP_25KF:
27         c->cputype = CPU_25KF;
28         __cpu_name[cpu] = "MIPS 25Kc";
29+ /* Probe for L2 cache */
30+ c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
31         break;
32     case PRID_IMP_34K:
33         c->cputype = CPU_34K;
34+++ b/arch/mips/mm/Makefile
35@@ -33,6 +33,5 @@ obj-$(CONFIG_CPU_CAVIUM_OCTEON) += c-oct
36 obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o
37 obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o
38 obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
39-obj-$(CONFIG_MIPS_CPU_SCACHE) += sc-mips.o
40
41 EXTRA_CFLAGS += -Werror
42+++ b/arch/mips/mm/c-r4k.c
43@@ -1148,7 +1148,6 @@ static void __init loongson2_sc_init(voi
44
45 extern int r5k_sc_init(void);
46 extern int rm7k_sc_init(void);
47-extern int mips_sc_init(void);
48
49 static void __cpuinit setup_scache(void)
50 {
51@@ -1202,29 +1201,17 @@ static void __cpuinit setup_scache(void)
52 #endif
53
54     default:
55- if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
56- c->isa_level == MIPS_CPU_ISA_M32R2 ||
57- c->isa_level == MIPS_CPU_ISA_M64R1 ||
58- c->isa_level == MIPS_CPU_ISA_M64R2) {
59-#ifdef CONFIG_MIPS_CPU_SCACHE
60- if (mips_sc_init ()) {
61- scache_size = c->scache.ways * c->scache.sets * c->scache.linesz;
62- printk("MIPS secondary cache %ldkB, %s, linesize %d bytes.\n",
63- scache_size >> 10,
64- way_string[c->scache.ways], c->scache.linesz);
65- }
66-#else
67- if (!(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
68- panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
69-#endif
70- return;
71- }
72         sc_present = 0;
73     }
74
75     if (!sc_present)
76         return;
77
78+ if ((c->isa_level == MIPS_CPU_ISA_M32R1 ||
79+ c->isa_level == MIPS_CPU_ISA_M64R1) &&
80+ !(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
81+ panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
82+
83     /* compute a couple of other cache variables */
84     c->scache.waysize = scache_size / c->scache.ways;
85
target/linux/brcm47xx/patches-2.6.35/150-cpu_fixes.patch
295295     if (dc_lsize)
296296         protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
297297     if (!cpu_icache_snoops_remote_store && scache_size)
298@@ -1298,6 +1312,17 @@ static void __cpuinit coherency_setup(vo
298@@ -1311,6 +1325,17 @@ static void __cpuinit coherency_setup(vo
299299      * silly idea of putting something else there ...
300300      */
301301     switch (current_cpu_type()) {
...... 
313313     case CPU_R4000PC:
314314     case CPU_R4000SC:
315315     case CPU_R4000MC:
316@@ -1354,6 +1379,15 @@ void __cpuinit r4k_cache_init(void)
316@@ -1367,6 +1392,15 @@ void __cpuinit r4k_cache_init(void)
317317         break;
318318     }
319319
...... 
329329     probe_pcache();
330330     setup_scache();
331331
332@@ -1412,5 +1446,13 @@ void __cpuinit r4k_cache_init(void)
332@@ -1425,5 +1459,13 @@ void __cpuinit r4k_cache_init(void)
333333 #if !defined(CONFIG_MIPS_CMP)
334334     local_r4k___flush_cache_all(NULL);
335335 #endif
target/linux/brcm47xx/patches-2.6.35/170-128MB_ram_bugfix.patch
1+++ b/arch/mips/bcm47xx/prom.c
2@@ -126,6 +126,7 @@ static __init void prom_init_cmdline(voi
3 static __init void prom_init_mem(void)
4 {
5     unsigned long mem;
6+ unsigned long max;
7
8     /* Figure out memory size by finding aliases.
9      *
10@@ -134,21 +135,26 @@ static __init void prom_init_mem(void)
11      * want to reuse the memory used by CFE (around 4MB). That means cfe_*
12      * functions stop to work at some point during the boot, we should only
13      * call them at the beginning of the boot.
14+ *
15+ * BCM47XX uses 128MB for addressing the ram, if the system contains
16+ * less that that amount of ram it remaps the ram more often into the
17+ * available space.
18+ * Accessing memory after 128MB will cause an exception.
19+ * max contains the biggest possible address supported by the platform.
20+ * If the method wants to try something above we assume 128MB ram.
21      */
22+ max = ((unsigned long)(prom_init) | ((128 << 20) - 1));
23     for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) {
24+ if (((unsigned long)(prom_init) + mem) > max) {
25+ mem = (128 << 20);
26+ printk("assume 128MB RAM\n");
27+ break;
28+ }
29         if (*(unsigned long *)((unsigned long)(prom_init) + mem) ==
30             *(unsigned long *)(prom_init))
31             break;
32     }
33
34- /* Ignoring the last page when ddr size is 128M. Cached
35- * accesses to last page is causing the processor to prefetch
36- * using address above 128M stepping out of the ddr address
37- * space.
38- */
39- if (mem == 0x8000000)
40- mem -= 0x1000;
41-
42     add_memory_region(0, mem, BOOT_MEM_RAM);
43 }
44
target/linux/brcm47xx/patches-2.6.35/210-b44_phy_fix.patch
11--- a/drivers/net/b44.c
22+++ b/drivers/net/b44.c
3@@ -384,7 +384,7 @@ static void b44_set_flow_ctrl(struct b44
3@@ -381,11 +381,12 @@ static void b44_set_flow_ctrl(struct b44
44     __b44_set_flow_ctrl(bp, pause_enab);
55 }
66
77-#ifdef SSB_DRIVER_MIPS
8+#ifdef CONFIG_SSB_DRIVER_MIPS
9 extern char *nvram_get(char *name);
8-extern char *nvram_get(char *name);
9+#ifdef CONFIG_BCM47XX
10+
11+#include <asm/mach-bcm47xx/nvram.h>
1012 static void b44_wap54g10_workaround(struct b44 *bp)
1113 {
12@@ -421,12 +421,45 @@ static inline void b44_wap54g10_workarou
13 }
14 #endif
14- const char *str;
15+ char buf[20];
16     u32 val;
17     int err;
1518
16+#ifdef CONFIG_SSB_DRIVER_MIPS
19@@ -394,10 +395,9 @@ static void b44_wap54g10_workaround(stru
20      * see https://dev.openwrt.org/ticket/146
21      * check and reset bit "isolate"
22      */
23- str = nvram_get("boardnum");
24- if (!str)
25+ if (nvram_getenv("boardnum", buf, sizeof(buf)) > 0)
26         return;
27- if (simple_strtoul(str, NULL, 0) == 2) {
28+ if (simple_strtoul(buf, NULL, 0) == 2) {
29         err = __b44_readphy(bp, 0, MII_BMCR, &val);
30         if (err)
31             goto error;
32@@ -412,10 +412,43 @@ static void b44_wap54g10_workaround(stru
33 error:
34     pr_warning("PHY: cannot reset MII transceiver isolate bit\n");
35 }
36+
1737+static inline int startswith (const char *source, const char *cmp)
1838+{
1939+ return !strncmp(source,cmp,strlen(cmp));
2040+}
2141+
22+#define getvar(str) (nvram_get(str) ? : "")
23+
2442+static inline void b44_bcm47xx_workarounds(struct b44 *bp)
2543+{
44+ char buf[20];
2645+ /* Toshiba WRC-1000, Siemens SE505 v1, Askey RT-210W, RT-220W */
27+ if (simple_strtoul(getvar("boardnum"), NULL, 0) == 100) {
46+ if (nvram_getenv("boardnum", buf, sizeof(buf)) > 0)
47+ return;
48+ if (simple_strtoul(buf, NULL, 0) == 100) {
2849+ bp->phy_addr = B44_PHY_ADDR_NO_PHY;
2950+ } else {
3051+ /* WL-HDD */
3152+ struct ssb_device *sdev = bp->sdev;
32+ if (startswith(getvar("hardware_version"), "WL300-"))
33+ {
53+ if (nvram_getenv("hardware_version", buf, sizeof(buf)) > 0)
54+ return;
55+ if (startswith(buf, "WL300-")) {
3456+ if (sdev->bus->sprom.et0phyaddr == 0 &&
3557+ sdev->bus->sprom.et1phyaddr == 1)
3658+ bp->phy_addr = B44_PHY_ADDR_NO_PHY;
...... 
3961+ return;
4062+}
4163+
42+#else
64 #else
65+
66 static inline void b44_wap54g10_workaround(struct b44 *bp)
67 {
68 }
69+
4370+static inline void b44_bcm47xx_workarounds(struct b44 *bp)
4471+{
4572+}
46+#endif
47+
73 #endif
74
4875 static int b44_setup_phy(struct b44 *bp)
49 {
50     u32 val;
76@@ -424,6 +457,7 @@ static int b44_setup_phy(struct b44 *bp)
5177     int err;
5278
5379     b44_wap54g10_workaround(bp);
...... 
5581
5682     if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
5783         return 0;
58@@ -2089,6 +2122,8 @@ static int __devinit b44_get_invariants(
84@@ -2080,6 +2114,8 @@ static int __devinit b44_get_invariants(
5985      * valid PHY address. */
6086     bp->phy_addr &= 0x1F;
6187
target/linux/brcm47xx/patches-2.6.35/211-b44_timeout_spam.patch
11--- a/drivers/net/b44.c
22+++ b/drivers/net/b44.c
3@@ -191,10 +191,11 @@ static int b44_wait_bit(struct b44 *bp,
3@@ -188,10 +188,11 @@ static int b44_wait_bit(struct b44 *bp,
44         udelay(10);
55     }
66     if (i == timeout) {
target/linux/brcm47xx/patches-2.6.35/220-bcm5354.patch
11--- a/drivers/ssb/driver_chipcommon.c
22+++ b/drivers/ssb/driver_chipcommon.c
3@@ -260,6 +260,8 @@ void ssb_chipco_resume(struct ssb_chipco
3@@ -285,6 +285,8 @@ void ssb_chipco_resume(struct ssb_chipco
44 void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
55                              u32 *plltype, u32 *n, u32 *m)
66 {
...... 
99     *n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N);
1010     *plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
1111     switch (*plltype) {
12@@ -283,6 +285,8 @@ void ssb_chipco_get_clockcpu(struct ssb_
12@@ -308,6 +310,8 @@ void ssb_chipco_get_clockcpu(struct ssb_
1313 void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,
1414                  u32 *plltype, u32 *n, u32 *m)
1515 {
...... 
3131     }
3232--- a/drivers/ssb/main.c
3333+++ b/drivers/ssb/main.c
34@@ -1073,6 +1073,8 @@ u32 ssb_clockspeed(struct ssb_bus *bus)
34@@ -1075,6 +1075,8 @@ u32 ssb_clockspeed(struct ssb_bus *bus)
3535
3636     if (bus->chip_id == 0x5365) {
3737         rate = 100000000;
target/linux/brcm47xx/patches-2.6.35/250-ohci-ssb-usb2.patch
1 drivers/usb/host/ohci-ssb.c | 39 ++++++++++++++++++++++++++++++++++++---
2 1 file changed, 36 insertions(+), 3 deletions(-)
3
4+++ b/drivers/usb/host/ohci-ssb.c
5@@ -106,10 +106,42 @@ static int ssb_ohci_attach(struct ssb_de
6     int err = -ENOMEM;
7     u32 tmp, flags = 0;
8
9- if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV)
10+ if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
11+ /* Put the device into host-mode. */
12         flags |= SSB_OHCI_TMSLOW_HOSTMODE;
13-
14- ssb_device_enable(dev, flags);
15+ ssb_device_enable(dev, flags);
16+ } else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
17+ /*
18+ * USB 2.0 special considerations:
19+ *
20+ * 1. Since the core supports both OHCI and EHCI functions, it must
21+ * only be reset once.
22+ *
23+ * 2. In addition to the standard SSB reset sequence, the Host Control
24+ * Register must be programmed to bring the USB core and various
25+ * phy components out of reset.
26+ */
27+ ssb_device_enable(dev, 0);
28+ ssb_write32(dev, 0x200, 0x7ff);
29+ udelay(1);
30+ if (dev->id.revision == 1) { // bug in rev 1
31+
32+ /* Change Flush control reg */
33+ tmp = ssb_read32(dev, 0x400);
34+ tmp &= ~8;
35+ ssb_write32(dev, 0x400, tmp);
36+ tmp = ssb_read32(dev, 0x400);
37+ printk("USB20H fcr: 0x%0x\n", tmp);
38+
39+ /* Change Shim control reg */
40+ tmp = ssb_read32(dev, 0x304);
41+ tmp &= ~0x100;
42+ ssb_write32(dev, 0x304, tmp);
43+ tmp = ssb_read32(dev, 0x304);
44+ printk("USB20H shim: 0x%0x\n", tmp);
45+ }
46+ } else
47+ ssb_device_enable(dev, 0);
48
49     hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
50             dev_name(dev->dev));
51@@ -200,6 +232,7 @@ static int ssb_ohci_resume(struct ssb_de
52 static const struct ssb_device_id ssb_ohci_table[] = {
53     SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
54     SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
55+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
56     SSB_DEVTABLE_END
57 };
58 MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);
target/linux/brcm47xx/patches-2.6.35/260-ohci-set-dma-mask.patch
1 drivers/usb/host/ohci-ssb.c | 3 +++
2 1 file changed, 3 insertions(+)
3
4+++ b/drivers/usb/host/ohci-ssb.c
5@@ -106,6 +106,9 @@ static int ssb_ohci_attach(struct ssb_de
6     int err = -ENOMEM;
7     u32 tmp, flags = 0;
8
9+ if (ssb_dma_set_mask(dev, DMA_BIT_MASK(32)))
10+ return -EOPNOTSUPP;
11+
12     if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
13         /* Put the device into host-mode. */
14         flags |= SSB_OHCI_TMSLOW_HOSTMODE;
target/linux/brcm47xx/patches-2.6.35/270-ehci-ssb.patch
1 drivers/usb/host/Kconfig | 13 ++
2 drivers/usb/host/ehci-hcd.c | 12 ++
3 drivers/usb/host/ehci-ssb.c | 201 ++++++++++++++++++++++++++++++++++++++++++++
4 drivers/usb/host/ohci-ssb.c | 23 +++++
5 4 files changed, 247 insertions(+), 2 deletions(-)
6
7+++ b/drivers/usb/host/Kconfig
8@@ -150,6 +150,19 @@ config USB_OXU210HP_HCD
9       To compile this driver as a module, choose M here: the
10       module will be called oxu210hp-hcd.
11
12+config USB_EHCI_HCD_SSB
13+ bool "EHCI support for Broadcom SSB EHCI core"
14+ depends on USB_EHCI_HCD && SSB && EXPERIMENTAL
15+ default n
16+ ---help---
17+ Support for the Sonics Silicon Backplane (SSB) attached
18+ Broadcom USB EHCI core.
19+
20+ This device is present in some embedded devices with
21+ Broadcom based SSB bus.
22+
23+ If unsure, say N.
24+
25 config USB_ISP116X_HCD
26     tristate "ISP116X HCD support"
27     depends on USB
28+++ b/drivers/usb/host/ehci-hcd.c
29@@ -1158,6 +1158,11 @@ MODULE_LICENSE ("GPL");
30 #define PLATFORM_DRIVER ehci_atmel_driver
31 #endif
32
33+#ifdef CONFIG_USB_EHCI_HCD_SSB
34+#include "ehci-ssb.c"
35+#define SSB_EHCI_DRIVER ssb_ehci_driver
36+#endif
37+
38 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
39     !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
40     !defined(XILINX_OF_PLATFORM_DRIVER)
41+++ b/drivers/usb/host/ehci-ssb.c
42@@ -0,0 +1,158 @@
43+/*
44+ * Sonics Silicon Backplane
45+ * Broadcom USB-core EHCI driver (SSB bus glue)
46+ *
47+ * Copyright 2007 Steven Brown <sbrown@cortland.com>
48+ *
49+ * Derived from the OHCI-SSB driver
50+ * Copyright 2007 Michael Buesch <mb@bu3sch.de>
51+ *
52+ * Derived from the EHCI-PCI driver
53+ * Copyright (c) 2000-2004 by David Brownell
54+ *
55+ * Derived from the OHCI-PCI driver
56+ * Copyright 1999 Roman Weissgaerber
57+ * Copyright 2000-2002 David Brownell
58+ * Copyright 1999 Linus Torvalds
59+ * Copyright 1999 Gregory P. Smith
60+ *
61+ * Derived from the USBcore related parts of Broadcom-SB
62+ * Copyright 2005 Broadcom Corporation
63+ *
64+ * Licensed under the GNU/GPL. See COPYING for details.
65+ */
66+#include <linux/ssb/ssb.h>
67+
68+#define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29)
69+
70+struct ssb_ehci_device {
71+ struct ehci_hcd ehci; /* _must_ be at the beginning. */
72+
73+ u32 enable_flags;
74+};
75+
76+static inline
77+struct ssb_ehci_device *hcd_to_ssb_ehci(struct usb_hcd *hcd)
78+{
79+ return (struct ssb_ehci_device *)(hcd->hcd_priv);
80+}
81+
82+static int ssb_ehci_reset(struct usb_hcd *hcd)
83+{
84+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
85+ int err;
86+
87+ ehci->caps = hcd->regs;
88+ ehci->regs = hcd->regs +
89+ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
90+
91+ dbg_hcs_params(ehci, "reset");
92+ dbg_hcc_params(ehci, "reset");
93+
94+ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
95+
96+ err = ehci_halt(ehci);
97+
98+ if (err)
99+ return err;
100+
101+ err = ehci_init(hcd);
102+
103+ if (err)
104+ return err;
105+
106+ ehci_reset(ehci);
107+
108+ return err;
109+}
110+
111+static const struct hc_driver ssb_ehci_hc_driver = {
112+ .description = "ssb-usb-ehci",
113+ .product_desc = "SSB EHCI Controller",
114+ .hcd_priv_size = sizeof(struct ssb_ehci_device),
115+
116+ .irq = ehci_irq,
117+ .flags = HCD_MEMORY | HCD_USB2,
118+
119+ .reset = ssb_ehci_reset,
120+ .start = ehci_run,
121+ .stop = ehci_stop,
122+ .shutdown = ehci_shutdown,
123+
124+ .urb_enqueue = ehci_urb_enqueue,
125+ .urb_dequeue = ehci_urb_dequeue,
126+ .endpoint_disable = ehci_endpoint_disable,
127+ .endpoint_reset = ehci_endpoint_reset,
128+
129+ .get_frame_number = ehci_get_frame,
130+
131+ .hub_status_data = ehci_hub_status_data,
132+ .hub_control = ehci_hub_control,
133+ .bus_suspend = ehci_bus_suspend,
134+ .bus_resume = ehci_bus_resume,
135+ .relinquish_port = ehci_relinquish_port,
136+ .port_handed_over = ehci_port_handed_over,
137+
138+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
139+};
140+
141+static void ssb_ehci_detach(struct ssb_device *dev, struct usb_hcd *hcd)
142+{
143+ if (hcd->driver->shutdown)
144+ hcd->driver->shutdown(hcd);
145+
146+ usb_remove_hcd(hcd);
147+
148+ iounmap(hcd->regs);
149+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
150+
151+ usb_put_hcd(hcd);
152+}
153+EXPORT_SYMBOL_GPL(ssb_ehci_detach);
154+
155+static int ssb_ehci_attach(struct ssb_device *dev, struct usb_hcd **ehci_hcd)
156+{
157+ struct ssb_ehci_device *ehcidev;
158+ struct usb_hcd *hcd;
159+ int err = -ENOMEM;
160+ u32 tmp, flags = 0;
161+
162+ hcd = usb_create_hcd(&ssb_ehci_hc_driver, dev->dev,
163+ dev_name(dev->dev));
164+ if (!hcd)
165+ goto err_dev_disable;
166+
167+ ehcidev = hcd_to_ssb_ehci(hcd);
168+ ehcidev->enable_flags = flags;
169+ tmp = ssb_read32(dev, SSB_ADMATCH0);
170+ hcd->rsrc_start = ssb_admatch_base(tmp) + 0x800; /* ehci core offset */
171+ hcd->rsrc_len = 0x100; /* ehci reg block size */
172+ /*
173+ * start & size modified per sbutils.c
174+ */
175+ hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
176+ if (!hcd->regs)
177+ goto err_put_hcd;
178+ err = usb_add_hcd(hcd, dev->irq, IRQF_SHARED | IRQF_DISABLED);
179+ if (err)
180+ goto err_iounmap;
181+
182+ *ehci_hcd = hcd;
183+
184+ return err;
185+
186+err_iounmap:
187+ iounmap(hcd->regs);
188+err_put_hcd:
189+ usb_put_hcd(hcd);
190+err_dev_disable:
191+ ssb_device_disable(dev, flags);
192+ return err;
193+}
194+EXPORT_SYMBOL_GPL(ssb_ehci_attach);
195+
196+static const struct ssb_device_id ssb_ehci_table[] = {
197+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
198+ SSB_DEVTABLE_END
199+};
200+MODULE_DEVICE_TABLE(ssb, ssb_ehci_table);
201+++ b/drivers/usb/host/ohci-ssb.c
202@@ -17,6 +17,8 @@
203  */
204 #include <linux/ssb/ssb.h>
205
206+extern int ssb_ehci_attach(struct ssb_device *dev, struct usb_hcd **hcd);
207+extern void ssb_ehci_detach(struct ssb_device *dev, struct usb_hcd *hcd);
208
209 #define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29)
210
211@@ -24,6 +26,7 @@ struct ssb_ohci_device {
212     struct ohci_hcd ohci; /* _must_ be at the beginning. */
213
214     u32 enable_flags;
215+ struct usb_hcd *ehci_hcd;
216 };
217
218 static inline
219@@ -92,13 +95,25 @@ static const struct hc_driver ssb_ohci_h
220 static void ssb_ohci_detach(struct ssb_device *dev)
221 {
222     struct usb_hcd *hcd = ssb_get_drvdata(dev);
223+#ifdef CONFIG_USB_EHCI_HCD_SSB
224+ struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
225+#endif
226
227     usb_remove_hcd(hcd);
228     iounmap(hcd->regs);
229     usb_put_hcd(hcd);
230+
231+#ifdef CONFIG_USB_EHCI_HCD_SSB
232+ /*
233+ * Also detach ehci function
234+ */
235+ if (dev->id.coreid == SSB_DEV_USB20_HOST)
236+ ssb_ehci_detach(dev, ohcidev->ehci_hcd);
237+#endif
238     ssb_device_disable(dev, 0);
239 }
240
241+
242 static int ssb_ohci_attach(struct ssb_device *dev)
243 {
244     struct ssb_ohci_device *ohcidev;
245@@ -165,6 +180,14 @@ static int ssb_ohci_attach(struct ssb_de
246
247     ssb_set_drvdata(