Date:2010-07-19 22:25:20 (13 years 8 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(dev, hcd);
248
249+#ifdef CONFIG_USB_EHCI_HCD_SSB
250+ /*
251+ * attach ehci function in this core
252+ */
253+ if (dev->id.coreid == SSB_DEV_USB20_HOST)
254+ err = ssb_ehci_attach(dev, &(ohcidev->ehci_hcd));
255+#endif
256+
257     return err;
258
259 err_iounmap:
target/linux/brcm47xx/patches-2.6.35/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.35/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.35/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.35/700-ssb-gigabit-ethernet-driver.patch
88
99 #include <net/checksum.h>
1010 #include <net/ip.h>
11@@ -471,8 +472,9 @@ static void _tw32_flush(struct tg3 *tp,
11@@ -494,8 +495,9 @@ static void _tw32_flush(struct tg3 *tp,
1212 static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val)
1313 {
1414     tp->write32_mbox(tp, off, val);
...... 
2020         tp->read32_mbox(tp, off);
2121 }
2222
23@@ -482,7 +484,7 @@ static void tg3_write32_tx_mbox(struct t
23@@ -505,7 +507,7 @@ static void tg3_write32_tx_mbox(struct t
2424     writel(val, mbox);
2525     if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG)
2626         writel(val, mbox);
...... 
2929         readl(mbox);
3030 }
3131
32@@ -783,7 +785,7 @@ static void tg3_switch_clocks(struct tg3
32@@ -807,7 +809,7 @@ static void tg3_switch_clocks(struct tg3
3333
3434 #define PHY_BUSY_LOOPS 5000
3535
...... 
3838 {
3939     u32 frame_val;
4040     unsigned int loops;
41@@ -797,7 +799,7 @@ static int tg3_readphy(struct tg3 *tp, i
41@@ -821,7 +823,7 @@ static int tg3_readphy(struct tg3 *tp, i
4242
4343     *val = 0x0;
4444
...... 
4747               MI_COM_PHY_ADDR_MASK);
4848     frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
4949               MI_COM_REG_ADDR_MASK);
50@@ -832,7 +834,12 @@ static int tg3_readphy(struct tg3 *tp, i
50@@ -856,7 +858,12 @@ static int tg3_readphy(struct tg3 *tp, i
5151     return ret;
5252 }
5353
...... 
6161 {
6262     u32 frame_val;
6363     unsigned int loops;
64@@ -848,7 +855,7 @@ static int tg3_writephy(struct tg3 *tp,
64@@ -872,7 +879,7 @@ static int tg3_writephy(struct tg3 *tp,
6565         udelay(80);
6666     }
6767
...... 
7070               MI_COM_PHY_ADDR_MASK);
7171     frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
7272               MI_COM_REG_ADDR_MASK);
73@@ -881,6 +888,11 @@ static int tg3_writephy(struct tg3 *tp,
73@@ -905,6 +912,11 @@ static int tg3_writephy(struct tg3 *tp,
7474     return ret;
7575 }
7676
...... 
8282 static int tg3_bmcr_reset(struct tg3 *tp)
8383 {
8484     u32 phy_control;
85@@ -2389,6 +2401,9 @@ static int tg3_nvram_read(struct tg3 *tp
85@@ -2411,6 +2423,9 @@ static int tg3_nvram_read(struct tg3 *tp
8686 {
8787     int ret;
8888
...... 
9292     if (!(tp->tg3_flags & TG3_FLAG_NVRAM))
9393         return tg3_nvram_read_using_eeprom(tp, offset, val);
9494
95@@ -2720,8 +2735,10 @@ static int tg3_set_power_state(struct tg
95@@ -2742,8 +2757,10 @@ static int tg3_set_power_state(struct tg
9696     tg3_frob_aux_power(tp);
9797
9898     /* Workaround for unstable PLL clock */
...... 
105105         u32 val = tr32(0x7d00);
106106
107107         val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1);
108@@ -3214,6 +3231,14 @@ relink:
108@@ -3236,6 +3253,14 @@ relink:
109109
110110         tg3_phy_copper_begin(tp);
111111
...... 
120120         tg3_readphy(tp, MII_BMSR, &tmp);
121121         if (!tg3_readphy(tp, MII_BMSR, &tmp) &&
122122             (tmp & BMSR_LSTATUS))
123@@ -6675,6 +6700,11 @@ static int tg3_poll_fw(struct tg3 *tp)
123@@ -6719,6 +6744,11 @@ static int tg3_poll_fw(struct tg3 *tp)
124124     int i;
125125     u32 val;
126126
...... 
132132     if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
133133         /* Wait up to 20ms for init done. */
134134         for (i = 0; i < 200; i++) {
135@@ -6958,6 +6988,14 @@ static int tg3_chip_reset(struct tg3 *tp
135@@ -7002,6 +7032,14 @@ static int tg3_chip_reset(struct tg3 *tp
136136         tw32(0x5000, 0x400);
137137     }
138138
...... 
147147     tw32(GRC_MODE, tp->grc_mode);
148148
149149     if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) {
150@@ -7135,9 +7173,12 @@ static int tg3_halt_cpu(struct tg3 *tp,
150@@ -7179,9 +7217,12 @@ static int tg3_halt_cpu(struct tg3 *tp,
151151         return -ENODEV;
152152     }
153153
...... 
163163     return 0;
164164 }
165165
166@@ -7199,6 +7240,11 @@ static int tg3_load_5701_a0_firmware_fix
166@@ -7244,6 +7285,11 @@ static int tg3_load_5701_a0_firmware_fix
167167     const __be32 *fw_data;
168168     int err, i;
169169
...... 
175175     fw_data = (void *)tp->fw->data;
176176
177177     /* Firmware blob starts with version numbers, followed by
178@@ -7256,6 +7302,11 @@ static int tg3_load_tso_firmware(struct
178@@ -7302,6 +7348,11 @@ static int tg3_load_tso_firmware(struct
179179     unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size;
180180     int err, i;
181181
...... 
187187     if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
188188         return 0;
189189
190@@ -8380,6 +8431,11 @@ static void tg3_timer(unsigned long __op
190@@ -8446,6 +8497,11 @@ static void tg3_timer(unsigned long __op
191191
192192     spin_lock(&tp->lock);
193193
...... 
199199     if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
200200         /* All of this garbage is because when using non-tagged
201201          * IRQ status the mailbox/status_block protocol the chip
202@@ -10279,6 +10335,11 @@ static int tg3_test_nvram(struct tg3 *tp
202@@ -10113,6 +10169,11 @@ static int tg3_test_nvram(struct tg3 *tp
203203     if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM)
204204         return 0;
205205
...... 
211211     if (tg3_nvram_read(tp, 0, &magic) != 0)
212212         return -EIO;
213213
214@@ -11098,7 +11159,7 @@ static int tg3_ioctl(struct net_device *
214@@ -10932,7 +10993,7 @@ static int tg3_ioctl(struct net_device *
215215             return -EAGAIN;
216216
217217         spin_lock_bh(&tp->lock);
...... 
220220         spin_unlock_bh(&tp->lock);
221221
222222         data->val_out = mii_regval;
223@@ -11114,7 +11175,7 @@ static int tg3_ioctl(struct net_device *
223@@ -10948,7 +11009,7 @@ static int tg3_ioctl(struct net_device *
224224             return -EAGAIN;
225225
226226         spin_lock_bh(&tp->lock);
...... 
229229         spin_unlock_bh(&tp->lock);
230230
231231         return err;
232@@ -11759,6 +11820,12 @@ static void __devinit tg3_get_5717_nvram
232@@ -11593,6 +11654,12 @@ static void __devinit tg3_get_5717_nvram
233233 /* Chips other than 5700/5701 use the NVRAM for fetching info. */
234234 static void __devinit tg3_nvram_init(struct tg3 *tp)
235235 {
...... 
242242     tw32_f(GRC_EEPROM_ADDR,
243243          (EEPROM_ADDR_FSM_RESET |
244244           (EEPROM_DEFAULT_CLOCK_PERIOD <<
245@@ -12020,6 +12087,9 @@ static int tg3_nvram_write_block(struct
245@@ -11855,6 +11922,9 @@ static int tg3_nvram_write_block(struct
246246 {
247247     int ret;
248248
...... 
252252     if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) {
253253         tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl &
254254                ~GRC_LCLCTRL_GPIO_OUTPUT1);
255@@ -13360,6 +13430,11 @@ static int __devinit tg3_get_invariants(
255@@ -13227,6 +13297,11 @@ static int __devinit tg3_get_invariants(
256256           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)))
257257         tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG;
258258
...... 
264264     /* Get eeprom hw config before calling tg3_set_power_state().
265265      * In particular, the TG3_FLG2_IS_NIC flag must be
266266      * determined before calling tg3_set_power_state() so that
267@@ -13753,6 +13828,10 @@ static int __devinit tg3_get_device_addr
267@@ -13624,6 +13699,10 @@ static int __devinit tg3_get_device_addr
268268     }
269269
270270     if (!is_valid_ether_addr(&dev->dev_addr[0])) {
...... 
275275 #ifdef CONFIG_SPARC
276276         if (!tg3_get_default_macaddr_sparc(tp))
277277             return 0;
278@@ -14272,6 +14351,7 @@ static char * __devinit tg3_phy_string(s
278@@ -14144,6 +14223,7 @@ static char * __devinit tg3_phy_string(s
279279     case TG3_PHY_ID_BCM5704: return "5704";
280280     case TG3_PHY_ID_BCM5705: return "5705";
281281     case TG3_PHY_ID_BCM5750: return "5750";
...... 
283283     case TG3_PHY_ID_BCM5752: return "5752";
284284     case TG3_PHY_ID_BCM5714: return "5714";
285285     case TG3_PHY_ID_BCM5780: return "5780";
286@@ -14481,6 +14561,13 @@ static int __devinit tg3_init_one(struct
286@@ -14354,6 +14434,13 @@ static int __devinit tg3_init_one(struct
287287         tp->msg_enable = tg3_debug;
288288     else
289289         tp->msg_enable = TG3_DEF_MSG_ENABLE;
...... 
309309
310310 #define NIC_SRAM_RX_MINI_BUFFER_DESC 0x00001000
311311
312@@ -2930,6 +2933,7 @@ struct tg3 {
312@@ -2931,6 +2934,7 @@ struct tg3 {
313313 #define TG3_PHY_ID_BCM5704 0x60008190
314314 #define TG3_PHY_ID_BCM5705 0x600081a0
315315 #define TG3_PHY_ID_BCM5750 0x60008180
...... 
317317 #define TG3_PHY_ID_BCM5752 0x60008100
318318 #define TG3_PHY_ID_BCM5714 0x60008340
319319 #define TG3_PHY_ID_BCM5780 0x60008350
320@@ -2964,7 +2968,8 @@ struct tg3 {
320@@ -2965,7 +2969,8 @@ struct tg3 {
321321      (X) == TG3_PHY_ID_BCM5755 || (X) == TG3_PHY_ID_BCM5756 || \
322322      (X) == TG3_PHY_ID_BCM5906 || (X) == TG3_PHY_ID_BCM5761 || \
323323      (X) == TG3_PHY_ID_BCM5718C || (X) == TG3_PHY_ID_BCM5718S || \
target/linux/brcm47xx/patches-2.6.35/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.35/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.35/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.35/940-bcm47xx-yenta.patch
11--- a/drivers/pcmcia/yenta_socket.c
22+++ b/drivers/pcmcia/yenta_socket.c
3@@ -924,6 +924,8 @@ static unsigned int yenta_probe_irq(stru
3@@ -922,6 +922,8 @@ static unsigned int yenta_probe_irq(stru
44      * Probe for usable interrupts using the force
55      * register to generate bogus card status events.
66      */
...... 
99     cb_writel(socket, CB_SOCKET_EVENT, -1);
1010     cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
1111     reg = exca_readb(socket, I365_CSCINT);
12@@ -939,6 +941,7 @@ static unsigned int yenta_probe_irq(stru
12@@ -937,6 +939,7 @@ static unsigned int yenta_probe_irq(stru
1313     }
1414     cb_writel(socket, CB_SOCKET_MASK, 0);
1515     exca_writeb(socket, I365_CSCINT, reg);
...... 
1717
1818     mask = probe_irq_mask(val) & 0xffff;
1919
20@@ -1022,6 +1025,10 @@ static void yenta_get_socket_capabilitie
20@@ -1021,6 +1024,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@@ -1259,6 +1266,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.35/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/generic/patches-2.6.34/975-ssb_update.patch
1--- a/drivers/net/b44.c
2@@ -135,7 +135,6 @@ static void b44_init_rings(struct b44 *)
3
4 static void b44_init_hw(struct b44 *, int);
5
6-static int dma_desc_align_mask;
7 static int dma_desc_sync_size;
8 static int instance;
9
10@@ -150,9 +149,8 @@ static inline void b44_sync_dma_desc_for
11                         unsigned long offset,
12                         enum dma_data_direction dir)
13 {
14- ssb_dma_sync_single_range_for_device(sdev, dma_base,
15- offset & dma_desc_align_mask,
16- dma_desc_sync_size, dir);
17+ dma_sync_single_for_device(sdev->dma_dev, dma_base + offset,
18+ dma_desc_sync_size, dir);
19 }
20
21 static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev,
22@@ -160,9 +158,8 @@ static inline void b44_sync_dma_desc_for
23                          unsigned long offset,
24                          enum dma_data_direction dir)
25 {
26- ssb_dma_sync_single_range_for_cpu(sdev, dma_base,
27- offset & dma_desc_align_mask,
28- dma_desc_sync_size, dir);
29+ dma_sync_single_for_cpu(sdev->dma_dev, dma_base + offset,
30+ dma_desc_sync_size, dir);
31 }
32
33 static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
34@@ -608,10 +605,10 @@ static void b44_tx(struct b44 *bp)
35
36         BUG_ON(skb == NULL);
37
38- ssb_dma_unmap_single(bp->sdev,
39- rp->mapping,
40- skb->len,
41- DMA_TO_DEVICE);
42+ dma_unmap_single(bp->sdev->dma_dev,
43+ rp->mapping,
44+ skb->len,
45+ DMA_TO_DEVICE);
46         rp->skb = NULL;
47         dev_kfree_skb_irq(skb);
48     }
49@@ -648,29 +645,29 @@ static int b44_alloc_rx_skb(struct b44 *
50     if (skb == NULL)
51         return -ENOMEM;
52
53- mapping = ssb_dma_map_single(bp->sdev, skb->data,
54- RX_PKT_BUF_SZ,
55- DMA_FROM_DEVICE);
56+ mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
57+ RX_PKT_BUF_SZ,
58+ DMA_FROM_DEVICE);
59
60     /* Hardware bug work-around, the chip is unable to do PCI DMA
61        to/from anything above 1GB :-( */
62- if (ssb_dma_mapping_error(bp->sdev, mapping) ||
63+ if (dma_mapping_error(bp->sdev->dma_dev, mapping) ||
64         mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
65         /* Sigh... */
66- if (!ssb_dma_mapping_error(bp->sdev, mapping))
67- ssb_dma_unmap_single(bp->sdev, mapping,
68+ if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
69+ dma_unmap_single(bp->sdev->dma_dev, mapping,
70                          RX_PKT_BUF_SZ, DMA_FROM_DEVICE);
71         dev_kfree_skb_any(skb);
72         skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
73         if (skb == NULL)
74             return -ENOMEM;
75- mapping = ssb_dma_map_single(bp->sdev, skb->data,
76- RX_PKT_BUF_SZ,
77- DMA_FROM_DEVICE);
78- if (ssb_dma_mapping_error(bp->sdev, mapping) ||
79- mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
80- if (!ssb_dma_mapping_error(bp->sdev, mapping))
81- ssb_dma_unmap_single(bp->sdev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
82+ mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
83+ RX_PKT_BUF_SZ,
84+ DMA_FROM_DEVICE);
85+ if (dma_mapping_error(bp->sdev->dma_dev, mapping) ||
86+ mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
87+ if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
88+ dma_unmap_single(bp->sdev->dma_dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
89             dev_kfree_skb_any(skb);
90             return -ENOMEM;
91         }
92@@ -745,9 +742,9 @@ static void b44_recycle_rx(struct b44 *b
93                          dest_idx * sizeof(*dest_desc),
94                          DMA_BIDIRECTIONAL);
95
96- ssb_dma_sync_single_for_device(bp->sdev, dest_map->mapping,
97- RX_PKT_BUF_SZ,
98- DMA_FROM_DEVICE);
99+ dma_sync_single_for_device(bp->sdev->dma_dev, dest_map->mapping,
100+ RX_PKT_BUF_SZ,
101+ DMA_FROM_DEVICE);
102 }
103
104 static int b44_rx(struct b44 *bp, int budget)
105@@ -767,9 +764,9 @@ static int b44_rx(struct b44 *bp, int bu
106         struct rx_header *rh;
107         u16 len;
108
109- ssb_dma_sync_single_for_cpu(bp->sdev, map,
110- RX_PKT_BUF_SZ,
111- DMA_FROM_DEVICE);
112+ dma_sync_single_for_cpu(bp->sdev->dma_dev, map,
113+ RX_PKT_BUF_SZ,
114+ DMA_FROM_DEVICE);
115         rh = (struct rx_header *) skb->data;
116         len = le16_to_cpu(rh->len);
117         if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) ||
118@@ -801,8 +798,8 @@ static int b44_rx(struct b44 *bp, int bu
119             skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod);
120             if (skb_size < 0)
121                 goto drop_it;
122- ssb_dma_unmap_single(bp->sdev, map,
123- skb_size, DMA_FROM_DEVICE);
124+ dma_unmap_single(bp->sdev->dma_dev, map,
125+ skb_size, DMA_FROM_DEVICE);
126             /* Leave out rx_header */
127             skb_put(skb, len + RX_PKT_OFFSET);
128             skb_pull(skb, RX_PKT_OFFSET);
129@@ -954,24 +951,24 @@ static netdev_tx_t b44_start_xmit(struct
130         goto err_out;
131     }
132
133- mapping = ssb_dma_map_single(bp->sdev, skb->data, len, DMA_TO_DEVICE);
134- if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
135+ mapping = dma_map_single(bp->sdev->dma_dev, skb->data, len, DMA_TO_DEVICE);
136+ if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
137         struct sk_buff *bounce_skb;
138
139         /* Chip can't handle DMA to/from >1GB, use bounce buffer */
140- if (!ssb_dma_mapping_error(bp->sdev, mapping))
141- ssb_dma_unmap_single(bp->sdev, mapping, len,
142+ if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
143+ dma_unmap_single(bp->sdev->dma_dev, mapping, len,
144                          DMA_TO_DEVICE);
145
146         bounce_skb = __netdev_alloc_skb(dev, len, GFP_ATOMIC | GFP_DMA);
147         if (!bounce_skb)
148             goto err_out;
149
150- mapping = ssb_dma_map_single(bp->sdev, bounce_skb->data,
151- len, DMA_TO_DEVICE);
152- if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
153- if (!ssb_dma_mapping_error(bp->sdev, mapping))
154- ssb_dma_unmap_single(bp->sdev, mapping,
155+ mapping = dma_map_single(bp->sdev->dma_dev, bounce_skb->data,
156+ len, DMA_TO_DEVICE);
157+ if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
158+ if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
159+ dma_unmap_single(bp->sdev->dma_dev, mapping,
160                              len, DMA_TO_DEVICE);
161             dev_kfree_skb_any(bounce_skb);
162             goto err_out;
163@@ -1014,8 +1011,6 @@ static netdev_tx_t b44_start_xmit(struct
164     if (TX_BUFFS_AVAIL(bp) < 1)
165         netif_stop_queue(dev);
166
167- dev->trans_start = jiffies;
168-
169 out_unlock:
170     spin_unlock_irqrestore(&bp->lock, flags);
171
172@@ -1070,8 +1065,8 @@ static void b44_free_rings(struct b44 *b
173
174         if (rp->skb == NULL)
175             continue;
176- ssb_dma_unmap_single(bp->sdev, rp->mapping, RX_PKT_BUF_SZ,
177- DMA_FROM_DEVICE);
178+ dma_unmap_single(bp->sdev->dma_dev, rp->mapping, RX_PKT_BUF_SZ,
179+ DMA_FROM_DEVICE);
180         dev_kfree_skb_any(rp->skb);
181         rp->skb = NULL;
182     }
183@@ -1082,8 +1077,8 @@ static void b44_free_rings(struct b44 *b
184
185         if (rp->skb == NULL)
186             continue;
187- ssb_dma_unmap_single(bp->sdev, rp->mapping, rp->skb->len,
188- DMA_TO_DEVICE);
189+ dma_unmap_single(bp->sdev->dma_dev, rp->mapping, rp->skb->len,
190+ DMA_TO_DEVICE);
191         dev_kfree_skb_any(rp->skb);
192         rp->skb = NULL;
193     }
194@@ -1105,14 +1100,12 @@ static void b44_init_rings(struct b44 *b
195     memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
196
197     if (bp->flags & B44_FLAG_RX_RING_HACK)
198- ssb_dma_sync_single_for_device(bp->sdev, bp->rx_ring_dma,
199- DMA_TABLE_BYTES,
200- DMA_BIDIRECTIONAL);
201+ dma_sync_single_for_device(bp->sdev->dma_dev, bp->rx_ring_dma,
202+ DMA_TABLE_BYTES, DMA_BIDIRECTIONAL);
203
204     if (bp->flags & B44_FLAG_TX_RING_HACK)
205- ssb_dma_sync_single_for_device(bp->sdev, bp->tx_ring_dma,
206- DMA_TABLE_BYTES,
207- DMA_TO_DEVICE);
208+ dma_sync_single_for_device(bp->sdev->dma_dev, bp->tx_ring_dma,
209+ DMA_TABLE_BYTES, DMA_TO_DEVICE);
210
211     for (i = 0; i < bp->rx_pending; i++) {
212         if (b44_alloc_rx_skb(bp, -1, i) < 0)
213@@ -1132,27 +1125,23 @@ static void b44_free_consistent(struct b
214     bp->tx_buffers = NULL;
215     if (bp->rx_ring) {
216         if (bp->flags & B44_FLAG_RX_RING_HACK) {
217- ssb_dma_unmap_single(bp->sdev, bp->rx_ring_dma,
218- DMA_TABLE_BYTES,
219- DMA_BIDIRECTIONAL);
220+ dma_unmap_single(bp->sdev->dma_dev, bp->rx_ring_dma,
221+ DMA_TABLE_BYTES, DMA_BIDIRECTIONAL);
222             kfree(bp->rx_ring);
223         } else
224- ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES,
225- bp->rx_ring, bp->rx_ring_dma,
226- GFP_KERNEL);
227+ dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
228+ bp->rx_ring, bp->rx_ring_dma);
229         bp->rx_ring = NULL;
230         bp->flags &= ~B44_FLAG_RX_RING_HACK;
231     }
232     if (bp->tx_ring) {
233         if (bp->flags & B44_FLAG_TX_RING_HACK) {
234- ssb_dma_unmap_single(bp->sdev, bp->tx_ring_dma,
235- DMA_TABLE_BYTES,
236- DMA_TO_DEVICE);
237+ dma_unmap_single(bp->sdev->dma_dev, bp->tx_ring_dma,
238+ DMA_TABLE_BYTES, DMA_TO_DEVICE);
239             kfree(bp->tx_ring);
240         } else
241- ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES,
242- bp->tx_ring, bp->tx_ring_dma,
243- GFP_KERNEL);
244+ dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
245+ bp->tx_ring, bp->tx_ring_dma);
246         bp->tx_ring = NULL;
247         bp->flags &= ~B44_FLAG_TX_RING_HACK;
248     }
249@@ -1177,7 +1166,8 @@ static int b44_alloc_consistent(struct b
250         goto out_err;
251
252     size = DMA_TABLE_BYTES;
253- bp->rx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->rx_ring_dma, gfp);
254+ bp->rx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size,
255+ &bp->rx_ring_dma, gfp);
256     if (!bp->rx_ring) {
257         /* Allocation may have failed due to pci_alloc_consistent
258            insisting on use of GFP_DMA, which is more restrictive
259@@ -1189,11 +1179,11 @@ static int b44_alloc_consistent(struct b
260         if (!rx_ring)
261             goto out_err;
262
263- rx_ring_dma = ssb_dma_map_single(bp->sdev, rx_ring,
264- DMA_TABLE_BYTES,
265- DMA_BIDIRECTIONAL);
266+ rx_ring_dma = dma_map_single(bp->sdev->dma_dev, rx_ring,
267+ DMA_TABLE_BYTES,
268+ DMA_BIDIRECTIONAL);
269
270- if (ssb_dma_mapping_error(bp->sdev, rx_ring_dma) ||
271+ if (dma_mapping_error(bp->sdev->dma_dev, rx_ring_dma) ||
272             rx_ring_dma + size > DMA_BIT_MASK(30)) {
273             kfree(rx_ring);
274             goto out_err;
275@@ -1204,7 +1194,8 @@ static int b44_alloc_consistent(struct b
276         bp->flags |= B44_FLAG_RX_RING_HACK;
277     }
278
279- bp->tx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->tx_ring_dma, gfp);
280+ bp->tx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size,
281+ &bp->tx_ring_dma, gfp);
282     if (!bp->tx_ring) {
283         /* Allocation may have failed due to ssb_dma_alloc_consistent
284            insisting on use of GFP_DMA, which is more restrictive
285@@ -1216,11 +1207,11 @@ static int b44_alloc_consistent(struct b
286         if (!tx_ring)
287             goto out_err;
288
289- tx_ring_dma = ssb_dma_map_single(bp->sdev, tx_ring,
290- DMA_TABLE_BYTES,
291- DMA_TO_DEVICE);
292+ tx_ring_dma = dma_map_single(bp->sdev->dma_dev, tx_ring,
293+ DMA_TABLE_BYTES,
294+ DMA_TO_DEVICE);
295
296- if (ssb_dma_mapping_error(bp->sdev, tx_ring_dma) ||
297+ if (dma_mapping_error(bp->sdev->dma_dev, tx_ring_dma) ||
298             tx_ring_dma + size > DMA_BIT_MASK(30)) {
299             kfree(tx_ring);
300             goto out_err;
301@@ -2178,12 +2169,14 @@ static int __devinit b44_init_one(struct
302             "Failed to powerup the bus\n");
303         goto err_out_free_dev;
304     }
305- err = ssb_dma_set_mask(sdev, DMA_BIT_MASK(30));
306- if (err) {
307+
308+ if (dma_set_mask(sdev->dma_dev, DMA_BIT_MASK(30)) ||
309+ dma_set_coherent_mask(sdev->dma_dev, DMA_BIT_MASK(30))) {
310         dev_err(sdev->dev,
311             "Required 30BIT DMA mask unsupported by the system\n");
312         goto err_out_powerdown;
313     }
314+
315     err = b44_get_invariants(bp);
316     if (err) {
317         dev_err(sdev->dev,
318@@ -2346,7 +2339,6 @@ static int __init b44_init(void)
319     int err;
320
321     /* Setup paramaters for syncing RX/TX DMA descriptors */
322- dma_desc_align_mask = ~(dma_desc_align_size - 1);
323     dma_desc_sync_size = max_t(unsigned int, dma_desc_align_size, sizeof(struct dma_desc));
324
325     err = b44_pci_init();
1326--- a/drivers/ssb/driver_chipcommon.c
2327+++ b/drivers/ssb/driver_chipcommon.c
3@@ -233,6 +233,8 @@ void ssb_chipcommon_init(struct ssb_chip
328@@ -209,6 +209,24 @@ static void chipco_powercontrol_init(str
329     }
330 }
331
332+/* http://bcm-v4.sipsolutions.net/802.11/PmuFastPwrupDelay */
333+static u16 pmu_fast_powerup_delay(struct ssb_chipcommon *cc)
334+{
335+ struct ssb_bus *bus = cc->dev->bus;
336+
337+ switch (bus->chip_id) {
338+ case 0x4312:
339+ case 0x4322:
340+ case 0x4328:
341+ return 7000;
342+ case 0x4325:
343+ /* TODO: */
344+ default:
345+ return 15000;
346+ }
347+}
348+
349+/* http://bcm-v4.sipsolutions.net/802.11/ClkctlFastPwrupDelay */
350 static void calc_fast_powerup_delay(struct ssb_chipcommon *cc)
351 {
352     struct ssb_bus *bus = cc->dev->bus;
353@@ -218,6 +236,12 @@ static void calc_fast_powerup_delay(stru
354
355     if (bus->bustype != SSB_BUSTYPE_PCI)
356         return;
357+
358+ if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
359+ cc->fast_pwrup_delay = pmu_fast_powerup_delay(cc);
360+ return;
361+ }
362+
363     if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL))
364         return;
365
366@@ -233,6 +257,9 @@ void ssb_chipcommon_init(struct ssb_chip
4367 {
5368     if (!cc->dev)
6369         return; /* We don't have a ChipCommon */
7370+ if (cc->dev->id.revision >= 11)
8371+ cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT);
372+ ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status);
9373     ssb_pmu_init(cc);
10374     chipco_powercontrol_init(cc);
11375     ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
12@@ -370,6 +372,7 @@ u32 ssb_chipco_gpio_control(struct ssb_c
376@@ -370,6 +397,7 @@ u32 ssb_chipco_gpio_control(struct ssb_c
13377 {
14378     return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value);
15379 }
...... 
17382
18383 u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value)
19384 {
385--- a/drivers/ssb/driver_chipcommon_pmu.c
386@@ -502,9 +502,9 @@ static void ssb_pmu_resources_init(struc
387         chipco_write32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, max_msk);
388 }
389
390+/* http://bcm-v4.sipsolutions.net/802.11/SSB/PmuInit */
391 void ssb_pmu_init(struct ssb_chipcommon *cc)
392 {
393- struct ssb_bus *bus = cc->dev->bus;
394     u32 pmucap;
395
396     if (!(cc->capabilities & SSB_CHIPCO_CAP_PMU))
397@@ -516,15 +516,12 @@ void ssb_pmu_init(struct ssb_chipcommon
398     ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n",
399             cc->pmu.rev, pmucap);
400
401- if (cc->pmu.rev >= 1) {
402- if ((bus->chip_id == 0x4325) && (bus->chip_rev < 2)) {
403- chipco_mask32(cc, SSB_CHIPCO_PMU_CTL,
404- ~SSB_CHIPCO_PMU_CTL_NOILPONW);
405- } else {
406- chipco_set32(cc, SSB_CHIPCO_PMU_CTL,
407- SSB_CHIPCO_PMU_CTL_NOILPONW);
408- }
409- }
410+ if (cc->pmu.rev == 1)
411+ chipco_mask32(cc, SSB_CHIPCO_PMU_CTL,
412+ ~SSB_CHIPCO_PMU_CTL_NOILPONW);
413+ else
414+ chipco_set32(cc, SSB_CHIPCO_PMU_CTL,
415+ SSB_CHIPCO_PMU_CTL_NOILPONW);
416     ssb_pmu_pll_init(cc);
417     ssb_pmu_resources_init(cc);
418 }
20419--- a/drivers/ssb/main.c
21420+++ b/drivers/ssb/main.c
22@@ -834,6 +834,9 @@ int ssb_bus_pcibus_register(struct ssb_b
421@@ -486,11 +486,12 @@ static int ssb_devices_register(struct s
422 #ifdef CONFIG_SSB_PCIHOST
423             sdev->irq = bus->host_pci->irq;
424             dev->parent = &bus->host_pci->dev;
425+ sdev->dma_dev = dev->parent;
426 #endif
427             break;
428         case SSB_BUSTYPE_PCMCIA:
429 #ifdef CONFIG_SSB_PCMCIAHOST
430- sdev->irq = bus->host_pcmcia->irq.AssignedIRQ;
431+ sdev->irq = bus->host_pcmcia->irq;
432             dev->parent = &bus->host_pcmcia->dev;
433 #endif
434             break;
435@@ -501,6 +502,7 @@ static int ssb_devices_register(struct s
436             break;
437         case SSB_BUSTYPE_SSB:
438             dev->dma_mask = &dev->coherent_dma_mask;
439+ sdev->dma_dev = dev;
440             break;
441         }
442
443@@ -834,6 +836,9 @@ int ssb_bus_pcibus_register(struct ssb_b
23444     if (!err) {
24445         ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on "
25446                "PCI device %s\n", dev_name(&host_pci->dev));
...... 
29451     }
30452
31453     return err;
454@@ -1223,80 +1228,6 @@ u32 ssb_dma_translation(struct ssb_devic
455 }
456 EXPORT_SYMBOL(ssb_dma_translation);
457
458-int ssb_dma_set_mask(struct ssb_device *dev, u64 mask)
459-{
460-#ifdef CONFIG_SSB_PCIHOST
461- int err;
462-#endif
463-
464- switch (dev->bus->bustype) {
465- case SSB_BUSTYPE_PCI:
466-#ifdef CONFIG_SSB_PCIHOST
467- err = pci_set_dma_mask(dev->bus->host_pci, mask);
468- if (err)
469- return err;
470- err = pci_set_consistent_dma_mask(dev->bus->host_pci, mask);
471- return err;
472-#endif
473- case SSB_BUSTYPE_SSB:
474- return dma_set_mask(dev->dev, mask);
475- default:
476- __ssb_dma_not_implemented(dev);
477- }
478- return -ENOSYS;
479-}
480-EXPORT_SYMBOL(ssb_dma_set_mask);
481-
482-void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size,
483- dma_addr_t *dma_handle, gfp_t gfp_flags)
484-{
485- switch (dev->bus->bustype) {
486- case SSB_BUSTYPE_PCI:
487-#ifdef CONFIG_SSB_PCIHOST
488- if (gfp_flags & GFP_DMA) {
489- /* Workaround: The PCI API does not support passing
490- * a GFP flag. */
491- return dma_alloc_coherent(&dev->bus->host_pci->dev,
492- size, dma_handle, gfp_flags);
493- }
494- return pci_alloc_consistent(dev->bus->host_pci, size, dma_handle);
495-#endif
496- case SSB_BUSTYPE_SSB:
497- return dma_alloc_coherent(dev->dev, size, dma_handle, gfp_flags);
498- default:
499- __ssb_dma_not_implemented(dev);
500- }
501- return NULL;
502-}
503-EXPORT_SYMBOL(ssb_dma_alloc_consistent);
504-
505-void ssb_dma_free_consistent(struct ssb_device *dev, size_t size,
506- void *vaddr, dma_addr_t dma_handle,
507- gfp_t gfp_flags)
508-{
509- switch (dev->bus->bustype) {
510- case SSB_BUSTYPE_PCI:
511-#ifdef CONFIG_SSB_PCIHOST
512- if (gfp_flags & GFP_DMA) {
513- /* Workaround: The PCI API does not support passing
514- * a GFP flag. */
515- dma_free_coherent(&dev->bus->host_pci->dev,
516- size, vaddr, dma_handle);
517- return;
518- }
519- pci_free_consistent(dev->bus->host_pci, size,
520- vaddr, dma_handle);
521- return;
522-#endif
523- case SSB_BUSTYPE_SSB:
524- dma_free_coherent(dev->dev, size, vaddr, dma_handle);
525- return;
526- default:
527- __ssb_dma_not_implemented(dev);
528- }
529-}
530-EXPORT_SYMBOL(ssb_dma_free_consistent);
531-
532 int ssb_bus_may_powerdown(struct ssb_bus *bus)
533 {
534     struct ssb_chipcommon *cc;
32535--- a/drivers/ssb/pci.c
33536+++ b/drivers/ssb/pci.c
34537@@ -168,7 +168,7 @@ err_pci:
...... 
40543 /* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
41544 #define SPEX16(_outvar, _offset, _mask, _shift) \
42545     out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
43@@ -254,7 +254,7 @@ static int sprom_do_read(struct ssb_bus
546@@ -254,7 +254,7 @@ static int sprom_do_read(struct ssb_bus
44547     int i;
45548
46549     for (i = 0; i < bus->sprom_size; i++)
...... 
58561         mmiowb();
59562         msleep(20);
60563     }
61@@ -621,6 +621,14 @@ static int ssb_pci_sprom_get(struct ssb_
564@@ -621,6 +621,28 @@ static int ssb_pci_sprom_get(struct ssb_
62565     int err = -ENOMEM;
63566     u16 *buf;
64567
...... 
66569+ ssb_printk(KERN_ERR PFX "No SPROM available!\n");
67570+ return -ENODEV;
68571+ }
69+
70+ bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ?
71+ SSB_SPROM_BASE1 : SSB_SPROM_BASE31;
572+ if (bus->chipco.dev) { /* can be unavailible! */
573+ /*
574+ * get SPROM offset: SSB_SPROM_BASE1 except for
575+ * chipcommon rev >= 31 or chip ID is 0x4312 and
576+ * chipcommon status & 3 == 2
577+ */
578+ if (bus->chipco.dev->id.revision >= 31)
579+ bus->sprom_offset = SSB_SPROM_BASE31;
580+ else if (bus->chip_id == 0x4312 &&
581+ (bus->chipco.status & 0x03) == 2)
582+ bus->sprom_offset = SSB_SPROM_BASE31;
583+ else
584+ bus->sprom_offset = SSB_SPROM_BASE1;
585+ } else {
586+ bus->sprom_offset = SSB_SPROM_BASE1;
587+ }
588+ ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
72589+
73590     buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
74591     if (!buf)
75592         goto out;
76593--- a/drivers/ssb/sprom.c
77594+++ b/drivers/ssb/sprom.c
78@@ -176,3 +176,17 @@ const struct ssb_sprom *ssb_get_fallback
595@@ -176,3 +176,18 @@ const struct ssb_sprom *ssb_get_fallback
79596 {
80597     return fallback_sprom;
81598 }
...... 
88605+ /* this routine differs from specs as we do not access SPROM directly
89606+ on PCMCIA */
90607+ if (bus->bustype == SSB_BUSTYPE_PCI &&
608+ bus->chipco.dev && /* can be unavailible! */
91609+ bus->chipco.dev->id.revision >= 31)
92610+ return bus->chipco.capabilities & SSB_CHIPCO_CAP_SPROM;
93611+
...... 
95613+}
96614--- a/include/linux/ssb/ssb.h
97615+++ b/include/linux/ssb/ssb.h
616@@ -167,7 +167,7 @@ struct ssb_device {
617      * is an optimization. */
618     const struct ssb_bus_ops *ops;
619
620- struct device *dev;
621+ struct device *dev, *dma_dev;
622
623     struct ssb_bus *bus;
624     struct ssb_device_id id;
98625@@ -305,6 +305,7 @@ struct ssb_bus {
99626     /* ID information about the Chip. */
100627     u16 chip_id;
...... 
113640 /* Set a fallback SPROM.
114641  * See kdoc at the function definition for complete documentation. */
115642 extern int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom);
643@@ -466,14 +470,6 @@ extern u32 ssb_dma_translation(struct ss
644 #define SSB_DMA_TRANSLATION_MASK 0xC0000000
645 #define SSB_DMA_TRANSLATION_SHIFT 30
646
647-extern int ssb_dma_set_mask(struct ssb_device *dev, u64 mask);
648-
649-extern void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size,
650- dma_addr_t *dma_handle, gfp_t gfp_flags);
651-extern void ssb_dma_free_consistent(struct ssb_device *dev, size_t size,
652- void *vaddr, dma_addr_t dma_handle,
653- gfp_t gfp_flags);
654-
655 static inline void __cold __ssb_dma_not_implemented(struct ssb_device *dev)
656 {
657 #ifdef CONFIG_SSB_DEBUG
658@@ -482,155 +478,6 @@ static inline void __cold __ssb_dma_not_
659 #endif /* DEBUG */
660 }
661
662-static inline int ssb_dma_mapping_error(struct ssb_device *dev, dma_addr_t addr)
663-{
664- switch (dev->bus->bustype) {
665- case SSB_BUSTYPE_PCI:
666-#ifdef CONFIG_SSB_PCIHOST
667- return pci_dma_mapping_error(dev->bus->host_pci, addr);
668-#endif
669- break;
670- case SSB_BUSTYPE_SSB:
671- return dma_mapping_error(dev->dev, addr);
672- default:
673- break;
674- }
675- __ssb_dma_not_implemented(dev);
676- return -ENOSYS;
677-}
678-
679-static inline dma_addr_t ssb_dma_map_single(struct ssb_device *dev, void *p,
680- size_t size, enum dma_data_direction dir)
681-{
682- switch (dev->bus->bustype) {
683- case SSB_BUSTYPE_PCI:
684-#ifdef CONFIG_SSB_PCIHOST
685- return pci_map_single(dev->bus->host_pci, p, size, dir);
686-#endif
687- break;
688- case SSB_BUSTYPE_SSB:
689- return dma_map_single(dev->dev, p, size, dir);
690- default:
691- break;
692- }
693- __ssb_dma_not_implemented(dev);
694- return 0;
695-}
696-
697-static inline void ssb_dma_unmap_single(struct ssb_device *dev, dma_addr_t dma_addr,
698- size_t size, enum dma_data_direction dir)
699-{
700- switch (dev->bus->bustype) {
701- case SSB_BUSTYPE_PCI:
702-#ifdef CONFIG_SSB_PCIHOST
703- pci_unmap_single(dev->bus->host_pci, dma_addr, size, dir);
704- return;
705-#endif
706- break;
707- case SSB_BUSTYPE_SSB:
708- dma_unmap_single(dev->dev, dma_addr, size, dir);
709- return;
710- default:
711- break;
712- }
713- __ssb_dma_not_implemented(dev);
714-}
715-
716-static inline void ssb_dma_sync_single_for_cpu(struct ssb_device *dev,
717- dma_addr_t dma_addr,
718- size_t size,
719- enum dma_data_direction dir)
720-{
721- switch (dev->bus->bustype) {
722- case SSB_BUSTYPE_PCI:
723-#ifdef CONFIG_SSB_PCIHOST
724- pci_dma_sync_single_for_cpu(dev->bus->host_pci, dma_addr,
725- size, dir);
726- return;
727-#endif
728- break;
729- case SSB_BUSTYPE_SSB:
730- dma_sync_single_for_cpu(dev->dev, dma_addr, size, dir);
731- return;
732- default:
733- break;
734- }
735- __ssb_dma_not_implemented(dev);
736-}
737-
738-static inline void ssb_dma_sync_single_for_device(struct ssb_device *dev,
739- dma_addr_t dma_addr,
740- size_t size,
741- enum dma_data_direction dir)
742-{
743- switch (dev->bus->bustype) {
744- case SSB_BUSTYPE_PCI:
745-#ifdef CONFIG_SSB_PCIHOST
746- pci_dma_sync_single_for_device(dev->bus->host_pci, dma_addr,
747- size, dir);
748- return;
749-#endif
750- break;
751- case SSB_BUSTYPE_SSB:
752- dma_sync_single_for_device(dev->dev, dma_addr, size, dir);
753- return;
754- default:
755- break;
756- }
757- __ssb_dma_not_implemented(dev);
758-}
759-
760-static inline void ssb_dma_sync_single_range_for_cpu(struct ssb_device *dev,
761- dma_addr_t dma_addr,
762- unsigned long offset,
763- size_t size,
764- enum dma_data_direction dir)
765-{
766- switch (dev->bus->bustype) {
767- case SSB_BUSTYPE_PCI:
768-#ifdef CONFIG_SSB_PCIHOST
769- /* Just sync everything. That's all the PCI API can do. */
770- pci_dma_sync_single_for_cpu(dev->bus->host_pci, dma_addr,
771- offset + size, dir);
772- return;
773-#endif
774- break;
775- case SSB_BUSTYPE_SSB:
776- dma_sync_single_range_for_cpu(dev->dev, dma_addr, offset,
777- size, dir);
778- return;
779- default:
780- break;
781- }
782- __ssb_dma_not_implemented(dev);
783-}
784-
785-static inline void ssb_dma_sync_single_range_for_device(struct ssb_device *dev,
786- dma_addr_t dma_addr,
787- unsigned long offset,
788- size_t size,
789- enum dma_data_direction dir)
790-{
791- switch (dev->bus->bustype) {
792- case SSB_BUSTYPE_PCI:
793-#ifdef CONFIG_SSB_PCIHOST
794- /* Just sync everything. That's all the PCI API can do. */
795- pci_dma_sync_single_for_device(dev->bus->host_pci, dma_addr,
796- offset + size, dir);
797- return;
798-#endif
799- break;
800- case SSB_BUSTYPE_SSB:
801- dma_sync_single_range_for_device(dev->dev, dma_addr, offset,
802- size, dir);
803- return;
804- default:
805- break;
806- }
807- __ssb_dma_not_implemented(dev);
808-}
809-
810-
811 #ifdef CONFIG_SSB_PCIHOST
812 /* PCI-host wrapper driver */
813 extern int ssb_pcihost_register(struct pci_driver *driver);
116814--- a/include/linux/ssb/ssb_driver_chipcommon.h
117815+++ b/include/linux/ssb/ssb_driver_chipcommon.h
118816@@ -53,6 +53,7 @@
target/linux/generic/patches-2.6.34/976-ssb_add_dma_dev.patch
1From: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
2
3Add dma_dev, a pointer to struct device, to struct ssb_device. We pass it
4to the generic DMA API with SSB_BUSTYPE_PCI and SSB_BUSTYPE_SSB.
5ssb_devices_register() sets up it properly.
6
7This is preparation for replacing the ssb bus specific DMA API (ssb_dma_*)
8with the generic DMA API.
9
10Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
11Acked-by: Michael Buesch <mb@bu3sch.de>
12Cc: Gary Zambrano <zambrano@broadcom.com>
13Cc: Stefano Brivio <stefano.brivio@polimi.it>
14Cc: Larry Finger <Larry.Finger@lwfinger.net>
15Cc: John W. Linville <linville@tuxdriver.com>
16Acked-by: David S. Miller <davem@davemloft.net>
17Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
18
19 drivers/ssb/main.c | 2 ++
20 include/linux/ssb/ssb.h | 2 +-
21 2 files changed, 3 insertions(+), 1 deletion(-)
22
23+++ b/drivers/ssb/main.c
24@@ -486,6 +486,7 @@ static int ssb_devices_register(struct s
25 #ifdef CONFIG_SSB_PCIHOST
26             sdev->irq = bus->host_pci->irq;
27             dev->parent = &bus->host_pci->dev;
28+ sdev->dma_dev = dev->parent;
29 #endif
30             break;
31         case SSB_BUSTYPE_PCMCIA:
32@@ -501,6 +502,7 @@ static int ssb_devices_register(struct s
33             break;
34         case SSB_BUSTYPE_SSB:
35             dev->dma_mask = &dev->coherent_dma_mask;
36+ sdev->dma_dev = dev;
37             break;
38         }
39
40+++ b/include/linux/ssb/ssb.h
41@@ -167,7 +167,7 @@ struct ssb_device {
42      * is an optimization. */
43     const struct ssb_bus_ops *ops;
44
45- struct device *dev;
46+ struct device *dev, *dma_dev;
47
48     struct ssb_bus *bus;
49     struct ssb_device_id id;
target/linux/generic/patches-2.6.35/975-ssb_update.patch
1--- a/drivers/net/b44.c
2@@ -135,7 +135,6 @@ static void b44_init_rings(struct b44 *)
3
4 static void b44_init_hw(struct b44 *, int);
5
6-static int dma_desc_align_mask;
7 static int dma_desc_sync_size;
8 static int instance;
9
10@@ -150,9 +149,8 @@ static inline void b44_sync_dma_desc_for
11                         unsigned long offset,
12                         enum dma_data_direction dir)
13 {
14- ssb_dma_sync_single_range_for_device(sdev, dma_base,
15- offset & dma_desc_align_mask,
16- dma_desc_sync_size, dir);
17+ dma_sync_single_for_device(sdev->dma_dev, dma_base + offset,
18+ dma_desc_sync_size, dir);
19 }
20
21 static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev,
22@@ -160,9 +158,8 @@ static inline void b44_sync_dma_desc_for
23                          unsigned long offset,
24                          enum dma_data_direction dir)
25 {
26- ssb_dma_sync_single_range_for_cpu(sdev, dma_base,
27- offset & dma_desc_align_mask,
28- dma_desc_sync_size, dir);
29+ dma_sync_single_for_cpu(sdev->dma_dev, dma_base + offset,
30+ dma_desc_sync_size, dir);
31 }
32
33 static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
34@@ -608,10 +605,10 @@ static void b44_tx(struct b44 *bp)
35
36         BUG_ON(skb == NULL);
37
38- ssb_dma_unmap_single(bp->sdev,
39- rp->mapping,
40- skb->len,
41- DMA_TO_DEVICE);
42+ dma_unmap_single(bp->sdev->dma_dev,
43+ rp->mapping,
44+ skb->len,
45+ DMA_TO_DEVICE);
46         rp->skb = NULL;
47         dev_kfree_skb_irq(skb);
48     }
49@@ -648,29 +645,29 @@ static int b44_alloc_rx_skb(struct b44 *
50     if (skb == NULL)
51         return -ENOMEM;
52
53- mapping = ssb_dma_map_single(bp->sdev, skb->data,
54- RX_PKT_BUF_SZ,
55- DMA_FROM_DEVICE);
56+ mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
57+ RX_PKT_BUF_SZ,
58+ DMA_FROM_DEVICE);
59
60     /* Hardware bug work-around, the chip is unable to do PCI DMA
61        to/from anything above 1GB :-( */
62- if (ssb_dma_mapping_error(bp->sdev, mapping) ||
63+ if (dma_mapping_error(bp->sdev->dma_dev, mapping) ||
64         mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
65         /* Sigh... */
66- if (!ssb_dma_mapping_error(bp->sdev, mapping))
67- ssb_dma_unmap_single(bp->sdev, mapping,
68+ if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
69+ dma_unmap_single(bp->sdev->dma_dev, mapping,
70                          RX_PKT_BUF_SZ, DMA_FROM_DEVICE);
71         dev_kfree_skb_any(skb);
72         skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
73         if (skb == NULL)
74             return -ENOMEM;
75- mapping = ssb_dma_map_single(bp->sdev, skb->data,
76- RX_PKT_BUF_SZ,
77- DMA_FROM_DEVICE);
78- if (ssb_dma_mapping_error(bp->sdev, mapping) ||
79- mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
80- if (!ssb_dma_mapping_error(bp->sdev, mapping))
81- ssb_dma_unmap_single(bp->sdev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
82+ mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
83+ RX_PKT_BUF_SZ,
84+ DMA_FROM_DEVICE);
85+ if (dma_mapping_error(bp->sdev->dma_dev, mapping) ||
86+ mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
87+ if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
88+ dma_unmap_single(bp->sdev->dma_dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
89             dev_kfree_skb_any(skb);
90             return -ENOMEM;
91         }
92@@ -745,9 +742,9 @@ static void b44_recycle_rx(struct b44 *b
93                          dest_idx * sizeof(*dest_desc),
94                          DMA_BIDIRECTIONAL);
95
96- ssb_dma_sync_single_for_device(bp->sdev, dest_map->mapping,
97- RX_PKT_BUF_SZ,
98- DMA_FROM_DEVICE);
99+ dma_sync_single_for_device(bp->sdev->dma_dev, dest_map->mapping,
100+ RX_PKT_BUF_SZ,
101+ DMA_FROM_DEVICE);
102 }
103
104 static int b44_rx(struct b44 *bp, int budget)
105@@ -767,9 +764,9 @@ static int b44_rx(struct b44 *bp, int bu
106         struct rx_header *rh;
107         u16 len;
108
109- ssb_dma_sync_single_for_cpu(bp->sdev, map,
110- RX_PKT_BUF_SZ,
111- DMA_FROM_DEVICE);
112+ dma_sync_single_for_cpu(bp->sdev->dma_dev, map,
113+ RX_PKT_BUF_SZ,
114+ DMA_FROM_DEVICE);
115         rh = (struct rx_header *) skb->data;
116         len = le16_to_cpu(rh->len);
117         if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) ||
118@@ -801,8 +798,8 @@ static int b44_rx(struct b44 *bp, int bu
119             skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod);
120             if (skb_size < 0)
121                 goto drop_it;
122- ssb_dma_unmap_single(bp->sdev, map,
123- skb_size, DMA_FROM_DEVICE);
124+ dma_unmap_single(bp->sdev->dma_dev, map,
125+ skb_size, DMA_FROM_DEVICE);
126             /* Leave out rx_header */
127             skb_put(skb, len + RX_PKT_OFFSET);
128             skb_pull(skb, RX_PKT_OFFSET);
129@@ -954,24 +951,24 @@ static netdev_tx_t b44_start_xmit(struct
130         goto err_out;
131     }
132
133- mapping = ssb_dma_map_single(bp->sdev, skb->data, len, DMA_TO_DEVICE);
134- if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
135+ mapping = dma_map_single(bp->sdev->dma_dev, skb->data, len, DMA_TO_DEVICE);
136+ if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
137         struct sk_buff *bounce_skb;
138
139         /* Chip can't handle DMA to/from >1GB, use bounce buffer */
140- if (!ssb_dma_mapping_error(bp->sdev, mapping))
141- ssb_dma_unmap_single(bp->sdev, mapping, len,
142+ if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
143+ dma_unmap_single(bp->sdev->dma_dev, mapping, len,
144                          DMA_TO_DEVICE);
145
146         bounce_skb = __netdev_alloc_skb(dev, len, GFP_ATOMIC | GFP_DMA);
147         if (!bounce_skb)
148             goto err_out;
149
150- mapping = ssb_dma_map_single(bp->sdev, bounce_skb->data,
151- len, DMA_TO_DEVICE);
152- if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
153- if (!ssb_dma_mapping_error(bp->sdev, mapping))
154- ssb_dma_unmap_single(bp->sdev, mapping,
155+ mapping = dma_map_single(bp->sdev->dma_dev, bounce_skb->data,
156+ len, DMA_TO_DEVICE);
157+ if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
158+ if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
159+ dma_unmap_single(bp->sdev->dma_dev, mapping,
160                              len, DMA_TO_DEVICE);
161             dev_kfree_skb_any(bounce_skb);
162             goto err_out;
163@@ -1068,8 +1065,8 @@ static void b44_free_rings(struct b44 *b
164
165         if (rp->skb == NULL)
166             continue;
167- ssb_dma_unmap_single(bp->sdev, rp->mapping, RX_PKT_BUF_SZ,
168- DMA_FROM_DEVICE);
169+ dma_unmap_single(bp->sdev->dma_dev, rp->mapping, RX_PKT_BUF_SZ,
170+ DMA_FROM_DEVICE);
171         dev_kfree_skb_any(rp->skb);
172         rp->skb = NULL;
173     }
174@@ -1080,8 +1077,8 @@ static void b44_free_rings(struct b44 *b
175
176         if (rp->skb == NULL)
177             continue;
178- ssb_dma_unmap_single(bp->sdev, rp->mapping, rp->skb->len,
179- DMA_TO_DEVICE);
180+ dma_unmap_single(bp->sdev->dma_dev, rp->mapping, rp->skb->len,
181+ DMA_TO_DEVICE);
182         dev_kfree_skb_any(rp->skb);
183         rp->skb = NULL;
184     }
185@@ -1103,14 +1100,12 @@ static void b44_init_rings(struct b44 *b
186     memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
187
188     if (bp->flags & B44_FLAG_RX_RING_HACK)
189- ssb_dma_sync_single_for_device(bp->sdev, bp->rx_ring_dma,
190- DMA_TABLE_BYTES,
191- DMA_BIDIRECTIONAL);
192+ dma_sync_single_for_device(bp->sdev->dma_dev, bp->rx_ring_dma,
193+ DMA_TABLE_BYTES, DMA_BIDIRECTIONAL);
194
195     if (bp->flags & B44_FLAG_TX_RING_HACK)
196- ssb_dma_sync_single_for_device(bp->sdev, bp->tx_ring_dma,
197- DMA_TABLE_BYTES,
198- DMA_TO_DEVICE);
199+ dma_sync_single_for_device(bp->sdev->dma_dev, bp->tx_ring_dma,
200+ DMA_TABLE_BYTES, DMA_TO_DEVICE);
201
202     for (i = 0; i < bp->rx_pending; i++) {
203         if (b44_alloc_rx_skb(bp, -1, i) < 0)
204@@ -1130,27 +1125,23 @@ static void b44_free_consistent(struct b
205     bp->tx_buffers = NULL;
206     if (bp->rx_ring) {
207         if (bp->flags & B44_FLAG_RX_RING_HACK) {
208- ssb_dma_unmap_single(bp->sdev, bp->rx_ring_dma,
209- DMA_TABLE_BYTES,
210- DMA_BIDIRECTIONAL);
211+ dma_unmap_single(bp->sdev->dma_dev, bp->rx_ring_dma,
212+ DMA_TABLE_BYTES, DMA_BIDIRECTIONAL);
213             kfree(bp->rx_ring);
214         } else
215- ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES,
216- bp->rx_ring, bp->rx_ring_dma,
217- GFP_KERNEL);
218+ dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
219+ bp->rx_ring, bp->rx_ring_dma);
220         bp->rx_ring = NULL;
221         bp->flags &= ~B44_FLAG_RX_RING_HACK;
222     }
223     if (bp->tx_ring) {
224         if (bp->flags & B44_FLAG_TX_RING_HACK) {
225- ssb_dma_unmap_single(bp->sdev, bp->tx_ring_dma,
226- DMA_TABLE_BYTES,
227- DMA_TO_DEVICE);
228+ dma_unmap_single(bp->sdev->dma_dev, bp->tx_ring_dma,
229+ DMA_TABLE_BYTES, DMA_TO_DEVICE);
230             kfree(bp->tx_ring);
231         } else
232- ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES,
233- bp->tx_ring, bp->tx_ring_dma,
234- GFP_KERNEL);
235+ dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
236+ bp->tx_ring, bp->tx_ring_dma);
237         bp->tx_ring = NULL;
238         bp->flags &= ~B44_FLAG_TX_RING_HACK;
239     }
240@@ -1175,7 +1166,8 @@ static int b44_alloc_consistent(struct b
241         goto out_err;
242
243     size = DMA_TABLE_BYTES;
244- bp->rx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->rx_ring_dma, gfp);
245+ bp->rx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size,
246+ &bp->rx_ring_dma, gfp);
247     if (!bp->rx_ring) {
248         /* Allocation may have failed due to pci_alloc_consistent
249            insisting on use of GFP_DMA, which is more restrictive
250@@ -1187,11 +1179,11 @@ static int b44_alloc_consistent(struct b
251         if (!rx_ring)
252             goto out_err;
253
254- rx_ring_dma = ssb_dma_map_single(bp->sdev, rx_ring,
255- DMA_TABLE_BYTES,
256- DMA_BIDIRECTIONAL);
257+ rx_ring_dma = dma_map_single(bp->sdev->dma_dev, rx_ring,
258+ DMA_TABLE_BYTES,
259+ DMA_BIDIRECTIONAL);
260
261- if (ssb_dma_mapping_error(bp->sdev, rx_ring_dma) ||
262+ if (dma_mapping_error(bp->sdev->dma_dev, rx_ring_dma) ||
263             rx_ring_dma + size > DMA_BIT_MASK(30)) {
264             kfree(rx_ring);
265             goto out_err;
266@@ -1202,7 +1194,8 @@ static int b44_alloc_consistent(struct b
267         bp->flags |= B44_FLAG_RX_RING_HACK;
268     }
269
270- bp->tx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->tx_ring_dma, gfp);
271+ bp->tx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size,
272+ &bp->tx_ring_dma, gfp);
273     if (!bp->tx_ring) {
274         /* Allocation may have failed due to ssb_dma_alloc_consistent
275            insisting on use of GFP_DMA, which is more restrictive
276@@ -1214,11 +1207,11 @@ static int b44_alloc_consistent(struct b
277         if (!tx_ring)
278             goto out_err;
279
280- tx_ring_dma = ssb_dma_map_single(bp->sdev, tx_ring,
281- DMA_TABLE_BYTES,
282- DMA_TO_DEVICE);
283+ tx_ring_dma = dma_map_single(bp->sdev->dma_dev, tx_ring,
284+ DMA_TABLE_BYTES,
285+ DMA_TO_DEVICE);
286
287- if (ssb_dma_mapping_error(bp->sdev, tx_ring_dma) ||
288+ if (dma_mapping_error(bp->sdev->dma_dev, tx_ring_dma) ||
289             tx_ring_dma + size > DMA_BIT_MASK(30)) {
290             kfree(tx_ring);
291             goto out_err;
292@@ -2176,12 +2169,14 @@ static int __devinit b44_init_one(struct
293             "Failed to powerup the bus\n");
294         goto err_out_free_dev;
295     }
296- err = ssb_dma_set_mask(sdev, DMA_BIT_MASK(30));
297- if (err) {
298+
299+ if (dma_set_mask(sdev->dma_dev, DMA_BIT_MASK(30)) ||
300+ dma_set_coherent_mask(sdev->dma_dev, DMA_BIT_MASK(30))) {
301         dev_err(sdev->dev,
302             "Required 30BIT DMA mask unsupported by the system\n");
303         goto err_out_powerdown;
304     }
305+
306     err = b44_get_invariants(bp);
307     if (err) {
308         dev_err(sdev->dev,
309@@ -2344,7 +2339,6 @@ static int __init b44_init(void)
310     int err;
311
312     /* Setup paramaters for syncing RX/TX DMA descriptors */
313- dma_desc_align_mask = ~(dma_desc_align_size - 1);
314     dma_desc_sync_size = max_t(unsigned int, dma_desc_align_size, sizeof(struct dma_desc));
315
316     err = b44_pci_init();
317--- a/drivers/ssb/driver_chipcommon.c
318@@ -209,6 +209,24 @@ static void chipco_powercontrol_init(str
319     }
320 }
321
322+/* http://bcm-v4.sipsolutions.net/802.11/PmuFastPwrupDelay */
323+static u16 pmu_fast_powerup_delay(struct ssb_chipcommon *cc)
324+{
325+ struct ssb_bus *bus = cc->dev->bus;
326+
327+ switch (bus->chip_id) {
328+ case 0x4312:
329+ case 0x4322:
330+ case 0x4328:
331+ return 7000;
332+ case 0x4325:
333+ /* TODO: */
334+ default:
335+ return 15000;
336+ }
337+}
338+
339+/* http://bcm-v4.sipsolutions.net/802.11/ClkctlFastPwrupDelay */
340 static void calc_fast_powerup_delay(struct ssb_chipcommon *cc)
341 {
342     struct ssb_bus *bus = cc->dev->bus;
343@@ -218,6 +236,12 @@ static void calc_fast_powerup_delay(stru
344
345     if (bus->bustype != SSB_BUSTYPE_PCI)
346         return;
347+
348+ if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
349+ cc->fast_pwrup_delay = pmu_fast_powerup_delay(cc);
350+ return;
351+ }
352+
353     if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL))
354         return;
355
356@@ -235,6 +259,7 @@ void ssb_chipcommon_init(struct ssb_chip
357         return; /* We don't have a ChipCommon */
358     if (cc->dev->id.revision >= 11)
359         cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT);
360+ ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status);
361     ssb_pmu_init(cc);
362     chipco_powercontrol_init(cc);
363     ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
364--- a/drivers/ssb/driver_chipcommon_pmu.c
365@@ -502,9 +502,9 @@ static void ssb_pmu_resources_init(struc
366         chipco_write32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, max_msk);
367 }
368
369+/* http://bcm-v4.sipsolutions.net/802.11/SSB/PmuInit */
370 void ssb_pmu_init(struct ssb_chipcommon *cc)
371 {
372- struct ssb_bus *bus = cc->dev->bus;
373     u32 pmucap;
374
375     if (!(cc->capabilities & SSB_CHIPCO_CAP_PMU))
376@@ -516,15 +516,12 @@ void ssb_pmu_init(struct ssb_chipcommon
377     ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n",
378             cc->pmu.rev, pmucap);
379
380- if (cc->pmu.rev >= 1) {
381- if ((bus->chip_id == 0x4325) && (bus->chip_rev < 2)) {
382- chipco_mask32(cc, SSB_CHIPCO_PMU_CTL,
383- ~SSB_CHIPCO_PMU_CTL_NOILPONW);
384- } else {
385- chipco_set32(cc, SSB_CHIPCO_PMU_CTL,
386- SSB_CHIPCO_PMU_CTL_NOILPONW);
387- }
388- }
389+ if (cc->pmu.rev == 1)
390+ chipco_mask32(cc, SSB_CHIPCO_PMU_CTL,
391+ ~SSB_CHIPCO_PMU_CTL_NOILPONW);
392+ else
393+ chipco_set32(cc, SSB_CHIPCO_PMU_CTL,
394+ SSB_CHIPCO_PMU_CTL_NOILPONW);
395     ssb_pmu_pll_init(cc);
396     ssb_pmu_resources_init(cc);
397 }
398--- a/drivers/ssb/main.c
399@@ -486,6 +486,7 @@ static int ssb_devices_register(struct s
400 #ifdef CONFIG_SSB_PCIHOST
401             sdev->irq = bus->host_pci->irq;
402             dev->parent = &bus->host_pci->dev;
403+ sdev->dma_dev = dev->parent;
404 #endif
405             break;
406         case SSB_BUSTYPE_PCMCIA:
407@@ -501,6 +502,7 @@ static int ssb_devices_register(struct s
408             break;
409         case SSB_BUSTYPE_SSB:
410             dev->dma_mask = &dev->coherent_dma_mask;
411+ sdev->dma_dev = dev;
412             break;
413         }
414
415@@ -1226,80 +1228,6 @@ u32 ssb_dma_translation(struct ssb_devic
416 }
417 EXPORT_SYMBOL(ssb_dma_translation);
418
419-int ssb_dma_set_mask(struct ssb_device *dev, u64 mask)
420-{
421-#ifdef CONFIG_SSB_PCIHOST
422- int err;
423-#endif
424-
425- switch (dev->bus->bustype) {
426- case SSB_BUSTYPE_PCI:
427-#ifdef CONFIG_SSB_PCIHOST
428- err = pci_set_dma_mask(dev->bus->host_pci, mask);
429- if (err)
430- return err;
431- err = pci_set_consistent_dma_mask(dev->bus->host_pci, mask);
432- return err;
433-#endif
434- case SSB_BUSTYPE_SSB:
435- return dma_set_mask(dev->dev, mask);
436- default:
437- __ssb_dma_not_implemented(dev);
438- }
439- return -ENOSYS;
440-}
441-EXPORT_SYMBOL(ssb_dma_set_mask);
442-
443-void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size,
444- dma_addr_t *dma_handle, gfp_t gfp_flags)
445-{
446- switch (dev->bus->bustype) {
447- case SSB_BUSTYPE_PCI:
448-#ifdef CONFIG_SSB_PCIHOST
449- if (gfp_flags & GFP_DMA) {
450- /* Workaround: The PCI API does not support passing
451- * a GFP flag. */
452- return dma_alloc_coherent(&dev->bus->host_pci->dev,
453- size, dma_handle, gfp_flags);
454- }
455- return pci_alloc_consistent(dev->bus->host_pci, size, dma_handle);
456-#endif
457- case SSB_BUSTYPE_SSB:
458- return dma_alloc_coherent(dev->dev, size, dma_handle, gfp_flags);
459- default:
460- __ssb_dma_not_implemented(dev);
461- }
462- return NULL;
463-}
464-EXPORT_SYMBOL(ssb_dma_alloc_consistent);
465-
466-void ssb_dma_free_consistent(struct ssb_device *dev, size_t size,
467- void *vaddr, dma_addr_t dma_handle,
468- gfp_t gfp_flags)
469-{
470- switch (dev->bus->bustype) {
471- case SSB_BUSTYPE_PCI:
472-#ifdef CONFIG_SSB_PCIHOST
473- if (gfp_flags & GFP_DMA) {
474- /* Workaround: The PCI API does not support passing
475- * a GFP flag. */
476- dma_free_coherent(&dev->bus->host_pci->dev,
477- size, vaddr, dma_handle);
478- return;
479- }
480- pci_free_consistent(dev->bus->host_pci, size,
481- vaddr, dma_handle);
482- return;
483-#endif
484- case SSB_BUSTYPE_SSB:
485- dma_free_coherent(dev->dev, size, vaddr, dma_handle);
486- return;
487- default:
488- __ssb_dma_not_implemented(dev);
489- }
490-}
491-EXPORT_SYMBOL(ssb_dma_free_consistent);
492-
493 int ssb_bus_may_powerdown(struct ssb_bus *bus)
494 {
495     struct ssb_chipcommon *cc;
496--- a/drivers/ssb/pci.c
497@@ -626,11 +626,22 @@ static int ssb_pci_sprom_get(struct ssb_
498         return -ENODEV;
499     }
500     if (bus->chipco.dev) { /* can be unavailible! */
501- bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ?
502- SSB_SPROM_BASE1 : SSB_SPROM_BASE31;
503+ /*
504+ * get SPROM offset: SSB_SPROM_BASE1 except for
505+ * chipcommon rev >= 31 or chip ID is 0x4312 and
506+ * chipcommon status & 3 == 2
507+ */
508+ if (bus->chipco.dev->id.revision >= 31)
509+ bus->sprom_offset = SSB_SPROM_BASE31;
510+ else if (bus->chip_id == 0x4312 &&
511+ (bus->chipco.status & 0x03) == 2)
512+ bus->sprom_offset = SSB_SPROM_BASE31;
513+ else
514+ bus->sprom_offset = SSB_SPROM_BASE1;
515     } else {
516         bus->sprom_offset = SSB_SPROM_BASE1;
517     }
518+ ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
519
520     buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
521     if (!buf)
522--- a/include/linux/ssb/ssb.h
523@@ -167,7 +167,7 @@ struct ssb_device {
524      * is an optimization. */
525     const struct ssb_bus_ops *ops;
526
527- struct device *dev;
528+ struct device *dev, *dma_dev;
529
530     struct ssb_bus *bus;
531     struct ssb_device_id id;
532@@ -470,14 +470,6 @@ extern u32 ssb_dma_translation(struct ss
533 #define SSB_DMA_TRANSLATION_MASK 0xC0000000
534 #define SSB_DMA_TRANSLATION_SHIFT 30
535
536-extern int ssb_dma_set_mask(struct ssb_device *dev, u64 mask);
537-
538-extern void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size,
539- dma_addr_t *dma_handle, gfp_t gfp_flags);
540-extern void ssb_dma_free_consistent(struct ssb_device *dev, size_t size,
541- void *vaddr, dma_addr_t dma_handle,
542- gfp_t gfp_flags);
543-
544 static inline void __cold __ssb_dma_not_implemented(struct ssb_device *dev)
545 {
546 #ifdef CONFIG_SSB_DEBUG
547@@ -486,155 +478,6 @@ static inline void __cold __ssb_dma_not_
548 #endif /* DEBUG */
549 }
550
551-static inline int ssb_dma_mapping_error(struct ssb_device *dev, dma_addr_t addr)
552-{
553- switch (dev->bus->bustype) {
554- case SSB_BUSTYPE_PCI:
555-#ifdef CONFIG_SSB_PCIHOST
556- return pci_dma_mapping_error(dev->bus->host_pci, addr);
557-#endif
558- break;
559- case SSB_BUSTYPE_SSB:
560- return dma_mapping_error(dev->dev, addr);
561- default:
562- break;
563- }
564- __ssb_dma_not_implemented(dev);
565- return -ENOSYS;
566-}
567-
568-static inline dma_addr_t ssb_dma_map_single(struct ssb_device *dev, void *p,
569- size_t size, enum dma_data_direction dir)
570-{
571- switch (dev->bus->bustype) {
572- case SSB_BUSTYPE_PCI:
573-#ifdef CONFIG_SSB_PCIHOST
574- return pci_map_single(dev->bus->host_pci, p, size, dir);
575-#endif
576- break;
577- case SSB_BUSTYPE_SSB:
578- return dma_map_single(dev->dev, p, size, dir);
579- default:
580- break;
581- }
582- __ssb_dma_not_implemented(dev);
583- return 0;
584-}
585-
586-static inline void ssb_dma_unmap_single(struct ssb_device *dev, dma_addr_t dma_addr,
587- size_t size, enum dma_data_direction dir)
588-{
589- switch (dev->bus->bustype) {
590- case SSB_BUSTYPE_PCI:
591-#ifdef CONFIG_SSB_PCIHOST
592- pci_unmap_single(dev->bus->host_pci, dma_addr, size, dir);
593- return;
594-#endif
595- break;
596- case SSB_BUSTYPE_SSB:
597- dma_unmap_single(dev->dev, dma_addr, size, dir);
598- return;
599- default:
600- break;
601- }
602- __ssb_dma_not_implemented(dev);
603-}
604-
605-static inline void ssb_dma_sync_single_for_cpu(struct ssb_device *dev,
606- dma_addr_t dma_addr,
607- size_t size,
608- enum dma_data_direction dir)
609-{
610- switch (dev->bus->bustype) {
611- case SSB_BUSTYPE_PCI:
612-#ifdef CONFIG_SSB_PCIHOST
613- pci_dma_sync_single_for_cpu(dev->bus->host_pci, dma_addr,
614- size, dir);
615- return;
616-#endif
617- break;
618- case SSB_BUSTYPE_SSB:
619- dma_sync_single_for_cpu(dev->dev, dma_addr, size, dir);
620- return;
621- default:
622- break;
623- }
624- __ssb_dma_not_implemented(dev);
625-}
626-
627-static inline void ssb_dma_sync_single_for_device(struct ssb_device *dev,
628- dma_addr_t dma_addr,
629- size_t size,
630- enum dma_data_direction dir)
631-{
632- switch (dev->bus->bustype) {
633- case SSB_BUSTYPE_PCI:
634-#ifdef CONFIG_SSB_PCIHOST
635- pci_dma_sync_single_for_device(dev->bus->host_pci, dma_addr,
636- size, dir);
637- return;
638-#endif
639- break;
640- case SSB_BUSTYPE_SSB:
641- dma_sync_single_for_device(dev->dev, dma_addr, size, dir);
642- return;
643- default:
644- break;
645- }
646- __ssb_dma_not_implemented(dev);
647-}
648-
649-static inline void ssb_dma_sync_single_range_for_cpu(struct ssb_device *dev,
650- dma_addr_t dma_addr,
651- unsigned long offset,
652- size_t size,
653- enum dma_data_direction dir)
654-{
655- switch (dev->bus->bustype) {
656- case SSB_BUSTYPE_PCI:
657-#ifdef CONFIG_SSB_PCIHOST
658- /* Just sync everything. That's all the PCI API can do. */
659- pci_dma_sync_single_for_cpu(dev->bus->host_pci, dma_addr,
660- offset + size, dir);
661- return;
662-#endif
663- break;
664- case SSB_BUSTYPE_SSB:
665- dma_sync_single_range_for_cpu(dev->dev, dma_addr, offset,
666- size, dir);
667- return;
668- default:
669- break;
670- }
671- __ssb_dma_not_implemented(dev);
672-}
673-
674-static inline void ssb_dma_sync_single_range_for_device(struct ssb_device *dev,
675- dma_addr_t dma_addr,
676- unsigned long offset,
677- size_t size,
678- enum dma_data_direction dir)
679-{
680- switch (dev->bus->bustype) {
681- case SSB_BUSTYPE_PCI:
682-#ifdef CONFIG_SSB_PCIHOST
683- /* Just sync everything. That's all the PCI API can do. */
684- pci_dma_sync_single_for_device(dev->bus->host_pci, dma_addr,
685- offset + size, dir);
686- return;
687-#endif
688- break;
689- case SSB_BUSTYPE_SSB:
690- dma_sync_single_range_for_device(dev->dev, dma_addr, offset,
691- size, dir);
692- return;
693- default:
694- break;
695- }
696- __ssb_dma_not_implemented(dev);
697-}
698-
699-
700 #ifdef CONFIG_SSB_PCIHOST
701 /* PCI-host wrapper driver */
702 extern int ssb_pcihost_register(struct pci_driver *driver);
target/linux/generic/patches-2.6.35/976-ssb_add_dma_dev.patch
1From: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
2
3Add dma_dev, a pointer to struct device, to struct ssb_device. We pass it
4to the generic DMA API with SSB_BUSTYPE_PCI and SSB_BUSTYPE_SSB.
5ssb_devices_register() sets up it properly.
6
7This is preparation for replacing the ssb bus specific DMA API (ssb_dma_*)
8with the generic DMA API.
9
10Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
11Acked-by: Michael Buesch <mb@bu3sch.de>
12Cc: Gary Zambrano <zambrano@broadcom.com>
13Cc: Stefano Brivio <stefano.brivio@polimi.it>
14Cc: Larry Finger <Larry.Finger@lwfinger.net>
15Cc: John W. Linville <linville@tuxdriver.com>
16Acked-by: David S. Miller <davem@davemloft.net>
17Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
18
19 drivers/ssb/main.c | 2 ++
20 include/linux/ssb/ssb.h | 2 +-
21 2 files changed, 3 insertions(+), 1 deletion(-)
22
23+++ b/drivers/ssb/main.c
24@@ -486,6 +486,7 @@ static int ssb_devices_register(struct s
25 #ifdef CONFIG_SSB_PCIHOST
26             sdev->irq = bus->host_pci->irq;
27             dev->parent = &bus->host_pci->dev;
28+ sdev->dma_dev = dev->parent;
29 #endif
30             break;
31         case SSB_BUSTYPE_PCMCIA:
32@@ -501,6 +502,7 @@ static int ssb_devices_register(struct s
33             break;
34         case SSB_BUSTYPE_SSB:
35             dev->dma_mask = &dev->coherent_dma_mask;
36+ sdev->dma_dev = dev;
37             break;
38         }
39
40+++ b/include/linux/ssb/ssb.h
41@@ -167,7 +167,7 @@ struct ssb_device {
42      * is an optimization. */
43     const struct ssb_bus_ops *ops;
44
45- struct device *dev;
46+ struct device *dev, *dma_dev;
47
48     struct ssb_bus *bus;
49     struct ssb_device_id id;

Archive Download the corresponding diff file



interactive