source: clfs-embedded/patches/linux-2.6.30.5-openwrt-bcm47xx-fixes-1.patch@ 8172859

Last change on this file since 8172859 was ffc7663, checked in by Maarten Lankhorst <mlankhorst@…>, 15 years ago

book: Update kernel packages and patches

  • Property mode set to 100644
File size: 103.8 KB
  • arch/mips/Kconfig

    diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
    index 25f3b0a..868126c 100644
    a b config BCM47XX  
    5353        select SSB_DRIVER_MIPS
    5454        select SSB_DRIVER_EXTIF
    5555        select SSB_EMBEDDED
     56        select SSB_B43_PCI_BRIDGE if PCI
    5657        select SSB_PCICORE_HOSTMODE if PCI
    5758        select GENERIC_GPIO
    58         select SYS_HAS_EARLY_PRINTK
    5959        select CFE
    6060        help
    6161         Support for BCM47XX based boards
    config MIPS_MALTA  
    195195        select I8259
    196196        select MIPS_BOARDS_GEN
    197197        select MIPS_BONITO64
    198         select MIPS_CPU_SCACHE
    199198        select PCI_GT64XXX_PCI0
    200199        select MIPS_MSC
    201200        select SWAP_IO_SPACE
    config IP22_CPU_SCACHE  
    14551454        bool
    14561455        select BOARD_SCACHE
    14571456
    1458 #
    1459 # Support for a MIPS32 / MIPS64 style S-caches
    1460 #
    1461 config MIPS_CPU_SCACHE
    1462         bool
    1463         select BOARD_SCACHE
    1464 
    14651457config R5000_CPU_SCACHE
    14661458        bool
    14671459        select BOARD_SCACHE
  • arch/mips/bcm47xx/Makefile

    diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile
    index 35294b1..9e62430 100644
    a b  
    33# under Linux.
    44#
    55
    6 obj-y := gpio.o irq.o prom.o serial.o setup.o time.o wgt634u.o
     6obj-y := cfe_env.o gpio.o irq.o nvram.o prom.o serial.o setup.o time.o
  • new file arch/mips/bcm47xx/cfe_env.c

    diff --git a/arch/mips/bcm47xx/cfe_env.c b/arch/mips/bcm47xx/cfe_env.c
    new file mode 100644
    index 0000000..c1d5eee
    - +  
     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
  • new file arch/mips/bcm47xx/include/nvram.h

    diff --git a/arch/mips/bcm47xx/include/nvram.h b/arch/mips/bcm47xx/include/nvram.h
    new file mode 100644
    index 0000000..6bb18e8
    - +  
     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
  • arch/mips/bcm47xx/irq.c

    diff --git a/arch/mips/bcm47xx/irq.c b/arch/mips/bcm47xx/irq.c
    index 325757a..f087cf6 100644
    a b  
    11/*
    22 *  Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
     3 *  Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
    34 *
    45 *  This program is free software; you can redistribute  it and/or modify it
    56 *  under  the terms of  the GNU General  Public License as published by the
     
    2324 */
    2425
    2526#include <linux/types.h>
     27#include <linux/errno.h>
     28#include <linux/init.h>
    2629#include <linux/interrupt.h>
    2730#include <linux/irq.h>
     31#include <linux/pci.h>
     32#include <linux/ssb/ssb.h>
     33
    2834#include <asm/irq_cpu.h>
    2935
     36
     37extern struct ssb_bus ssb_bcm47xx;
     38
     39
    3040void plat_irq_dispatch(void)
    3141{
    3242        u32 cause;
  • new file arch/mips/bcm47xx/nvram.c

    diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c
    new file mode 100644
    index 0000000..71a2106
    - +  
     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 "include/nvram.h"
     28
     29#define MB * 1048576
     30extern struct ssb_bus ssb_bcm47xx;
     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_bcm47xx.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);
  • arch/mips/bcm47xx/prom.c

    diff --git a/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c
    index 079e33d..75132cf 100644
    a b  
    3232#include <asm/fw/cfe/cfe_error.h>
    3333
    3434static int cfe_cons_handle;
     35static void (* __prom_putchar)(char c);
    3536
    3637const char *get_system_type(void)
    3738{
    const char *get_system_type(void)  
    4041
    4142void prom_putchar(char c)
    4243{
     44        if (__prom_putchar)
     45                __prom_putchar(c);
     46}
     47
     48void prom_putchar_cfe(char c)
     49{
    4350        while (cfe_write(cfe_cons_handle, &c, 1) == 0)
    4451                ;
    4552}
    4653
    47 static __init void prom_init_cfe(void)
     54static __init int prom_init_cfe(void)
    4855{
    4956        uint32_t cfe_ept;
    5057        uint32_t cfe_handle;
    5158        uint32_t cfe_eptseal;
    52         int argc = fw_arg0;
    53         char **envp = (char **) fw_arg2;
    54         int *prom_vec = (int *) fw_arg3;
    5559
    56         /*
    57          * Check if a loader was used; if NOT, the 4 arguments are
    58          * what CFE gives us (handle, 0, EPT and EPTSEAL)
    59          */
    60         if (argc < 0) {
    61                 cfe_handle = (uint32_t)argc;
    62                 cfe_ept = (uint32_t)envp;
    63                 cfe_eptseal = (uint32_t)prom_vec;
    64         } else {
    65                 if ((int)prom_vec < 0) {
    66                         /*
    67                          * Old loader; all it gives us is the handle,
    68                          * so use the "known" entrypoint and assume
    69                          * the seal.
    70                          */
    71                         cfe_handle = (uint32_t)prom_vec;
    72                         cfe_ept = 0xBFC00500;
    73                         cfe_eptseal = CFE_EPTSEAL;
    74                 } else {
    75                         /*
    76                          * Newer loaders bundle the handle/ept/eptseal
    77                          * Note: prom_vec is in the loader's useg
    78                          * which is still alive in the TLB.
    79                          */
    80                         cfe_handle = prom_vec[0];
    81                         cfe_ept = prom_vec[2];
    82                         cfe_eptseal = prom_vec[3];
    83                 }
    84         }
     60        cfe_eptseal = (uint32_t) fw_arg3;
     61        cfe_handle = (uint32_t) fw_arg0;
     62        cfe_ept = (uint32_t) fw_arg2;
    8563
    86         if (cfe_eptseal != CFE_EPTSEAL) {
    87                 /* too early for panic to do any good */
    88                 printk(KERN_ERR "CFE's entrypoint seal doesn't match.");
    89                 while (1) ;
    90         }
     64        if (cfe_eptseal != CFE_EPTSEAL)
     65                return -1;
    9166
    9267        cfe_init(cfe_handle, cfe_ept);
     68        return 0;
    9369}
    9470
    95 static __init void prom_init_console(void)
     71static __init void prom_init_console_cfe(void)
    9672{
    9773        /* Initialize CFE console */
    9874        cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
    9975}
    10076
    101 static __init void prom_init_cmdline(void)
     77static __init void prom_init_cmdline_cfe(void)
    10278{
    10379        char buf[CL_SIZE];
    10480
    static __init void prom_init_mem(void)  
    146122
    147123void __init prom_init(void)
    148124{
    149         prom_init_cfe();
    150         prom_init_console();
    151         prom_init_cmdline();
     125        if (prom_init_cfe() == 0) {
     126                //prom_init_console_cfe();
     127                //prom_init_cmdline_cfe();
     128                __prom_putchar = prom_putchar_cfe;
     129        }
     130
    152131        prom_init_mem();
    153132}
    154133
  • arch/mips/bcm47xx/setup.c

    diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
    index 2f580fa..0a7bd49 100644
    a b  
    22 *  Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
    33 *  Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
    44 *  Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
    5  *  Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
     5 *  Copyright (C) 2006-2008 Michael Buesch <mb@bu3sch.de>
    66 *
    77 *  This program is free software; you can redistribute  it and/or modify it
    88 *  under  the terms of  the GNU General  Public License as published by the
     
    2525 *  675 Mass Ave, Cambridge, MA 02139, USA.
    2626 */
    2727
     28#include <linux/init.h>
    2829#include <linux/types.h>
    2930#include <linux/ssb/ssb.h>
    3031#include <linux/ssb/ssb_embedded.h>
     32#include <linux/tty.h>
     33#include <linux/serial.h>
     34#include <linux/serial_core.h>
     35#include <linux/serial_reg.h>
     36#include <linux/serial_8250.h>
    3137#include <asm/bootinfo.h>
    3238#include <asm/reboot.h>
    3339#include <asm/time.h>
    34 #include <bcm47xx.h>
    3540#include <asm/fw/cfe/cfe_api.h>
     41#include <linux/pm.h>
     42
     43#include "include/nvram.h"
    3644
    3745struct ssb_bus ssb_bcm47xx;
    3846EXPORT_SYMBOL(ssb_bcm47xx);
    3947
     48extern void bcm47xx_pci_init(void);
     49
    4050static void bcm47xx_machine_restart(char *command)
    4151{
    4252        printk(KERN_ALERT "Please stand by while rebooting the system...\n");
    static void bcm47xx_machine_halt(void)  
    5666                cpu_relax();
    5767}
    5868
    59 static void str2eaddr(char *str, char *dest)
     69static void e_aton(char *str, char *dest)
    6070{
    6171        int i = 0;
    6272
    static void str2eaddr(char *str, char *dest)  
    7383        }
    7484}
    7585
    76 static int bcm47xx_get_invariants(struct ssb_bus *bus,
    77                                    struct ssb_init_invariants *iv)
     86static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
     87{
     88        char *s;
     89
     90        memset(sprom, 0xFF, sizeof(struct ssb_sprom));
     91
     92        sprom->revision = 1;
     93        if ((s = nvram_get("il0macaddr")))
     94                e_aton(s, sprom->il0mac);
     95        if ((s = nvram_get("et0macaddr")))
     96                e_aton(s, sprom->et0mac);
     97        if ((s = nvram_get("et1macaddr")))
     98                e_aton(s, sprom->et1mac);
     99        if ((s = nvram_get("et0phyaddr")))
     100                sprom->et0phyaddr = simple_strtoul(s, NULL, 0);
     101        if ((s = nvram_get("et1phyaddr")))
     102                sprom->et1phyaddr = simple_strtoul(s, NULL, 0);
     103        if ((s = nvram_get("et0mdcport")))
     104                sprom->et0mdcport = !!simple_strtoul(s, NULL, 10);
     105        if ((s = nvram_get("et1mdcport")))
     106                sprom->et1mdcport = !!simple_strtoul(s, NULL, 10);
     107        if ((s = nvram_get("pa0b0")))
     108                sprom->pa0b0 = simple_strtoul(s, NULL, 0);
     109        if ((s = nvram_get("pa0b1")))
     110                sprom->pa0b1 = simple_strtoul(s, NULL, 0);
     111        if ((s = nvram_get("pa0b2")))
     112                sprom->pa0b2 = simple_strtoul(s, NULL, 0);
     113        if ((s = nvram_get("pa1b0")))
     114                sprom->pa1b0 = simple_strtoul(s, NULL, 0);
     115        if ((s = nvram_get("pa1b1")))
     116                sprom->pa1b1 = simple_strtoul(s, NULL, 0);
     117        if ((s = nvram_get("pa1b2")))
     118                sprom->pa1b2 = simple_strtoul(s, NULL, 0);
     119        if ((s = nvram_get("wl0gpio0")))
     120                sprom->gpio0 = simple_strtoul(s, NULL, 0);
     121        if ((s = nvram_get("wl0gpio1")))
     122                sprom->gpio1 = simple_strtoul(s, NULL, 0);
     123        if ((s = nvram_get("wl0gpio2")))
     124                sprom->gpio2 = simple_strtoul(s, NULL, 0);
     125        if ((s = nvram_get("wl0gpio3")))
     126                sprom->gpio3 = simple_strtoul(s, NULL, 0);
     127        if ((s = nvram_get("pa0maxpwr")))
     128                sprom->maxpwr_bg = simple_strtoul(s, NULL, 0);
     129        if ((s = nvram_get("pa1maxpwr")))
     130                sprom->maxpwr_a = simple_strtoul(s, NULL, 0);
     131        if ((s = nvram_get("pa0itssit")))
     132                sprom->itssi_bg = simple_strtoul(s, NULL, 0);
     133        if ((s = nvram_get("pa1itssit")))
     134                sprom->itssi_a = simple_strtoul(s, NULL, 0);
     135        sprom->boardflags_lo = 0;
     136        if ((s = nvram_get("boardflags")))
     137                sprom->boardflags_lo = simple_strtoul(s, NULL, 0);
     138        sprom->boardflags_hi = 0;
     139        if ((s = nvram_get("boardflags2")))
     140                sprom->boardflags_hi = simple_strtoul(s, NULL, 0);
     141}
     142
     143static int bcm47xx_get_invariants(struct ssb_bus *bus, struct ssb_init_invariants *iv)
    78144{
    79         char buf[100];
    80 
    81         /* Fill boardinfo structure */
    82         memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
    83 
    84         if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0)
    85                 iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
    86         if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0)
    87                 iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
    88         if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0)
    89                 iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
    90 
    91         /* Fill sprom structure */
    92         memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
    93         iv->sprom.revision = 3;
    94 
    95         if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
    96                 str2eaddr(buf, iv->sprom.et0mac);
    97         if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
    98                 str2eaddr(buf, iv->sprom.et1mac);
    99         if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
    100                 iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 10);
    101         if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
    102                 iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 10);
    103         if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
    104                 iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
    105         if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
    106                 iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
     145        char *s;
     146
     147        iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
     148        if ((s = nvram_get("boardtype")))
     149                iv->boardinfo.type = (u16)simple_strtoul(s, NULL, 0);
     150        if ((s = nvram_get("boardrev")))
     151                iv->boardinfo.rev = (u16)simple_strtoul(s, NULL, 0);
     152
     153        bcm47xx_fill_sprom(&iv->sprom);
     154
     155        if ((s = nvram_get("cardbus")))
     156                iv->has_cardbus_slot = !!simple_strtoul(s, NULL, 10);
    107157
    108158        return 0;
    109159}
    110160
    111161void __init plat_mem_setup(void)
    112162{
    113         int err;
     163        int i, err;
     164        char *s;
     165        struct ssb_mipscore *mcore;
     166
     167        err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE, bcm47xx_get_invariants);
     168        if (err) {
     169                const char *msg = "Failed to initialize SSB bus (err %d)\n";
     170                printk(msg, err); /* Make sure the message gets out of the box. */
     171                panic(msg, err);
     172        }
     173        mcore = &ssb_bcm47xx.mipscore;
    114174
    115         err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
    116                                       bcm47xx_get_invariants);
    117         if (err)
    118                 panic("Failed to initialize SSB bus (err %d)\n", err);
     175        s = nvram_get("kernel_args");
     176        if (s && !strncmp(s, "console=ttyS1", 13)) {
     177                struct ssb_serial_port port;
     178
     179                printk("Swapping serial ports!\n");
     180                /* swap serial ports */
     181                memcpy(&port, &mcore->serial_ports[0], sizeof(port));
     182                memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1], sizeof(port));
     183                memcpy(&mcore->serial_ports[1], &port, sizeof(port));
     184        }
     185
     186        for (i = 0; i < mcore->nr_serial_ports; i++) {
     187                struct ssb_serial_port *port = &(mcore->serial_ports[i]);
     188                struct uart_port s;
     189
     190                memset(&s, 0, sizeof(s));
     191                s.line = i;
     192                s.mapbase = (unsigned int) port->regs;
     193                s.membase = port->regs;
     194                s.irq = port->irq + 2;
     195                s.uartclk = port->baud_base;
     196                s.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
     197                s.iotype = SERIAL_IO_MEM;
     198                s.regshift = port->reg_shift;
     199
     200                early_serial_setup(&s);
     201        }
     202        printk("Serial init done.\n");
    119203
    120204        _machine_restart = bcm47xx_machine_restart;
    121205        _machine_halt = bcm47xx_machine_halt;
    122206        pm_power_off = bcm47xx_machine_halt;
    123207}
    124208
     209static int __init bcm47xx_register_gpiodev(void)
     210{
     211        static struct resource res = {
     212                .start = 0xFFFFFFFF,
     213        };
     214        struct platform_device *pdev;
     215
     216        pdev = platform_device_register_simple("GPIODEV", 0, &res, 1);
     217        if (!pdev) {
     218                printk(KERN_ERR "bcm47xx: GPIODEV init failed\n");
     219                return -ENODEV;
     220        }
     221
     222        return 0;
     223}
     224device_initcall(bcm47xx_register_gpiodev);
  • arch/mips/bcm47xx/time.c

    diff --git a/arch/mips/bcm47xx/time.c b/arch/mips/bcm47xx/time.c
    index 0c6f47b..08c23ad 100644
    a b  
    2222 *  675 Mass Ave, Cambridge, MA 02139, USA.
    2323 */
    2424
    25 
    2625#include <linux/init.h>
     26#include <linux/kernel.h>
     27#include <linux/sched.h>
     28#include <linux/serial_reg.h>
     29#include <linux/interrupt.h>
    2730#include <linux/ssb/ssb.h>
     31#include <asm/addrspace.h>
     32#include <asm/io.h>
    2833#include <asm/time.h>
    29 #include <bcm47xx.h>
     34
     35extern struct ssb_bus ssb_bcm47xx;
    3036
    3137void __init plat_time_init(void)
    3238{
  • deleted file rch/mips/bcm47xx/wgt634u.c

    diff --git a/arch/mips/bcm47xx/wgt634u.c b/arch/mips/bcm47xx/wgt634u.c
    deleted file mode 100644
    index ef00e7f..0000000
    + -  
    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) 2007 Aurelien Jarno <aurelien@aurel32.net>
    7  */
    8 
    9 #include <linux/platform_device.h>
    10 #include <linux/module.h>
    11 #include <linux/leds.h>
    12 #include <linux/mtd/physmap.h>
    13 #include <linux/ssb/ssb.h>
    14 #include <linux/interrupt.h>
    15 #include <linux/reboot.h>
    16 #include <linux/gpio.h>
    17 #include <asm/mach-bcm47xx/bcm47xx.h>
    18 
    19 /* GPIO definitions for the WGT634U */
    20 #define WGT634U_GPIO_LED        3
    21 #define WGT634U_GPIO_RESET      2
    22 #define WGT634U_GPIO_TP1        7
    23 #define WGT634U_GPIO_TP2        6
    24 #define WGT634U_GPIO_TP3        5
    25 #define WGT634U_GPIO_TP4        4
    26 #define WGT634U_GPIO_TP5        1
    27 
    28 static struct gpio_led wgt634u_leds[] = {
    29         {
    30                 .name = "power",
    31                 .gpio = WGT634U_GPIO_LED,
    32                 .active_low = 1,
    33                 .default_trigger = "heartbeat",
    34         },
    35 };
    36 
    37 static struct gpio_led_platform_data wgt634u_led_data = {
    38         .num_leds =     ARRAY_SIZE(wgt634u_leds),
    39         .leds =         wgt634u_leds,
    40 };
    41 
    42 static struct platform_device wgt634u_gpio_leds = {
    43         .name =         "leds-gpio",
    44         .id =           -1,
    45         .dev = {
    46                 .platform_data = &wgt634u_led_data,
    47         }
    48 };
    49 
    50 
    51 /* 8MiB flash. The struct mtd_partition matches original Netgear WGT634U
    52    firmware. */
    53 static struct mtd_partition wgt634u_partitions[] = {
    54         {
    55                 .name       = "cfe",
    56                 .offset     = 0,
    57                 .size       = 0x60000,          /* 384k */
    58                 .mask_flags = MTD_WRITEABLE     /* force read-only */
    59         },
    60         {
    61                 .name   = "config",
    62                 .offset = 0x60000,
    63                 .size   = 0x20000               /* 128k */
    64         },
    65         {
    66                 .name   = "linux",
    67                 .offset = 0x80000,
    68                 .size   = 0x140000              /* 1280k */
    69         },
    70         {
    71                 .name   = "jffs",
    72                 .offset = 0x1c0000,
    73                 .size   = 0x620000              /* 6272k */
    74         },
    75         {
    76                 .name   = "nvram",
    77                 .offset = 0x7e0000,
    78                 .size   = 0x20000               /* 128k */
    79         },
    80 };
    81 
    82 static struct physmap_flash_data wgt634u_flash_data = {
    83         .parts    = wgt634u_partitions,
    84         .nr_parts = ARRAY_SIZE(wgt634u_partitions)
    85 };
    86 
    87 static struct resource wgt634u_flash_resource = {
    88         .flags = IORESOURCE_MEM,
    89 };
    90 
    91 static struct platform_device wgt634u_flash = {
    92         .name          = "physmap-flash",
    93         .id            = 0,
    94         .dev           = { .platform_data = &wgt634u_flash_data, },
    95         .resource      = &wgt634u_flash_resource,
    96         .num_resources = 1,
    97 };
    98 
    99 /* Platform devices */
    100 static struct platform_device *wgt634u_devices[] __initdata = {
    101         &wgt634u_flash,
    102         &wgt634u_gpio_leds,
    103 };
    104 
    105 static irqreturn_t gpio_interrupt(int irq, void *ignored)
    106 {
    107         int state;
    108 
    109         /* Interrupts are shared, check if the current one is
    110            a GPIO interrupt. */
    111         if (!ssb_chipco_irq_status(&ssb_bcm47xx.chipco,
    112                                    SSB_CHIPCO_IRQ_GPIO))
    113                 return IRQ_NONE;
    114 
    115         state = gpio_get_value(WGT634U_GPIO_RESET);
    116 
    117         /* Interrupt are level triggered, revert the interrupt polarity
    118            to clear the interrupt. */
    119         gpio_polarity(WGT634U_GPIO_RESET, state);
    120 
    121         if (!state) {
    122                 printk(KERN_INFO "Reset button pressed");
    123                 ctrl_alt_del();
    124         }
    125 
    126         return IRQ_HANDLED;
    127 }
    128 
    129 static int __init wgt634u_init(void)
    130 {
    131         /* There is no easy way to detect that we are running on a WGT634U
    132          * machine. Use the MAC address as an heuristic. Netgear Inc. has
    133          * been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx.
    134          */
    135 
    136         u8 *et0mac = ssb_bcm47xx.sprom.et0mac;
    137 
    138         if (et0mac[0] == 0x00 &&
    139             ((et0mac[1] == 0x09 && et0mac[2] == 0x5b) ||
    140              (et0mac[1] == 0x0f && et0mac[2] == 0xb5))) {
    141                 struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
    142 
    143                 printk(KERN_INFO "WGT634U machine detected.\n");
    144 
    145                 if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET),
    146                                  gpio_interrupt, IRQF_SHARED,
    147                                  "WGT634U GPIO", &ssb_bcm47xx.chipco)) {
    148                         gpio_direction_input(WGT634U_GPIO_RESET);
    149                         gpio_intmask(WGT634U_GPIO_RESET, 1);
    150                         ssb_chipco_irq_mask(&ssb_bcm47xx.chipco,
    151                                             SSB_CHIPCO_IRQ_GPIO,
    152                                             SSB_CHIPCO_IRQ_GPIO);
    153                 }
    154 
    155                 wgt634u_flash_data.width = mcore->flash_buswidth;
    156                 wgt634u_flash_resource.start = mcore->flash_window;
    157                 wgt634u_flash_resource.end = mcore->flash_window
    158                                            + mcore->flash_window_size
    159                                            - 1;
    160                 return platform_add_devices(wgt634u_devices,
    161                                             ARRAY_SIZE(wgt634u_devices));
    162         } else
    163                 return -ENODEV;
    164 }
    165 
    166 module_init(wgt634u_init);
    167 
  • arch/mips/include/asm/bootinfo.h

    diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
    index 610fe3a..35d7d8f 100644
    a b  
    5757#define MACH_MIKROTIK_RB532     0       /* Mikrotik RouterBoard 532     */
    5858#define MACH_MIKROTIK_RB532A    1       /* Mikrotik RouterBoard 532A    */
    5959
     60/*
     61 * Valid machtype for group Broadcom
     62 */
     63#define MACH_GROUP_BRCM         23      /* Broadcom                     */
     64#define MACH_BCM47XX            1       /* Broadcom BCM47xx             */
     65
    6066#define CL_SIZE                 COMMAND_LINE_SIZE
    6167
    6268extern char *system_type;
  • arch/mips/include/asm/cacheflush.h

    diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h
    index 03b1d69..517bb16 100644
    a b  
    3232extern void (*flush_cache_all)(void);
    3333extern void (*__flush_cache_all)(void);
    3434extern void (*flush_cache_mm)(struct mm_struct *mm);
    35 #define flush_cache_dup_mm(mm)  do { (void) (mm); } while (0)
     35#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
    3636extern void (*flush_cache_range)(struct vm_area_struct *vma,
    3737        unsigned long start, unsigned long end);
    3838extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
  • arch/mips/include/asm/cpu-features.h

    diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
    index c0047f8..e7591aa 100644
    a b  
    104104#ifndef cpu_has_pindexed_dcache
    105105#define cpu_has_pindexed_dcache (cpu_data[0].dcache.flags & MIPS_CACHE_PINDEX)
    106106#endif
     107#ifndef cpu_use_kmap_coherent
     108#define cpu_use_kmap_coherent 1
     109#endif
    107110
    108111/*
    109112 * I-Cache snoops remote store.  This only matters on SMP.  Some multiprocessors
  • new file arch/mips/include/asm/mach-bcm47xx/cpu-feature-overrides.h

    diff --git a/arch/mips/include/asm/mach-bcm47xx/cpu-feature-overrides.h b/arch/mips/include/asm/mach-bcm47xx/cpu-feature-overrides.h
    new file mode 100644
    index 0000000..b4fe0c3
    - +  
     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 Ralf Baechle (ralf@linux-mips.org)
     7 */
     8#ifndef __ASM_MACH_BCM47XX_CPU_FEATURE_OVERRIDES_H
     9#define __ASM_MACH_BCM47XX_CPU_FEATURE_OVERRIDES_H
     10
     11#define cpu_use_kmap_coherent   0
     12
     13#endif /* __ASM_MACH_BCM47XX_CPU_FEATURE_OVERRIDES_H */
  • new file arch/mips/include/asm/mach-bcm47xx/kernel-entry-init.h

    diff --git a/arch/mips/include/asm/mach-bcm47xx/kernel-entry-init.h b/arch/mips/include/asm/mach-bcm47xx/kernel-entry-init.h
    new file mode 100644
    index 0000000..7df0dc2
    - +  
     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 */
  • arch/mips/include/asm/page.h

    diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h
    index 9f946e4..65ccdf2 100644
    a b  
    3535#ifndef __ASSEMBLY__
    3636
    3737#include <linux/pfn.h>
     38#include <asm/cpu-features.h>
    3839#include <asm/io.h>
    3940
    4041extern void build_clear_page(void);
    static inline void clear_user_page(void *addr, unsigned long vaddr,  
    7071                flush_data_cache_page((unsigned long)addr);
    7172}
    7273
    73 extern void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
    74         struct page *to);
    75 struct vm_area_struct;
    76 extern void copy_user_highpage(struct page *to, struct page *from,
    77         unsigned long vaddr, struct vm_area_struct *vma);
     74static inline void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
     75        struct page *to)
     76{
     77        extern void (*flush_data_cache_page)(unsigned long addr);
    7878
    79 #define __HAVE_ARCH_COPY_USER_HIGHPAGE
     79        copy_page(vto, vfrom);
     80        if (!cpu_has_ic_fills_f_dc ||
     81            pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
     82                flush_data_cache_page((unsigned long)vto);
     83}
    8084
    8185/*
    8286 * These are used to make use of C type-checking..
  • arch/mips/include/asm/r4kcache.h

    diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h
    index 4c140db..befb69e 100644
    a b  
    1717#include <asm/cpu-features.h>
    1818#include <asm/mipsmtregs.h>
    1919
     20#ifdef CONFIG_BCM47XX
     21#include <asm/paccess.h>
     22#include <linux/ssb/ssb.h>
     23#define BCM4710_DUMMY_RREG() bcm4710_dummy_rreg()
     24
     25static inline unsigned long bcm4710_dummy_rreg(void) {
     26      return (*(volatile unsigned long *)(KSEG1ADDR(SSB_ENUM_BASE + SSB_IMSTATE)));
     27}
     28
     29#define BCM4710_FILL_TLB(addr) bcm4710_fill_tlb((void*)(addr))
     30
     31static inline unsigned long bcm4710_fill_tlb(void *addr) {
     32      return (*(unsigned long *)addr);
     33}
     34
     35#define BCM4710_PROTECTED_FILL_TLB(addr) bcm4710_protected_fill_tlb((void*)(addr))
     36
     37static inline void bcm4710_protected_fill_tlb(void *addr) {
     38      unsigned long x;
     39      get_dbe(x, (unsigned long *)addr);;
     40}
     41
     42#else
     43#define BCM4710_DUMMY_RREG()
     44
     45#define BCM4710_FILL_TLB(addr)
     46#define BCM4710_PROTECTED_FILL_TLB(addr)
     47#endif
     48
    2049/*
    2150 * This macro return a properly sign-extended address suitable as base address
    2251 * for indexed cache operations.  Two issues here:
    static inline void flush_icache_line_indexed(unsigned long addr)  
    150179static inline void flush_dcache_line_indexed(unsigned long addr)
    151180{
    152181        __dflush_prologue
     182        BCM4710_DUMMY_RREG();
    153183        cache_op(Index_Writeback_Inv_D, addr);
    154184        __dflush_epilogue
    155185}
    static inline void flush_icache_line(unsigned long addr)  
    169199static inline void flush_dcache_line(unsigned long addr)
    170200{
    171201        __dflush_prologue
     202        BCM4710_DUMMY_RREG();
    172203        cache_op(Hit_Writeback_Inv_D, addr);
    173204        __dflush_epilogue
    174205}
    static inline void flush_dcache_line(unsigned long addr)  
    176207static inline void invalidate_dcache_line(unsigned long addr)
    177208{
    178209        __dflush_prologue
     210        BCM4710_DUMMY_RREG();
    179211        cache_op(Hit_Invalidate_D, addr);
    180212        __dflush_epilogue
    181213}
    static inline void flush_scache_line(unsigned long addr)  
    208240 */
    209241static inline void protected_flush_icache_line(unsigned long addr)
    210242{
     243        BCM4710_DUMMY_RREG();
    211244        protected_cache_op(Hit_Invalidate_I, addr);
    212245}
    213246
    static inline void protected_flush_icache_line(unsigned long addr)  
    219252 */
    220253static inline void protected_writeback_dcache_line(unsigned long addr)
    221254{
     255        BCM4710_DUMMY_RREG();
    222256        protected_cache_op(Hit_Writeback_Inv_D, addr);
    223257}
    224258
    static inline void invalidate_tcache_page(unsigned long addr)  
    339373                : "r" (base),                                           \
    340374                  "i" (op));
    341375
     376static inline void blast_dcache(void)
     377{
     378        unsigned long start = KSEG0;
     379        unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways;
     380        unsigned long end = (start + dcache_size);
     381
     382        do {
     383                BCM4710_DUMMY_RREG();
     384                cache_op(Index_Writeback_Inv_D, start);
     385                start += current_cpu_data.dcache.linesz;
     386        } while(start < end);
     387}
     388
     389static inline void blast_dcache_page(unsigned long page)
     390{
     391        unsigned long start = page;
     392        unsigned long end = start + PAGE_SIZE;
     393
     394        BCM4710_FILL_TLB(start);
     395        do {
     396                BCM4710_DUMMY_RREG();
     397                cache_op(Hit_Writeback_Inv_D, start);
     398                start += current_cpu_data.dcache.linesz;
     399        } while(start < end);
     400}
     401
     402static inline void blast_dcache_page_indexed(unsigned long page)
     403{
     404        unsigned long start = page;
     405        unsigned long end = start + PAGE_SIZE;
     406        unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
     407        unsigned long ws_end = current_cpu_data.dcache.ways <<
     408                               current_cpu_data.dcache.waybit;
     409        unsigned long ws, addr;
     410        for (ws = 0; ws < ws_end; ws += ws_inc) {
     411                start = page + ws;
     412                for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) {
     413                        BCM4710_DUMMY_RREG();
     414                        cache_op(Index_Writeback_Inv_D, addr);
     415                }
     416        }
     417}
     418
     419
    342420/* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
    343 #define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \
     421#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, war) \
    344422static inline void blast_##pfx##cache##lsize(void)                      \
    345423{                                                                       \
    346424        unsigned long start = INDEX_BASE;                               \
    static inline void blast_##pfx##cache##lsize(void) \  
    352430                                                                        \
    353431        __##pfx##flush_prologue                                         \
    354432                                                                        \
     433        war                                                             \
    355434        for (ws = 0; ws < ws_end; ws += ws_inc)                         \
    356435                for (addr = start; addr < end; addr += lsize * 32)      \
    357436                        cache##lsize##_unroll32(addr|ws, indexop);      \
    static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \  
    366445                                                                        \
    367446        __##pfx##flush_prologue                                         \
    368447                                                                        \
     448        war                                                             \
    369449        do {                                                            \
    370450                cache##lsize##_unroll32(start, hitop);                  \
    371451                start += lsize * 32;                                    \
    static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page)  
    384464                               current_cpu_data.desc.waybit;            \
    385465        unsigned long ws, addr;                                         \
    386466                                                                        \
     467        war                                                             \
     468                                                                        \
    387469        __##pfx##flush_prologue                                         \
    388470                                                                        \
    389471        for (ws = 0; ws < ws_end; ws += ws_inc)                         \
    static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page)  
    393475        __##pfx##flush_epilogue                                         \
    394476}
    395477
    396 __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
    397 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
    398 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
    399 __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
    400 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
    401 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
    402 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
    403 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
    404 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
    405 
    406 __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16)
    407 __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32)
    408 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16)
    409 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32)
    410 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64)
    411 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128)
     478__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
     479__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, BCM4710_FILL_TLB(start);)
     480__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
     481__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
     482__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, BCM4710_FILL_TLB(start);)
     483__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
     484__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, BCM4710_FILL_TLB(start);)
     485__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
     486__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
     487
     488__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, )
     489__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, )
     490__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, )
     491__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, )
     492__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, )
     493__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, )
    412494
    413495/* build blast_xxx_range, protected_blast_xxx_range */
    414 #define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \
     496#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, war, war2) \
    415497static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
    416498                                                    unsigned long end)  \
    417499{                                                                       \
    418500        unsigned long lsize = cpu_##desc##_line_size();                 \
    419501        unsigned long addr = start & ~(lsize - 1);                      \
    420502        unsigned long aend = (end - 1) & ~(lsize - 1);                  \
     503        war                                                             \
    421504                                                                        \
    422505        __##pfx##flush_prologue                                         \
    423506                                                                        \
    424507        while (1) {                                                     \
     508                war2                                            \
    425509                prot##cache_op(hitop, addr);                            \
    426510                if (addr == aend)                                       \
    427511                        break;                                          \
    static inline void prot##blast_##pfx##cache##_range(unsigned long start, \  
    431515        __##pfx##flush_epilogue                                         \
    432516}
    433517
    434 __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
    435 __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_)
    436 __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_)
    437 __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, )
    438 __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, )
     518__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, BCM4710_PROTECTED_FILL_TLB(addr); BCM4710_PROTECTED_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
     519__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_,, )
     520__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_,, )
     521__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D,, BCM4710_FILL_TLB(addr); BCM4710_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
     522__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD,,, )
    439523/* blast_inv_dcache_range */
    440 __BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, )
    441 __BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, )
     524__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D,,,BCM4710_DUMMY_RREG();)
     525__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD,,, )
    442526
    443527#endif /* _ASM_R4KCACHE_H */
  • arch/mips/include/asm/stackframe.h

    diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
    index db0fa7b..fd23784 100644
    a b  
    426426                .macro  RESTORE_SP_AND_RET
    427427                LONG_L  sp, PT_R29(sp)
    428428                .set    mips3
     429#ifdef CONFIG_BCM47XX
     430                nop
     431                nop
     432#endif
    429433                eret
    430434                .set    mips0
    431435                .endm
  • arch/mips/kernel/cpu-probe.c

    diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
    index b13b8eb..8141700 100644
    a b static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)  
    753753        case PRID_IMP_25KF:
    754754                c->cputype = CPU_25KF;
    755755                __cpu_name[cpu] = "MIPS 25Kc";
     756                /* Probe for L2 cache */
     757                c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
    756758                break;
    757759        case PRID_IMP_34K:
    758760                c->cputype = CPU_34K;
  • arch/mips/kernel/genex.S

    diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
    index 8882e57..e6ddba2 100644
    a b  
    2222#include <asm/page.h>
    2323#include <asm/thread_info.h>
    2424
     25#ifdef CONFIG_BCM47XX
     26# ifdef eret
     27#  undef eret
     28# endif
     29# define eret                                   \
     30        .set push;                              \
     31        .set noreorder;                         \
     32         nop;                                   \
     33         nop;                                   \
     34         eret;                                  \
     35        .set pop;
     36#endif
     37
    2538#define PANIC_PIC(msg)                                  \
    2639                .set push;                              \
    2740                .set    reorder;                        \
    NESTED(except_vec1_generic, 0, sp)  
    5265NESTED(except_vec3_generic, 0, sp)
    5366        .set    push
    5467        .set    noat
     68#ifdef CONFIG_BCM47XX
     69        nop
     70#endif
    5571#if R5432_CP0_INTERRUPT_WAR
    5672        mfc0    k0, CP0_INDEX
    5773#endif
    NESTED(except_vec3_r4000, 0, sp)  
    7591        .set    push
    7692        .set    mips3
    7793        .set    noat
     94#ifdef CONFIG_BCM47XX
     95        nop
     96#endif
    7897        mfc0    k1, CP0_CAUSE
    7998        li      k0, 31<<2
    8099        andi    k1, k1, 0x7c
  • arch/mips/mm/Makefile

    diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
    index d7ec955..d666c4e 100644
    a b obj-$(CONFIG_CPU_CAVIUM_OCTEON) += c-octeon.o cex-oct.o tlb-r4k.o  
    3232obj-$(CONFIG_IP22_CPU_SCACHE)   += sc-ip22.o
    3333obj-$(CONFIG_R5000_CPU_SCACHE)  += sc-r5k.o
    3434obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
    35 obj-$(CONFIG_MIPS_CPU_SCACHE)   += sc-mips.o
    3635
    3736EXTRA_CFLAGS += -Werror
  • arch/mips/mm/c-r4k.c

    diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
    index 171951d..258f8ca 100644
    a b  
    3434#include <asm/cacheflush.h> /* for run_uncached() */
    3535
    3636
     37/* For enabling BCM4710 cache workarounds */
     38int bcm4710 = 0;
     39
    3740/*
    3841 * Special Variant of smp_call_function for use by cache functions:
    3942 *
    static void __cpuinit r4k_blast_dcache_page_setup(void)  
    104107{
    105108        unsigned long  dc_lsize = cpu_dcache_line_size();
    106109
     110        if (bcm4710)
     111                r4k_blast_dcache_page = blast_dcache_page;
     112        else
    107113        if (dc_lsize == 0)
    108114                r4k_blast_dcache_page = (void *)cache_noop;
    109115        else if (dc_lsize == 16)
    static void __cpuinit r4k_blast_dcache_page_indexed_setup(void)  
    118124{
    119125        unsigned long dc_lsize = cpu_dcache_line_size();
    120126
     127        if (bcm4710)
     128                r4k_blast_dcache_page_indexed = blast_dcache_page_indexed;
     129        else
    121130        if (dc_lsize == 0)
    122131                r4k_blast_dcache_page_indexed = (void *)cache_noop;
    123132        else if (dc_lsize == 16)
    static void __cpuinit r4k_blast_dcache_setup(void)  
    132141{
    133142        unsigned long dc_lsize = cpu_dcache_line_size();
    134143
     144        if (bcm4710)
     145                r4k_blast_dcache = blast_dcache;
     146        else
    135147        if (dc_lsize == 0)
    136148                r4k_blast_dcache = (void *)cache_noop;
    137149        else if (dc_lsize == 16)
    static inline void local_r4k___flush_cache_all(void * args)  
    348360        }
    349361}
    350362
    351 static void r4k___flush_cache_all(void)
     363void r4k___flush_cache_all(void)
    352364{
    353365        r4k_on_each_cpu(local_r4k___flush_cache_all, NULL, 1);
    354366}
    static inline void local_r4k_flush_cache_page(void *args)  
    482494                 */
    483495                map_coherent = (cpu_has_dc_aliases &&
    484496                                page_mapped(page) && !Page_dcache_dirty(page));
    485                 if (map_coherent)
     497                if (map_coherent && cpu_use_kmap_coherent)
    486498                        vaddr = kmap_coherent(page, addr);
    487499                else
    488500                        vaddr = kmap_atomic(page, KM_USER0);
    static inline void local_r4k_flush_cache_page(void *args)  
    505517        }
    506518
    507519        if (vaddr) {
    508                 if (map_coherent)
     520                if (map_coherent && cpu_use_kmap_coherent)
    509521                        kunmap_coherent();
    510522                else
    511523                        kunmap_atomic(vaddr, KM_USER0);
    512524        }
    513525}
    514526
    515 static void r4k_flush_cache_page(struct vm_area_struct *vma,
     527void r4k_flush_cache_page(struct vm_area_struct *vma,
    516528        unsigned long addr, unsigned long pfn)
    517529{
    518530        struct flush_cache_page_args args;
    static void local_r4k_flush_cache_sigtramp(void * arg)  
    667679        unsigned long addr = (unsigned long) arg;
    668680
    669681        R4600_HIT_CACHEOP_WAR_IMPL;
     682        BCM4710_PROTECTED_FILL_TLB(addr);
     683        BCM4710_PROTECTED_FILL_TLB(addr + 4);
    670684        if (dc_lsize)
    671685                protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
    672686        if (!cpu_icache_snoops_remote_store && scache_size)
    static void __init loongson2_sc_init(void)  
    11351149
    11361150extern int r5k_sc_init(void);
    11371151extern int rm7k_sc_init(void);
    1138 extern int mips_sc_init(void);
    11391152
    11401153static void __cpuinit setup_scache(void)
    11411154{
    static void __cpuinit setup_scache(void)  
    11891202#endif
    11901203
    11911204        default:
    1192                 if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
    1193                     c->isa_level == MIPS_CPU_ISA_M32R2 ||
    1194                     c->isa_level == MIPS_CPU_ISA_M64R1 ||
    1195                     c->isa_level == MIPS_CPU_ISA_M64R2) {
    1196 #ifdef CONFIG_MIPS_CPU_SCACHE
    1197                         if (mips_sc_init ()) {
    1198                                 scache_size = c->scache.ways * c->scache.sets * c->scache.linesz;
    1199                                 printk("MIPS secondary cache %ldkB, %s, linesize %d bytes.\n",
    1200                                        scache_size >> 10,
    1201                                        way_string[c->scache.ways], c->scache.linesz);
    1202                         }
    1203 #else
    1204                         if (!(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
    1205                                 panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
    1206 #endif
    1207                         return;
    1208                 }
    12091205                sc_present = 0;
    12101206        }
    12111207
    12121208        if (!sc_present)
    12131209                return;
    12141210
     1211        if ((c->isa_level == MIPS_CPU_ISA_M32R1 ||
     1212             c->isa_level == MIPS_CPU_ISA_M64R1) &&
     1213            !(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
     1214                panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
     1215
    12151216        /* compute a couple of other cache variables */
    12161217        c->scache.waysize = scache_size / c->scache.ways;
    12171218
    static void __cpuinit coherency_setup(void)  
    12981299         * silly idea of putting something else there ...
    12991300         */
    13001301        switch (current_cpu_type()) {
     1302        case CPU_BCM3302:
     1303                {
     1304                        u32 cm;
     1305                        cm = read_c0_diag();
     1306                        /* Enable icache */
     1307                        cm |= (1 << 31);
     1308                        /* Enable dcache */
     1309                        cm |= (1 << 30);
     1310                        write_c0_diag(cm);
     1311                }
     1312                break;
    13011313        case CPU_R4000PC:
    13021314        case CPU_R4000SC:
    13031315        case CPU_R4000MC:
    void __cpuinit r4k_cache_init(void)  
    13541366                break;
    13551367        }
    13561368
     1369        /* Check if special workarounds are required */
     1370#ifdef CONFIG_BCM47XX
     1371        if (current_cpu_data.cputype == CPU_BCM4710 && (current_cpu_data.processor_id & 0xff) == 0) {
     1372                printk("Enabling BCM4710A0 cache workarounds.\n");
     1373                bcm4710 = 1;
     1374        } else
     1375#endif
     1376                bcm4710 = 0;
     1377
    13571378        probe_pcache();
    13581379        setup_scache();
    13591380
    void __cpuinit r4k_cache_init(void)  
    14121433#if !defined(CONFIG_MIPS_CMP)
    14131434        local_r4k___flush_cache_all(NULL);
    14141435#endif
     1436#ifdef CONFIG_BCM47XX
     1437        {
     1438                static void (*_coherency_setup)(void);
     1439                _coherency_setup = (void (*)(void)) KSEG1ADDR(coherency_setup);
     1440                _coherency_setup();
     1441        }
     1442#else
    14151443        coherency_setup();
     1444#endif
    14161445}
     1446
     1447// fuse package DCACHE BUG patch exports
     1448void (*fuse_flush_cache_all)(void) = r4k___flush_cache_all;
     1449void (*fuse_flush_cache_page)(struct vm_area_struct *vma, unsigned long page,
     1450        unsigned long pfn) = r4k_flush_cache_page;
     1451EXPORT_SYMBOL(fuse_flush_cache_page);
     1452EXPORT_SYMBOL(fuse_flush_cache_all);
  • arch/mips/mm/init.c

    diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
    index c551129..e733f78 100644
    a b void kunmap_coherent(void)  
    198198        preempt_check_resched();
    199199}
    200200
    201 void copy_user_highpage(struct page *to, struct page *from,
    202         unsigned long vaddr, struct vm_area_struct *vma)
    203 {
    204         void *vfrom, *vto;
    205 
    206         vto = kmap_atomic(to, KM_USER1);
    207         if (cpu_has_dc_aliases &&
    208             page_mapped(from) && !Page_dcache_dirty(from)) {
    209                 vfrom = kmap_coherent(from, vaddr);
    210                 copy_page(vto, vfrom);
    211                 kunmap_coherent();
    212         } else {
    213                 vfrom = kmap_atomic(from, KM_USER0);
    214                 copy_page(vto, vfrom);
    215                 kunmap_atomic(vfrom, KM_USER0);
    216         }
    217         if ((!cpu_has_ic_fills_f_dc) ||
    218             pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
    219                 flush_data_cache_page((unsigned long)vto);
    220         kunmap_atomic(vto, KM_USER1);
    221         /* Make sure this page is cleared on other CPU's too before using it */
    222         smp_wmb();
    223 }
    224 
    225201void copy_to_user_page(struct vm_area_struct *vma,
    226202        struct page *page, unsigned long vaddr, void *dst, const void *src,
    227203        unsigned long len)
    228204{
    229         if (cpu_has_dc_aliases &&
     205        if (cpu_has_dc_aliases && cpu_use_kmap_coherent &&
    230206            page_mapped(page) && !Page_dcache_dirty(page)) {
    231207                void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
    232208                memcpy(vto, src, len);
    void copy_from_user_page(struct vm_area_struct *vma,  
    244220        struct page *page, unsigned long vaddr, void *dst, const void *src,
    245221        unsigned long len)
    246222{
    247         if (cpu_has_dc_aliases &&
     223        if (cpu_has_dc_aliases && cpu_use_kmap_coherent &&
    248224            page_mapped(page) && !Page_dcache_dirty(page)) {
    249225                void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
    250226                memcpy(dst, vfrom, len);
  • arch/mips/mm/tlbex.c

    diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
    index 0615b62..b0d64df 100644
    a b build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)  
    544544#endif
    545545        uasm_i_addu(p, ptr, tmp, ptr);
    546546#else
     547#ifdef CONFIG_BCM47XX
     548        uasm_i_nop(p);
     549#endif
    547550        UASM_i_LA_mostly(p, ptr, pgdc);
    548551#endif
    549552        uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
    static void __cpuinit build_r4000_tlb_refill_handler(void)  
    677680#ifdef CONFIG_64BIT
    678681        build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */
    679682#else
     683# ifdef CONFIG_BCM47XX
     684        uasm_i_nop(&p);
     685# endif
    680686        build_get_pgde32(&p, K0, K1); /* get pgd in K1 */
    681687#endif
    682688
    static void __cpuinit build_r4000_tlb_refill_handler(void)  
    684690        build_update_entries(&p, K0, K1);
    685691        build_tlb_write_entry(&p, &l, &r, tlb_random);
    686692        uasm_l_leave(&l, p);
     693#ifdef CONFIG_BCM47XX
     694        uasm_i_nop(&p);
     695#endif
    687696        uasm_i_eret(&p); /* return from trap */
    688697
    689698#ifdef CONFIG_64BIT
    build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l,  
    10841093#ifdef CONFIG_64BIT
    10851094        build_get_pmde64(p, l, r, pte, ptr); /* get pmd in ptr */
    10861095#else
     1096# ifdef CONFIG_BCM47XX
     1097        uasm_i_nop(p);
     1098# endif
    10871099        build_get_pgde32(p, pte, ptr); /* get pgd in ptr */
    10881100#endif
    10891101
    build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l,  
    11111123        build_update_entries(p, tmp, ptr);
    11121124        build_tlb_write_entry(p, l, r, tlb_indexed);
    11131125        uasm_l_leave(l, *p);
     1126#ifdef CONFIG_BCM47XX
     1127        uasm_i_nop(p);
     1128#endif
    11141129        uasm_i_eret(p); /* return from trap */
    11151130
    11161131#ifdef CONFIG_64BIT
  • arch/mips/pci/pci.c

    diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
    index b0eb9e7..85c152a 100644
    a b static int pcibios_enable_resources(struct pci_dev *dev, int mask)  
    185185                if ((idx == PCI_ROM_RESOURCE) &&
    186186                                (!(r->flags & IORESOURCE_ROM_ENABLE)))
    187187                        continue;
    188                 if (!r->start && r->end) {
    189                         printk(KERN_ERR "PCI: Device %s not available "
    190                                "because of resource collisions\n",
     188                if (!r->start && r->end)
     189                        printk(KERN_WARNING "PCI: Device %s resource"
     190                               "collisions detected. Ignoring...\n",
    191191                               pci_name(dev));
    192                         return -EINVAL;
    193                 }
    194192                if (r->flags & IORESOURCE_IO)
    195193                        cmd |= PCI_COMMAND_IO;
    196194                if (r->flags & IORESOURCE_MEM)
  • drivers/mtd/maps/Kconfig

    diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
    index 82923bd..4fa8a05 100644
    a b config MTD_CFI_FLAGADM  
    343343          Mapping for the Flaga digital module. If you don't have one, ignore
    344344          this setting.
    345345
     346config MTD_BCM47XX
     347        tristate "BCM47xx flash device"
     348        depends on MIPS && MTD_CFI && BCM47XX
     349        help
     350          Support for the flash chips on the BCM947xx board.
     351
    346352config MTD_REDWOOD
    347353        tristate "CFI Flash devices mapped on IBM Redwood"
    348354        depends on MTD_CFI && ( REDWOOD_4 || REDWOOD_5 || REDWOOD_6 )
  • drivers/mtd/maps/Makefile

    diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
    index 2dbc1be..d45138c 100644
    a b obj-$(CONFIG_MTD_PMC_MSP_RAMROOT)+= pmcmsp-ramroot.o  
    2929obj-$(CONFIG_MTD_PCMCIA)        += pcmciamtd.o
    3030obj-$(CONFIG_MTD_RPXLITE)       += rpxlite.o
    3131obj-$(CONFIG_MTD_TQM8XXL)       += tqm8xxl.o
     32obj-$(CONFIG_MTD_BCM47XX)       += bcm47xx-flash.o
    3233obj-$(CONFIG_MTD_SA1100)        += sa1100-flash.o
    3334obj-$(CONFIG_MTD_IPAQ)          += ipaq-flash.o
    3435obj-$(CONFIG_MTD_SBC_GXX)       += sbc_gxx.o
  • new file drivers/mtd/maps/bcm47xx-flash.c

    diff --git a/drivers/mtd/maps/bcm47xx-flash.c b/drivers/mtd/maps/bcm47xx-flash.c
    new file mode 100644
    index 0000000..3ceec40
    - +  
     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
     225
     226
     227static int __init
     228find_root(struct mtd_info *mtd, size_t size, struct mtd_partition *part)
     229{
     230        struct trx_header trx, *trx2;
     231        unsigned char buf[512], *block;
     232        int off, blocksize;
     233        u32 i, crc = ~0;
     234        size_t len;
     235        struct squashfs_super_block *sb = (struct squashfs_super_block *) buf;
     236
     237        blocksize = mtd->erasesize;
     238        if (blocksize < 0x10000)
     239                blocksize = 0x10000;
     240
     241        for (off = (128*1024); off < size; off += blocksize) {
     242                memset(&trx, 0xe5, sizeof(trx));
     243
     244                /*
     245                 * Read into buffer
     246                 */
     247                if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) ||
     248                    len != sizeof(trx))
     249                        continue;
     250
     251                /* found a TRX header */
     252                if (le32_to_cpu(trx.magic) == TRX_MAGIC) {
     253                        part->offset = le32_to_cpu(trx.offsets[2]) ? :
     254                                le32_to_cpu(trx.offsets[1]);
     255                        part->size = le32_to_cpu(trx.len);
     256
     257                        part->size -= part->offset;
     258                        part->offset += off;
     259
     260                        goto found;
     261                }
     262        }
     263
     264        printk(KERN_NOTICE
     265               "%s: Couldn't find root filesystem\n",
     266               mtd->name);
     267        return -1;
     268
     269 found:
     270        if (part->size == 0)
     271                return 0;
     272       
     273        if (mtd->read(mtd, part->offset, sizeof(buf), &len, buf) || len != sizeof(buf))
     274                return 0;
     275
     276        /* Move the fs outside of the trx */
     277        part->size = 0;
     278
     279        if (trx.len != part->offset + part->size - off) {
     280                /* Update the trx offsets and length */
     281                trx.len = part->offset + part->size - off;
     282       
     283                /* Update the trx crc32 */
     284                for (i = (u32) &(((struct trx_header *)NULL)->flag_version); i <= trx.len; i += sizeof(buf)) {
     285                        if (mtd->read(mtd, off + i, sizeof(buf), &len, buf) || len != sizeof(buf))
     286                                return 0;
     287                        crc = crc32_le(crc, buf, min(sizeof(buf), trx.len - i));
     288                }
     289                trx.crc32 = crc;
     290
     291                /* read first eraseblock from the trx */
     292                block = kmalloc(mtd->erasesize, GFP_KERNEL);
     293                trx2 = (struct trx_header *) block;
     294                if (mtd->read(mtd, off, mtd->erasesize, &len, block) || len != mtd->erasesize) {
     295                        printk("Error accessing the first trx eraseblock\n");
     296                        return 0;
     297                }
     298               
     299                printk("Updating TRX offsets and length:\n");
     300                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);
     301                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);
     302
     303                /* Write updated trx header to the flash */
     304                memcpy(block, &trx, sizeof(trx));
     305                if (mtd->unlock)
     306                        mtd->unlock(mtd, off, mtd->erasesize);
     307                erase_write(mtd, off, mtd->erasesize, block);
     308                if (mtd->sync)
     309                        mtd->sync(mtd);
     310                kfree(block);
     311                printk("Done\n");
     312        }
     313       
     314        return part->size;
     315}
     316
     317struct mtd_partition * __init
     318init_mtd_partitions(struct mtd_info *mtd, size_t size)
     319{
     320        int cfe_size;
     321
     322        if ((cfe_size = find_cfe_size(mtd,size)) < 0)
     323                return NULL;
     324
     325        /* boot loader */
     326        bcm47xx_parts[0].offset = 0;
     327        bcm47xx_parts[0].size   = cfe_size;
     328
     329        /* nvram */
     330        if (cfe_size != 384 * 1024) {
     331                bcm47xx_parts[3].offset = size - ROUNDUP(NVRAM_SPACE, mtd->erasesize);
     332                bcm47xx_parts[3].size   = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
     333        } else {
     334                /* nvram (old 128kb config partition on netgear wgt634u) */
     335                bcm47xx_parts[3].offset = bcm47xx_parts[0].size;
     336                bcm47xx_parts[3].size   = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
     337        }
     338
     339        /* linux (kernel and rootfs) */
     340        if (cfe_size != 384 * 1024) {
     341                bcm47xx_parts[1].offset = bcm47xx_parts[0].size;
     342                bcm47xx_parts[1].size   = bcm47xx_parts[3].offset -
     343                        bcm47xx_parts[1].offset;
     344        } else {
     345                /* do not count the elf loader, which is on one block */
     346                bcm47xx_parts[1].offset = bcm47xx_parts[0].size +
     347                        bcm47xx_parts[3].size + mtd->erasesize;
     348                bcm47xx_parts[1].size   = size -
     349                        bcm47xx_parts[0].size -
     350                        (2*bcm47xx_parts[3].size) -
     351                        mtd->erasesize;
     352        }
     353
     354        /* find and size rootfs */
     355        find_root(mtd,size,&bcm47xx_parts[2]);
     356        bcm47xx_parts[2].size = size - bcm47xx_parts[2].offset - bcm47xx_parts[3].size;
     357
     358        return bcm47xx_parts;
     359}
     360#endif
     361
     362int __init init_bcm47xx_map(void)
     363{
     364#ifdef CONFIG_SSB
     365        struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
     366#endif
     367        size_t size;
     368        int ret = 0;
     369#ifdef CONFIG_MTD_PARTITIONS
     370        struct mtd_partition *parts;
     371        int i;
     372#endif
     373
     374#ifdef CONFIG_SSB
     375        u32 window = mcore->flash_window;
     376        u32 window_size = mcore->flash_window_size;
     377
     378        printk("flash init: 0x%08x 0x%08x\n", window, window_size);
     379        bcm47xx_map.phys = window;
     380        bcm47xx_map.size = window_size;
     381        bcm47xx_map.bankwidth = mcore->flash_buswidth;
     382        bcm47xx_map.virt = ioremap_nocache(window, window_size);
     383#else
     384        printk("flash init: 0x%08x 0x%08x\n", WINDOW_ADDR, WINDOW_SIZE);
     385        bcm47xx_map.virt = ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
     386#endif
     387
     388        if (!bcm47xx_map.virt) {
     389                printk("Failed to ioremap\n");
     390                return -EIO;
     391        }
     392
     393        simple_map_init(&bcm47xx_map);
     394       
     395        if (!(bcm47xx_mtd = do_map_probe("cfi_probe", &bcm47xx_map))) {
     396                printk("Failed to do_map_probe\n");
     397                iounmap((void *)bcm47xx_map.virt);
     398                return -ENXIO;
     399        }
     400
     401        /* override copy_from routine */
     402        bcm47xx_map.copy_from = bcm47xx_map_copy_from;
     403
     404        bcm47xx_mtd->owner = THIS_MODULE;
     405
     406        size = bcm47xx_mtd->size;
     407
     408        printk(KERN_NOTICE "Flash device: 0x%x at 0x%x\n", size, WINDOW_ADDR);
     409
     410#ifdef CONFIG_MTD_PARTITIONS
     411        parts = init_mtd_partitions(bcm47xx_mtd, size);
     412        for (i = 0; parts[i].name; i++);
     413        ret = add_mtd_partitions(bcm47xx_mtd, parts, i);
     414        if (ret) {
     415                printk(KERN_ERR "Flash: add_mtd_partitions failed\n");
     416                goto fail;
     417        }
     418#endif
     419        return 0;
     420
     421 fail:
     422        if (bcm47xx_mtd)
     423                map_destroy(bcm47xx_mtd);
     424        if (bcm47xx_map.virt)
     425                iounmap((void *)bcm47xx_map.virt);
     426        bcm47xx_map.virt = 0;
     427        return ret;
     428}
     429
     430void __exit cleanup_bcm47xx_map(void)
     431{
     432#ifdef CONFIG_MTD_PARTITIONS
     433        del_mtd_partitions(bcm47xx_mtd);
     434#endif
     435        map_destroy(bcm47xx_mtd);
     436        iounmap((void *)bcm47xx_map.virt);
     437}
     438
     439module_init(init_bcm47xx_map);
     440module_exit(cleanup_bcm47xx_map);
  • drivers/net/b44.c

    diff --git a/drivers/net/b44.c b/drivers/net/b44.c
    index b70b81e..2508e77 100644
    a b static int b44_phy_reset(struct b44 *bp)  
    339339                }
    340340        }
    341341
    342         return 0;
     342        return err;
    343343}
    344344
    345345static void __b44_set_flow_ctrl(struct b44 *bp, u32 pause_flags)
    static int b44_rx(struct b44 *bp, int budget)  
    815815                        struct sk_buff *copy_skb;
    816816
    817817                        b44_recycle_rx(bp, cons, bp->rx_prod);
    818                         copy_skb = dev_alloc_skb(len + 2);
     818                        copy_skb = netdev_alloc_skb(bp->dev, len + 2);
    819819                        if (copy_skb == NULL)
    820820                                goto drop_it_no_recycle;
    821821
    static int __devinit b44_init_one(struct ssb_device *sdev,  
    22202220         */
    22212221        b44_chip_reset(bp, B44_CHIP_RESET_FULL);
    22222222
     2223        /* do a phy reset to test if there is an active phy */
     2224        if (b44_phy_reset(bp) < 0)
     2225                bp->phy_addr = B44_PHY_ADDR_NO_PHY;
     2226
    22232227        printk(KERN_INFO "%s: Broadcom 44xx/47xx 10/100BaseT Ethernet %pM\n",
    22242228               dev->name, dev->dev_addr);
    22252229
  • drivers/net/tg3.c

    diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
    index 201be42..70b7c7b 100644
    a b  
    4141#include <linux/prefetch.h>
    4242#include <linux/dma-mapping.h>
    4343#include <linux/firmware.h>
     44#include <linux/ssb/ssb_driver_gige.h>
    4445
    4546#include <net/checksum.h>
    4647#include <net/ip.h>
    static void _tw32_flush(struct tg3 *tp, u32 off, u32 val, u32 usec_wait)  
    446447static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val)
    447448{
    448449        tp->write32_mbox(tp, off, val);
    449         if (!(tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) &&
    450             !(tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND))
     450        if ((tp->tg3_flags3 & TG3_FLG3_FLUSH_POSTED_WRITES) ||
     451            (!(tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) &&
     452             !(tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND)))
    451453                tp->read32_mbox(tp, off);
    452454}
    453455
    static void tg3_write32_tx_mbox(struct tg3 *tp, u32 off, u32 val)  
    457459        writel(val, mbox);
    458460        if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG)
    459461                writel(val, mbox);
    460         if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
     462        if ((tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) || (tp->tg3_flags3 & TG3_FLG3_FLUSH_POSTED_WRITES))
    461463                readl(mbox);
    462464}
    463465
    static void tg3_switch_clocks(struct tg3 *tp)  
    729731
    730732#define PHY_BUSY_LOOPS  5000
    731733
    732 static int tg3_readphy(struct tg3 *tp, int reg, u32 *val)
     734static int __tg3_readphy(struct tg3 *tp, unsigned int phy_addr, int reg, u32 *val)
    733735{
    734736        u32 frame_val;
    735737        unsigned int loops;
    static int tg3_readphy(struct tg3 *tp, int reg, u32 *val)  
    743745
    744746        *val = 0x0;
    745747
    746         frame_val  = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) &
     748        frame_val  = ((phy_addr << MI_COM_PHY_ADDR_SHIFT) &
    747749                      MI_COM_PHY_ADDR_MASK);
    748750        frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
    749751                      MI_COM_REG_ADDR_MASK);
    static int tg3_readphy(struct tg3 *tp, int reg, u32 *val)  
    778780        return ret;
    779781}
    780782
    781 static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
     783static int tg3_readphy(struct tg3 *tp, int reg, u32 *val)
     784{
     785        return __tg3_readphy(tp, PHY_ADDR, reg, val);
     786}
     787
     788static int __tg3_writephy(struct tg3 *tp, unsigned int phy_addr, int reg, u32 val)
    782789{
    783790        u32 frame_val;
    784791        unsigned int loops;
    static int tg3_writephy(struct tg3 *tp, int reg, u32 val)  
    794801                udelay(80);
    795802        }
    796803
    797         frame_val  = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) &
     804        frame_val  = ((phy_addr << MI_COM_PHY_ADDR_SHIFT) &
    798805                      MI_COM_PHY_ADDR_MASK);
    799806        frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
    800807                      MI_COM_REG_ADDR_MASK);
    static int tg3_writephy(struct tg3 *tp, int reg, u32 val)  
    827834        return ret;
    828835}
    829836
     837static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
     838{
     839        return __tg3_writephy(tp, PHY_ADDR, reg, val);
     840}
     841
    830842static int tg3_bmcr_reset(struct tg3 *tp)
    831843{
    832844        u32 phy_control;
    static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val)  
    22622274{
    22632275        int ret;
    22642276
     2277        if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE)
     2278                return -ENODEV;
     2279
    22652280        if (!(tp->tg3_flags & TG3_FLAG_NVRAM))
    22662281                return tg3_nvram_read_using_eeprom(tp, offset, val);
    22672282
    static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)  
    25952610        tg3_frob_aux_power(tp);
    25962611
    25972612        /* Workaround for unstable PLL clock */
    2598         if ((GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX) ||
    2599             (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX)) {
     2613        if ((tp->phy_id & PHY_ID_MASK != PHY_ID_BCM5750_2) &&
     2614                                /* !!! FIXME !!! */
     2615            ((GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX) ||
     2616            (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX))) {
    26002617                u32 val = tr32(0x7d00);
    26012618
    26022619                val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1);
    relink:  
    30883105
    30893106                tg3_phy_copper_begin(tp);
    30903107
     3108                if (tp->tg3_flags3 & TG3_FLG3_ROBOSWITCH) {
     3109                        current_link_up = 1;
     3110                        current_speed = SPEED_1000; //FIXME
     3111                        current_duplex = DUPLEX_FULL;
     3112                        tp->link_config.active_speed = current_speed;
     3113                        tp->link_config.active_duplex = current_duplex;
     3114                }
     3115
    30913116                tg3_readphy(tp, MII_BMSR, &tmp);
    30923117                if (!tg3_readphy(tp, MII_BMSR, &tmp) &&
    30933118                    (tmp & BMSR_LSTATUS))
    static int tg3_poll_fw(struct tg3 *tp)  
    60006025        int i;
    60016026        u32 val;
    60026027
     6028        if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE) {
     6029                /* We don't use firmware. */
     6030                return 0;
     6031        }
     6032
    60036033        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
    60046034                /* Wait up to 20ms for init done. */
    60056035                for (i = 0; i < 200; i++) {
    static int tg3_chip_reset(struct tg3 *tp)  
    62566286                tw32(0x5000, 0x400);
    62576287        }
    62586288
     6289        if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE) {
     6290                /* BCM4785: In order to avoid repercussions from using potentially
     6291                 * defective internal ROM, stop the Rx RISC CPU, which is not
     6292                 * required. */
     6293                tg3_stop_fw(tp);
     6294                tg3_halt_cpu(tp, RX_CPU_BASE);
     6295        }
     6296
    62596297        tw32(GRC_MODE, tp->grc_mode);
    62606298
    62616299        if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) {
    static int tg3_halt_cpu(struct tg3 *tp, u32 offset)  
    64066444                return -ENODEV;
    64076445        }
    64086446
    6409         /* Clear firmware's nvram arbitration. */
    6410         if (tp->tg3_flags & TG3_FLAG_NVRAM)
    6411                 tw32(NVRAM_SWARB, SWARB_REQ_CLR0);
     6447        if (!(tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE)) {
     6448                /* Clear firmware's nvram arbitration. */
     6449                if (tp->tg3_flags & TG3_FLAG_NVRAM)
     6450                        tw32(NVRAM_SWARB, SWARB_REQ_CLR0);
     6451        }
     6452
    64126453        return 0;
    64136454}
    64146455
    static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)  
    64716512        const __be32 *fw_data;
    64726513        int err, i;
    64736514
     6515        if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE) {
     6516                /* We don't use firmware. */
     6517                return 0;
     6518        }
     6519
    64746520        fw_data = (void *)tp->fw->data;
    64756521
    64766522        /* Firmware blob starts with version numbers, followed by
    static int tg3_load_tso_firmware(struct tg3 *tp)  
    65306576        unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size;
    65316577        int err, i;
    65326578
     6579        if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE) {
     6580                /* We don't use firmware. */
     6581                return 0;
     6582        }
     6583
    65336584        if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
    65346585                return 0;
    65356586
    static void tg3_timer(unsigned long __opaque)  
    74357486
    74367487        spin_lock(&tp->lock);
    74377488
     7489        if (tp->tg3_flags3 & TG3_FLG3_FLUSH_POSTED_WRITES) {
     7490                /* BCM4785: Flush posted writes from GbE to host memory. */
     7491                tr32(HOSTCC_MODE);
     7492        }
     7493
    74387494        if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
    74397495                /* All of this garbage is because when using non-tagged
    74407496                 * IRQ status the mailbox/status_block protocol the chip
    static int tg3_test_nvram(struct tg3 *tp)  
    92019257        __be32 *buf;
    92029258        int i, j, k, err = 0, size;
    92039259
     9260        if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE) {
     9261                /* We don't have NVRAM. */
     9262                return 0;
     9263        }
     9264
    92049265        if (tg3_nvram_read(tp, 0, &magic) != 0)
    92059266                return -EIO;
    92069267
    static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)  
    999410055                        return -EAGAIN;
    999510056
    999610057                spin_lock_bh(&tp->lock);
    9997                 err = tg3_readphy(tp, data->reg_num & 0x1f, &mii_regval);
     10058                err = __tg3_readphy(tp, data->phy_id & 0x1f, data->reg_num & 0x1f, &mii_regval);
    999810059                spin_unlock_bh(&tp->lock);
    999910060
    1000010061                data->val_out = mii_regval;
    static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)  
    1001310074                        return -EAGAIN;
    1001410075
    1001510076                spin_lock_bh(&tp->lock);
    10016                 err = tg3_writephy(tp, data->reg_num & 0x1f, data->val_in);
     10077                err = __tg3_writephy(tp, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
    1001710078                spin_unlock_bh(&tp->lock);
    1001810079
    1001910080                return err;
    static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp)  
    1060110662/* Chips other than 5700/5701 use the NVRAM for fetching info. */
    1060210663static void __devinit tg3_nvram_init(struct tg3 *tp)
    1060310664{
     10665        if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE) {
     10666                /* No NVRAM and EEPROM on the SSB Broadcom GigE core. */
     10667                tp->tg3_flags &= ~(TG3_FLAG_NVRAM | TG3_FLAG_NVRAM_BUFFERED);
     10668                return;
     10669        }
     10670
    1060410671        tw32_f(GRC_EEPROM_ADDR,
    1060510672             (EEPROM_ADDR_FSM_RESET |
    1060610673              (EEPROM_DEFAULT_CLOCK_PERIOD <<
    static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf)  
    1085910926{
    1086010927        int ret;
    1086110928
     10929        if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE)
     10930                return -ENODEV;
     10931
    1086210932        if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) {
    1086310933                tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl &
    1086410934                       ~GRC_LCLCTRL_GPIO_OUTPUT1);
    static int __devinit tg3_get_invariants(struct tg3 *tp)  
    1206312133                tp->write32 = tg3_write_flush_reg32;
    1206412134        }
    1206512135
    12066 
    1206712136        if ((tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) ||
    1206812137            (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)) {
    1206912138                tp->write32_tx_mbox = tg3_write32_tx_mbox;
    static int __devinit tg3_get_invariants(struct tg3 *tp)  
    1209912168              GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)))
    1210012169                tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG;
    1210112170
     12171        if (tp->tg3_flags3 & TG3_FLG3_FLUSH_POSTED_WRITES) {
     12172                tp->write32_tx_mbox = tg3_write_flush_reg32;
     12173                tp->write32_rx_mbox = tg3_write_flush_reg32;
     12174        }
     12175
    1210212176        /* Get eeprom hw config before calling tg3_set_power_state().
    1210312177         * In particular, the TG3_FLG2_IS_NIC flag must be
    1210412178         * determined before calling tg3_set_power_state() so that
    static int __devinit tg3_get_device_address(struct tg3 *tp)  
    1247412548        }
    1247512549
    1247612550        if (!is_valid_ether_addr(&dev->dev_addr[0])) {
     12551                if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE)
     12552                        ssb_gige_get_macaddr(tp->pdev, &dev->dev_addr[0]);
     12553        }
     12554        if (!is_valid_ether_addr(&dev->dev_addr[0])) {
    1247712555#ifdef CONFIG_SPARC
    1247812556                if (!tg3_get_default_macaddr_sparc(tp))
    1247912557                        return 0;
    static char * __devinit tg3_phy_string(struct tg3 *tp)  
    1296513043        case PHY_ID_BCM5704:    return "5704";
    1296613044        case PHY_ID_BCM5705:    return "5705";
    1296713045        case PHY_ID_BCM5750:    return "5750";
     13046        case PHY_ID_BCM5750_2:  return "5750-2";
    1296813047        case PHY_ID_BCM5752:    return "5752";
    1296913048        case PHY_ID_BCM5714:    return "5714";
    1297013049        case PHY_ID_BCM5780:    return "5780";
    static int __devinit tg3_init_one(struct pci_dev *pdev,  
    1317513254                tp->msg_enable = tg3_debug;
    1317613255        else
    1317713256                tp->msg_enable = TG3_DEF_MSG_ENABLE;
     13257        if (pdev_is_ssb_gige_core(pdev)) {
     13258                tp->tg3_flags3 |= TG3_FLG3_IS_SSB_CORE;
     13259                if (ssb_gige_must_flush_posted_writes(pdev))
     13260                        tp->tg3_flags3 |= TG3_FLG3_FLUSH_POSTED_WRITES;
     13261                if (ssb_gige_have_roboswitch(pdev))
     13262                        tp->tg3_flags3 |= TG3_FLG3_ROBOSWITCH;
     13263        }
    1317813264
    1317913265        /* The word/byte swap controls here control register access byte
    1318013266         * swapping.  DMA data byte swapping is controlled in the GRC_MODE
  • drivers/net/tg3.h

    diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
    index cb4c62a..5364876 100644
    a b  
    18491849#define  NIC_SRAM_RGMII_STD_IBND_DISABLE 0x00000004
    18501850#define  NIC_SRAM_RGMII_EXT_IBND_RX_EN   0x00000008
    18511851#define  NIC_SRAM_RGMII_EXT_IBND_TX_EN   0x00000010
     1852#define TG3_FLG3_IS_SSB_CORE            0x00000800
     1853#define TG3_FLG3_FLUSH_POSTED_WRITES    0x00001000
     1854#define TG3_FLG3_ROBOSWITCH             0x00002000
    18521855
    18531856#define NIC_SRAM_RX_MINI_BUFFER_DESC    0x00001000
    18541857
    struct tg3 {  
    26952698#define PHY_ID_BCM5714                  0x60008340
    26962699#define PHY_ID_BCM5780                  0x60008350
    26972700#define PHY_ID_BCM5755                  0xbc050cc0
     2701#define PHY_ID_BCM5750_2                0xbc050cd0
    26982702#define PHY_ID_BCM5787                  0xbc050ce0
    26992703#define PHY_ID_BCM5756                  0xbc050ed0
    27002704#define PHY_ID_BCM5784                  0xbc050fa0
    struct tg3 {  
    27392743         (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \
    27402744         (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM5756 || \
    27412745         (X) == PHY_ID_BCM5906 || (X) == PHY_ID_BCM5761 || \
    2742          (X) == PHY_ID_BCM8002)
     2746         (X) == PHY_ID_BCM8002 || (X) == PHY_ID_BCM5750_2)
    27432747
    27442748        struct tg3_hw_stats             *hw_stats;
    27452749        dma_addr_t                      stats_mapping;
  • drivers/ssb/Kconfig

    diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig
    index 540a294..6c2f443 100644
    a b config SSB_DRIVER_MIPS  
    126126config SSB_EMBEDDED
    127127        bool
    128128        depends on SSB_DRIVER_MIPS
     129        select USB_EHCI_HCD_SSB
     130        select USB_OHCI_HCD_SSB
    129131        default y
    130132
    131133config SSB_DRIVER_EXTIF
  • drivers/ssb/driver_chipcommon.c

    diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c
    index 9681536..7a26028 100644
    a b void ssb_chipco_resume(struct ssb_chipcommon *cc)  
    258258void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
    259259                             u32 *plltype, u32 *n, u32 *m)
    260260{
     261        if ((chipco_read32(cc, SSB_CHIPCO_CHIPID) & SSB_CHIPCO_IDMASK) == 0x5354)
     262                return;
    261263        *n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N);
    262264        *plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
    263265        switch (*plltype) {
    void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,  
    281283void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,
    282284                                 u32 *plltype, u32 *n, u32 *m)
    283285{
     286        if ((chipco_read32(cc, SSB_CHIPCO_CHIPID) & SSB_CHIPCO_IDMASK) == 0x5354)
     287                return;
    284288        *n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N);
    285289        *plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
    286290        switch (*plltype) {
  • drivers/ssb/driver_mipscore.c

    diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c
    index 3fd3e3b..f30186d 100644
    a b static const u32 ipsflag_irq_shift[] = {  
    4949
    5050static inline u32 ssb_irqflag(struct ssb_device *dev)
    5151{
    52         return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG;
     52        u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
     53        if (tpsflag)
     54                return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG;
     55        else
     56                /* not irq supported */
     57                return 0x3f;
     58}
     59
     60static struct ssb_device *find_device(struct ssb_device *rdev, int irqflag)
     61{
     62        struct ssb_bus *bus = rdev->bus;
     63        int i;
     64        for (i = 0; i < bus->nr_devices; i++) {
     65                struct ssb_device *dev;
     66                dev = &(bus->devices[i]);
     67                if (ssb_irqflag(dev) == irqflag)
     68                        return dev;
     69        }
     70        return NULL;
    5371}
    5472
    5573/* Get the MIPS IRQ assignment for a specified device.
    5674 * If unassigned, 0 is returned.
     75 * If disabled, 5 is returned.
     76 * If not supported, 6 is returned.
    5777 */
    5878unsigned int ssb_mips_irq(struct ssb_device *dev)
    5979{
    6080        struct ssb_bus *bus = dev->bus;
     81        struct ssb_device *mdev = bus->mipscore.dev;
    6182        u32 irqflag;
    6283        u32 ipsflag;
    6384        u32 tmp;
    6485        unsigned int irq;
    6586
    6687        irqflag = ssb_irqflag(dev);
     88        if (irqflag == 0x3f)
     89                return 6;
    6790        ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG);
    6891        for (irq = 1; irq <= 4; irq++) {
    6992                tmp = ((ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]);
    7093                if (tmp == irqflag)
    7194                        break;
    7295        }
    73         if (irq == 5)
    74                 irq = 0;
     96        if (irq == 5) {
     97                if ((1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))
     98                        irq = 0;
     99        }
    75100
    76101        return irq;
    77102}
    static void set_irq(struct ssb_device *dev, unsigned int irq)  
    97122        struct ssb_device *mdev = bus->mipscore.dev;
    98123        u32 irqflag = ssb_irqflag(dev);
    99124
     125        BUG_ON(oldirq == 6);
     126
    100127        dev->irq = irq + 2;
    101128
    102         ssb_dprintk(KERN_INFO PFX
    103                     "set_irq: core 0x%04x, irq %d => %d\n",
    104                     dev->id.coreid, oldirq, irq);
    105129        /* clear the old irq */
    106130        if (oldirq == 0)
    107131                ssb_write32(mdev, SSB_INTVEC, (~(1 << irqflag) & ssb_read32(mdev, SSB_INTVEC)));
    108         else
     132        else if (oldirq != 5)
    109133                clear_irq(bus, oldirq);
    110134
    111135        /* assign the new one */
    112136        if (irq == 0) {
    113137                ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) | ssb_read32(mdev, SSB_INTVEC)));
    114138        } else {
     139                u32 ipsflag = ssb_read32(mdev, SSB_IPSFLAG);
     140                if ((ipsflag & ipsflag_irq_mask[irq]) != ipsflag_irq_mask[irq]) {
     141                        u32 oldipsflag = (ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq];
     142                        struct ssb_device *olddev = find_device(dev, oldipsflag);
     143                        if (olddev)
     144                                set_irq(olddev, 0);
     145                }
    115146                irqflag <<= ipsflag_irq_shift[irq];
    116                 irqflag |= (ssb_read32(mdev, SSB_IPSFLAG) & ~ipsflag_irq_mask[irq]);
     147                irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]);
    117148                ssb_write32(mdev, SSB_IPSFLAG, irqflag);
    118149        }
     150        ssb_dprintk(KERN_INFO PFX
     151                    "set_irq: core 0x%04x, irq %d => %d\n",
     152                    dev->id.coreid, oldirq+2, irq+2);
     153}
     154
     155static void print_irq(struct ssb_device *dev, unsigned int irq)
     156{
     157        int i;
     158        static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
     159        ssb_dprintk(KERN_INFO PFX
     160                "core 0x%04x, irq :", dev->id.coreid);
     161        for (i = 0; i <= 6; i++) {
     162                ssb_dprintk(" %s%s", irq_name[i], i==irq?"*":" ");
     163        }
     164        ssb_dprintk("\n");
     165}
     166
     167static void dump_irq(struct ssb_bus *bus)
     168{
     169        int i;
     170        for (i = 0; i < bus->nr_devices; i++) {
     171                struct ssb_device *dev;
     172                dev = &(bus->devices[i]);
     173                print_irq(dev, ssb_mips_irq(dev));
     174        }
    119175}
    120176
    121177static void ssb_mips_serial_init(struct ssb_mipscore *mcore)
    u32 ssb_cpu_clock(struct ssb_mipscore *mcore)  
    161217
    162218        if ((pll_type == SSB_PLLTYPE_5) || (bus->chip_id == 0x5365)) {
    163219                rate = 200000000;
     220        } else if (bus->chip_id == 0x5354) {
     221                rate = 240000000;
    164222        } else {
    165223                rate = ssb_calc_clock_rate(pll_type, n, m);
    166224        }
    void ssb_mipscore_init(struct ssb_mipscore *mcore)  
    195253        else if (bus->chipco.dev)
    196254                ssb_chipco_timing_init(&bus->chipco, ns);
    197255
     256        dump_irq(bus);
    198257        /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */
    199258        for (irq = 2, i = 0; i < bus->nr_devices; i++) {
     259                int mips_irq;
    200260                dev = &(bus->devices[i]);
    201                 dev->irq = ssb_mips_irq(dev) + 2;
     261                mips_irq = ssb_mips_irq(dev);
     262                if (mips_irq > 4)
     263                        dev->irq = 0;
     264                else
     265                        dev->irq = mips_irq + 2;
     266                if (dev->irq > 5)
     267                        continue;
    202268                switch (dev->id.coreid) {
    203269                case SSB_DEV_USB11_HOST:
    204270                        /* shouldn't need a separate irq line for non-4710, most of them have a proper
    205271                         * external usb controller on the pci */
    206272                        if ((bus->chip_id == 0x4710) && (irq <= 4)) {
    207273                                set_irq(dev, irq++);
    208                                 break;
    209274                        }
     275                        break;
    210276                        /* fallthrough */
    211277                case SSB_DEV_PCI:
    212278                case SSB_DEV_ETHERNET:
    void ssb_mipscore_init(struct ssb_mipscore *mcore)  
    220286                        }
    221287                }
    222288        }
     289        ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n");
     290        dump_irq(bus);
    223291
    224292        ssb_mips_serial_init(mcore);
    225293        ssb_mips_flash_detect(mcore);
  • drivers/ssb/main.c

    diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
    index 65a1ed9..4705122 100644
    a b u32 ssb_clockspeed(struct ssb_bus *bus)  
    10101010
    10111011        if (bus->chip_id == 0x5365) {
    10121012                rate = 100000000;
     1013        } else if (bus->chip_id == 0x5354) {
     1014                rate = 120000000;
    10131015        } else {
    10141016                rate = ssb_calc_clock_rate(plltype, clkctl_n, clkctl_m);
    10151017                if (plltype == SSB_PLLTYPE_3) /* 25Mhz, 2 dividers */
  • drivers/usb/host/Kconfig

    diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
    index 845479f..59f8079 100644
    a b config USB_OXU210HP_HCD  
    106106          To compile this driver as a module, choose M here: the
    107107          module will be called oxu210hp-hcd.
    108108
     109config USB_EHCI_HCD_SSB
     110        bool "EHCI support for Broadcom SSB EHCI core"
     111        depends on USB_EHCI_HCD && SSB && EXPERIMENTAL
     112        default n
     113        ---help---
     114          Support for the Sonics Silicon Backplane (SSB) attached
     115          Broadcom USB EHCI core.
     116
     117          This device is present in some embedded devices with
     118          Broadcom based SSB bus.
     119
     120          If unsure, say N.
     121
    109122config USB_ISP116X_HCD
    110123        tristate "ISP116X HCD support"
    111124        depends on USB
  • drivers/usb/host/ehci-hcd.c

    diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
    index c637207..5c248d9 100644
    a b MODULE_LICENSE ("GPL");  
    10721072#define PLATFORM_DRIVER         ixp4xx_ehci_driver
    10731073#endif
    10741074
    1075 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
    1076     !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER)
     1075#ifdef CONFIG_USB_EHCI_HCD_SSB
     1076#include "ehci-ssb.c"
     1077#define SSB_EHCI_DRIVER         ssb_ehci_driver
     1078#endif
     1079
     1080#if !defined(PCI_DRIVER) && \
     1081    !defined(PLATFORM_DRIVER) && \
     1082    !defined(PS3_SYSTEM_BUS_DRIVER) && \
     1083    !defined(OF_PLATFORM_DRIVER) && \
     1084    !defined(SSB_EHCI_DRIVER)
    10771085#error "missing bus glue for ehci-hcd"
    10781086#endif
    10791087
  • new file drivers/usb/host/ehci-ssb.c

    diff --git a/drivers/usb/host/ehci-ssb.c b/drivers/usb/host/ehci-ssb.c
    new file mode 100644
    index 0000000..be90a5c
    - +  
     1/*
     2 * Sonics Silicon Backplane
     3 * Broadcom USB-core EHCI driver (SSB bus glue)
     4 *
     5 * Copyright 2007 Steven Brown <sbrown@cortland.com>
     6 *
     7 * Derived from the OHCI-SSB driver
     8 * Copyright 2007 Michael Buesch <mb@bu3sch.de>
     9 *
     10 * Derived from the EHCI-PCI driver
     11 * Copyright (c) 2000-2004 by David Brownell
     12 *
     13 * Derived from the OHCI-PCI driver
     14 * Copyright 1999 Roman Weissgaerber
     15 * Copyright 2000-2002 David Brownell
     16 * Copyright 1999 Linus Torvalds
     17 * Copyright 1999 Gregory P. Smith
     18 *
     19 * Derived from the USBcore related parts of Broadcom-SB
     20 * Copyright 2005 Broadcom Corporation
     21 *
     22 * Licensed under the GNU/GPL. See COPYING for details.
     23 */
     24#include <linux/ssb/ssb.h>
     25
     26#define SSB_OHCI_TMSLOW_HOSTMODE        (1 << 29)
     27
     28struct ssb_ehci_device {
     29        struct ehci_hcd ehci; /* _must_ be at the beginning. */
     30
     31        u32 enable_flags;
     32};
     33
     34static inline
     35struct ssb_ehci_device *hcd_to_ssb_ehci(struct usb_hcd *hcd)
     36{
     37        return (struct ssb_ehci_device *)(hcd->hcd_priv);
     38}
     39
     40
     41static int ssb_ehci_reset(struct usb_hcd *hcd)
     42{
     43        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
     44        int err;
     45
     46        ehci->caps = hcd->regs;
     47        ehci->regs = hcd->regs +
     48                HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
     49
     50        dbg_hcs_params(ehci, "reset");
     51        dbg_hcc_params(ehci, "reset");
     52
     53        ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
     54
     55        err = ehci_halt(ehci);
     56
     57        if (err)
     58                return err;
     59
     60        err = ehci_init(hcd);
     61
     62        if (err)
     63                return err;
     64
     65        ehci_port_power(ehci, 0);
     66
     67        return err;
     68}
     69
     70static int ssb_ehci_start(struct usb_hcd *hcd)
     71{
     72        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
     73        int err;
     74
     75        err = ehci_run(hcd);
     76        if (err < 0) {
     77                ehci_err(ehci, "can't start\n");
     78                ehci_stop(hcd);
     79        }
     80
     81        return err;
     82}
     83
     84#ifdef CONFIG_PM
     85static int ssb_ehci_hcd_suspend(struct usb_hcd *hcd, pm_message_t message)
     86{
     87        struct ssb_ehci_device *ehcidev = hcd_to_ssb_ehci(hcd);
     88        struct ehci_hcd *ehci = &ehcidev->ehci;
     89        unsigned long flags;
     90
     91        spin_lock_irqsave(&ehci->lock, flags);
     92
     93        ehci_writel(ehci, EHCI_INTR_MIE, &ehci->regs->intrdisable);
     94        ehci_readl(ehci, &ehci->regs->intrdisable); /* commit write */
     95
     96        /* make sure snapshot being resumed re-enumerates everything */
     97        if (message.event == PM_EVENT_PRETHAW)
     98                ehci_usb_reset(ehci);
     99
     100        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
     101
     102        spin_unlock_irqrestore(&ehci->lock, flags);
     103        return 0;
     104}
     105
     106static int ssb_ehci_hcd_resume(struct usb_hcd *hcd)
     107{
     108        set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
     109        usb_hcd_resume_root_hub(hcd);
     110        return 0;
     111}
     112#endif /* CONFIG_PM */
     113
     114static const struct hc_driver ssb_ehci_hc_driver = {
     115        .description            = "ssb-usb-ehci",
     116        .product_desc           = "SSB EHCI Controller",
     117        .hcd_priv_size          = sizeof(struct ssb_ehci_device),
     118
     119        .irq                    = ehci_irq,
     120        .flags                  = HCD_MEMORY | HCD_USB2,
     121
     122        .reset                  = ssb_ehci_reset,
     123        .start                  = ssb_ehci_start,
     124        .stop                   = ehci_stop,
     125        .shutdown               = ehci_shutdown,
     126
     127#ifdef CONFIG_PM
     128        .suspend                = ssb_ehci_hcd_suspend,
     129        .resume                 = ssb_ehci_hcd_resume,
     130#endif
     131
     132        .urb_enqueue            = ehci_urb_enqueue,
     133        .urb_dequeue            = ehci_urb_dequeue,
     134        .endpoint_disable       = ehci_endpoint_disable,
     135
     136        .get_frame_number       = ehci_get_frame,
     137
     138        .hub_status_data        = ehci_hub_status_data,
     139        .hub_control            = ehci_hub_control,
     140#ifdef CONFIG_PM
     141        .bus_suspend            = ehci_bus_suspend,
     142        .bus_resume             = ehci_bus_resume,
     143#endif
     144
     145};
     146
     147static void ssb_ehci_detach(struct ssb_device *dev, struct usb_hcd *hcd)
     148{
     149
     150        usb_remove_hcd(hcd);
     151        iounmap(hcd->regs);
     152        usb_put_hcd(hcd);
     153}
     154EXPORT_SYMBOL_GPL(ssb_ehci_detach);
     155
     156static int ssb_ehci_attach(struct ssb_device *dev, struct usb_hcd **ehci_hcd)
     157{
     158        struct ssb_ehci_device *ehcidev;
     159        struct usb_hcd *hcd;
     160        int err = -ENOMEM;
     161        u32 tmp, flags = 0;
     162
     163        hcd = usb_create_hcd(&ssb_ehci_hc_driver, dev->dev,
     164                dev_name(dev->dev));
     165        if (!hcd)
     166                goto err_dev_disable;
     167
     168        ehcidev = hcd_to_ssb_ehci(hcd);
     169        ehcidev->enable_flags = flags;
     170        tmp = ssb_read32(dev, SSB_ADMATCH0);
     171        hcd->rsrc_start = ssb_admatch_base(tmp) + 0x800; /* ehci core offset */
     172        hcd->rsrc_len = 0x100; /* ehci reg block size */
     173        /*
     174         * start & size modified per sbutils.c
     175         */
     176        hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
     177        if (!hcd->regs)
     178                goto err_put_hcd;
     179        err = usb_add_hcd(hcd, dev->irq, IRQF_SHARED | IRQF_DISABLED);
     180        if (err)
     181                goto err_iounmap;
     182
     183        *ehci_hcd = hcd;
     184
     185        return err;
     186
     187err_iounmap:
     188        iounmap(hcd->regs);
     189err_put_hcd:
     190        usb_put_hcd(hcd);
     191err_dev_disable:
     192        ssb_device_disable(dev, flags);
     193        return err;
     194}
     195EXPORT_SYMBOL_GPL(ssb_ehci_attach);
     196
     197static const struct ssb_device_id ssb_ehci_table[] = {
     198        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
     199        SSB_DEVTABLE_END
     200};
     201MODULE_DEVICE_TABLE(ssb, ssb_ehci_table);
  • drivers/usb/host/ohci-ssb.c

    diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c
    index 23fd6a8..599f7b5 100644
    a b  
    1717 */
    1818#include <linux/ssb/ssb.h>
    1919
     20extern int ssb_ehci_attach(struct ssb_device *dev, struct usb_hcd **hcd);
     21extern void ssb_ehci_detach(struct ssb_device *dev, struct usb_hcd *hcd);
    2022
    2123#define SSB_OHCI_TMSLOW_HOSTMODE        (1 << 29)
    2224
    struct ssb_ohci_device {  
    2426        struct ohci_hcd ohci; /* _must_ be at the beginning. */
    2527
    2628        u32 enable_flags;
     29        struct usb_hcd *ehci_hcd;
    2730};
    2831
    2932static inline
    static const struct hc_driver ssb_ohci_hc_driver = {  
    9295static void ssb_ohci_detach(struct ssb_device *dev)
    9396{
    9497        struct usb_hcd *hcd = ssb_get_drvdata(dev);
     98#ifdef CONFIG_USB_EHCI_HCD_SSB
     99        struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
     100#endif
    95101
    96102        usb_remove_hcd(hcd);
    97103        iounmap(hcd->regs);
    98104        usb_put_hcd(hcd);
     105
     106#ifdef CONFIG_USB_EHCI_HCD_SSB
     107        /*
     108         * Also detach ehci function
     109         */
     110        if (dev->id.coreid == SSB_DEV_USB20_HOST)
     111                ssb_ehci_detach(dev, ohcidev->ehci_hcd);
     112#endif
    99113        ssb_device_disable(dev, 0);
    100114}
    101115
     116
    102117static int ssb_ohci_attach(struct ssb_device *dev)
    103118{
    104119        struct ssb_ohci_device *ohcidev;
    static int ssb_ohci_attach(struct ssb_device *dev)  
    106121        int err = -ENOMEM;
    107122        u32 tmp, flags = 0;
    108123
    109         if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV)
     124        /*
     125         * THE FOLLOWING COMMENTS PRESERVED FROM GPL SOURCE RELEASE
     126         *
     127         * The USB core requires a special bit to be set during core
     128         * reset to enable host (OHCI) mode. Resetting the SB core in
     129         * pcibios_enable_device() is a hack for compatibility with
     130         * vanilla usb-ohci so that it does not have to know about
     131         * SB. A driver that wants to use the USB core in device mode
     132         * should know about SB and should reset the bit back to 0
     133         * after calling pcibios_enable_device().
     134         */
     135
     136        if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
    110137                flags |= SSB_OHCI_TMSLOW_HOSTMODE;
     138                ssb_device_enable(dev, flags);
     139        }
     140
     141        /*
     142         * USB 2.0 special considerations:
     143         *
     144         * 1. Since the core supports both OHCI and EHCI functions, it must
     145         *    only be reset once.
     146         *
     147         * 2. In addition to the standard SB reset sequence, the Host Control
     148         *    Register must be programmed to bring the USB core and various
     149         *    phy components out of reset.
     150         */
     151
     152        else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
     153#warning FIX ME need test for core being up & exit
     154                ssb_device_enable(dev, 0);
     155                ssb_write32(dev, 0x200, 0x7ff);
     156                udelay(1);
     157                if (dev->id.revision == 1) { // bug in rev 1
     158
     159                        /* Change Flush control reg */
     160                        tmp = ssb_read32(dev, 0x400);
     161                        tmp &= ~8;
     162                        ssb_write32(dev, 0x400, tmp);
     163                        tmp = ssb_read32(dev, 0x400);
     164                        printk("USB20H fcr: 0x%0x\n", tmp);
     165
     166                        /* Change Shim control reg */
     167                        tmp = ssb_read32(dev, 0x304);
     168                        tmp &= ~0x100;
     169                        ssb_write32(dev, 0x304, tmp);
     170                        tmp = ssb_read32(dev, 0x304);
     171                        printk("USB20H shim: 0x%0x\n", tmp);
     172                }
     173        }
     174        else
     175                ssb_device_enable(dev, 0);
    111176
    112         ssb_device_enable(dev, flags);
     177 /*
     178  * Set dma mask - 32 bit mask is just an assumption
     179  */
     180 if (ssb_dma_set_mask(dev, DMA_32BIT_MASK))
     181   return -EOPNOTSUPP;
    113182
    114183        hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
    115184                        dev_name(dev->dev));
    static int ssb_ohci_attach(struct ssb_device *dev)  
    130199
    131200        ssb_set_drvdata(dev, hcd);
    132201
     202#ifdef CONFIG_USB_EHCI_HCD_SSB
     203        /*
     204         * attach ehci function in this core
     205         */
     206        if (dev->id.coreid == SSB_DEV_USB20_HOST)
     207                err = ssb_ehci_attach(dev, &(ohcidev->ehci_hcd));
     208#endif
     209
    133210        return err;
    134211
    135212err_iounmap:
    static int ssb_ohci_resume(struct ssb_device *dev)  
    200277static const struct ssb_device_id ssb_ohci_table[] = {
    201278        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
    202279        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
     280        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
    203281        SSB_DEVTABLE_END
    204282};
    205283MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);
  • drivers/watchdog/Kconfig

    diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
    index 5eb8f21..fadc751 100644
    a b config TXX9_WDT  
    764764        help
    765765          Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs.
    766766
     767config BCM47XX_WDT
     768        tristate "Broadcom BCM47xx Watchdog Timer"
     769        depends on BCM47XX
     770        help
     771          Hardware driver for the Broadcom BCM47xx Watchog Timer.
     772
    767773# PARISC Architecture
    768774
    769775# POWERPC Architecture
  • drivers/watchdog/Makefile

    diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
    index 7f8c56b..99eab0f 100644
    a b obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o  
    105105obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
    106106obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
    107107obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
     108obj-$(CONFIG_BCM47XX_WDT) += bcm47xx_wdt.o
    108109
    109110# PARISC Architecture
    110111
  • new file drivers/watchdog/bcm47xx_wdt.c

    diff --git a/drivers/watchdog/bcm47xx_wdt.c b/drivers/watchdog/bcm47xx_wdt.c
    new file mode 100644
    index 0000000..3a192c7
    - +  
     1/*
     2 *  Watchdog driver for Broadcom BCM47XX
     3 *
     4 *  Copyright (C) 2008 Aleksandar Radovanovic <biblbroks@sezampro.rs>
     5 *  Copyright (C) 2009 Matthieu CASTET <castet.matthieu@free.fr>
     6 *
     7 *  This program is free software; you can redistribute it and/or
     8 *  modify it under the terms of the GNU General Public License
     9 *  as published by the Free Software Foundation; either version
     10 *  2 of the License, or (at your option) any later version.
     11 */
     12
     13#include <linux/bitops.h>
     14#include <linux/errno.h>
     15#include <linux/fs.h>
     16#include <linux/init.h>
     17#include <linux/kernel.h>
     18#include <linux/miscdevice.h>
     19#include <linux/module.h>
     20#include <linux/moduleparam.h>
     21#include <linux/reboot.h>
     22#include <linux/types.h>
     23#include <linux/uaccess.h>
     24#include <linux/watchdog.h>
     25#include <linux/timer.h>
     26#include <linux/jiffies.h>
     27#include <linux/ssb/ssb_embedded.h>
     28#include <asm/mach-bcm47xx/bcm47xx.h>
     29
     30#define DRV_NAME                "bcm47xx_wdt"
     31
     32#define WDT_DEFAULT_TIME        30      /* seconds */
     33#define WDT_MAX_TIME            256     /* seconds */
     34
     35static int wdt_time = WDT_DEFAULT_TIME;
     36static int nowayout = WATCHDOG_NOWAYOUT;
     37
     38module_param(wdt_time, int, 0);
     39MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="
     40                                __MODULE_STRING(WDT_DEFAULT_TIME) ")");
     41
     42#ifdef CONFIG_WATCHDOG_NOWAYOUT
     43module_param(nowayout, int, 0);
     44MODULE_PARM_DESC(nowayout,
     45                "Watchdog cannot be stopped once started (default="
     46                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
     47#endif
     48
     49static unsigned long bcm47xx_wdt_busy;
     50static char expect_release;
     51static struct timer_list wdt_timer;
     52static atomic_t ticks;
     53
     54static inline void bcm47xx_wdt_hw_start(void)
     55{
     56        /* this is 2,5s on 100Mhz clock  and 2s on 133 Mhz */
     57        ssb_watchdog_timer_set(&ssb_bcm47xx, 0xfffffff);
     58}
     59
     60static inline int bcm47xx_wdt_hw_stop(void)
     61{
     62        return ssb_watchdog_timer_set(&ssb_bcm47xx, 0);
     63}
     64
     65static void bcm47xx_timer_tick(unsigned long unused)
     66{
     67        if (!atomic_dec_and_test(&ticks)) {
     68                bcm47xx_wdt_hw_start();
     69                mod_timer(&wdt_timer, jiffies + HZ);
     70        } else {
     71                printk(KERN_CRIT DRV_NAME "Watchdog will fire soon!!!\n");
     72        }
     73}
     74
     75static inline void bcm47xx_wdt_pet(void)
     76{
     77        atomic_set(&ticks, wdt_time);
     78}
     79
     80static void bcm47xx_wdt_start(void)
     81{
     82        bcm47xx_wdt_pet();
     83        bcm47xx_timer_tick(0);
     84}
     85
     86static void bcm47xx_wdt_pause(void)
     87{
     88        del_timer_sync(&wdt_timer);
     89        bcm47xx_wdt_hw_stop();
     90}
     91
     92static void bcm47xx_wdt_stop(void)
     93{
     94        bcm47xx_wdt_pause();
     95}
     96
     97static int bcm47xx_wdt_settimeout(int new_time)
     98{
     99        if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
     100                return -EINVAL;
     101
     102        wdt_time = new_time;
     103        return 0;
     104}
     105
     106static int bcm47xx_wdt_open(struct inode *inode, struct file *file)
     107{
     108        if (test_and_set_bit(0, &bcm47xx_wdt_busy))
     109                return -EBUSY;
     110
     111        bcm47xx_wdt_start();
     112        return nonseekable_open(inode, file);
     113}
     114
     115static int bcm47xx_wdt_release(struct inode *inode, struct file *file)
     116{
     117        if (expect_release == 42) {
     118                bcm47xx_wdt_stop();
     119        } else {
     120                printk(KERN_CRIT DRV_NAME
     121                        ": Unexpected close, not stopping watchdog!\n");
     122                bcm47xx_wdt_start();
     123        }
     124
     125        clear_bit(0, &bcm47xx_wdt_busy);
     126        expect_release = 0;
     127        return 0;
     128}
     129
     130static ssize_t bcm47xx_wdt_write(struct file *file, const char __user *data,
     131                              size_t len, loff_t *ppos)
     132{
     133        if (len) {
     134                if (!nowayout) {
     135                        size_t i;
     136
     137                        expect_release = 0;
     138
     139                        for (i = 0; i != len; i++) {
     140                                char c;
     141                                if (get_user(c, data + i))
     142                                        return -EFAULT;
     143                                if (c == 'V')
     144                                        expect_release = 42;
     145                        }
     146                }
     147                bcm47xx_wdt_pet();
     148        }
     149        return len;
     150}
     151
     152static struct watchdog_info bcm47xx_wdt_info = {
     153        .identity       = DRV_NAME,
     154        .options        = WDIOF_SETTIMEOUT |
     155                                WDIOF_KEEPALIVEPING |
     156                                WDIOF_MAGICCLOSE,
     157};
     158
     159static long bcm47xx_wdt_ioctl(struct file *file,
     160                                        unsigned int cmd, unsigned long arg)
     161{
     162        void __user *argp = (void __user *)arg;
     163        int __user *p = argp;
     164        int new_value, retval = -EINVAL;;
     165
     166        switch (cmd) {
     167        case WDIOC_GETSUPPORT:
     168                return copy_to_user(argp, &bcm47xx_wdt_info,
     169                                sizeof(bcm47xx_wdt_info)) ? -EFAULT : 0;
     170
     171        case WDIOC_GETSTATUS:
     172        case WDIOC_GETBOOTSTATUS:
     173                return put_user(0, p);
     174
     175        case WDIOC_SETOPTIONS:
     176                if (get_user(new_value, p))
     177                        return -EFAULT;
     178
     179                if (new_value & WDIOS_DISABLECARD) {
     180                        bcm47xx_wdt_stop();
     181                        retval = 0;
     182                }
     183
     184                if (new_value & WDIOS_ENABLECARD) {
     185                        bcm47xx_wdt_start();
     186                        retval = 0;
     187                }
     188
     189                return retval;
     190
     191        case WDIOC_KEEPALIVE:
     192                bcm47xx_wdt_pet();
     193                return 0;
     194
     195        case WDIOC_SETTIMEOUT:
     196                if (get_user(new_value, p))
     197                        return -EFAULT;
     198
     199                if (bcm47xx_wdt_settimeout(new_value))
     200                        return -EINVAL;
     201
     202                bcm47xx_wdt_pet();
     203
     204        case WDIOC_GETTIMEOUT:
     205                return put_user(wdt_time, p);
     206
     207        default:
     208                return -ENOTTY;
     209        }
     210}
     211
     212static int bcm47xx_wdt_notify_sys(struct notifier_block *this,
     213           unsigned long code, void *unused)
     214{
     215        if (code == SYS_DOWN || code == SYS_HALT)
     216                bcm47xx_wdt_stop();
     217        return NOTIFY_DONE;
     218}
     219
     220static const struct file_operations bcm47xx_wdt_fops = {
     221        .owner          = THIS_MODULE,
     222        .llseek         = no_llseek,
     223        .unlocked_ioctl = bcm47xx_wdt_ioctl,
     224        .open           = bcm47xx_wdt_open,
     225        .release        = bcm47xx_wdt_release,
     226        .write          = bcm47xx_wdt_write,
     227};
     228
     229static struct miscdevice bcm47xx_wdt_miscdev = {
     230        .minor          = WATCHDOG_MINOR,
     231        .name           = "watchdog",
     232        .fops           = &bcm47xx_wdt_fops,
     233};
     234
     235static struct notifier_block bcm47xx_wdt_notifier = {
     236        .notifier_call = bcm47xx_wdt_notify_sys,
     237};
     238
     239static int __init bcm47xx_wdt_init(void)
     240{
     241        int ret;
     242
     243        if (bcm47xx_wdt_hw_stop() < 0)
     244                return -ENODEV;
     245
     246        setup_timer(&wdt_timer, bcm47xx_timer_tick, 0L);
     247
     248        if (bcm47xx_wdt_settimeout(wdt_time)) {
     249                bcm47xx_wdt_settimeout(WDT_DEFAULT_TIME);
     250                printk(KERN_INFO DRV_NAME
     251                        ": wdt_time value must be 1 <= wdt_time <= 256, using %d\n",
     252                        wdt_time);
     253        }
     254
     255        ret = register_reboot_notifier(&bcm47xx_wdt_notifier);
     256        if (ret)
     257                return ret;
     258
     259        ret = misc_register(&bcm47xx_wdt_miscdev);
     260        if (ret) {
     261                unregister_reboot_notifier(&bcm47xx_wdt_notifier);
     262                return ret;
     263        }
     264
     265        printk(KERN_INFO "BCM47xx Watchdog Timer enabled (%d seconds%s)\n",
     266                                wdt_time, nowayout ? ", nowayout" : "");
     267        return 0;
     268}
     269
     270static void __exit bcm47xx_wdt_exit(void)
     271{
     272        if (!nowayout)
     273                bcm47xx_wdt_stop();
     274
     275        misc_deregister(&bcm47xx_wdt_miscdev);
     276
     277        unregister_reboot_notifier(&bcm47xx_wdt_notifier);
     278}
     279
     280module_init(bcm47xx_wdt_init);
     281module_exit(bcm47xx_wdt_exit);
     282
     283MODULE_AUTHOR("Aleksandar Radovanovic");
     284MODULE_DESCRIPTION("Watchdog driver for Broadcom BCM47xx");
     285MODULE_LICENSE("GPL");
     286MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
  • fs/fuse/dev.c

    diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
    index ba76b68..c22aefd 100644
    a b static void fuse_copy_finish(struct fuse_copy_state *cs)  
    527527        }
    528528}
    529529
     530#ifdef DCACHE_BUG
     531extern void (*fuse_flush_cache_all)(void);
     532extern void (*fuse_flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
     533#endif
     534
    530535/*
    531536 * Get another pagefull of userspace buffer, and map it to kernel
    532537 * address space, and lock request
    static int fuse_copy_fill(struct fuse_copy_state *cs)  
    535540{
    536541        unsigned long offset;
    537542        int err;
     543#ifdef DCACHE_BUG
     544        struct vm_area_struct *vma;
     545#endif
    538546
    539547        unlock_request(cs->fc, cs->req);
    540548        fuse_copy_finish(cs);
    static int fuse_copy_fill(struct fuse_copy_state *cs)  
    546554                cs->nr_segs--;
    547555        }
    548556        down_read(&current->mm->mmap_sem);
     557#ifndef DCACHE_BUG
    549558        err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0,
    550559                             &cs->pg, NULL);
     560#else
     561        err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0,
     562                             &cs->pg, &vma);
     563#endif
    551564        up_read(&current->mm->mmap_sem);
    552565        if (err < 0)
    553566                return err;
    554567        BUG_ON(err != 1);
    555568        offset = cs->addr % PAGE_SIZE;
    556569        cs->mapaddr = kmap_atomic(cs->pg, KM_USER0);
     570#ifdef DCACHE_BUG
     571        fuse_flush_cache_page(vma, cs->addr, page_to_pfn(cs->pg));
     572#endif
    557573        cs->buf = cs->mapaddr + offset;
    558574        cs->len = min(PAGE_SIZE - offset, cs->seglen);
    559575        cs->seglen -= cs->len;
    static int fuse_copy_do(struct fuse_copy_state *cs, void **val, unsigned *size)  
    567583{
    568584        unsigned ncpy = min(*size, cs->len);
    569585        if (val) {
     586#ifdef DCACHE_BUG
     587                // patch from mailing list, it is very important, otherwise,
     588                // can't mount, or ls mount point will hang
     589                fuse_flush_cache_all();
     590#endif
    570591                if (cs->write)
    571592                        memcpy(cs->buf, *val, ncpy);
    572593                else
  • fs/fuse/fuse_i.h

    diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
    index 6fc5aed..ca2cc6b 100644
    a b  
    88
    99#ifndef _FS_FUSE_I_H
    1010#define _FS_FUSE_I_H
     11#define DCACHE_BUG
    1112
    1213#include <linux/fuse.h>
    1314#include <linux/fs.h>
  • fs/fuse/inode.c

    diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
    index 91f7c85..8827ce8 100644
    a b static int __init fuse_init(void)  
    10551055        printk(KERN_INFO "fuse init (API version %i.%i)\n",
    10561056               FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
    10571057
     1058#ifdef DCACHE_BUG
     1059printk("fuse init: DCACHE_BUG enabled\n");
     1060#endif
     1061
    10581062        INIT_LIST_HEAD(&fuse_conn_list);
    10591063        res = fuse_fs_init();
    10601064        if (res)
  • include/linux/pci_ids.h

    diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
    index 0f71812..6087a7d 100644
    a b  
    21062106#define PCI_DEVICE_ID_TIGON3_5906M      0x1713
    21072107#define PCI_DEVICE_ID_BCM4401           0x4401
    21082108#define PCI_DEVICE_ID_BCM4401B0         0x4402
     2109#define PCI_DEVICE_ID_BCM4713           0x4713
    21092110
    21102111#define PCI_VENDOR_ID_TOPIC             0x151f
    21112112#define PCI_DEVICE_ID_TOPIC_TP560       0x0000
Note: See TracBrowser for help on using the repository browser.