source: trunk/target/linux/brcm47xx/patches-2.6.37/820-wgt634u-nvram-fix.patch @ 26801

Last change on this file since 26801 was 26801, checked in by hauke, 5 years ago

brcm47xx: add fallback sprom for pci devices without an own sprom.

If there is no sprom on an ssb based pci device on the brcm47xx
architecture ssb now asks the architecture code to look into the nvram
to get some sprom data for this device. Now we are able to read out
pci/1/1/ foo or pci/1/3/ foo config options.

This will fix some problems where the wireless devices does not got an
mac address and the following message was show:
ssb: WARNING: Invalid SPROM CRC (corrupt SPROM)

File size: 7.6 KB
  • arch/mips/bcm47xx/Makefile

    The Netgear wgt634u uses a different format for storing the 
    configuration. This patch is needed to read out the correct 
    configuration. The cfe_env.c file uses a different method way to read 
    out the configuration than the in kernel cfe config reader.
    
    a b  
    33# under Linux. 
    44# 
    55 
    6 obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o 
     6obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o cfe_env.o 
  • new file arch/mips/bcm47xx/cfe_env.c

    - +  
     1/* 
     2 * CFE environment variable access 
     3 * 
     4 * Copyright 2001-2003, Broadcom Corporation 
     5 * Copyright 2006, Felix Fietkau <nbd@openwrt.org> 
     6 *  
     7 * This program is free software; you can redistribute  it and/or modify it 
     8 * under  the terms of  the GNU General  Public License as published by the 
     9 * Free Software Foundation;  either version 2 of the  License, or (at your 
     10 * option) any later version. 
     11 */ 
     12 
     13#include <linux/init.h> 
     14#include <linux/module.h> 
     15#include <linux/kernel.h> 
     16#include <linux/string.h> 
     17#include <asm/io.h> 
     18#include <asm/uaccess.h> 
     19 
     20#define NVRAM_SIZE       (0x1ff0) 
     21static char _nvdata[NVRAM_SIZE]; 
     22static char _valuestr[256]; 
     23 
     24/* 
     25 * TLV types.  These codes are used in the "type-length-value" 
     26 * encoding of the items stored in the NVRAM device (flash or EEPROM) 
     27 * 
     28 * The layout of the flash/nvram is as follows: 
     29 * 
     30 * <type> <length> <data ...> <type> <length> <data ...> <type_end> 
     31 * 
     32 * The type code of "ENV_TLV_TYPE_END" marks the end of the list. 
     33 * The "length" field marks the length of the data section, not 
     34 * including the type and length fields. 
     35 * 
     36 * Environment variables are stored as follows: 
     37 * 
     38 * <type_env> <length> <flags> <name> = <value> 
     39 * 
     40 * If bit 0 (low bit) is set, the length is an 8-bit value. 
     41 * If bit 0 (low bit) is clear, the length is a 16-bit value 
     42 *  
     43 * Bit 7 set indicates "user" TLVs.  In this case, bit 0 still 
     44 * indicates the size of the length field.   
     45 * 
     46 * Flags are from the constants below: 
     47 * 
     48 */ 
     49#define ENV_LENGTH_16BITS       0x00    /* for low bit */ 
     50#define ENV_LENGTH_8BITS        0x01 
     51 
     52#define ENV_TYPE_USER           0x80 
     53 
     54#define ENV_CODE_SYS(n,l) (((n)<<1)|(l)) 
     55#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER) 
     56 
     57/* 
     58 * The actual TLV types we support 
     59 */ 
     60 
     61#define ENV_TLV_TYPE_END        0x00     
     62#define ENV_TLV_TYPE_ENV        ENV_CODE_SYS(0,ENV_LENGTH_8BITS) 
     63 
     64/* 
     65 * Environment variable flags  
     66 */ 
     67 
     68#define ENV_FLG_NORMAL          0x00    /* normal read/write */ 
     69#define ENV_FLG_BUILTIN         0x01    /* builtin - not stored in flash */ 
     70#define ENV_FLG_READONLY        0x02    /* read-only - cannot be changed */ 
     71 
     72#define ENV_FLG_MASK            0xFF    /* mask of attributes we keep */ 
     73#define ENV_FLG_ADMIN           0x100   /* lets us internally override permissions */ 
     74 
     75 
     76/*  ********************************************************************* 
     77    *  _nvram_read(buffer,offset,length) 
     78    *   
     79    *  Read data from the NVRAM device 
     80    *   
     81    *  Input parameters:  
     82    *      buffer - destination buffer 
     83    *      offset - offset of data to read 
     84    *      length - number of bytes to read 
     85    *       
     86    *  Return value: 
     87    *      number of bytes read, or <0 if error occured 
     88    ********************************************************************* */ 
     89static int 
     90_nvram_read(unsigned char *nv_buf, unsigned char *buffer, int offset, int length) 
     91{ 
     92    int i; 
     93    if (offset > NVRAM_SIZE) 
     94        return -1;  
     95 
     96    for ( i = 0; i < length; i++) { 
     97        buffer[i] = ((volatile unsigned char*)nv_buf)[offset + i]; 
     98    } 
     99    return length; 
     100} 
     101 
     102 
     103static char* 
     104_strnchr(const char *dest,int c,size_t cnt) 
     105{ 
     106        while (*dest && (cnt > 0)) { 
     107        if (*dest == c) return (char *) dest; 
     108        dest++; 
     109        cnt--; 
     110        } 
     111        return NULL; 
     112} 
     113 
     114 
     115 
     116/* 
     117 * Core support API: Externally visible. 
     118 */ 
     119 
     120/* 
     121 * Get the value of an NVRAM variable 
     122 * @param       name    name of variable to get 
     123 * @return      value of variable or NULL if undefined 
     124 */ 
     125 
     126char*  
     127cfe_env_get(unsigned char *nv_buf, char* name) 
     128{ 
     129    int size; 
     130    unsigned char *buffer; 
     131    unsigned char *ptr; 
     132    unsigned char *envval; 
     133    unsigned int reclen; 
     134    unsigned int rectype; 
     135    int offset; 
     136    int flg; 
     137     
     138        if (!strcmp(name, "nvram_type")) 
     139                return "cfe"; 
     140         
     141    size = NVRAM_SIZE; 
     142    buffer = &_nvdata[0]; 
     143 
     144    ptr = buffer; 
     145    offset = 0; 
     146 
     147    /* Read the record type and length */ 
     148    if (_nvram_read(nv_buf, ptr,offset,1) != 1) { 
     149        goto error; 
     150    } 
     151     
     152    while ((*ptr != ENV_TLV_TYPE_END)  && (size > 1)) { 
     153 
     154        /* Adjust pointer for TLV type */ 
     155        rectype = *(ptr); 
     156        offset++; 
     157        size--; 
     158 
     159        /*  
     160         * Read the length.  It can be either 1 or 2 bytes 
     161         * depending on the code  
     162         */ 
     163        if (rectype & ENV_LENGTH_8BITS) { 
     164            /* Read the record type and length - 8 bits */ 
     165            if (_nvram_read(nv_buf, ptr,offset,1) != 1) { 
     166                goto error; 
     167            } 
     168            reclen = *(ptr); 
     169            size--; 
     170            offset++; 
     171        } 
     172        else { 
     173            /* Read the record type and length - 16 bits, MSB first */ 
     174            if (_nvram_read(nv_buf, ptr,offset,2) != 2) { 
     175                goto error; 
     176            } 
     177            reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1); 
     178            size -= 2; 
     179            offset += 2; 
     180        } 
     181 
     182        if (reclen > size) 
     183            break;      /* should not happen, bad NVRAM */ 
     184 
     185        switch (rectype) { 
     186            case ENV_TLV_TYPE_ENV: 
     187                /* Read the TLV data */ 
     188                if (_nvram_read(nv_buf, ptr,offset,reclen) != reclen) 
     189                    goto error; 
     190                flg = *ptr++; 
     191                envval = (unsigned char *) _strnchr(ptr,'=',(reclen-1)); 
     192                if (envval) { 
     193                    *envval++ = '\0'; 
     194                    memcpy(_valuestr,envval,(reclen-1)-(envval-ptr)); 
     195                    _valuestr[(reclen-1)-(envval-ptr)] = '\0'; 
     196#if 0                    
     197                    printk(KERN_INFO "NVRAM:%s=%s\n", ptr, _valuestr); 
     198#endif 
     199                    if(!strcmp(ptr, name)){ 
     200                        return _valuestr; 
     201                    } 
     202                    if((strlen(ptr) > 1) && !strcmp(&ptr[1], name)) 
     203                        return _valuestr; 
     204                } 
     205                break; 
     206                 
     207            default:  
     208                /* Unknown TLV type, skip it. */ 
     209                break; 
     210            } 
     211 
     212        /* 
     213         * Advance to next TLV  
     214         */ 
     215                 
     216        size -= (int)reclen; 
     217        offset += reclen; 
     218 
     219        /* Read the next record type */ 
     220        ptr = buffer; 
     221        if (_nvram_read(nv_buf, ptr,offset,1) != 1) 
     222            goto error; 
     223        } 
     224 
     225error: 
     226    return NULL; 
     227 
     228} 
     229 
  • arch/mips/bcm47xx/nvram.c

    a b  
    2121#include <asm/mach-bcm47xx/bcm47xx.h> 
    2222 
    2323static char nvram_buf[NVRAM_SPACE]; 
     24static int cfe_env; 
     25extern char *cfe_env_get(char *nv_buf, const char *name); 
    2426 
    2527/* Probe for NVRAM header */ 
    2628static void early_nvram_init(void) 
    static void early_nvram_init(void) 
    3335 
    3436        base = mcore->flash_window; 
    3537        lim = mcore->flash_window_size; 
     38        cfe_env = 0; 
     39 
     40        /* XXX: hack for supporting the CFE environment stuff on WGT634U */ 
     41        if (lim >= 8 * 1024 * 1024) { 
     42                src = (u32 *) KSEG1ADDR(base + 8 * 1024 * 1024 - 0x2000); 
     43                dst = (u32 *) nvram_buf; 
     44 
     45                if ((*src & 0xff00ff) == 0x000001) { 
     46                        printk("early_nvram_init: WGT634U NVRAM found.\n"); 
     47 
     48                        for (i = 0; i < 0x1ff0; i++) { 
     49                                if (*src == 0xFFFFFFFF) 
     50                                        break; 
     51                                *dst++ = *src++; 
     52                        } 
     53                        cfe_env = 1; 
     54                        return; 
     55                } 
     56        } 
    3657 
    3758        off = FLASH_MIN; 
    3859        while (off <= lim) { 
    int nvram_getenv(char *name, char *val, 
    7495        if (!nvram_buf[0]) 
    7596                early_nvram_init(); 
    7697 
     98        if (cfe_env) { 
     99                value = cfe_env_get(nvram_buf, name); 
     100                snprintf(val, val_len, "%s", value); 
     101                return 0; 
     102        } 
     103 
    77104        /* Look for name=value and return value */ 
    78105        var = &nvram_buf[sizeof(struct nvram_header)]; 
    79106        end = nvram_buf + sizeof(nvram_buf) - 2; 
    char *nvram_get(const char *name) 
    103130        if (!nvram_buf[0]) 
    104131                early_nvram_init(); 
    105132 
     133        if (cfe_env) 
     134                return cfe_env_get(nvram_buf, name); 
     135 
    106136        /* Look for name=value and return value */ 
    107137        var = &nvram_buf[sizeof(struct nvram_header)]; 
    108138        end = nvram_buf + sizeof(nvram_buf) - 2; 
Note: See TracBrowser for help on using the repository browser.