1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-11-24 04:56:14 +02:00

brcm47xx: prepare brcm47xx patches for sending to mainline.

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@22296 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
hauke 2010-07-19 20:25:20 +00:00
parent 03685da10d
commit 9fe2a2d554
57 changed files with 4172 additions and 1658 deletions

View File

@ -0,0 +1,474 @@
/*
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
* Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
*
* original functions for finding root filesystem from Mike Baker
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Copyright 2001-2003, Broadcom Corporation
* All Rights Reserved.
*
* THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
* KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
* SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
*
* Flash mapping for BCM947XX boards
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#ifdef CONFIG_MTD_PARTITIONS
#include <linux/mtd/partitions.h>
#endif
#include <linux/crc32.h>
#ifdef CONFIG_SSB
#include <linux/ssb/ssb.h>
#endif
#include <asm/io.h>
#define TRX_MAGIC 0x30524448 /* "HDR0" */
#define TRX_VERSION 1
#define TRX_MAX_LEN 0x3A0000
#define TRX_NO_HEADER 1 /* Do not write TRX header */
#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */
#define TRX_MAX_OFFSET 3
struct trx_header {
u32 magic; /* "HDR0" */
u32 len; /* Length of file including header */
u32 crc32; /* 32-bit CRC from flag_version to end of file */
u32 flag_version; /* 0:15 flags, 16:31 version */
u32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */
};
#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
#define NVRAM_SPACE 0x8000
#define WINDOW_ADDR 0x1fc00000
#define WINDOW_SIZE 0x400000
#define BUSWIDTH 2
#ifdef CONFIG_SSB
extern struct ssb_bus ssb_bcm47xx;
#endif
static struct mtd_info *bcm47xx_mtd;
static void bcm47xx_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
if (len==1) {
memcpy_fromio(to, map->virt + from, len);
} else {
int i;
u16 *dest = (u16 *) to;
u16 *src = (u16 *) (map->virt + from);
for (i = 0; i < (len / 2); i++) {
dest[i] = src[i];
}
if (len & 1)
*((u8 *)dest+len-1) = src[i] & 0xff;
}
}
static struct map_info bcm47xx_map = {
name: "Physically mapped flash",
size: WINDOW_SIZE,
bankwidth: BUSWIDTH,
phys: WINDOW_ADDR,
};
#ifdef CONFIG_MTD_PARTITIONS
static struct mtd_partition bcm47xx_parts[] = {
{ name: "cfe", offset: 0, size: 0, mask_flags: MTD_WRITEABLE, },
{ name: "linux", offset: 0, size: 0, },
{ name: "rootfs", offset: 0, size: 0, },
{ name: "nvram", offset: 0, size: 0, },
{ name: NULL, },
};
static int __init
find_cfe_size(struct mtd_info *mtd, size_t size)
{
struct trx_header *trx;
unsigned char buf[512];
int off;
size_t len;
int blocksize;
trx = (struct trx_header *) buf;
blocksize = mtd->erasesize;
if (blocksize < 0x10000)
blocksize = 0x10000;
for (off = (128*1024); off < size; off += blocksize) {
memset(buf, 0xe5, sizeof(buf));
/*
* Read into buffer
*/
if (mtd->read(mtd, off, sizeof(buf), &len, buf) ||
len != sizeof(buf))
continue;
/* found a TRX header */
if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
goto found;
}
}
printk(KERN_NOTICE
"%s: Couldn't find bootloader size\n",
mtd->name);
return -1;
found:
printk(KERN_NOTICE "bootloader size: %d\n", off);
return off;
}
/*
* Copied from mtdblock.c
*
* Cache stuff...
*
* Since typical flash erasable sectors are much larger than what Linux's
* buffer cache can handle, we must implement read-modify-write on flash
* sectors for each block write requests. To avoid over-erasing flash sectors
* and to speed things up, we locally cache a whole flash sector while it is
* being written to until a different sector is required.
*/
static void erase_callback(struct erase_info *done)
{
wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
wake_up(wait_q);
}
static int erase_write (struct mtd_info *mtd, unsigned long pos,
int len, const char *buf)
{
struct erase_info erase;
DECLARE_WAITQUEUE(wait, current);
wait_queue_head_t wait_q;
size_t retlen;
int ret;
/*
* First, let's erase the flash block.
*/
init_waitqueue_head(&wait_q);
erase.mtd = mtd;
erase.callback = erase_callback;
erase.addr = pos;
erase.len = len;
erase.priv = (u_long)&wait_q;
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&wait_q, &wait);
ret = mtd->erase(mtd, &erase);
if (ret) {
set_current_state(TASK_RUNNING);
remove_wait_queue(&wait_q, &wait);
printk (KERN_WARNING "erase of region [0x%lx, 0x%x] "
"on \"%s\" failed\n",
pos, len, mtd->name);
return ret;
}
schedule(); /* Wait for erase to finish. */
remove_wait_queue(&wait_q, &wait);
/*
* Next, writhe data to flash.
*/
ret = mtd->write (mtd, pos, len, &retlen, buf);
if (ret)
return ret;
if (retlen != len)
return -EIO;
return 0;
}
static int __init
find_dual_image_off (struct mtd_info *mtd, size_t size)
{
struct trx_header trx;
int off, blocksize;
size_t len;
blocksize = mtd->erasesize;
if (blocksize < 0x10000)
blocksize = 0x10000;
for (off = (128*1024); off < size; off += blocksize) {
memset(&trx, 0xe5, sizeof(trx));
/*
* Read into buffer
*/
if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) ||
len != sizeof(trx))
continue;
/* found last TRX header */
if (le32_to_cpu(trx.magic) == TRX_MAGIC){
if (le32_to_cpu(trx.flag_version >> 16)==2){
printk("dual image TRX header found\n");
return size/2;
} else {
return 0;
}
}
}
return 0;
}
static int __init
find_root(struct mtd_info *mtd, size_t size, struct mtd_partition *part)
{
struct trx_header trx, *trx2;
unsigned char buf[512], *block;
int off, blocksize;
u32 i, crc = ~0;
size_t len;
blocksize = mtd->erasesize;
if (blocksize < 0x10000)
blocksize = 0x10000;
for (off = (128*1024); off < size; off += blocksize) {
memset(&trx, 0xe5, sizeof(trx));
/*
* Read into buffer
*/
if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) ||
len != sizeof(trx))
continue;
/* found a TRX header */
if (le32_to_cpu(trx.magic) == TRX_MAGIC) {
part->offset = le32_to_cpu(trx.offsets[2]) ? :
le32_to_cpu(trx.offsets[1]);
part->size = le32_to_cpu(trx.len);
part->size -= part->offset;
part->offset += off;
goto found;
}
}
printk(KERN_NOTICE
"%s: Couldn't find root filesystem\n",
mtd->name);
return -1;
found:
if (part->size == 0)
return 0;
if (mtd->read(mtd, part->offset, sizeof(buf), &len, buf) || len != sizeof(buf))
return 0;
/* Move the fs outside of the trx */
part->size = 0;
if (trx.len != part->offset + part->size - off) {
/* Update the trx offsets and length */
trx.len = part->offset + part->size - off;
/* Update the trx crc32 */
for (i = (u32) &(((struct trx_header *)NULL)->flag_version); i <= trx.len; i += sizeof(buf)) {
if (mtd->read(mtd, off + i, sizeof(buf), &len, buf) || len != sizeof(buf))
return 0;
crc = crc32_le(crc, buf, min(sizeof(buf), trx.len - i));
}
trx.crc32 = crc;
/* read first eraseblock from the trx */
block = kmalloc(mtd->erasesize, GFP_KERNEL);
trx2 = (struct trx_header *) block;
if (mtd->read(mtd, off, mtd->erasesize, &len, block) || len != mtd->erasesize) {
printk("Error accessing the first trx eraseblock\n");
return 0;
}
printk("Updating TRX offsets and length:\n");
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);
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);
/* Write updated trx header to the flash */
memcpy(block, &trx, sizeof(trx));
if (mtd->unlock)
mtd->unlock(mtd, off, mtd->erasesize);
erase_write(mtd, off, mtd->erasesize, block);
if (mtd->sync)
mtd->sync(mtd);
kfree(block);
printk("Done\n");
}
return part->size;
}
struct mtd_partition * __init
init_mtd_partitions(struct mtd_info *mtd, size_t size)
{
int cfe_size;
int dual_image_offset = 0;
if ((cfe_size = find_cfe_size(mtd,size)) < 0)
return NULL;
/* boot loader */
bcm47xx_parts[0].offset = 0;
bcm47xx_parts[0].size = cfe_size;
/* nvram */
if (cfe_size != 384 * 1024) {
bcm47xx_parts[3].offset = size - ROUNDUP(NVRAM_SPACE, mtd->erasesize);
bcm47xx_parts[3].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
} else {
/* nvram (old 128kb config partition on netgear wgt634u) */
bcm47xx_parts[3].offset = bcm47xx_parts[0].size;
bcm47xx_parts[3].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
}
/* dual image offset*/
printk("Looking for dual image\n");
dual_image_offset=find_dual_image_off(mtd,size);
/* linux (kernel and rootfs) */
if (cfe_size != 384 * 1024) {
bcm47xx_parts[1].offset = bcm47xx_parts[0].size;
bcm47xx_parts[1].size = bcm47xx_parts[3].offset - dual_image_offset -
bcm47xx_parts[1].offset;
} else {
/* do not count the elf loader, which is on one block */
bcm47xx_parts[1].offset = bcm47xx_parts[0].size +
bcm47xx_parts[3].size + mtd->erasesize;
bcm47xx_parts[1].size = size -
bcm47xx_parts[0].size -
(2*bcm47xx_parts[3].size) -
mtd->erasesize;
}
/* find and size rootfs */
find_root(mtd,size,&bcm47xx_parts[2]);
bcm47xx_parts[2].size = size - dual_image_offset - bcm47xx_parts[2].offset - bcm47xx_parts[3].size;
return bcm47xx_parts;
}
#endif
int __init init_bcm47xx_map(void)
{
#ifdef CONFIG_SSB
struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
#endif
size_t size;
int ret = 0;
#ifdef CONFIG_MTD_PARTITIONS
struct mtd_partition *parts;
int i;
#endif
#ifdef CONFIG_SSB
u32 window = mcore->flash_window;
u32 window_size = mcore->flash_window_size;
printk("flash init: 0x%08x 0x%08x\n", window, window_size);
bcm47xx_map.phys = window;
bcm47xx_map.size = window_size;
bcm47xx_map.bankwidth = mcore->flash_buswidth;
bcm47xx_map.virt = ioremap_nocache(window, window_size);
#else
printk("flash init: 0x%08x 0x%08x\n", WINDOW_ADDR, WINDOW_SIZE);
bcm47xx_map.virt = ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
#endif
if (!bcm47xx_map.virt) {
printk("Failed to ioremap\n");
return -EIO;
}
simple_map_init(&bcm47xx_map);
if (!(bcm47xx_mtd = do_map_probe("cfi_probe", &bcm47xx_map))) {
printk("Failed to do_map_probe\n");
iounmap((void *)bcm47xx_map.virt);
return -ENXIO;
}
/* override copy_from routine */
bcm47xx_map.copy_from = bcm47xx_map_copy_from;
bcm47xx_mtd->owner = THIS_MODULE;
size = bcm47xx_mtd->size;
printk(KERN_NOTICE "Flash device: 0x%x at 0x%x\n", size, WINDOW_ADDR);
#ifdef CONFIG_MTD_PARTITIONS
parts = init_mtd_partitions(bcm47xx_mtd, size);
for (i = 0; parts[i].name; i++);
ret = add_mtd_partitions(bcm47xx_mtd, parts, i);
if (ret) {
printk(KERN_ERR "Flash: add_mtd_partitions failed\n");
goto fail;
}
#endif
return 0;
fail:
if (bcm47xx_mtd)
map_destroy(bcm47xx_mtd);
if (bcm47xx_map.virt)
iounmap((void *)bcm47xx_map.virt);
bcm47xx_map.virt = 0;
return ret;
}
void __exit cleanup_bcm47xx_map(void)
{
#ifdef CONFIG_MTD_PARTITIONS
del_mtd_partitions(bcm47xx_mtd);
#endif
map_destroy(bcm47xx_mtd);
iounmap((void *)bcm47xx_map.virt);
}
module_init(init_bcm47xx_map);
module_exit(cleanup_bcm47xx_map);

View File

@ -0,0 +1,474 @@
/*
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
* Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
*
* original functions for finding root filesystem from Mike Baker
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Copyright 2001-2003, Broadcom Corporation
* All Rights Reserved.
*
* THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
* KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
* SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
*
* Flash mapping for BCM947XX boards
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#ifdef CONFIG_MTD_PARTITIONS
#include <linux/mtd/partitions.h>
#endif
#include <linux/crc32.h>
#ifdef CONFIG_SSB
#include <linux/ssb/ssb.h>
#endif
#include <asm/io.h>
#define TRX_MAGIC 0x30524448 /* "HDR0" */
#define TRX_VERSION 1
#define TRX_MAX_LEN 0x3A0000
#define TRX_NO_HEADER 1 /* Do not write TRX header */
#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */
#define TRX_MAX_OFFSET 3
struct trx_header {
u32 magic; /* "HDR0" */
u32 len; /* Length of file including header */
u32 crc32; /* 32-bit CRC from flag_version to end of file */
u32 flag_version; /* 0:15 flags, 16:31 version */
u32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */
};
#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
#define NVRAM_SPACE 0x8000
#define WINDOW_ADDR 0x1fc00000
#define WINDOW_SIZE 0x400000
#define BUSWIDTH 2
#ifdef CONFIG_SSB
extern struct ssb_bus ssb_bcm47xx;
#endif
static struct mtd_info *bcm47xx_mtd;
static void bcm47xx_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
if (len==1) {
memcpy_fromio(to, map->virt + from, len);
} else {
int i;
u16 *dest = (u16 *) to;
u16 *src = (u16 *) (map->virt + from);
for (i = 0; i < (len / 2); i++) {
dest[i] = src[i];
}
if (len & 1)
*((u8 *)dest+len-1) = src[i] & 0xff;
}
}
static struct map_info bcm47xx_map = {
name: "Physically mapped flash",
size: WINDOW_SIZE,
bankwidth: BUSWIDTH,
phys: WINDOW_ADDR,
};
#ifdef CONFIG_MTD_PARTITIONS
static struct mtd_partition bcm47xx_parts[] = {
{ name: "cfe", offset: 0, size: 0, mask_flags: MTD_WRITEABLE, },
{ name: "linux", offset: 0, size: 0, },
{ name: "rootfs", offset: 0, size: 0, },
{ name: "nvram", offset: 0, size: 0, },
{ name: NULL, },
};
static int __init
find_cfe_size(struct mtd_info *mtd, size_t size)
{
struct trx_header *trx;
unsigned char buf[512];
int off;
size_t len;
int blocksize;
trx = (struct trx_header *) buf;
blocksize = mtd->erasesize;
if (blocksize < 0x10000)
blocksize = 0x10000;
for (off = (128*1024); off < size; off += blocksize) {
memset(buf, 0xe5, sizeof(buf));
/*
* Read into buffer
*/
if (mtd->read(mtd, off, sizeof(buf), &len, buf) ||
len != sizeof(buf))
continue;
/* found a TRX header */
if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
goto found;
}
}
printk(KERN_NOTICE
"%s: Couldn't find bootloader size\n",
mtd->name);
return -1;
found:
printk(KERN_NOTICE "bootloader size: %d\n", off);
return off;
}
/*
* Copied from mtdblock.c
*
* Cache stuff...
*
* Since typical flash erasable sectors are much larger than what Linux's
* buffer cache can handle, we must implement read-modify-write on flash
* sectors for each block write requests. To avoid over-erasing flash sectors
* and to speed things up, we locally cache a whole flash sector while it is
* being written to until a different sector is required.
*/
static void erase_callback(struct erase_info *done)
{
wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
wake_up(wait_q);
}
static int erase_write (struct mtd_info *mtd, unsigned long pos,
int len, const char *buf)
{
struct erase_info erase;
DECLARE_WAITQUEUE(wait, current);
wait_queue_head_t wait_q;
size_t retlen;
int ret;
/*
* First, let's erase the flash block.
*/
init_waitqueue_head(&wait_q);
erase.mtd = mtd;
erase.callback = erase_callback;
erase.addr = pos;
erase.len = len;
erase.priv = (u_long)&wait_q;
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&wait_q, &wait);
ret = mtd->erase(mtd, &erase);
if (ret) {
set_current_state(TASK_RUNNING);
remove_wait_queue(&wait_q, &wait);
printk (KERN_WARNING "erase of region [0x%lx, 0x%x] "
"on \"%s\" failed\n",
pos, len, mtd->name);
return ret;
}
schedule(); /* Wait for erase to finish. */
remove_wait_queue(&wait_q, &wait);
/*
* Next, writhe data to flash.
*/
ret = mtd->write (mtd, pos, len, &retlen, buf);
if (ret)
return ret;
if (retlen != len)
return -EIO;
return 0;
}
static int __init
find_dual_image_off (struct mtd_info *mtd, size_t size)
{
struct trx_header trx;
int off, blocksize;
size_t len;
blocksize = mtd->erasesize;
if (blocksize < 0x10000)
blocksize = 0x10000;
for (off = (128*1024); off < size; off += blocksize) {
memset(&trx, 0xe5, sizeof(trx));
/*
* Read into buffer
*/
if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) ||
len != sizeof(trx))
continue;
/* found last TRX header */
if (le32_to_cpu(trx.magic) == TRX_MAGIC){
if (le32_to_cpu(trx.flag_version >> 16)==2){
printk("dual image TRX header found\n");
return size/2;
} else {
return 0;
}
}
}
return 0;
}
static int __init
find_root(struct mtd_info *mtd, size_t size, struct mtd_partition *part)
{
struct trx_header trx, *trx2;
unsigned char buf[512], *block;
int off, blocksize;
u32 i, crc = ~0;
size_t len;
blocksize = mtd->erasesize;
if (blocksize < 0x10000)
blocksize = 0x10000;
for (off = (128*1024); off < size; off += blocksize) {
memset(&trx, 0xe5, sizeof(trx));
/*
* Read into buffer
*/
if (mtd->read(mtd, off, sizeof(trx), &len, (char *) &trx) ||
len != sizeof(trx))
continue;
/* found a TRX header */
if (le32_to_cpu(trx.magic) == TRX_MAGIC) {
part->offset = le32_to_cpu(trx.offsets[2]) ? :
le32_to_cpu(trx.offsets[1]);
part->size = le32_to_cpu(trx.len);
part->size -= part->offset;
part->offset += off;
goto found;
}
}
printk(KERN_NOTICE
"%s: Couldn't find root filesystem\n",
mtd->name);
return -1;
found:
if (part->size == 0)
return 0;
if (mtd->read(mtd, part->offset, sizeof(buf), &len, buf) || len != sizeof(buf))
return 0;
/* Move the fs outside of the trx */
part->size = 0;
if (trx.len != part->offset + part->size - off) {
/* Update the trx offsets and length */
trx.len = part->offset + part->size - off;
/* Update the trx crc32 */
for (i = (u32) &(((struct trx_header *)NULL)->flag_version); i <= trx.len; i += sizeof(buf)) {
if (mtd->read(mtd, off + i, sizeof(buf), &len, buf) || len != sizeof(buf))
return 0;
crc = crc32_le(crc, buf, min(sizeof(buf), trx.len - i));
}
trx.crc32 = crc;
/* read first eraseblock from the trx */
block = kmalloc(mtd->erasesize, GFP_KERNEL);
trx2 = (struct trx_header *) block;
if (mtd->read(mtd, off, mtd->erasesize, &len, block) || len != mtd->erasesize) {
printk("Error accessing the first trx eraseblock\n");
return 0;
}
printk("Updating TRX offsets and length:\n");
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);
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);
/* Write updated trx header to the flash */
memcpy(block, &trx, sizeof(trx));
if (mtd->unlock)
mtd->unlock(mtd, off, mtd->erasesize);
erase_write(mtd, off, mtd->erasesize, block);
if (mtd->sync)
mtd->sync(mtd);
kfree(block);
printk("Done\n");
}
return part->size;
}
struct mtd_partition * __init
init_mtd_partitions(struct mtd_info *mtd, size_t size)
{
int cfe_size;
int dual_image_offset = 0;
if ((cfe_size = find_cfe_size(mtd,size)) < 0)
return NULL;
/* boot loader */
bcm47xx_parts[0].offset = 0;
bcm47xx_parts[0].size = cfe_size;
/* nvram */
if (cfe_size != 384 * 1024) {
bcm47xx_parts[3].offset = size - ROUNDUP(NVRAM_SPACE, mtd->erasesize);
bcm47xx_parts[3].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
} else {
/* nvram (old 128kb config partition on netgear wgt634u) */
bcm47xx_parts[3].offset = bcm47xx_parts[0].size;
bcm47xx_parts[3].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
}
/* dual image offset*/
printk("Looking for dual image\n");
dual_image_offset=find_dual_image_off(mtd,size);
/* linux (kernel and rootfs) */
if (cfe_size != 384 * 1024) {
bcm47xx_parts[1].offset = bcm47xx_parts[0].size;
bcm47xx_parts[1].size = bcm47xx_parts[3].offset - dual_image_offset -
bcm47xx_parts[1].offset;
} else {
/* do not count the elf loader, which is on one block */
bcm47xx_parts[1].offset = bcm47xx_parts[0].size +
bcm47xx_parts[3].size + mtd->erasesize;
bcm47xx_parts[1].size = size -
bcm47xx_parts[0].size -
(2*bcm47xx_parts[3].size) -
mtd->erasesize;
}
/* find and size rootfs */
find_root(mtd,size,&bcm47xx_parts[2]);
bcm47xx_parts[2].size = size - dual_image_offset - bcm47xx_parts[2].offset - bcm47xx_parts[3].size;
return bcm47xx_parts;
}
#endif
int __init init_bcm47xx_map(void)
{
#ifdef CONFIG_SSB
struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
#endif
size_t size;
int ret = 0;
#ifdef CONFIG_MTD_PARTITIONS
struct mtd_partition *parts;
int i;
#endif
#ifdef CONFIG_SSB
u32 window = mcore->flash_window;
u32 window_size = mcore->flash_window_size;
printk("flash init: 0x%08x 0x%08x\n", window, window_size);
bcm47xx_map.phys = window;
bcm47xx_map.size = window_size;
bcm47xx_map.bankwidth = mcore->flash_buswidth;
bcm47xx_map.virt = ioremap_nocache(window, window_size);
#else
printk("flash init: 0x%08x 0x%08x\n", WINDOW_ADDR, WINDOW_SIZE);
bcm47xx_map.virt = ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
#endif
if (!bcm47xx_map.virt) {
printk("Failed to ioremap\n");
return -EIO;
}
simple_map_init(&bcm47xx_map);
if (!(bcm47xx_mtd = do_map_probe("cfi_probe", &bcm47xx_map))) {
printk("Failed to do_map_probe\n");
iounmap((void *)bcm47xx_map.virt);
return -ENXIO;
}
/* override copy_from routine */
bcm47xx_map.copy_from = bcm47xx_map_copy_from;
bcm47xx_mtd->owner = THIS_MODULE;
size = bcm47xx_mtd->size;
printk(KERN_NOTICE "Flash device: 0x%x at 0x%x\n", size, WINDOW_ADDR);
#ifdef CONFIG_MTD_PARTITIONS
parts = init_mtd_partitions(bcm47xx_mtd, size);
for (i = 0; parts[i].name; i++);
ret = add_mtd_partitions(bcm47xx_mtd, parts, i);
if (ret) {
printk(KERN_ERR "Flash: add_mtd_partitions failed\n");
goto fail;
}
#endif
return 0;
fail:
if (bcm47xx_mtd)
map_destroy(bcm47xx_mtd);
if (bcm47xx_map.virt)
iounmap((void *)bcm47xx_map.virt);
bcm47xx_map.virt = 0;
return ret;
}
void __exit cleanup_bcm47xx_map(void)
{
#ifdef CONFIG_MTD_PARTITIONS
del_mtd_partitions(bcm47xx_mtd);
#endif
map_destroy(bcm47xx_mtd);
iounmap((void *)bcm47xx_map.virt);
}
module_init(init_bcm47xx_map);
module_exit(cleanup_bcm47xx_map);

View File

@ -0,0 +1,254 @@
commit 121915c4ee0812a14bc8d752bc210d0238d755c1
Author: Waldemar Brodkorb <mips@waldemar-brodkorb.de>
Date: Tue Jun 8 19:06:01 2010 +0200
MIPS: BCM47xx: Add NVRAM support devices
When trying to netboot a Linksys WRT54GS WLAN router, the bootup fails,
because of following error message:
...
[ 0.424000] b44: b44.c:v2.0
[ 0.424000] b44: Invalid MAC address found in EEPROM
[ 0.432000] b44 ssb0:1: Problem fetching invariants of chip,aborting
[ 0.436000] b44: probe of ssb0:1 failed with error -22
...
The router uses a CFE bootloader, but most of the needed environment
variables for network card initialization, are not available from CFE
via printenv and even though not via cfe_getenv().
The required environment variables are saved in a special partition
in flash memory. The attached patch implement nvram_getenv and enables
bootup via NFS root on my router.
Most of the patch is extracted from the OpenWrt subversion repository and
stripped down and cleaned up to just fix this issue.
[Ralf: sorted out header file inclusions. Lots of unneded headers and such
that should have been included.]
Signed-off-by: Waldemar Brodkorb <wbx@openadk.org>
Reviewed-by: Phil Sutter <phil@nwl.cc>
To: linux-mips@linux-mips.org
Cc: Hauke Mehrtens <hauke@hauke-m.de>
Patchwork: http://patchwork.linux-mips.org/patch/1359/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -3,4 +3,4 @@
# under Linux.
#
-obj-y := gpio.o irq.o prom.o serial.o setup.o time.o wgt634u.o
+obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
--- /dev/null
+++ b/arch/mips/bcm47xx/nvram.c
@@ -0,0 +1,94 @@
+/*
+ * BCM947xx nvram variable access
+ *
+ * Copyright (C) 2005 Broadcom Corporation
+ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/ssb/ssb.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <asm/addrspace.h>
+#include <asm/mach-bcm47xx/nvram.h>
+#include <asm/mach-bcm47xx/bcm47xx.h>
+
+static char nvram_buf[NVRAM_SPACE];
+
+/* Probe for NVRAM header */
+static void __init early_nvram_init(void)
+{
+ struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
+ struct nvram_header *header;
+ int i;
+ u32 base, lim, off;
+ u32 *src, *dst;
+
+ base = mcore->flash_window;
+ lim = mcore->flash_window_size;
+
+ off = FLASH_MIN;
+ while (off <= lim) {
+ /* Windowed flash access */
+ header = (struct nvram_header *)
+ KSEG1ADDR(base + off - NVRAM_SPACE);
+ if (header->magic == NVRAM_HEADER)
+ goto found;
+ off <<= 1;
+ }
+
+ /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
+ header = (struct nvram_header *) KSEG1ADDR(base + 4096);
+ if (header->magic == NVRAM_HEADER)
+ goto found;
+
+ header = (struct nvram_header *) KSEG1ADDR(base + 1024);
+ if (header->magic == NVRAM_HEADER)
+ goto found;
+
+ return;
+
+found:
+ src = (u32 *) header;
+ dst = (u32 *) nvram_buf;
+ for (i = 0; i < sizeof(struct nvram_header); i += 4)
+ *dst++ = *src++;
+ for (; i < header->len && i < NVRAM_SPACE; i += 4)
+ *dst++ = le32_to_cpu(*src++);
+}
+
+int nvram_getenv(char *name, char *val, size_t val_len)
+{
+ char *var, *value, *end, *eq;
+
+ if (!name)
+ return 1;
+
+ if (!nvram_buf[0])
+ early_nvram_init();
+
+ /* Look for name=value and return value */
+ var = &nvram_buf[sizeof(struct nvram_header)];
+ end = nvram_buf + sizeof(nvram_buf) - 2;
+ end[0] = end[1] = '\0';
+ for (; *var; var = value + strlen(value) + 1) {
+ eq = strchr(var, '=');
+ if (!eq)
+ break;
+ value = eq + 1;
+ if ((eq - var) == strlen(name) &&
+ strncmp(var, name, (eq - var)) == 0) {
+ snprintf(val, val_len, "%s", value);
+ return 0;
+ }
+ }
+ return 1;
+}
+EXPORT_SYMBOL(nvram_getenv);
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -1,8 +1,8 @@
/*
* Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
- * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -33,6 +33,7 @@
#include <asm/time.h>
#include <bcm47xx.h>
#include <asm/fw/cfe/cfe_api.h>
+#include <asm/mach-bcm47xx/nvram.h>
struct ssb_bus ssb_bcm47xx;
EXPORT_SYMBOL(ssb_bcm47xx);
@@ -81,28 +82,42 @@ static int bcm47xx_get_invariants(struct
/* Fill boardinfo structure */
memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
- if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0)
+ if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 ||
+ nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
- if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0)
+ if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 ||
+ nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
- if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0)
+ if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 ||
+ nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
/* Fill sprom structure */
memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
iv->sprom.revision = 3;
- if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
+ if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 ||
+ nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
str2eaddr(buf, iv->sprom.et0mac);
- if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
+
+ if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 ||
+ nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
str2eaddr(buf, iv->sprom.et1mac);
- if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
- iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 10);
- if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
- iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 10);
- if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
+
+ if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ||
+ nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
+ iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0);
+
+ if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ||
+ nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
+ iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0);
+
+ if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 ||
+ nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
- if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
+
+ if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 ||
+ nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
return 0;
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm47xx/nvram.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2005, Broadcom Corporation
+ * Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __NVRAM_H
+#define __NVRAM_H
+
+#include <linux/types.h>
+
+struct nvram_header {
+ u32 magic;
+ u32 len;
+ u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
+ u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */
+ u32 config_ncdl; /* ncdl values for memc */
+};
+
+#define NVRAM_HEADER 0x48534C46 /* 'FLSH' */
+#define NVRAM_VERSION 1
+#define NVRAM_HEADER_SIZE 20
+#define NVRAM_SPACE 0x8000
+
+#define FLASH_MIN 0x00020000 /* Minimum flash size */
+
+#define NVRAM_MAX_VALUE_LEN 255
+#define NVRAM_MAX_PARAM_LEN 64
+
+extern int nvram_getenv(char *name, char *val, size_t val_len);
+
+#endif

View File

@ -1,3 +1,24 @@
From b6d850fe4035d6bee7199119358e06f802aa19ed Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 18 Jul 2010 12:49:41 +0200
Subject: [PATCH 1/5] MIPS: BCM47xx: Really fix 128MB RAM problem
The previews patch 84a6fcb368a080620d12fc4d79e07902dbee7335 was wrong,
I got wrong success reports.
The bcm47xx architecture maps the ram into a 128MB address space. It
will be paced there as often as goes into the 128MB. The detection
tries to find the position where the same memory is found. When reading
over 128MB the processor will throw an exception. If 128MB ram is
installed, it will not find the same memory because it tries to read
over the 128MB boarder. Now it just assumes 128MB installed ram if it
can not find that the ram is repeating.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/bcm47xx/prom.c | 22 ++++++++++++++--------
1 files changed, 14 insertions(+), 8 deletions(-)
--- a/arch/mips/bcm47xx/prom.c --- a/arch/mips/bcm47xx/prom.c
+++ b/arch/mips/bcm47xx/prom.c +++ b/arch/mips/bcm47xx/prom.c
@@ -126,6 +126,7 @@ static __init void prom_init_cmdline(voi @@ -126,6 +126,7 @@ static __init void prom_init_cmdline(voi

View File

@ -0,0 +1,158 @@
From d6c049e08568aac29fff854ea0385e63c7150e09 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 18 Jul 2010 13:34:32 +0200
Subject: [PATCH 2/5] MIPS: BCM47xx: Fill more values into ssb sprom
Most of the values are stored in the nvram and not in the CFE. At first
the nvram should be read and if there is no value it should look into
the CFE. Now more values are read out because the b43 and b43legacy
drivers needs them.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/bcm47xx/setup.c | 122 +++++++++++++++++++++++++++++++++------------
1 files changed, 89 insertions(+), 33 deletions(-)
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -74,6 +74,86 @@ static void str2eaddr(char *str, char *d
}
}
+static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
+{
+ char buf[100];
+
+ memset(sprom, 0, sizeof(struct ssb_sprom));
+
+ sprom->revision = 3;
+ if (nvram_getenv("il0macaddr", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("il0macaddr", buf, sizeof(buf)) >= 0)
+ str2eaddr(buf, sprom->il0mac);
+ if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
+ str2eaddr(buf, sprom->et0mac);
+ if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
+ str2eaddr(buf, sprom->et1mac);
+ if (nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
+ sprom->et0phyaddr = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
+ sprom->et1phyaddr = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
+ sprom->et0mdcport = !!simple_strtoul(buf, NULL, 10);
+ if (nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
+ sprom->et1mdcport = !!simple_strtoul(buf, NULL, 10);
+ if (nvram_getenv("pa0b0", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa0b0", buf, sizeof(buf)) >= 0)
+ sprom->pa0b0 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("pa0b1", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa0b1", buf, sizeof(buf)) >= 0)
+ sprom->pa0b1 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("pa0b2", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa0b2", buf, sizeof(buf)) >= 0)
+ sprom->pa0b2 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("pa1b0", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa1b0", buf, sizeof(buf)) >= 0)
+ sprom->pa1b0 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("pa1b1", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa1b1", buf, sizeof(buf)) >= 0)
+ sprom->pa1b1 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("pa1b2", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa1b2", buf, sizeof(buf)) >= 0)
+ sprom->pa1b2 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("wl0gpio0", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("wl0gpio0", buf, sizeof(buf)) >= 0)
+ sprom->gpio0 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("wl0gpio1", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("wl0gpio1", buf, sizeof(buf)) >= 0)
+ sprom->gpio1 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("wl0gpio2", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("wl0gpio2", buf, sizeof(buf)) >= 0)
+ sprom->gpio2 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("wl0gpio3", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("wl0gpio3", buf, sizeof(buf)) >= 0)
+ sprom->gpio3 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("pa0maxpwr", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa0maxpwr", buf, sizeof(buf)) >= 0)
+ sprom->maxpwr_bg = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("pa1maxpwr", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa1maxpwr", buf, sizeof(buf)) >= 0)
+ sprom->maxpwr_a = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("pa0itssit", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa0itssit", buf, sizeof(buf)) >= 0)
+ sprom->itssi_bg = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("pa1itssit", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa1itssit", buf, sizeof(buf)) >= 0)
+ sprom->itssi_a = simple_strtoul(buf, NULL, 0);
+ sprom->boardflags_lo = 0;
+ if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("boardflags", buf, sizeof(buf)) >= 0)
+ sprom->boardflags_lo = simple_strtoul(buf, NULL, 0);
+ sprom->boardflags_hi = 0;
+ if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("boardflags", buf, sizeof(buf)) >= 0)
+ sprom->boardflags_hi = simple_strtoul(buf, NULL, 0);
+}
+
static int bcm47xx_get_invariants(struct ssb_bus *bus,
struct ssb_init_invariants *iv)
{
@@ -82,43 +162,19 @@ static int bcm47xx_get_invariants(struct
/* Fill boardinfo structure */
memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
- if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 ||
- nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
+ iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
+ if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("boardtype", buf, sizeof(buf)) >= 0)
iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
- if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 ||
- nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
- iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
- if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 ||
- nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
+ if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("boardrev", buf, sizeof(buf)) >= 0)
iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
- /* Fill sprom structure */
- memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
- iv->sprom.revision = 3;
-
- if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 ||
- nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
- str2eaddr(buf, iv->sprom.et0mac);
-
- if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 ||
- nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
- str2eaddr(buf, iv->sprom.et1mac);
-
- if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ||
- nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
- iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0);
-
- if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ||
- nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
- iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0);
-
- if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 ||
- nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
- iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
-
- if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 ||
- nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
- iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
+ bcm47xx_fill_sprom(&iv->sprom);
+
+ if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("cardbus", buf, sizeof(buf)) >= 0)
+ iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
return 0;
}

View File

@ -0,0 +1,23 @@
From b1a0abc936bf61689d1e8a56c423b232cff24da5 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 18 Jul 2010 13:58:09 +0200
Subject: [PATCH 3/5] MIPS: BCM47xx: Activate SSB_B43_PCI_BRIDGE by default
The b43_pci_bridge is needed to use the b43 driver with brcm47xx.
Activate it by default if pci is available.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/Kconfig | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -62,6 +62,7 @@ config BCM47XX
select SSB_DRIVER_MIPS
select SSB_DRIVER_EXTIF
select SSB_EMBEDDED
+ select SSB_B43_PCI_BRIDGE if PCI
select SSB_PCICORE_HOSTMODE if PCI
select GENERIC_GPIO
select SYS_HAS_EARLY_PRINTK

View File

@ -0,0 +1,81 @@
From 4c6a515310f29c89f25a54a115cde905f97330f8 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 18 Jul 2010 14:59:24 +0200
Subject: [PATCH 4/5] MIPS: BCM47xx: Setup and register serial early
Swap the first and second serial if console=ttyS1 was set.
Set it up and register it for early serial support.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/Kconfig | 1 -
arch/mips/bcm47xx/setup.c | 36 +++++++++++++++++++++++++++++++++++-
2 files changed, 35 insertions(+), 2 deletions(-)
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -65,7 +65,6 @@ config BCM47XX
select SSB_B43_PCI_BRIDGE if PCI
select SSB_PCICORE_HOSTMODE if PCI
select GENERIC_GPIO
- select SYS_HAS_EARLY_PRINTK
select CFE
help
Support for BCM47XX based boards
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -28,6 +28,8 @@
#include <linux/types.h>
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_embedded.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
#include <asm/bootinfo.h>
#include <asm/reboot.h>
#include <asm/time.h>
@@ -181,12 +183,44 @@ static int bcm47xx_get_invariants(struct
void __init plat_mem_setup(void)
{
- int err;
+ int i, err;
+ char buf[100];
+ struct ssb_mipscore *mcore;
err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
bcm47xx_get_invariants);
if (err)
panic("Failed to initialize SSB bus (err %d)\n", err);
+ mcore = &ssb_bcm47xx.mipscore;
+
+ nvram_getenv("kernel_args", buf, sizeof(buf));
+ if (!strncmp(buf, "console=ttyS1", 13)) {
+ struct ssb_serial_port port;
+
+ printk("Swapping serial ports!\n");
+ /* swap serial ports */
+ memcpy(&port, &mcore->serial_ports[0], sizeof(port));
+ memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1], sizeof(port));
+ memcpy(&mcore->serial_ports[1], &port, sizeof(port));
+ }
+
+ for (i = 0; i < mcore->nr_serial_ports; i++) {
+ struct ssb_serial_port *port = &(mcore->serial_ports[i]);
+ struct uart_port s;
+
+ memset(&s, 0, sizeof(s));
+ s.line = i;
+ s.mapbase = (unsigned int) port->regs;
+ s.membase = port->regs;
+ s.irq = port->irq + 2;
+ s.uartclk = port->baud_base;
+ s.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ s.iotype = SERIAL_IO_MEM;
+ s.regshift = port->reg_shift;
+
+ early_serial_setup(&s);
+ }
+ printk("Serial init done.\n");
_machine_restart = bcm47xx_machine_restart;
_machine_halt = bcm47xx_machine_halt;

View File

@ -0,0 +1,130 @@
From 6bd2c73ed31a2dfe7eab04d32c17318a5c62f9d4 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 18 Jul 2010 15:11:26 +0200
Subject: [PATCH 5/5] MIPS: BCM47xx: Remove CFE console
Do not use the CFE console. It causes hangs on some devices like the
Buffalo WHR-HP-G54.
This was reported in https://dev.openwrt.org/ticket/4061 and
https://forum.openwrt.org/viewtopic.php?id=17063
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/bcm47xx/prom.c | 82 +++------------------------------------------
1 files changed, 6 insertions(+), 76 deletions(-)
--- a/arch/mips/bcm47xx/prom.c
+++ b/arch/mips/bcm47xx/prom.c
@@ -31,96 +31,28 @@
#include <asm/fw/cfe/cfe_api.h>
#include <asm/fw/cfe/cfe_error.h>
-static int cfe_cons_handle;
-
const char *get_system_type(void)
{
return "Broadcom BCM47XX";
}
-void prom_putchar(char c)
-{
- while (cfe_write(cfe_cons_handle, &c, 1) == 0)
- ;
-}
-
-static __init void prom_init_cfe(void)
+static __init int prom_init_cfe(void)
{
uint32_t cfe_ept;
uint32_t cfe_handle;
uint32_t cfe_eptseal;
- int argc = fw_arg0;
- char **envp = (char **) fw_arg2;
- int *prom_vec = (int *) fw_arg3;
-
- /*
- * Check if a loader was used; if NOT, the 4 arguments are
- * what CFE gives us (handle, 0, EPT and EPTSEAL)
- */
- if (argc < 0) {
- cfe_handle = (uint32_t)argc;
- cfe_ept = (uint32_t)envp;
- cfe_eptseal = (uint32_t)prom_vec;
- } else {
- if ((int)prom_vec < 0) {
- /*
- * Old loader; all it gives us is the handle,
- * so use the "known" entrypoint and assume
- * the seal.
- */
- cfe_handle = (uint32_t)prom_vec;
- cfe_ept = 0xBFC00500;
- cfe_eptseal = CFE_EPTSEAL;
- } else {
- /*
- * Newer loaders bundle the handle/ept/eptseal
- * Note: prom_vec is in the loader's useg
- * which is still alive in the TLB.
- */
- cfe_handle = prom_vec[0];
- cfe_ept = prom_vec[2];
- cfe_eptseal = prom_vec[3];
- }
- }
+
+ cfe_eptseal = (uint32_t) fw_arg3;
+ cfe_handle = (uint32_t) fw_arg0;
+ cfe_ept = (uint32_t) fw_arg2;
if (cfe_eptseal != CFE_EPTSEAL) {
- /* too early for panic to do any good */
printk(KERN_ERR "CFE's entrypoint seal doesn't match.");
- while (1) ;
+ return -1;
}
cfe_init(cfe_handle, cfe_ept);
-}
-
-static __init void prom_init_console(void)
-{
- /* Initialize CFE console */
- cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
-}
-
-static __init void prom_init_cmdline(void)
-{
- static char buf[COMMAND_LINE_SIZE] __initdata;
-
- /* Get the kernel command line from CFE */
- if (cfe_getenv("LINUX_CMDLINE", buf, COMMAND_LINE_SIZE) >= 0) {
- buf[COMMAND_LINE_SIZE - 1] = 0;
- strcpy(arcs_cmdline, buf);
- }
-
- /* Force a console handover by adding a console= argument if needed,
- * as CFE is not available anymore later in the boot process. */
- if ((strstr(arcs_cmdline, "console=")) == NULL) {
- /* Try to read the default serial port used by CFE */
- if ((cfe_getenv("BOOT_CONSOLE", buf, COMMAND_LINE_SIZE) < 0)
- || (strncmp("uart", buf, 4)))
- /* Default to uart0 */
- strcpy(buf, "uart0");
-
- /* Compute the new command line */
- snprintf(arcs_cmdline, COMMAND_LINE_SIZE, "%s console=ttyS%c,115200",
- arcs_cmdline, buf[4]);
- }
+ return 0;
}
static __init void prom_init_mem(void)
@@ -161,8 +93,6 @@ static __init void prom_init_mem(void)
void __init prom_init(void)
{
prom_init_cfe();
- prom_init_console();
- prom_init_cmdline();
prom_init_mem();
}

View File

@ -0,0 +1,95 @@
From cb33ffbdd8491c58b35958ec74c39b3a5c7fabe8 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 18 Jul 2010 21:25:03 +0200
Subject: [PATCH 1/2] USB: Add USB 2.0 to ssb ohci driver
This adds USB 2.0 support to ssb ohci driver.
This work was done based on Braodcom source code in the OpenWRT project.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
drivers/usb/host/ohci-ssb.c | 55 ++++++++++++++++++++++++++++++++++++++++--
1 files changed, 52 insertions(+), 3 deletions(-)
--- a/drivers/usb/host/ohci-ssb.c
+++ b/drivers/usb/host/ohci-ssb.c
@@ -92,9 +92,12 @@ static const struct hc_driver ssb_ohci_h
static void ssb_ohci_detach(struct ssb_device *dev)
{
struct usb_hcd *hcd = ssb_get_drvdata(dev);
+ if (hcd->driver->shutdown)
+ hcd->driver->shutdown(hcd);
usb_remove_hcd(hcd);
iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
ssb_device_disable(dev, 0);
}
@@ -106,10 +109,55 @@ static int ssb_ohci_attach(struct ssb_de
int err = -ENOMEM;
u32 tmp, flags = 0;
- if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV)
- flags |= SSB_OHCI_TMSLOW_HOSTMODE;
+ if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
+ dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
+ return -EOPNOTSUPP;
- ssb_device_enable(dev, flags);
+ if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
+ /* Put the device into host-mode. */
+ flags |= SSB_OHCI_TMSLOW_HOSTMODE;
+ ssb_device_enable(dev, flags);
+ } else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
+ /*
+ * USB 2.0 special considerations:
+ *
+ * 1. Since the core supports both ehci and EHCI functions, it must
+ * only be reset once.
+ *
+ * 2. In addition to the standard SSB reset sequence, the Host Control
+ * Register must be programmed to bring the USB core and various
+ * phy components out of reset.
+ */
+ ssb_device_enable(dev, 0);
+ ssb_write32(dev, 0x200, 0x7ff);
+
+ /* Change Flush control reg */
+ tmp = ssb_read32(dev, 0x400);
+ tmp &= ~8;
+ ssb_write32(dev, 0x400, tmp);
+ tmp = ssb_read32(dev, 0x400);
+
+ /* Change Shim control reg */
+ tmp = ssb_read32(dev, 0x304);
+ tmp &= ~0x100;
+ ssb_write32(dev, 0x304, tmp);
+ tmp = ssb_read32(dev, 0x304);
+
+ udelay(1);
+
+ /* Work around for 5354 failures */
+ if ((dev->id.revision == 2) && (dev->bus->chip_id == 0x5354)) {
+ /* Change syn01 reg */
+ tmp = 0x00fe00fe;
+ ssb_write32(dev, 0x894, tmp);
+
+ /* Change syn03 reg */
+ tmp = ssb_read32(dev, 0x89c);
+ tmp |= 0x1;
+ ssb_write32(dev, 0x89c, tmp);
+ }
+ } else
+ ssb_device_enable(dev, 0);
hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
dev_name(dev->dev));
@@ -200,6 +248,7 @@ static int ssb_ohci_resume(struct ssb_de
static const struct ssb_device_id ssb_ohci_table[] = {
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
SSB_DEVTABLE_END
};
MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);

View File

@ -1,9 +1,17 @@
From cb269cf1f97c316a5184080814a751687c72b718 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 18 Jul 2010 21:29:40 +0200
Subject: [PATCH 2/2] USB: Add ehci ssb driver
Support for the Sonics Silicon Backplane (SSB) attached Broadcom USB EHCI core.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
--- ---
drivers/usb/host/Kconfig | 13 ++ drivers/usb/host/Kconfig | 13 ++
drivers/usb/host/ehci-hcd.c | 12 ++ drivers/usb/host/ehci-hcd.c | 23 ++++-
drivers/usb/host/ehci-ssb.c | 201 ++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/ehci-ssb.c | 258 +++++++++++++++++++++++++++++++++++++++++++
drivers/usb/host/ohci-ssb.c | 23 +++++ 3 files changed, 292 insertions(+), 2 deletions(-)
4 files changed, 247 insertions(+), 2 deletions(-) create mode 100644 drivers/usb/host/ehci-ssb.c
--- a/drivers/usb/host/Kconfig --- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig
@ -13,7 +21,7 @@
+config USB_EHCI_HCD_SSB +config USB_EHCI_HCD_SSB
+ bool "EHCI support for Broadcom SSB EHCI core" + bool "EHCI support for Broadcom SSB EHCI core"
+ depends on USB_EHCI_HCD && SSB && EXPERIMENTAL + depends on USB_EHCI_HCD && (SSB = y || SSB = USB_EHCI_HCD) && EXPERIMENTAL
+ default n + default n
+ ---help--- + ---help---
+ Support for the Sonics Silicon Backplane (SSB) attached + Support for the Sonics Silicon Backplane (SSB) attached
@ -29,33 +37,63 @@
depends on USB depends on USB
--- a/drivers/usb/host/ehci-hcd.c --- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c
@@ -1159,8 +1159,16 @@ MODULE_LICENSE ("GPL"); @@ -1159,8 +1159,14 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_atmel_driver #define PLATFORM_DRIVER ehci_atmel_driver
#endif #endif
-#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
- !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER)
+#ifdef CONFIG_USB_EHCI_HCD_SSB +#ifdef CONFIG_USB_EHCI_HCD_SSB
+#include "ehci-ssb.c" +#include "ehci-ssb.c"
+#define SSB_EHCI_DRIVER ssb_ehci_driver +#define SSB_EHCI_DRIVER ssb_ehci_driver
+#endif +#endif
+ +
+#if !defined(PCI_DRIVER) && \ #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
+ !defined(PLATFORM_DRIVER) && \ - !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER)
+ !defined(PS3_SYSTEM_BUS_DRIVER) && \ + !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
+ !defined(OF_PLATFORM_DRIVER) && \
+ !defined(SSB_EHCI_DRIVER) + !defined(SSB_EHCI_DRIVER)
#error "missing bus glue for ehci-hcd" #error "missing bus glue for ehci-hcd"
#endif #endif
@@ -1214,10 +1220,20 @@ static int __init ehci_hcd_init(void)
if (retval < 0)
goto clean3;
#endif
+
+#ifdef SSB_EHCI_DRIVER
+ retval = ssb_driver_register(&SSB_EHCI_DRIVER);
+ if (retval < 0)
+ goto clean4;
+#endif
return retval;
+#ifdef SSB_EHCI_DRIVER
+ /* ssb_driver_unregister(&SSB_EHCI_DRIVER); */
+clean4:
+#endif
#ifdef OF_PLATFORM_DRIVER
- /* of_unregister_platform_driver(&OF_PLATFORM_DRIVER); */
+ of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
clean3:
#endif
#ifdef PS3_SYSTEM_BUS_DRIVER
@@ -1256,6 +1272,9 @@ static void __exit ehci_hcd_cleanup(void
#ifdef PS3_SYSTEM_BUS_DRIVER
ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
#endif
+#ifdef SSB_EHCI_DRIVER
+ ssb_driver_unregister(&SSB_EHCI_DRIVER);
+#endif
#ifdef DEBUG
debugfs_remove(ehci_debug_root);
#endif
--- /dev/null --- /dev/null
+++ b/drivers/usb/host/ehci-ssb.c +++ b/drivers/usb/host/ehci-ssb.c
@@ -0,0 +1,158 @@ @@ -0,0 +1,258 @@
+/* +/*
+ * Sonics Silicon Backplane + * Sonics Silicon Backplane
+ * Broadcom USB-core EHCI driver (SSB bus glue) + * Broadcom USB-core EHCI driver (SSB bus glue)
+ * + *
+ * Copyright 2007 Steven Brown <sbrown@cortland.com> + * Copyright 2007 Steven Brown <sbrown@cortland.com>
+ * Copyright 2010 Hauke Mehrtens <hauke@hauke-m.de>
+ * + *
+ * Derived from the OHCI-SSB driver + * Derived from the OHCI-SSB driver
+ * Copyright 2007 Michael Buesch <mb@bu3sch.de> + * Copyright 2007 Michael Buesch <mb@bu3sch.de>
@ -76,12 +114,9 @@
+ */ + */
+#include <linux/ssb/ssb.h> +#include <linux/ssb/ssb.h>
+ +
+#define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29)
+ +
+struct ssb_ehci_device { +struct ssb_ehci_device {
+ struct ehci_hcd ehci; /* _must_ be at the beginning. */ + struct ehci_hcd ehci; /* _must_ be at the beginning. */
+
+ u32 enable_flags;
+}; +};
+ +
+static inline +static inline
@ -141,34 +176,78 @@
+ +
+ .hub_status_data = ehci_hub_status_data, + .hub_status_data = ehci_hub_status_data,
+ .hub_control = ehci_hub_control, + .hub_control = ehci_hub_control,
+#if defined(CONFIG_PM)
+ .bus_suspend = ehci_bus_suspend, + .bus_suspend = ehci_bus_suspend,
+ .bus_resume = ehci_bus_resume, + .bus_resume = ehci_bus_resume,
+#endif
+ .relinquish_port = ehci_relinquish_port, + .relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over, + .port_handed_over = ehci_port_handed_over,
+ +
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, + .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+}; +};
+ +
+static void ssb_ehci_detach(struct ssb_device *dev, struct usb_hcd *hcd) +static void ssb_ehci_detach(struct ssb_device *dev)
+{ +{
+ struct usb_hcd *hcd = ssb_get_drvdata(dev);
+ if (hcd->driver->shutdown) + if (hcd->driver->shutdown)
+ hcd->driver->shutdown(hcd); + hcd->driver->shutdown(hcd);
+ +
+ usb_remove_hcd(hcd); + usb_remove_hcd(hcd);
+
+ iounmap(hcd->regs); + iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+ usb_put_hcd(hcd); + usb_put_hcd(hcd);
+ ssb_device_disable(dev, 0);
+} +}
+EXPORT_SYMBOL_GPL(ssb_ehci_detach);
+ +
+static int ssb_ehci_attach(struct ssb_device *dev, struct usb_hcd **ehci_hcd) +static int ssb_ehci_attach(struct ssb_device *dev)
+{ +{
+ struct ssb_ehci_device *ehcidev; + struct ssb_ehci_device *ehcidev;
+ struct usb_hcd *hcd; + struct usb_hcd *hcd;
+ int err = -ENOMEM; + int err = -ENOMEM;
+ u32 tmp, flags = 0; + u32 tmp;
+
+ if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
+ dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
+ return -EOPNOTSUPP;
+
+ /*
+ * USB 2.0 special considerations:
+ *
+ * 1. Since the core supports both ehci and EHCI functions, it must
+ * only be reset once.
+ *
+ * 2. In addition to the standard SSB reset sequence, the Host Control
+ * Register must be programmed to bring the USB core and various
+ * phy components out of reset.
+ */
+ ssb_device_enable(dev, 0);
+ ssb_write32(dev, 0x200, 0x7ff);
+
+ /* Change Flush control reg */
+ tmp = ssb_read32(dev, 0x400);
+ tmp &= ~8;
+ ssb_write32(dev, 0x400, tmp);
+ tmp = ssb_read32(dev, 0x400);
+
+ /* Change Shim control reg */
+ tmp = ssb_read32(dev, 0x304);
+ tmp &= ~0x100;
+ ssb_write32(dev, 0x304, tmp);
+ tmp = ssb_read32(dev, 0x304);
+
+ udelay(1);
+
+ /* Work around for 5354 failures */
+ if ((dev->id.revision == 2) && (dev->bus->chip_id == 0x5354)) {
+ /* Change syn01 reg */
+ tmp = 0x00fe00fe;
+ ssb_write32(dev, 0x894, tmp);
+
+ /* Change syn03 reg */
+ tmp = ssb_read32(dev, 0x89c);
+ tmp |= 0x1;
+ ssb_write32(dev, 0x89c, tmp);
+ }
+ +
+ hcd = usb_create_hcd(&ssb_ehci_hc_driver, dev->dev, + hcd = usb_create_hcd(&ssb_ehci_hc_driver, dev->dev,
+ dev_name(dev->dev)); + dev_name(dev->dev));
@ -176,7 +255,6 @@
+ goto err_dev_disable; + goto err_dev_disable;
+ +
+ ehcidev = hcd_to_ssb_ehci(hcd); + ehcidev = hcd_to_ssb_ehci(hcd);
+ ehcidev->enable_flags = flags;
+ tmp = ssb_read32(dev, SSB_ADMATCH0); + tmp = ssb_read32(dev, SSB_ADMATCH0);
+ hcd->rsrc_start = ssb_admatch_base(tmp) + 0x800; /* ehci core offset */ + hcd->rsrc_start = ssb_admatch_base(tmp) + 0x800; /* ehci core offset */
+ hcd->rsrc_len = 0x100; /* ehci reg block size */ + hcd->rsrc_len = 0x100; /* ehci reg block size */
@ -186,11 +264,11 @@
+ hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+ if (!hcd->regs) + if (!hcd->regs)
+ goto err_put_hcd; + goto err_put_hcd;
+ err = usb_add_hcd(hcd, dev->irq, IRQF_SHARED | IRQF_DISABLED); + err = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED);
+ if (err) + if (err)
+ goto err_iounmap; + goto err_iounmap;
+ +
+ *ehci_hcd = hcd; + ssb_set_drvdata(dev, hcd);
+ +
+ return err; + return err;
+ +
@ -199,73 +277,72 @@
+err_put_hcd: +err_put_hcd:
+ usb_put_hcd(hcd); + usb_put_hcd(hcd);
+err_dev_disable: +err_dev_disable:
+ ssb_device_disable(dev, flags); + ssb_device_disable(dev, 0);
+ return err; + return err;
+} +}
+EXPORT_SYMBOL_GPL(ssb_ehci_attach); +
+static int ssb_ehci_probe(struct ssb_device *dev,
+ const struct ssb_device_id *id)
+{
+ int err;
+ u16 chipid_top;
+
+ /* USBcores are only connected on embedded devices. */
+ chipid_top = (dev->bus->chip_id & 0xFF00);
+ if (chipid_top != 0x4700 && chipid_top != 0x5300)
+ return -ENODEV;
+
+ /* TODO: Probably need checks here; is the core connected? */
+
+ if (usb_disabled())
+ return -ENODEV;
+
+ err = ssb_ehci_attach(dev);
+
+ return err;
+}
+
+static void ssb_ehci_remove(struct ssb_device *dev)
+{
+ ssb_ehci_detach(dev);
+}
+
+#ifdef CONFIG_PM
+
+static int ssb_ehci_suspend(struct ssb_device *dev, pm_message_t state)
+{
+ ssb_device_disable(dev, 0);
+
+ return 0;
+}
+
+static int ssb_ehci_resume(struct ssb_device *dev)
+{
+ struct usb_hcd *hcd = ssb_get_drvdata(dev);
+ struct ssb_ehci_device *ehcidev = hcd_to_ssb_ehci(hcd);
+
+ ssb_device_enable(dev, 0);
+
+ ehci_finish_controller_resume(hcd);
+ return 0;
+}
+
+#else /* !CONFIG_PM */
+#define ssb_ehci_suspend NULL
+#define ssb_ehci_resume NULL
+#endif /* CONFIG_PM */
+ +
+static const struct ssb_device_id ssb_ehci_table[] = { +static const struct ssb_device_id ssb_ehci_table[] = {
+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV), + SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
+ SSB_DEVTABLE_END + SSB_DEVTABLE_END
+}; +};
+MODULE_DEVICE_TABLE(ssb, ssb_ehci_table); +MODULE_DEVICE_TABLE(ssb, ssb_ehci_table);
--- a/drivers/usb/host/ohci-ssb.c
+++ b/drivers/usb/host/ohci-ssb.c
@@ -17,6 +17,8 @@
*/
#include <linux/ssb/ssb.h>
+extern int ssb_ehci_attach(struct ssb_device *dev, struct usb_hcd **hcd);
+extern void ssb_ehci_detach(struct ssb_device *dev, struct usb_hcd *hcd);
#define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29)
@@ -24,6 +26,7 @@ struct ssb_ohci_device {
struct ohci_hcd ohci; /* _must_ be at the beginning. */
u32 enable_flags;
+ struct usb_hcd *ehci_hcd;
};
static inline
@@ -92,13 +95,25 @@ static const struct hc_driver ssb_ohci_h
static void ssb_ohci_detach(struct ssb_device *dev)
{
struct usb_hcd *hcd = ssb_get_drvdata(dev);
+#ifdef CONFIG_USB_EHCI_HCD_SSB
+ struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
+#endif
usb_remove_hcd(hcd);
iounmap(hcd->regs);
usb_put_hcd(hcd);
+ +
+#ifdef CONFIG_USB_EHCI_HCD_SSB +static struct ssb_driver ssb_ehci_driver = {
+ /* + .name = KBUILD_MODNAME,
+ * Also detach ehci function + .id_table = ssb_ehci_table,
+ */ + .probe = ssb_ehci_probe,
+ if (dev->id.coreid == SSB_DEV_USB20_HOST) + .remove = ssb_ehci_remove,
+ ssb_ehci_detach(dev, ohcidev->ehci_hcd); + .suspend = ssb_ehci_suspend,
+#endif + .resume = ssb_ehci_resume,
ssb_device_disable(dev, 0); +};
}
+
static int ssb_ohci_attach(struct ssb_device *dev)
{
struct ssb_ohci_device *ohcidev;
@@ -165,6 +180,14 @@ static int ssb_ohci_attach(struct ssb_de
ssb_set_drvdata(dev, hcd);
+#ifdef CONFIG_USB_EHCI_HCD_SSB
+ /*
+ * attach ehci function in this core
+ */
+ if (dev->id.coreid == SSB_DEV_USB20_HOST)
+ err = ssb_ehci_attach(dev, &(ohcidev->ehci_hcd));
+#endif
+
return err;
err_iounmap:

View File

@ -1,89 +0,0 @@
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -205,7 +205,6 @@ config MIPS_MALTA
select I8259
select MIPS_BOARDS_GEN
select MIPS_BONITO64
- select MIPS_CPU_SCACHE
select PCI_GT64XXX_PCI0
select MIPS_MSC
select SWAP_IO_SPACE
@@ -1589,13 +1588,6 @@ config IP22_CPU_SCACHE
bool
select BOARD_SCACHE
-#
-# Support for a MIPS32 / MIPS64 style S-caches
-#
-config MIPS_CPU_SCACHE
- bool
- select BOARD_SCACHE
-
config R5000_CPU_SCACHE
bool
select BOARD_SCACHE
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -772,6 +772,8 @@ static inline void cpu_probe_mips(struct
case PRID_IMP_25KF:
c->cputype = CPU_25KF;
__cpu_name[cpu] = "MIPS 25Kc";
+ /* Probe for L2 cache */
+ c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
break;
case PRID_IMP_34K:
c->cputype = CPU_34K;
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -33,6 +33,5 @@ obj-$(CONFIG_CPU_CAVIUM_OCTEON) += c-oct
obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o
obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o
obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
-obj-$(CONFIG_MIPS_CPU_SCACHE) += sc-mips.o
EXTRA_CFLAGS += -Werror
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1148,7 +1148,6 @@ static void __init loongson2_sc_init(voi
extern int r5k_sc_init(void);
extern int rm7k_sc_init(void);
-extern int mips_sc_init(void);
static void __cpuinit setup_scache(void)
{
@@ -1202,29 +1201,17 @@ static void __cpuinit setup_scache(void)
#endif
default:
- if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
- c->isa_level == MIPS_CPU_ISA_M32R2 ||
- c->isa_level == MIPS_CPU_ISA_M64R1 ||
- c->isa_level == MIPS_CPU_ISA_M64R2) {
-#ifdef CONFIG_MIPS_CPU_SCACHE
- if (mips_sc_init ()) {
- scache_size = c->scache.ways * c->scache.sets * c->scache.linesz;
- printk("MIPS secondary cache %ldkB, %s, linesize %d bytes.\n",
- scache_size >> 10,
- way_string[c->scache.ways], c->scache.linesz);
- }
-#else
- if (!(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
- panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
-#endif
- return;
- }
sc_present = 0;
}
if (!sc_present)
return;
+ if ((c->isa_level == MIPS_CPU_ISA_M32R1 ||
+ c->isa_level == MIPS_CPU_ISA_M64R1) &&
+ !(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
+ panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
+
/* compute a couple of other cache variables */
c->scache.waysize = scache_size / c->scache.ways;

View File

@ -295,7 +295,7 @@
if (dc_lsize) if (dc_lsize)
protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
if (!cpu_icache_snoops_remote_store && scache_size) if (!cpu_icache_snoops_remote_store && scache_size)
@@ -1298,6 +1312,17 @@ static void __cpuinit coherency_setup(vo @@ -1311,6 +1325,17 @@ static void __cpuinit coherency_setup(vo
* silly idea of putting something else there ... * silly idea of putting something else there ...
*/ */
switch (current_cpu_type()) { switch (current_cpu_type()) {
@ -313,7 +313,7 @@
case CPU_R4000PC: case CPU_R4000PC:
case CPU_R4000SC: case CPU_R4000SC:
case CPU_R4000MC: case CPU_R4000MC:
@@ -1354,6 +1379,15 @@ void __cpuinit r4k_cache_init(void) @@ -1367,6 +1392,15 @@ void __cpuinit r4k_cache_init(void)
break; break;
} }
@ -329,7 +329,7 @@
probe_pcache(); probe_pcache();
setup_scache(); setup_scache();
@@ -1412,5 +1446,13 @@ void __cpuinit r4k_cache_init(void) @@ -1425,5 +1459,13 @@ void __cpuinit r4k_cache_init(void)
#if !defined(CONFIG_MIPS_CMP) #if !defined(CONFIG_MIPS_CMP)
local_r4k___flush_cache_all(NULL); local_r4k___flush_cache_all(NULL);
#endif #endif

View File

@ -1,36 +1,58 @@
--- a/drivers/net/b44.c --- a/drivers/net/b44.c
+++ b/drivers/net/b44.c +++ b/drivers/net/b44.c
@@ -384,7 +384,7 @@ static void b44_set_flow_ctrl(struct b44 @@ -381,11 +381,12 @@ static void b44_set_flow_ctrl(struct b44
__b44_set_flow_ctrl(bp, pause_enab); __b44_set_flow_ctrl(bp, pause_enab);
} }
-#ifdef SSB_DRIVER_MIPS -#ifdef SSB_DRIVER_MIPS
+#ifdef CONFIG_SSB_DRIVER_MIPS -extern char *nvram_get(char *name);
extern char *nvram_get(char *name); +#ifdef CONFIG_BCM47XX
+
+#include <asm/mach-bcm47xx/nvram.h>
static void b44_wap54g10_workaround(struct b44 *bp) static void b44_wap54g10_workaround(struct b44 *bp)
{ {
@@ -421,12 +421,45 @@ static inline void b44_wap54g10_workarou - const char *str;
} + char buf[20];
#endif u32 val;
int err;
+#ifdef CONFIG_SSB_DRIVER_MIPS @@ -394,10 +395,9 @@ static void b44_wap54g10_workaround(stru
* see https://dev.openwrt.org/ticket/146
* check and reset bit "isolate"
*/
- str = nvram_get("boardnum");
- if (!str)
+ if (nvram_getenv("boardnum", buf, sizeof(buf)) > 0)
return;
- if (simple_strtoul(str, NULL, 0) == 2) {
+ if (simple_strtoul(buf, NULL, 0) == 2) {
err = __b44_readphy(bp, 0, MII_BMCR, &val);
if (err)
goto error;
@@ -412,10 +412,43 @@ static void b44_wap54g10_workaround(stru
error:
pr_warning("PHY: cannot reset MII transceiver isolate bit\n");
}
+
+static inline int startswith (const char *source, const char *cmp) +static inline int startswith (const char *source, const char *cmp)
+{ +{
+ return !strncmp(source,cmp,strlen(cmp)); + return !strncmp(source,cmp,strlen(cmp));
+} +}
+ +
+#define getvar(str) (nvram_get(str) ? : "")
+
+static inline void b44_bcm47xx_workarounds(struct b44 *bp) +static inline void b44_bcm47xx_workarounds(struct b44 *bp)
+{ +{
+ char buf[20];
+ /* Toshiba WRC-1000, Siemens SE505 v1, Askey RT-210W, RT-220W */ + /* Toshiba WRC-1000, Siemens SE505 v1, Askey RT-210W, RT-220W */
+ if (simple_strtoul(getvar("boardnum"), NULL, 0) == 100) { + if (nvram_getenv("boardnum", buf, sizeof(buf)) > 0)
+ return;
+ if (simple_strtoul(buf, NULL, 0) == 100) {
+ bp->phy_addr = B44_PHY_ADDR_NO_PHY; + bp->phy_addr = B44_PHY_ADDR_NO_PHY;
+ } else { + } else {
+ /* WL-HDD */ + /* WL-HDD */
+ struct ssb_device *sdev = bp->sdev; + struct ssb_device *sdev = bp->sdev;
+ if (startswith(getvar("hardware_version"), "WL300-")) + if (nvram_getenv("hardware_version", buf, sizeof(buf)) > 0)
+ { + return;
+ if (startswith(buf, "WL300-")) {
+ if (sdev->bus->sprom.et0phyaddr == 0 && + if (sdev->bus->sprom.et0phyaddr == 0 &&
+ sdev->bus->sprom.et1phyaddr == 1) + sdev->bus->sprom.et1phyaddr == 1)
+ bp->phy_addr = B44_PHY_ADDR_NO_PHY; + bp->phy_addr = B44_PHY_ADDR_NO_PHY;
@ -39,15 +61,19 @@
+ return; + return;
+} +}
+ +
+#else #else
+
static inline void b44_wap54g10_workaround(struct b44 *bp)
{
}
+
+static inline void b44_bcm47xx_workarounds(struct b44 *bp) +static inline void b44_bcm47xx_workarounds(struct b44 *bp)
+{ +{
+} +}
+#endif #endif
+
static int b44_setup_phy(struct b44 *bp) static int b44_setup_phy(struct b44 *bp)
{ @@ -424,6 +457,7 @@ static int b44_setup_phy(struct b44 *bp)
u32 val;
int err; int err;
b44_wap54g10_workaround(bp); b44_wap54g10_workaround(bp);
@ -55,7 +81,7 @@
if (bp->phy_addr == B44_PHY_ADDR_NO_PHY) if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
return 0; return 0;
@@ -2089,6 +2122,8 @@ static int __devinit b44_get_invariants( @@ -2080,6 +2114,8 @@ static int __devinit b44_get_invariants(
* valid PHY address. */ * valid PHY address. */
bp->phy_addr &= 0x1F; bp->phy_addr &= 0x1F;

View File

@ -1,6 +1,6 @@
--- a/drivers/net/b44.c --- a/drivers/net/b44.c
+++ b/drivers/net/b44.c +++ b/drivers/net/b44.c
@@ -191,10 +190,11 @@ static int b44_wait_bit(struct b44 *bp, @@ -188,10 +188,11 @@ static int b44_wait_bit(struct b44 *bp,
udelay(10); udelay(10);
} }
if (i == timeout) { if (i == timeout) {

View File

@ -1,6 +1,6 @@
--- a/drivers/ssb/driver_chipcommon.c --- a/drivers/ssb/driver_chipcommon.c
+++ b/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c
@@ -260,6 +260,8 @@ void ssb_chipco_resume(struct ssb_chipco @@ -285,6 +285,8 @@ void ssb_chipco_resume(struct ssb_chipco
void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc, void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
u32 *plltype, u32 *n, u32 *m) u32 *plltype, u32 *n, u32 *m)
{ {
@ -9,7 +9,7 @@
*n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N); *n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N);
*plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT); *plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
switch (*plltype) { switch (*plltype) {
@@ -283,6 +285,8 @@ void ssb_chipco_get_clockcpu(struct ssb_ @@ -308,6 +310,8 @@ void ssb_chipco_get_clockcpu(struct ssb_
void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc, void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,
u32 *plltype, u32 *n, u32 *m) u32 *plltype, u32 *n, u32 *m)
{ {
@ -31,7 +31,7 @@
} }
--- a/drivers/ssb/main.c --- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c +++ b/drivers/ssb/main.c
@@ -1073,6 +1073,8 @@ u32 ssb_clockspeed(struct ssb_bus *bus) @@ -1075,6 +1075,8 @@ u32 ssb_clockspeed(struct ssb_bus *bus)
if (bus->chip_id == 0x5365) { if (bus->chip_id == 0x5365) {
rate = 100000000; rate = 100000000;

View File

@ -1,60 +0,0 @@
---
drivers/usb/host/ohci-ssb.c | 39 ++++++++++++++++++++++++++++++++++++---
1 file changed, 36 insertions(+), 3 deletions(-)
--- a/drivers/usb/host/ohci-ssb.c
+++ b/drivers/usb/host/ohci-ssb.c
@@ -106,10 +106,42 @@ static int ssb_ohci_attach(struct ssb_de
int err = -ENOMEM;
u32 tmp, flags = 0;
- if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV)
+ if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
+ /* Put the device into host-mode. */
flags |= SSB_OHCI_TMSLOW_HOSTMODE;
-
- ssb_device_enable(dev, flags);
+ ssb_device_enable(dev, flags);
+ } else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
+ /*
+ * USB 2.0 special considerations:
+ *
+ * 1. Since the core supports both OHCI and EHCI functions, it must
+ * only be reset once.
+ *
+ * 2. In addition to the standard SSB reset sequence, the Host Control
+ * Register must be programmed to bring the USB core and various
+ * phy components out of reset.
+ */
+ ssb_device_enable(dev, 0);
+ ssb_write32(dev, 0x200, 0x7ff);
+ udelay(1);
+ if (dev->id.revision == 1) { // bug in rev 1
+
+ /* Change Flush control reg */
+ tmp = ssb_read32(dev, 0x400);
+ tmp &= ~8;
+ ssb_write32(dev, 0x400, tmp);
+ tmp = ssb_read32(dev, 0x400);
+ printk("USB20H fcr: 0x%0x\n", tmp);
+
+ /* Change Shim control reg */
+ tmp = ssb_read32(dev, 0x304);
+ tmp &= ~0x100;
+ ssb_write32(dev, 0x304, tmp);
+ tmp = ssb_read32(dev, 0x304);
+ printk("USB20H shim: 0x%0x\n", tmp);
+ }
+ } else
+ ssb_device_enable(dev, 0);
hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
dev_name(dev->dev));
@@ -200,6 +232,7 @@ static int ssb_ohci_resume(struct ssb_de
static const struct ssb_device_id ssb_ohci_table[] = {
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
SSB_DEVTABLE_END
};
MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);

View File

@ -1,16 +0,0 @@
---
drivers/usb/host/ohci-ssb.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/usb/host/ohci-ssb.c
+++ b/drivers/usb/host/ohci-ssb.c
@@ -106,6 +106,9 @@ static int ssb_ohci_attach(struct ssb_de
int err = -ENOMEM;
u32 tmp, flags = 0;
+ if (ssb_dma_set_mask(dev, DMA_BIT_MASK(32)))
+ return -EOPNOTSUPP;
+
if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
/* Put the device into host-mode. */
flags |= SSB_OHCI_TMSLOW_HOSTMODE;

View File

@ -1,63 +0,0 @@
This patch significantly improves the reliability of high speed
usb writes on the bcm5354. It implements a work around for version 2
of the usb20 core that was cribbed from the GPL sources for the
Asus wl500gpv2 and verified against the wl520gu sources.
Reference:
GPL/WL-520gu-NewUI/src/linux/linux/arch/mips/brcm-boards/bcm947xx/pcibios.c
GPL/WL-500gPV2-NewUI/src/linux/linux/arch/mips/brcm-boards/bcm947xx/pcibios.c
Signed-off-by: Steve Brown <sbrown@cortland.com>
---
drivers/usb/host/ohci-ssb.c | 37 +++++++++++++++++++++++--------------
1 file changed, 23 insertions(+), 14 deletions(-)
--- a/drivers/usb/host/ohci-ssb.c
+++ b/drivers/usb/host/ohci-ssb.c
@@ -141,22 +141,31 @@ static int ssb_ohci_attach(struct ssb_de
*/
ssb_device_enable(dev, 0);
ssb_write32(dev, 0x200, 0x7ff);
+
+ /* Change Flush control reg */
+ tmp = ssb_read32(dev, 0x400);
+ tmp &= ~8;
+ ssb_write32(dev, 0x400, tmp);
+ tmp = ssb_read32(dev, 0x400);
+
+ /* Change Shim control reg */
+ tmp = ssb_read32(dev, 0x304);
+ tmp &= ~0x100;
+ ssb_write32(dev, 0x304, tmp);
+ tmp = ssb_read32(dev, 0x304);
+
udelay(1);
- if (dev->id.revision == 1) { // bug in rev 1
- /* Change Flush control reg */
- tmp = ssb_read32(dev, 0x400);
- tmp &= ~8;
- ssb_write32(dev, 0x400, tmp);
- tmp = ssb_read32(dev, 0x400);
- printk("USB20H fcr: 0x%0x\n", tmp);
-
- /* Change Shim control reg */
- tmp = ssb_read32(dev, 0x304);
- tmp &= ~0x100;
- ssb_write32(dev, 0x304, tmp);
- tmp = ssb_read32(dev, 0x304);
- printk("USB20H shim: 0x%0x\n", tmp);
+ /* Work around for 5354 failures */
+ if ((dev->id.revision == 2) && (dev->bus->chip_id == 0x5354)) {
+ /* Change syn01 reg */
+ tmp = 0x00fe00fe;
+ ssb_write32(dev, 0x894, tmp);
+
+ /* Change syn03 reg */
+ tmp = ssb_read32(dev, 0x89c);
+ tmp |= 0x1;
+ ssb_write32(dev, 0x89c, tmp);
}
} else
ssb_device_enable(dev, 0);

View File

@ -18,7 +18,7 @@
unsigned long addr, unsigned long pfn) unsigned long addr, unsigned long pfn)
{ {
struct flush_cache_page_args args; struct flush_cache_page_args args;
@@ -1456,3 +1456,10 @@ void __cpuinit r4k_cache_init(void) @@ -1469,3 +1469,10 @@ void __cpuinit r4k_cache_init(void)
coherency_setup(); coherency_setup();
#endif #endif
} }

View File

@ -1,280 +1,39 @@
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -62,6 +62,7 @@ config BCM47XX
select SSB_DRIVER_MIPS
select SSB_DRIVER_EXTIF
select SSB_EMBEDDED
+ select SSB_B43_PCI_BRIDGE if PCI
select SSB_PCICORE_HOSTMODE if PCI
select GENERIC_GPIO
select SYS_HAS_EARLY_PRINTK
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -3,4 +3,4 @@
# under Linux.
#
-obj-y := gpio.o irq.o prom.o serial.o setup.o time.o wgt634u.o
+obj-y := cfe_env.o gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
--- a/arch/mips/bcm47xx/irq.c
+++ b/arch/mips/bcm47xx/irq.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
+ * Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -23,10 +24,19 @@
*/
#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/pci.h>
+#include <linux/ssb/ssb.h>
+
#include <asm/irq_cpu.h>
+
+extern struct ssb_bus ssb_bcm47xx;
+
+
void plat_irq_dispatch(void)
{
u32 cause;
--- a/arch/mips/bcm47xx/nvram.c --- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c
@@ -24,10 +24,10 @@ @@ -92,3 +92,30 @@ int nvram_getenv(char *name, char *val,
#include <asm/io.h> return 1;
#include <asm/uaccess.h> }
EXPORT_SYMBOL(nvram_getenv);
-#include <nvram.h> +
+#include "include/nvram.h" +char *nvram_get(const char *name)
+{
#define MB * 1048576 + char *var, *value, *end, *eq;
-extern struct ssb_bus ssb; +
+extern struct ssb_bus ssb_bcm47xx; + if (!name)
+ return NULL;
static char nvram_buf[NVRAM_SPACE]; +
static int cfe_env; + if (!nvram_buf[0])
@@ -36,7 +36,7 @@ extern char *cfe_env_get(char *nv_buf, c + early_nvram_init();
/* Probe for NVRAM header */ +
static void __init early_nvram_init(void) + /* Look for name=value and return value */
{ + var = &nvram_buf[sizeof(struct nvram_header)];
- struct ssb_mipscore *mcore = &ssb.mipscore; + end = nvram_buf + sizeof(nvram_buf) - 2;
+ struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore; + end[0] = end[1] = '\0';
struct nvram_header *header; + for (; *var; var = value + strlen(value) + 1) {
int i; + if (!(eq = strchr(var, '=')))
u32 base, lim, off; + break;
+ value = eq + 1;
+ if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0)
+ return value;
+ }
+
+ return NULL;
+}
+
+EXPORT_SYMBOL(nvram_get);
--- a/arch/mips/bcm47xx/setup.c --- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c
@@ -2,7 +2,7 @@ @@ -226,3 +226,20 @@ void __init plat_mem_setup(void)
* Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
* Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
- * Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2006-2008 Michael Buesch <mb@bu3sch.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -25,18 +25,28 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/init.h>
#include <linux/types.h>
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_embedded.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/serial_8250.h>
#include <asm/bootinfo.h>
#include <asm/reboot.h>
#include <asm/time.h>
-#include <bcm47xx.h>
#include <asm/fw/cfe/cfe_api.h>
+#include <linux/pm.h>
+
+#include "include/nvram.h"
struct ssb_bus ssb_bcm47xx;
EXPORT_SYMBOL(ssb_bcm47xx);
+extern void bcm47xx_pci_init(void);
+
static void bcm47xx_machine_restart(char *command)
{
printk(KERN_ALERT "Please stand by while rebooting the system...\n");
@@ -56,7 +66,7 @@ static void bcm47xx_machine_halt(void)
cpu_relax();
}
-static void str2eaddr(char *str, char *dest)
+static void e_aton(char *str, char *dest)
{
int i = 0;
@@ -73,51 +83,142 @@ static void str2eaddr(char *str, char *d
}
}
-static int bcm47xx_get_invariants(struct ssb_bus *bus,
- struct ssb_init_invariants *iv)
+static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
+{
+ char *s;
+
+ memset(sprom, 0xFF, sizeof(struct ssb_sprom));
+
+ sprom->revision = 1;
+ if ((s = nvram_get("il0macaddr")))
+ e_aton(s, sprom->il0mac);
+ if ((s = nvram_get("et0macaddr")))
+ e_aton(s, sprom->et0mac);
+ if ((s = nvram_get("et1macaddr")))
+ e_aton(s, sprom->et1mac);
+ if ((s = nvram_get("et0phyaddr")))
+ sprom->et0phyaddr = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("et1phyaddr")))
+ sprom->et1phyaddr = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("et0mdcport")))
+ sprom->et0mdcport = !!simple_strtoul(s, NULL, 10);
+ if ((s = nvram_get("et1mdcport")))
+ sprom->et1mdcport = !!simple_strtoul(s, NULL, 10);
+ if ((s = nvram_get("pa0b0")))
+ sprom->pa0b0 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("pa0b1")))
+ sprom->pa0b1 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("pa0b2")))
+ sprom->pa0b2 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("pa1b0")))
+ sprom->pa1b0 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("pa1b1")))
+ sprom->pa1b1 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("pa1b2")))
+ sprom->pa1b2 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("wl0gpio0")))
+ sprom->gpio0 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("wl0gpio1")))
+ sprom->gpio1 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("wl0gpio2")))
+ sprom->gpio2 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("wl0gpio3")))
+ sprom->gpio3 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("pa0maxpwr")))
+ sprom->maxpwr_bg = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("pa1maxpwr")))
+ sprom->maxpwr_a = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("pa0itssit")))
+ sprom->itssi_bg = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("pa1itssit")))
+ sprom->itssi_a = simple_strtoul(s, NULL, 0);
+ sprom->boardflags_lo = 0;
+ if ((s = nvram_get("boardflags")))
+ sprom->boardflags_lo = simple_strtoul(s, NULL, 0);
+ sprom->boardflags_hi = 0;
+ if ((s = nvram_get("boardflags2")))
+ sprom->boardflags_hi = simple_strtoul(s, NULL, 0);
+}
+
+static int bcm47xx_get_invariants(struct ssb_bus *bus, struct ssb_init_invariants *iv)
{
- char buf[100];
+ char *s;
+
+ iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
+ if ((s = nvram_get("boardtype")))
+ iv->boardinfo.type = (u16)simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("boardrev")))
+ iv->boardinfo.rev = (u16)simple_strtoul(s, NULL, 0);
- /* Fill boardinfo structure */
- memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
+ bcm47xx_fill_sprom(&iv->sprom);
- if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0)
- iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
- if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0)
- iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
- if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0)
- iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
-
- /* Fill sprom structure */
- memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
- iv->sprom.revision = 3;
-
- if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
- str2eaddr(buf, iv->sprom.et0mac);
- if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
- str2eaddr(buf, iv->sprom.et1mac);
- if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
- iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 10);
- if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
- iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 10);
- if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
- iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
- if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
- iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
+ if ((s = nvram_get("cardbus")))
+ iv->has_cardbus_slot = !!simple_strtoul(s, NULL, 10);
return 0;
}
void __init plat_mem_setup(void)
{
- int err;
+ int i, err;
+ char *s;
+ struct ssb_mipscore *mcore;
+
+ err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE, bcm47xx_get_invariants);
+ if (err) {
+ const char *msg = "Failed to initialize SSB bus (err %d)\n";
+ printk(msg, err); /* Make sure the message gets out of the box. */
+ panic(msg, err);
+ }
+ mcore = &ssb_bcm47xx.mipscore;
- err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
- bcm47xx_get_invariants);
- if (err)
- panic("Failed to initialize SSB bus (err %d)\n", err);
+ s = nvram_get("kernel_args");
+ if (s && !strncmp(s, "console=ttyS1", 13)) {
+ struct ssb_serial_port port;
+
+ printk("Swapping serial ports!\n");
+ /* swap serial ports */
+ memcpy(&port, &mcore->serial_ports[0], sizeof(port));
+ memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1], sizeof(port));
+ memcpy(&mcore->serial_ports[1], &port, sizeof(port));
+ }
+
+ for (i = 0; i < mcore->nr_serial_ports; i++) {
+ struct ssb_serial_port *port = &(mcore->serial_ports[i]);
+ struct uart_port s;
+
+ memset(&s, 0, sizeof(s));
+ s.line = i;
+ s.mapbase = (unsigned int) port->regs;
+ s.membase = port->regs;
+ s.irq = port->irq + 2;
+ s.uartclk = port->baud_base;
+ s.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ s.iotype = SERIAL_IO_MEM;
+ s.regshift = port->reg_shift;
+
+ early_serial_setup(&s);
+ }
+ printk("Serial init done.\n");
_machine_restart = bcm47xx_machine_restart;
_machine_halt = bcm47xx_machine_halt; _machine_halt = bcm47xx_machine_halt;
pm_power_off = bcm47xx_machine_halt; pm_power_off = bcm47xx_machine_halt;
} }
@ -295,25 +54,3 @@
+ return 0; + return 0;
+} +}
+device_initcall(bcm47xx_register_gpiodev); +device_initcall(bcm47xx_register_gpiodev);
--- a/arch/mips/bcm47xx/time.c
+++ b/arch/mips/bcm47xx/time.c
@@ -22,11 +22,17 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/serial_reg.h>
+#include <linux/interrupt.h>
#include <linux/ssb/ssb.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
#include <asm/time.h>
-#include <bcm47xx.h>
+
+extern struct ssb_bus ssb_bcm47xx;
void __init plat_time_init(void)
{

View File

@ -1,108 +0,0 @@
--- a/arch/mips/bcm47xx/prom.c
+++ b/arch/mips/bcm47xx/prom.c
@@ -32,6 +32,7 @@
#include <asm/fw/cfe/cfe_error.h>
static int cfe_cons_handle;
+static void (* __prom_putchar)(char c);
const char *get_system_type(void)
{
@@ -40,65 +41,40 @@ const char *get_system_type(void)
void prom_putchar(char c)
{
+ if (__prom_putchar)
+ __prom_putchar(c);
+}
+
+void prom_putchar_cfe(char c)
+{
while (cfe_write(cfe_cons_handle, &c, 1) == 0)
;
}
-static __init void prom_init_cfe(void)
+static __init int prom_init_cfe(void)
{
uint32_t cfe_ept;
uint32_t cfe_handle;
uint32_t cfe_eptseal;
- int argc = fw_arg0;
- char **envp = (char **) fw_arg2;
- int *prom_vec = (int *) fw_arg3;
-
- /*
- * Check if a loader was used; if NOT, the 4 arguments are
- * what CFE gives us (handle, 0, EPT and EPTSEAL)
- */
- if (argc < 0) {
- cfe_handle = (uint32_t)argc;
- cfe_ept = (uint32_t)envp;
- cfe_eptseal = (uint32_t)prom_vec;
- } else {
- if ((int)prom_vec < 0) {
- /*
- * Old loader; all it gives us is the handle,
- * so use the "known" entrypoint and assume
- * the seal.
- */
- cfe_handle = (uint32_t)prom_vec;
- cfe_ept = 0xBFC00500;
- cfe_eptseal = CFE_EPTSEAL;
- } else {
- /*
- * Newer loaders bundle the handle/ept/eptseal
- * Note: prom_vec is in the loader's useg
- * which is still alive in the TLB.
- */
- cfe_handle = prom_vec[0];
- cfe_ept = prom_vec[2];
- cfe_eptseal = prom_vec[3];
- }
- }
- if (cfe_eptseal != CFE_EPTSEAL) {
- /* too early for panic to do any good */
- printk(KERN_ERR "CFE's entrypoint seal doesn't match.");
- while (1) ;
- }
+ cfe_eptseal = (uint32_t) fw_arg3;
+ cfe_handle = (uint32_t) fw_arg0;
+ cfe_ept = (uint32_t) fw_arg2;
+
+ if (cfe_eptseal != CFE_EPTSEAL)
+ return -1;
cfe_init(cfe_handle, cfe_ept);
+ return 0;
}
-static __init void prom_init_console(void)
+static __init void prom_init_console_cfe(void)
{
/* Initialize CFE console */
cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
}
-static __init void prom_init_cmdline(void)
+static __init void prom_init_cmdline_cfe(void)
{
static char buf[COMMAND_LINE_SIZE] __initdata;
@@ -160,9 +136,12 @@ static __init void prom_init_mem(void)
void __init prom_init(void)
{
- prom_init_cfe();
- prom_init_console();
- prom_init_cmdline();
+ if (prom_init_cfe() == 0) {
+ //prom_init_console_cfe();
+ //prom_init_cmdline_cfe();
+ __prom_putchar = prom_putchar_cfe;
+ }
+
prom_init_mem();
}

View File

@ -4,8 +4,8 @@
# under Linux. # under Linux.
# #
-obj-y := cfe_env.o gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o -obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
+obj-y := cfe_env.o gpio.o irq.o nvram.o prom.o serial.o setup.o time.o +obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o
--- a/arch/mips/bcm47xx/wgt634u.c --- a/arch/mips/bcm47xx/wgt634u.c
+++ /dev/null +++ /dev/null
@@ -1,166 +0,0 @@ @@ -1,166 +0,0 @@

View File

@ -1,10 +0,0 @@
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -65,7 +65,6 @@ config BCM47XX
select SSB_B43_PCI_BRIDGE if PCI
select SSB_PCICORE_HOSTMODE if PCI
select GENERIC_GPIO
- select SYS_HAS_EARLY_PRINTK
select CFE
help
Support for BCM47XX based boards

View File

@ -17,7 +17,7 @@
mask = probe_irq_mask(val) & 0xffff; mask = probe_irq_mask(val) & 0xffff;
@@ -1022,6 +1025,10 @@ static void yenta_get_socket_capabilitie @@ -1023,6 +1026,10 @@ static void yenta_get_socket_capabilitie
else else
socket->socket.irq_mask = 0; socket->socket.irq_mask = 0;
@ -28,7 +28,7 @@
dev_printk(KERN_INFO, &socket->dev->dev, dev_printk(KERN_INFO, &socket->dev->dev,
"ISA IRQ mask 0x%04x, PCI irq %d\n", "ISA IRQ mask 0x%04x, PCI irq %d\n",
socket->socket.irq_mask, socket->cb_irq); socket->socket.irq_mask, socket->cb_irq);
@@ -1260,6 +1267,15 @@ static int __devinit yenta_probe(struct @@ -1261,6 +1268,15 @@ static int __devinit yenta_probe(struct
dev_printk(KERN_INFO, &dev->dev, dev_printk(KERN_INFO, &dev->dev,
"Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE)); "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));

View File

@ -1,16 +1,15 @@
--- a/arch/mips/bcm47xx/nvram.c --- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c
@@ -29,7 +29,9 @@ @@ -20,7 +20,8 @@
#define MB * 1048576 #include <asm/mach-bcm47xx/nvram.h>
extern struct ssb_bus ssb_bcm47xx; #include <asm/mach-bcm47xx/bcm47xx.h>
-static char nvram_buf[NVRAM_SPACE]; -static char nvram_buf[NVRAM_SPACE];
+char nvram_buf[NVRAM_SPACE]; +char nvram_buf[NVRAM_SPACE];
+EXPORT_SYMBOL(nvram_buf); +EXPORT_SYMBOL(nvram_buf);
+
static int cfe_env;
extern char *cfe_env_get(char *nv_buf, const char *name);
/* Probe for NVRAM header */
static void __init early_nvram_init(void)
--- a/arch/mips/mm/cache.c --- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c
@@ -52,6 +52,7 @@ void (*_dma_cache_wback)(unsigned long s @@ -52,6 +52,7 @@ void (*_dma_cache_wback)(unsigned long s

View File

@ -1,3 +1,24 @@
From b6d850fe4035d6bee7199119358e06f802aa19ed Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 18 Jul 2010 12:49:41 +0200
Subject: [PATCH 1/5] MIPS: BCM47xx: Really fix 128MB RAM problem
The previews patch 84a6fcb368a080620d12fc4d79e07902dbee7335 was wrong,
I got wrong success reports.
The bcm47xx architecture maps the ram into a 128MB address space. It
will be paced there as often as goes into the 128MB. The detection
tries to find the position where the same memory is found. When reading
over 128MB the processor will throw an exception. If 128MB ram is
installed, it will not find the same memory because it tries to read
over the 128MB boarder. Now it just assumes 128MB installed ram if it
can not find that the ram is repeating.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/bcm47xx/prom.c | 22 ++++++++++++++--------
1 files changed, 14 insertions(+), 8 deletions(-)
--- a/arch/mips/bcm47xx/prom.c --- a/arch/mips/bcm47xx/prom.c
+++ b/arch/mips/bcm47xx/prom.c +++ b/arch/mips/bcm47xx/prom.c
@@ -126,6 +126,7 @@ static __init void prom_init_cmdline(voi @@ -126,6 +126,7 @@ static __init void prom_init_cmdline(voi

View File

@ -0,0 +1,158 @@
From d6c049e08568aac29fff854ea0385e63c7150e09 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 18 Jul 2010 13:34:32 +0200
Subject: [PATCH 2/5] MIPS: BCM47xx: Fill more values into ssb sprom
Most of the values are stored in the nvram and not in the CFE. At first
the nvram should be read and if there is no value it should look into
the CFE. Now more values are read out because the b43 and b43legacy
drivers needs them.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/bcm47xx/setup.c | 122 +++++++++++++++++++++++++++++++++------------
1 files changed, 89 insertions(+), 33 deletions(-)
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -74,6 +74,86 @@ static void str2eaddr(char *str, char *d
}
}
+static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
+{
+ char buf[100];
+
+ memset(sprom, 0, sizeof(struct ssb_sprom));
+
+ sprom->revision = 3;
+ if (nvram_getenv("il0macaddr", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("il0macaddr", buf, sizeof(buf)) >= 0)
+ str2eaddr(buf, sprom->il0mac);
+ if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
+ str2eaddr(buf, sprom->et0mac);
+ if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
+ str2eaddr(buf, sprom->et1mac);
+ if (nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
+ sprom->et0phyaddr = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
+ sprom->et1phyaddr = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
+ sprom->et0mdcport = !!simple_strtoul(buf, NULL, 10);
+ if (nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
+ sprom->et1mdcport = !!simple_strtoul(buf, NULL, 10);
+ if (nvram_getenv("pa0b0", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa0b0", buf, sizeof(buf)) >= 0)
+ sprom->pa0b0 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("pa0b1", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa0b1", buf, sizeof(buf)) >= 0)
+ sprom->pa0b1 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("pa0b2", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa0b2", buf, sizeof(buf)) >= 0)
+ sprom->pa0b2 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("pa1b0", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa1b0", buf, sizeof(buf)) >= 0)
+ sprom->pa1b0 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("pa1b1", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa1b1", buf, sizeof(buf)) >= 0)
+ sprom->pa1b1 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("pa1b2", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa1b2", buf, sizeof(buf)) >= 0)
+ sprom->pa1b2 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("wl0gpio0", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("wl0gpio0", buf, sizeof(buf)) >= 0)
+ sprom->gpio0 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("wl0gpio1", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("wl0gpio1", buf, sizeof(buf)) >= 0)
+ sprom->gpio1 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("wl0gpio2", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("wl0gpio2", buf, sizeof(buf)) >= 0)
+ sprom->gpio2 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("wl0gpio3", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("wl0gpio3", buf, sizeof(buf)) >= 0)
+ sprom->gpio3 = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("pa0maxpwr", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa0maxpwr", buf, sizeof(buf)) >= 0)
+ sprom->maxpwr_bg = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("pa1maxpwr", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa1maxpwr", buf, sizeof(buf)) >= 0)
+ sprom->maxpwr_a = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("pa0itssit", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa0itssit", buf, sizeof(buf)) >= 0)
+ sprom->itssi_bg = simple_strtoul(buf, NULL, 0);
+ if (nvram_getenv("pa1itssit", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("pa1itssit", buf, sizeof(buf)) >= 0)
+ sprom->itssi_a = simple_strtoul(buf, NULL, 0);
+ sprom->boardflags_lo = 0;
+ if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("boardflags", buf, sizeof(buf)) >= 0)
+ sprom->boardflags_lo = simple_strtoul(buf, NULL, 0);
+ sprom->boardflags_hi = 0;
+ if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("boardflags", buf, sizeof(buf)) >= 0)
+ sprom->boardflags_hi = simple_strtoul(buf, NULL, 0);
+}
+
static int bcm47xx_get_invariants(struct ssb_bus *bus,
struct ssb_init_invariants *iv)
{
@@ -82,43 +162,19 @@ static int bcm47xx_get_invariants(struct
/* Fill boardinfo structure */
memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
- if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 ||
- nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
+ iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
+ if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("boardtype", buf, sizeof(buf)) >= 0)
iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
- if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 ||
- nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
- iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
- if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 ||
- nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
+ if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("boardrev", buf, sizeof(buf)) >= 0)
iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
- /* Fill sprom structure */
- memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
- iv->sprom.revision = 3;
-
- if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 ||
- nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
- str2eaddr(buf, iv->sprom.et0mac);
-
- if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 ||
- nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
- str2eaddr(buf, iv->sprom.et1mac);
-
- if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ||
- nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
- iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0);
-
- if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ||
- nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
- iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0);
-
- if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 ||
- nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
- iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
-
- if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 ||
- nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
- iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
+ bcm47xx_fill_sprom(&iv->sprom);
+
+ if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0 ||
+ cfe_getenv("cardbus", buf, sizeof(buf)) >= 0)
+ iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
return 0;
}

View File

@ -0,0 +1,23 @@
From b1a0abc936bf61689d1e8a56c423b232cff24da5 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 18 Jul 2010 13:58:09 +0200
Subject: [PATCH 3/5] MIPS: BCM47xx: Activate SSB_B43_PCI_BRIDGE by default
The b43_pci_bridge is needed to use the b43 driver with brcm47xx.
Activate it by default if pci is available.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/Kconfig | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -62,6 +62,7 @@ config BCM47XX
select SSB_DRIVER_MIPS
select SSB_DRIVER_EXTIF
select SSB_EMBEDDED
+ select SSB_B43_PCI_BRIDGE if PCI
select SSB_PCICORE_HOSTMODE if PCI
select GENERIC_GPIO
select SYS_HAS_EARLY_PRINTK

View File

@ -0,0 +1,81 @@
From 4c6a515310f29c89f25a54a115cde905f97330f8 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 18 Jul 2010 14:59:24 +0200
Subject: [PATCH 4/5] MIPS: BCM47xx: Setup and register serial early
Swap the first and second serial if console=ttyS1 was set.
Set it up and register it for early serial support.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/Kconfig | 1 -
arch/mips/bcm47xx/setup.c | 36 +++++++++++++++++++++++++++++++++++-
2 files changed, 35 insertions(+), 2 deletions(-)
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -65,7 +65,6 @@ config BCM47XX
select SSB_B43_PCI_BRIDGE if PCI
select SSB_PCICORE_HOSTMODE if PCI
select GENERIC_GPIO
- select SYS_HAS_EARLY_PRINTK
select CFE
help
Support for BCM47XX based boards
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -28,6 +28,8 @@
#include <linux/types.h>
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_embedded.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
#include <asm/bootinfo.h>
#include <asm/reboot.h>
#include <asm/time.h>
@@ -181,12 +183,44 @@ static int bcm47xx_get_invariants(struct
void __init plat_mem_setup(void)
{
- int err;
+ int i, err;
+ char buf[100];
+ struct ssb_mipscore *mcore;
err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
bcm47xx_get_invariants);
if (err)
panic("Failed to initialize SSB bus (err %d)\n", err);
+ mcore = &ssb_bcm47xx.mipscore;
+
+ nvram_getenv("kernel_args", buf, sizeof(buf));
+ if (!strncmp(buf, "console=ttyS1", 13)) {
+ struct ssb_serial_port port;
+
+ printk("Swapping serial ports!\n");
+ /* swap serial ports */
+ memcpy(&port, &mcore->serial_ports[0], sizeof(port));
+ memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1], sizeof(port));
+ memcpy(&mcore->serial_ports[1], &port, sizeof(port));
+ }
+
+ for (i = 0; i < mcore->nr_serial_ports; i++) {
+ struct ssb_serial_port *port = &(mcore->serial_ports[i]);
+ struct uart_port s;
+
+ memset(&s, 0, sizeof(s));
+ s.line = i;
+ s.mapbase = (unsigned int) port->regs;
+ s.membase = port->regs;
+ s.irq = port->irq + 2;
+ s.uartclk = port->baud_base;
+ s.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ s.iotype = SERIAL_IO_MEM;
+ s.regshift = port->reg_shift;
+
+ early_serial_setup(&s);
+ }
+ printk("Serial init done.\n");
_machine_restart = bcm47xx_machine_restart;
_machine_halt = bcm47xx_machine_halt;

View File

@ -0,0 +1,130 @@
From 6bd2c73ed31a2dfe7eab04d32c17318a5c62f9d4 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 18 Jul 2010 15:11:26 +0200
Subject: [PATCH 5/5] MIPS: BCM47xx: Remove CFE console
Do not use the CFE console. It causes hangs on some devices like the
Buffalo WHR-HP-G54.
This was reported in https://dev.openwrt.org/ticket/4061 and
https://forum.openwrt.org/viewtopic.php?id=17063
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/bcm47xx/prom.c | 82 +++------------------------------------------
1 files changed, 6 insertions(+), 76 deletions(-)
--- a/arch/mips/bcm47xx/prom.c
+++ b/arch/mips/bcm47xx/prom.c
@@ -31,96 +31,28 @@
#include <asm/fw/cfe/cfe_api.h>
#include <asm/fw/cfe/cfe_error.h>
-static int cfe_cons_handle;
-
const char *get_system_type(void)
{
return "Broadcom BCM47XX";
}
-void prom_putchar(char c)
-{
- while (cfe_write(cfe_cons_handle, &c, 1) == 0)
- ;
-}
-
-static __init void prom_init_cfe(void)
+static __init int prom_init_cfe(void)
{
uint32_t cfe_ept;
uint32_t cfe_handle;
uint32_t cfe_eptseal;
- int argc = fw_arg0;
- char **envp = (char **) fw_arg2;
- int *prom_vec = (int *) fw_arg3;
-
- /*
- * Check if a loader was used; if NOT, the 4 arguments are
- * what CFE gives us (handle, 0, EPT and EPTSEAL)
- */
- if (argc < 0) {
- cfe_handle = (uint32_t)argc;
- cfe_ept = (uint32_t)envp;
- cfe_eptseal = (uint32_t)prom_vec;
- } else {
- if ((int)prom_vec < 0) {
- /*
- * Old loader; all it gives us is the handle,
- * so use the "known" entrypoint and assume
- * the seal.
- */
- cfe_handle = (uint32_t)prom_vec;
- cfe_ept = 0xBFC00500;
- cfe_eptseal = CFE_EPTSEAL;
- } else {
- /*
- * Newer loaders bundle the handle/ept/eptseal
- * Note: prom_vec is in the loader's useg
- * which is still alive in the TLB.
- */
- cfe_handle = prom_vec[0];
- cfe_ept = prom_vec[2];
- cfe_eptseal = prom_vec[3];
- }
- }
+
+ cfe_eptseal = (uint32_t) fw_arg3;
+ cfe_handle = (uint32_t) fw_arg0;
+ cfe_ept = (uint32_t) fw_arg2;
if (cfe_eptseal != CFE_EPTSEAL) {
- /* too early for panic to do any good */
printk(KERN_ERR "CFE's entrypoint seal doesn't match.");
- while (1) ;
+ return -1;
}
cfe_init(cfe_handle, cfe_ept);
-}
-
-static __init void prom_init_console(void)
-{
- /* Initialize CFE console */
- cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
-}
-
-static __init void prom_init_cmdline(void)
-{
- static char buf[COMMAND_LINE_SIZE] __initdata;
-
- /* Get the kernel command line from CFE */
- if (cfe_getenv("LINUX_CMDLINE", buf, COMMAND_LINE_SIZE) >= 0) {
- buf[COMMAND_LINE_SIZE - 1] = 0;
- strcpy(arcs_cmdline, buf);
- }
-
- /* Force a console handover by adding a console= argument if needed,
- * as CFE is not available anymore later in the boot process. */
- if ((strstr(arcs_cmdline, "console=")) == NULL) {
- /* Try to read the default serial port used by CFE */
- if ((cfe_getenv("BOOT_CONSOLE", buf, COMMAND_LINE_SIZE) < 0)
- || (strncmp("uart", buf, 4)))
- /* Default to uart0 */
- strcpy(buf, "uart0");
-
- /* Compute the new command line */
- snprintf(arcs_cmdline, COMMAND_LINE_SIZE, "%s console=ttyS%c,115200",
- arcs_cmdline, buf[4]);
- }
+ return 0;
}
static __init void prom_init_mem(void)
@@ -161,8 +93,6 @@ static __init void prom_init_mem(void)
void __init prom_init(void)
{
prom_init_cfe();
- prom_init_console();
- prom_init_cmdline();
prom_init_mem();
}

View File

@ -0,0 +1,95 @@
From cb33ffbdd8491c58b35958ec74c39b3a5c7fabe8 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 18 Jul 2010 21:25:03 +0200
Subject: [PATCH 1/2] USB: Add USB 2.0 to ssb ohci driver
This adds USB 2.0 support to ssb ohci driver.
This work was done based on Braodcom source code in the OpenWRT project.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
drivers/usb/host/ohci-ssb.c | 55 ++++++++++++++++++++++++++++++++++++++++--
1 files changed, 52 insertions(+), 3 deletions(-)
--- a/drivers/usb/host/ohci-ssb.c
+++ b/drivers/usb/host/ohci-ssb.c
@@ -92,9 +92,12 @@ static const struct hc_driver ssb_ohci_h
static void ssb_ohci_detach(struct ssb_device *dev)
{
struct usb_hcd *hcd = ssb_get_drvdata(dev);
+ if (hcd->driver->shutdown)
+ hcd->driver->shutdown(hcd);
usb_remove_hcd(hcd);
iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
ssb_device_disable(dev, 0);
}
@@ -106,10 +109,55 @@ static int ssb_ohci_attach(struct ssb_de
int err = -ENOMEM;
u32 tmp, flags = 0;
- if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV)
- flags |= SSB_OHCI_TMSLOW_HOSTMODE;
+ if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
+ dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
+ return -EOPNOTSUPP;
- ssb_device_enable(dev, flags);
+ if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
+ /* Put the device into host-mode. */
+ flags |= SSB_OHCI_TMSLOW_HOSTMODE;
+ ssb_device_enable(dev, flags);
+ } else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
+ /*
+ * USB 2.0 special considerations:
+ *
+ * 1. Since the core supports both ehci and EHCI functions, it must
+ * only be reset once.
+ *
+ * 2. In addition to the standard SSB reset sequence, the Host Control
+ * Register must be programmed to bring the USB core and various
+ * phy components out of reset.
+ */
+ ssb_device_enable(dev, 0);
+ ssb_write32(dev, 0x200, 0x7ff);
+
+ /* Change Flush control reg */
+ tmp = ssb_read32(dev, 0x400);
+ tmp &= ~8;
+ ssb_write32(dev, 0x400, tmp);
+ tmp = ssb_read32(dev, 0x400);
+
+ /* Change Shim control reg */
+ tmp = ssb_read32(dev, 0x304);
+ tmp &= ~0x100;
+ ssb_write32(dev, 0x304, tmp);
+ tmp = ssb_read32(dev, 0x304);
+
+ udelay(1);
+
+ /* Work around for 5354 failures */
+ if ((dev->id.revision == 2) && (dev->bus->chip_id == 0x5354)) {
+ /* Change syn01 reg */
+ tmp = 0x00fe00fe;
+ ssb_write32(dev, 0x894, tmp);
+
+ /* Change syn03 reg */
+ tmp = ssb_read32(dev, 0x89c);
+ tmp |= 0x1;
+ ssb_write32(dev, 0x89c, tmp);
+ }
+ } else
+ ssb_device_enable(dev, 0);
hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
dev_name(dev->dev));
@@ -200,6 +248,7 @@ static int ssb_ohci_resume(struct ssb_de
static const struct ssb_device_id ssb_ohci_table[] = {
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
SSB_DEVTABLE_END
};
MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);

View File

@ -1,9 +1,17 @@
From cb269cf1f97c316a5184080814a751687c72b718 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 18 Jul 2010 21:29:40 +0200
Subject: [PATCH 2/2] USB: Add ehci ssb driver
Support for the Sonics Silicon Backplane (SSB) attached Broadcom USB EHCI core.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
--- ---
drivers/usb/host/Kconfig | 13 ++ drivers/usb/host/Kconfig | 13 ++
drivers/usb/host/ehci-hcd.c | 12 ++ drivers/usb/host/ehci-hcd.c | 23 ++++-
drivers/usb/host/ehci-ssb.c | 201 ++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/ehci-ssb.c | 258 +++++++++++++++++++++++++++++++++++++++++++
drivers/usb/host/ohci-ssb.c | 23 +++++ 3 files changed, 292 insertions(+), 2 deletions(-)
4 files changed, 247 insertions(+), 2 deletions(-) create mode 100644 drivers/usb/host/ehci-ssb.c
--- a/drivers/usb/host/Kconfig --- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig
@ -13,7 +21,7 @@
+config USB_EHCI_HCD_SSB +config USB_EHCI_HCD_SSB
+ bool "EHCI support for Broadcom SSB EHCI core" + bool "EHCI support for Broadcom SSB EHCI core"
+ depends on USB_EHCI_HCD && SSB && EXPERIMENTAL + depends on USB_EHCI_HCD && (SSB = y || SSB = USB_EHCI_HCD) && EXPERIMENTAL
+ default n + default n
+ ---help--- + ---help---
+ Support for the Sonics Silicon Backplane (SSB) attached + Support for the Sonics Silicon Backplane (SSB) attached
@ -29,7 +37,7 @@
depends on USB depends on USB
--- a/drivers/usb/host/ehci-hcd.c --- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c
@@ -1158,6 +1158,11 @@ MODULE_LICENSE ("GPL"); @@ -1158,9 +1158,14 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_atmel_driver #define PLATFORM_DRIVER ehci_atmel_driver
#endif #endif
@ -40,15 +48,53 @@
+ +
#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
!defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
!defined(XILINX_OF_PLATFORM_DRIVER) - !defined(XILINX_OF_PLATFORM_DRIVER)
+ !defined(XILINX_OF_PLATFORM_DRIVER) && !defined(SSB_EHCI_DRIVER)
#error "missing bus glue for ehci-hcd"
#endif
@@ -1220,10 +1225,21 @@ static int __init ehci_hcd_init(void)
if (retval < 0)
goto clean4;
#endif
+
+#ifdef SSB_EHCI_DRIVER
+ retval = ssb_driver_register(&SSB_EHCI_DRIVER);
+ if (retval < 0)
+ goto clean5;
+#endif
+
return retval;
+#ifdef SSB_EHCI_DRIVER
+ /* ssb_driver_unregister(&SSB_EHCI_DRIVER); */
+clean5:
+#endif
#ifdef XILINX_OF_PLATFORM_DRIVER
- /* of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); */
+ of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER);
clean4:
#endif
#ifdef OF_PLATFORM_DRIVER
@@ -1254,6 +1270,9 @@ module_init(ehci_hcd_init);
static void __exit ehci_hcd_cleanup(void)
{
+#ifdef SSB_EHCI_DRIVER
+ ssb_driver_unregister(&SSB_EHCI_DRIVER);
+#endif
#ifdef XILINX_OF_PLATFORM_DRIVER
of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER);
#endif
--- /dev/null --- /dev/null
+++ b/drivers/usb/host/ehci-ssb.c +++ b/drivers/usb/host/ehci-ssb.c
@@ -0,0 +1,158 @@ @@ -0,0 +1,258 @@
+/* +/*
+ * Sonics Silicon Backplane + * Sonics Silicon Backplane
+ * Broadcom USB-core EHCI driver (SSB bus glue) + * Broadcom USB-core EHCI driver (SSB bus glue)
+ * + *
+ * Copyright 2007 Steven Brown <sbrown@cortland.com> + * Copyright 2007 Steven Brown <sbrown@cortland.com>
+ * Copyright 2010 Hauke Mehrtens <hauke@hauke-m.de>
+ * + *
+ * Derived from the OHCI-SSB driver + * Derived from the OHCI-SSB driver
+ * Copyright 2007 Michael Buesch <mb@bu3sch.de> + * Copyright 2007 Michael Buesch <mb@bu3sch.de>
@ -69,12 +115,9 @@
+ */ + */
+#include <linux/ssb/ssb.h> +#include <linux/ssb/ssb.h>
+ +
+#define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29)
+ +
+struct ssb_ehci_device { +struct ssb_ehci_device {
+ struct ehci_hcd ehci; /* _must_ be at the beginning. */ + struct ehci_hcd ehci; /* _must_ be at the beginning. */
+
+ u32 enable_flags;
+}; +};
+ +
+static inline +static inline
@ -134,34 +177,78 @@
+ +
+ .hub_status_data = ehci_hub_status_data, + .hub_status_data = ehci_hub_status_data,
+ .hub_control = ehci_hub_control, + .hub_control = ehci_hub_control,
+#if defined(CONFIG_PM)
+ .bus_suspend = ehci_bus_suspend, + .bus_suspend = ehci_bus_suspend,
+ .bus_resume = ehci_bus_resume, + .bus_resume = ehci_bus_resume,
+#endif
+ .relinquish_port = ehci_relinquish_port, + .relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over, + .port_handed_over = ehci_port_handed_over,
+ +
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, + .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+}; +};
+ +
+static void ssb_ehci_detach(struct ssb_device *dev, struct usb_hcd *hcd) +static void ssb_ehci_detach(struct ssb_device *dev)
+{ +{
+ struct usb_hcd *hcd = ssb_get_drvdata(dev);
+ if (hcd->driver->shutdown) + if (hcd->driver->shutdown)
+ hcd->driver->shutdown(hcd); + hcd->driver->shutdown(hcd);
+ +
+ usb_remove_hcd(hcd); + usb_remove_hcd(hcd);
+
+ iounmap(hcd->regs); + iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+ usb_put_hcd(hcd); + usb_put_hcd(hcd);
+ ssb_device_disable(dev, 0);
+} +}
+EXPORT_SYMBOL_GPL(ssb_ehci_detach);
+ +
+static int ssb_ehci_attach(struct ssb_device *dev, struct usb_hcd **ehci_hcd) +static int ssb_ehci_attach(struct ssb_device *dev)
+{ +{
+ struct ssb_ehci_device *ehcidev; + struct ssb_ehci_device *ehcidev;
+ struct usb_hcd *hcd; + struct usb_hcd *hcd;
+ int err = -ENOMEM; + int err = -ENOMEM;
+ u32 tmp, flags = 0; + u32 tmp;
+
+ if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
+ dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
+ return -EOPNOTSUPP;
+
+ /*
+ * USB 2.0 special considerations:
+ *
+ * 1. Since the core supports both ehci and EHCI functions, it must
+ * only be reset once.
+ *
+ * 2. In addition to the standard SSB reset sequence, the Host Control
+ * Register must be programmed to bring the USB core and various
+ * phy components out of reset.
+ */
+ ssb_device_enable(dev, 0);
+ ssb_write32(dev, 0x200, 0x7ff);
+
+ /* Change Flush control reg */
+ tmp = ssb_read32(dev, 0x400);
+ tmp &= ~8;
+ ssb_write32(dev, 0x400, tmp);
+ tmp = ssb_read32(dev, 0x400);
+
+ /* Change Shim control reg */
+ tmp = ssb_read32(dev, 0x304);
+ tmp &= ~0x100;
+ ssb_write32(dev, 0x304, tmp);
+ tmp = ssb_read32(dev, 0x304);
+
+ udelay(1);
+
+ /* Work around for 5354 failures */
+ if ((dev->id.revision == 2) && (dev->bus->chip_id == 0x5354)) {
+ /* Change syn01 reg */
+ tmp = 0x00fe00fe;
+ ssb_write32(dev, 0x894, tmp);
+
+ /* Change syn03 reg */
+ tmp = ssb_read32(dev, 0x89c);
+ tmp |= 0x1;
+ ssb_write32(dev, 0x89c, tmp);
+ }
+ +
+ hcd = usb_create_hcd(&ssb_ehci_hc_driver, dev->dev, + hcd = usb_create_hcd(&ssb_ehci_hc_driver, dev->dev,
+ dev_name(dev->dev)); + dev_name(dev->dev));
@ -169,7 +256,6 @@
+ goto err_dev_disable; + goto err_dev_disable;
+ +
+ ehcidev = hcd_to_ssb_ehci(hcd); + ehcidev = hcd_to_ssb_ehci(hcd);
+ ehcidev->enable_flags = flags;
+ tmp = ssb_read32(dev, SSB_ADMATCH0); + tmp = ssb_read32(dev, SSB_ADMATCH0);
+ hcd->rsrc_start = ssb_admatch_base(tmp) + 0x800; /* ehci core offset */ + hcd->rsrc_start = ssb_admatch_base(tmp) + 0x800; /* ehci core offset */
+ hcd->rsrc_len = 0x100; /* ehci reg block size */ + hcd->rsrc_len = 0x100; /* ehci reg block size */
@ -179,11 +265,11 @@
+ hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+ if (!hcd->regs) + if (!hcd->regs)
+ goto err_put_hcd; + goto err_put_hcd;
+ err = usb_add_hcd(hcd, dev->irq, IRQF_SHARED | IRQF_DISABLED); + err = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED);
+ if (err) + if (err)
+ goto err_iounmap; + goto err_iounmap;
+ +
+ *ehci_hcd = hcd; + ssb_set_drvdata(dev, hcd);
+ +
+ return err; + return err;
+ +
@ -192,73 +278,72 @@
+err_put_hcd: +err_put_hcd:
+ usb_put_hcd(hcd); + usb_put_hcd(hcd);
+err_dev_disable: +err_dev_disable:
+ ssb_device_disable(dev, flags); + ssb_device_disable(dev, 0);
+ return err; + return err;
+} +}
+EXPORT_SYMBOL_GPL(ssb_ehci_attach); +
+static int ssb_ehci_probe(struct ssb_device *dev,
+ const struct ssb_device_id *id)
+{
+ int err;
+ u16 chipid_top;
+
+ /* USBcores are only connected on embedded devices. */
+ chipid_top = (dev->bus->chip_id & 0xFF00);
+ if (chipid_top != 0x4700 && chipid_top != 0x5300)
+ return -ENODEV;
+
+ /* TODO: Probably need checks here; is the core connected? */
+
+ if (usb_disabled())
+ return -ENODEV;
+
+ err = ssb_ehci_attach(dev);
+
+ return err;
+}
+
+static void ssb_ehci_remove(struct ssb_device *dev)
+{
+ ssb_ehci_detach(dev);
+}
+
+#ifdef CONFIG_PM
+
+static int ssb_ehci_suspend(struct ssb_device *dev, pm_message_t state)
+{
+ ssb_device_disable(dev, 0);
+
+ return 0;
+}
+
+static int ssb_ehci_resume(struct ssb_device *dev)
+{
+ struct usb_hcd *hcd = ssb_get_drvdata(dev);
+ struct ssb_ehci_device *ehcidev = hcd_to_ssb_ehci(hcd);
+
+ ssb_device_enable(dev, 0);
+
+ ehci_finish_controller_resume(hcd);
+ return 0;
+}
+
+#else /* !CONFIG_PM */
+#define ssb_ehci_suspend NULL
+#define ssb_ehci_resume NULL
+#endif /* CONFIG_PM */
+ +
+static const struct ssb_device_id ssb_ehci_table[] = { +static const struct ssb_device_id ssb_ehci_table[] = {
+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV), + SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
+ SSB_DEVTABLE_END + SSB_DEVTABLE_END
+}; +};
+MODULE_DEVICE_TABLE(ssb, ssb_ehci_table); +MODULE_DEVICE_TABLE(ssb, ssb_ehci_table);
--- a/drivers/usb/host/ohci-ssb.c
+++ b/drivers/usb/host/ohci-ssb.c
@@ -17,6 +17,8 @@
*/
#include <linux/ssb/ssb.h>
+extern int ssb_ehci_attach(struct ssb_device *dev, struct usb_hcd **hcd);
+extern void ssb_ehci_detach(struct ssb_device *dev, struct usb_hcd *hcd);
#define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29)
@@ -24,6 +26,7 @@ struct ssb_ohci_device {
struct ohci_hcd ohci; /* _must_ be at the beginning. */
u32 enable_flags;
+ struct usb_hcd *ehci_hcd;
};
static inline
@@ -92,13 +95,25 @@ static const struct hc_driver ssb_ohci_h
static void ssb_ohci_detach(struct ssb_device *dev)
{
struct usb_hcd *hcd = ssb_get_drvdata(dev);
+#ifdef CONFIG_USB_EHCI_HCD_SSB
+ struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
+#endif
usb_remove_hcd(hcd);
iounmap(hcd->regs);
usb_put_hcd(hcd);
+ +
+#ifdef CONFIG_USB_EHCI_HCD_SSB +static struct ssb_driver ssb_ehci_driver = {
+ /* + .name = KBUILD_MODNAME,
+ * Also detach ehci function + .id_table = ssb_ehci_table,
+ */ + .probe = ssb_ehci_probe,
+ if (dev->id.coreid == SSB_DEV_USB20_HOST) + .remove = ssb_ehci_remove,
+ ssb_ehci_detach(dev, ohcidev->ehci_hcd); + .suspend = ssb_ehci_suspend,
+#endif + .resume = ssb_ehci_resume,
ssb_device_disable(dev, 0); +};
}
+
static int ssb_ohci_attach(struct ssb_device *dev)
{
struct ssb_ohci_device *ohcidev;
@@ -165,6 +180,14 @@ static int ssb_ohci_attach(struct ssb_de
ssb_set_drvdata(dev, hcd);
+#ifdef CONFIG_USB_EHCI_HCD_SSB
+ /*
+ * attach ehci function in this core
+ */
+ if (dev->id.coreid == SSB_DEV_USB20_HOST)
+ err = ssb_ehci_attach(dev, &(ohcidev->ehci_hcd));
+#endif
+
return err;
err_iounmap:

View File

@ -1,89 +0,0 @@
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -205,7 +205,6 @@ config MIPS_MALTA
select I8259
select MIPS_BOARDS_GEN
select MIPS_BONITO64
- select MIPS_CPU_SCACHE
select PCI_GT64XXX_PCI0
select MIPS_MSC
select SWAP_IO_SPACE
@@ -1589,13 +1588,6 @@ config IP22_CPU_SCACHE
bool
select BOARD_SCACHE
-#
-# Support for a MIPS32 / MIPS64 style S-caches
-#
-config MIPS_CPU_SCACHE
- bool
- select BOARD_SCACHE
-
config R5000_CPU_SCACHE
bool
select BOARD_SCACHE
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -772,6 +772,8 @@ static inline void cpu_probe_mips(struct
case PRID_IMP_25KF:
c->cputype = CPU_25KF;
__cpu_name[cpu] = "MIPS 25Kc";
+ /* Probe for L2 cache */
+ c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
break;
case PRID_IMP_34K:
c->cputype = CPU_34K;
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -33,6 +33,5 @@ obj-$(CONFIG_CPU_CAVIUM_OCTEON) += c-oct
obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o
obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o
obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
-obj-$(CONFIG_MIPS_CPU_SCACHE) += sc-mips.o
EXTRA_CFLAGS += -Werror
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1148,7 +1148,6 @@ static void __init loongson2_sc_init(voi
extern int r5k_sc_init(void);
extern int rm7k_sc_init(void);
-extern int mips_sc_init(void);
static void __cpuinit setup_scache(void)
{
@@ -1202,29 +1201,17 @@ static void __cpuinit setup_scache(void)
#endif
default:
- if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
- c->isa_level == MIPS_CPU_ISA_M32R2 ||
- c->isa_level == MIPS_CPU_ISA_M64R1 ||
- c->isa_level == MIPS_CPU_ISA_M64R2) {
-#ifdef CONFIG_MIPS_CPU_SCACHE
- if (mips_sc_init ()) {
- scache_size = c->scache.ways * c->scache.sets * c->scache.linesz;
- printk("MIPS secondary cache %ldkB, %s, linesize %d bytes.\n",
- scache_size >> 10,
- way_string[c->scache.ways], c->scache.linesz);
- }
-#else
- if (!(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
- panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
-#endif
- return;
- }
sc_present = 0;
}
if (!sc_present)
return;
+ if ((c->isa_level == MIPS_CPU_ISA_M32R1 ||
+ c->isa_level == MIPS_CPU_ISA_M64R1) &&
+ !(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
+ panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
+
/* compute a couple of other cache variables */
c->scache.waysize = scache_size / c->scache.ways;

View File

@ -295,7 +295,7 @@
if (dc_lsize) if (dc_lsize)
protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
if (!cpu_icache_snoops_remote_store && scache_size) if (!cpu_icache_snoops_remote_store && scache_size)
@@ -1298,6 +1312,17 @@ static void __cpuinit coherency_setup(vo @@ -1311,6 +1325,17 @@ static void __cpuinit coherency_setup(vo
* silly idea of putting something else there ... * silly idea of putting something else there ...
*/ */
switch (current_cpu_type()) { switch (current_cpu_type()) {
@ -313,7 +313,7 @@
case CPU_R4000PC: case CPU_R4000PC:
case CPU_R4000SC: case CPU_R4000SC:
case CPU_R4000MC: case CPU_R4000MC:
@@ -1354,6 +1379,15 @@ void __cpuinit r4k_cache_init(void) @@ -1367,6 +1392,15 @@ void __cpuinit r4k_cache_init(void)
break; break;
} }
@ -329,7 +329,7 @@
probe_pcache(); probe_pcache();
setup_scache(); setup_scache();
@@ -1412,5 +1446,13 @@ void __cpuinit r4k_cache_init(void) @@ -1425,5 +1459,13 @@ void __cpuinit r4k_cache_init(void)
#if !defined(CONFIG_MIPS_CMP) #if !defined(CONFIG_MIPS_CMP)
local_r4k___flush_cache_all(NULL); local_r4k___flush_cache_all(NULL);
#endif #endif

View File

@ -1,36 +1,58 @@
--- a/drivers/net/b44.c --- a/drivers/net/b44.c
+++ b/drivers/net/b44.c +++ b/drivers/net/b44.c
@@ -384,7 +384,7 @@ static void b44_set_flow_ctrl(struct b44 @@ -381,11 +381,12 @@ static void b44_set_flow_ctrl(struct b44
__b44_set_flow_ctrl(bp, pause_enab); __b44_set_flow_ctrl(bp, pause_enab);
} }
-#ifdef SSB_DRIVER_MIPS -#ifdef SSB_DRIVER_MIPS
+#ifdef CONFIG_SSB_DRIVER_MIPS -extern char *nvram_get(char *name);
extern char *nvram_get(char *name); +#ifdef CONFIG_BCM47XX
+
+#include <asm/mach-bcm47xx/nvram.h>
static void b44_wap54g10_workaround(struct b44 *bp) static void b44_wap54g10_workaround(struct b44 *bp)
{ {
@@ -421,12 +421,45 @@ static inline void b44_wap54g10_workarou - const char *str;
} + char buf[20];
#endif u32 val;
int err;
+#ifdef CONFIG_SSB_DRIVER_MIPS @@ -394,10 +395,9 @@ static void b44_wap54g10_workaround(stru
* see https://dev.openwrt.org/ticket/146
* check and reset bit "isolate"
*/
- str = nvram_get("boardnum");
- if (!str)
+ if (nvram_getenv("boardnum", buf, sizeof(buf)) > 0)
return;
- if (simple_strtoul(str, NULL, 0) == 2) {
+ if (simple_strtoul(buf, NULL, 0) == 2) {
err = __b44_readphy(bp, 0, MII_BMCR, &val);
if (err)
goto error;
@@ -412,10 +412,43 @@ static void b44_wap54g10_workaround(stru
error:
pr_warning("PHY: cannot reset MII transceiver isolate bit\n");
}
+
+static inline int startswith (const char *source, const char *cmp) +static inline int startswith (const char *source, const char *cmp)
+{ +{
+ return !strncmp(source,cmp,strlen(cmp)); + return !strncmp(source,cmp,strlen(cmp));
+} +}
+ +
+#define getvar(str) (nvram_get(str) ? : "")
+
+static inline void b44_bcm47xx_workarounds(struct b44 *bp) +static inline void b44_bcm47xx_workarounds(struct b44 *bp)
+{ +{
+ char buf[20];
+ /* Toshiba WRC-1000, Siemens SE505 v1, Askey RT-210W, RT-220W */ + /* Toshiba WRC-1000, Siemens SE505 v1, Askey RT-210W, RT-220W */
+ if (simple_strtoul(getvar("boardnum"), NULL, 0) == 100) { + if (nvram_getenv("boardnum", buf, sizeof(buf)) > 0)
+ return;
+ if (simple_strtoul(buf, NULL, 0) == 100) {
+ bp->phy_addr = B44_PHY_ADDR_NO_PHY; + bp->phy_addr = B44_PHY_ADDR_NO_PHY;
+ } else { + } else {
+ /* WL-HDD */ + /* WL-HDD */
+ struct ssb_device *sdev = bp->sdev; + struct ssb_device *sdev = bp->sdev;
+ if (startswith(getvar("hardware_version"), "WL300-")) + if (nvram_getenv("hardware_version", buf, sizeof(buf)) > 0)
+ { + return;
+ if (startswith(buf, "WL300-")) {
+ if (sdev->bus->sprom.et0phyaddr == 0 && + if (sdev->bus->sprom.et0phyaddr == 0 &&
+ sdev->bus->sprom.et1phyaddr == 1) + sdev->bus->sprom.et1phyaddr == 1)
+ bp->phy_addr = B44_PHY_ADDR_NO_PHY; + bp->phy_addr = B44_PHY_ADDR_NO_PHY;
@ -39,15 +61,19 @@
+ return; + return;
+} +}
+ +
+#else #else
+
static inline void b44_wap54g10_workaround(struct b44 *bp)
{
}
+
+static inline void b44_bcm47xx_workarounds(struct b44 *bp) +static inline void b44_bcm47xx_workarounds(struct b44 *bp)
+{ +{
+} +}
+#endif #endif
+
static int b44_setup_phy(struct b44 *bp) static int b44_setup_phy(struct b44 *bp)
{ @@ -424,6 +457,7 @@ static int b44_setup_phy(struct b44 *bp)
u32 val;
int err; int err;
b44_wap54g10_workaround(bp); b44_wap54g10_workaround(bp);
@ -55,7 +81,7 @@
if (bp->phy_addr == B44_PHY_ADDR_NO_PHY) if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
return 0; return 0;
@@ -2089,6 +2122,8 @@ static int __devinit b44_get_invariants( @@ -2080,6 +2114,8 @@ static int __devinit b44_get_invariants(
* valid PHY address. */ * valid PHY address. */
bp->phy_addr &= 0x1F; bp->phy_addr &= 0x1F;

View File

@ -1,6 +1,6 @@
--- a/drivers/net/b44.c --- a/drivers/net/b44.c
+++ b/drivers/net/b44.c +++ b/drivers/net/b44.c
@@ -191,10 +191,11 @@ static int b44_wait_bit(struct b44 *bp, @@ -188,10 +188,11 @@ static int b44_wait_bit(struct b44 *bp,
udelay(10); udelay(10);
} }
if (i == timeout) { if (i == timeout) {

View File

@ -1,6 +1,6 @@
--- a/drivers/ssb/driver_chipcommon.c --- a/drivers/ssb/driver_chipcommon.c
+++ b/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c
@@ -260,6 +260,8 @@ void ssb_chipco_resume(struct ssb_chipco @@ -285,6 +285,8 @@ void ssb_chipco_resume(struct ssb_chipco
void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc, void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
u32 *plltype, u32 *n, u32 *m) u32 *plltype, u32 *n, u32 *m)
{ {
@ -9,7 +9,7 @@
*n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N); *n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N);
*plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT); *plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
switch (*plltype) { switch (*plltype) {
@@ -283,6 +285,8 @@ void ssb_chipco_get_clockcpu(struct ssb_ @@ -308,6 +310,8 @@ void ssb_chipco_get_clockcpu(struct ssb_
void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc, void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,
u32 *plltype, u32 *n, u32 *m) u32 *plltype, u32 *n, u32 *m)
{ {
@ -31,7 +31,7 @@
} }
--- a/drivers/ssb/main.c --- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c +++ b/drivers/ssb/main.c
@@ -1073,6 +1073,8 @@ u32 ssb_clockspeed(struct ssb_bus *bus) @@ -1075,6 +1075,8 @@ u32 ssb_clockspeed(struct ssb_bus *bus)
if (bus->chip_id == 0x5365) { if (bus->chip_id == 0x5365) {
rate = 100000000; rate = 100000000;

View File

@ -1,60 +0,0 @@
---
drivers/usb/host/ohci-ssb.c | 39 ++++++++++++++++++++++++++++++++++++---
1 file changed, 36 insertions(+), 3 deletions(-)
--- a/drivers/usb/host/ohci-ssb.c
+++ b/drivers/usb/host/ohci-ssb.c
@@ -106,10 +106,42 @@ static int ssb_ohci_attach(struct ssb_de
int err = -ENOMEM;
u32 tmp, flags = 0;
- if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV)
+ if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
+ /* Put the device into host-mode. */
flags |= SSB_OHCI_TMSLOW_HOSTMODE;
-
- ssb_device_enable(dev, flags);
+ ssb_device_enable(dev, flags);
+ } else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
+ /*
+ * USB 2.0 special considerations:
+ *
+ * 1. Since the core supports both OHCI and EHCI functions, it must
+ * only be reset once.
+ *
+ * 2. In addition to the standard SSB reset sequence, the Host Control
+ * Register must be programmed to bring the USB core and various
+ * phy components out of reset.
+ */
+ ssb_device_enable(dev, 0);
+ ssb_write32(dev, 0x200, 0x7ff);
+ udelay(1);
+ if (dev->id.revision == 1) { // bug in rev 1
+
+ /* Change Flush control reg */
+ tmp = ssb_read32(dev, 0x400);
+ tmp &= ~8;
+ ssb_write32(dev, 0x400, tmp);
+ tmp = ssb_read32(dev, 0x400);
+ printk("USB20H fcr: 0x%0x\n", tmp);
+
+ /* Change Shim control reg */
+ tmp = ssb_read32(dev, 0x304);
+ tmp &= ~0x100;
+ ssb_write32(dev, 0x304, tmp);
+ tmp = ssb_read32(dev, 0x304);
+ printk("USB20H shim: 0x%0x\n", tmp);
+ }
+ } else
+ ssb_device_enable(dev, 0);
hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
dev_name(dev->dev));
@@ -200,6 +232,7 @@ static int ssb_ohci_resume(struct ssb_de
static const struct ssb_device_id ssb_ohci_table[] = {
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
SSB_DEVTABLE_END
};
MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);

View File

@ -1,16 +0,0 @@
---
drivers/usb/host/ohci-ssb.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/usb/host/ohci-ssb.c
+++ b/drivers/usb/host/ohci-ssb.c
@@ -106,6 +106,9 @@ static int ssb_ohci_attach(struct ssb_de
int err = -ENOMEM;
u32 tmp, flags = 0;
+ if (ssb_dma_set_mask(dev, DMA_BIT_MASK(32)))
+ return -EOPNOTSUPP;
+
if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
/* Put the device into host-mode. */
flags |= SSB_OHCI_TMSLOW_HOSTMODE;

View File

@ -1,63 +0,0 @@
This patch significantly improves the reliability of high speed
usb writes on the bcm5354. It implements a work around for version 2
of the usb20 core that was cribbed from the GPL sources for the
Asus wl500gpv2 and verified against the wl520gu sources.
Reference:
GPL/WL-520gu-NewUI/src/linux/linux/arch/mips/brcm-boards/bcm947xx/pcibios.c
GPL/WL-500gPV2-NewUI/src/linux/linux/arch/mips/brcm-boards/bcm947xx/pcibios.c
Signed-off-by: Steve Brown <sbrown@cortland.com>
---
drivers/usb/host/ohci-ssb.c | 37 +++++++++++++++++++++++--------------
1 file changed, 23 insertions(+), 14 deletions(-)
--- a/drivers/usb/host/ohci-ssb.c
+++ b/drivers/usb/host/ohci-ssb.c
@@ -141,22 +141,31 @@ static int ssb_ohci_attach(struct ssb_de
*/
ssb_device_enable(dev, 0);
ssb_write32(dev, 0x200, 0x7ff);
+
+ /* Change Flush control reg */
+ tmp = ssb_read32(dev, 0x400);
+ tmp &= ~8;
+ ssb_write32(dev, 0x400, tmp);
+ tmp = ssb_read32(dev, 0x400);
+
+ /* Change Shim control reg */
+ tmp = ssb_read32(dev, 0x304);
+ tmp &= ~0x100;
+ ssb_write32(dev, 0x304, tmp);
+ tmp = ssb_read32(dev, 0x304);
+
udelay(1);
- if (dev->id.revision == 1) { // bug in rev 1
- /* Change Flush control reg */
- tmp = ssb_read32(dev, 0x400);
- tmp &= ~8;
- ssb_write32(dev, 0x400, tmp);
- tmp = ssb_read32(dev, 0x400);
- printk("USB20H fcr: 0x%0x\n", tmp);
-
- /* Change Shim control reg */
- tmp = ssb_read32(dev, 0x304);
- tmp &= ~0x100;
- ssb_write32(dev, 0x304, tmp);
- tmp = ssb_read32(dev, 0x304);
- printk("USB20H shim: 0x%0x\n", tmp);
+ /* Work around for 5354 failures */
+ if ((dev->id.revision == 2) && (dev->bus->chip_id == 0x5354)) {
+ /* Change syn01 reg */
+ tmp = 0x00fe00fe;
+ ssb_write32(dev, 0x894, tmp);
+
+ /* Change syn03 reg */
+ tmp = ssb_read32(dev, 0x89c);
+ tmp |= 0x1;
+ ssb_write32(dev, 0x89c, tmp);
}
} else
ssb_device_enable(dev, 0);

View File

@ -18,7 +18,7 @@
unsigned long addr, unsigned long pfn) unsigned long addr, unsigned long pfn)
{ {
struct flush_cache_page_args args; struct flush_cache_page_args args;
@@ -1456,3 +1456,10 @@ void __cpuinit r4k_cache_init(void) @@ -1469,3 +1469,10 @@ void __cpuinit r4k_cache_init(void)
coherency_setup(); coherency_setup();
#endif #endif
} }

View File

@ -1,280 +1,39 @@
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -62,6 +62,7 @@ config BCM47XX
select SSB_DRIVER_MIPS
select SSB_DRIVER_EXTIF
select SSB_EMBEDDED
+ select SSB_B43_PCI_BRIDGE if PCI
select SSB_PCICORE_HOSTMODE if PCI
select GENERIC_GPIO
select SYS_HAS_EARLY_PRINTK
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -3,4 +3,4 @@
# under Linux.
#
-obj-y := gpio.o irq.o prom.o serial.o setup.o time.o wgt634u.o
+obj-y := cfe_env.o gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
--- a/arch/mips/bcm47xx/irq.c
+++ b/arch/mips/bcm47xx/irq.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
+ * Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -23,10 +24,19 @@
*/
#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/pci.h>
+#include <linux/ssb/ssb.h>
+
#include <asm/irq_cpu.h>
+
+extern struct ssb_bus ssb_bcm47xx;
+
+
void plat_irq_dispatch(void)
{
u32 cause;
--- a/arch/mips/bcm47xx/nvram.c --- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c
@@ -24,10 +24,10 @@ @@ -92,3 +92,30 @@ int nvram_getenv(char *name, char *val,
#include <asm/io.h> return 1;
#include <asm/uaccess.h> }
EXPORT_SYMBOL(nvram_getenv);
-#include <nvram.h> +
+#include "include/nvram.h" +char *nvram_get(const char *name)
+{
#define MB * 1048576 + char *var, *value, *end, *eq;
-extern struct ssb_bus ssb; +
+extern struct ssb_bus ssb_bcm47xx; + if (!name)
+ return NULL;
static char nvram_buf[NVRAM_SPACE]; +
static int cfe_env; + if (!nvram_buf[0])
@@ -36,7 +36,7 @@ extern char *cfe_env_get(char *nv_buf, c + early_nvram_init();
/* Probe for NVRAM header */ +
static void __init early_nvram_init(void) + /* Look for name=value and return value */
{ + var = &nvram_buf[sizeof(struct nvram_header)];
- struct ssb_mipscore *mcore = &ssb.mipscore; + end = nvram_buf + sizeof(nvram_buf) - 2;
+ struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore; + end[0] = end[1] = '\0';
struct nvram_header *header; + for (; *var; var = value + strlen(value) + 1) {
int i; + if (!(eq = strchr(var, '=')))
u32 base, lim, off; + break;
+ value = eq + 1;
+ if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0)
+ return value;
+ }
+
+ return NULL;
+}
+
+EXPORT_SYMBOL(nvram_get);
--- a/arch/mips/bcm47xx/setup.c --- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c
@@ -2,7 +2,7 @@ @@ -226,3 +226,20 @@ void __init plat_mem_setup(void)
* Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
* Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
- * Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2006-2008 Michael Buesch <mb@bu3sch.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -25,18 +25,28 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/init.h>
#include <linux/types.h>
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_embedded.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/serial_8250.h>
#include <asm/bootinfo.h>
#include <asm/reboot.h>
#include <asm/time.h>
-#include <bcm47xx.h>
#include <asm/fw/cfe/cfe_api.h>
+#include <linux/pm.h>
+
+#include "include/nvram.h"
struct ssb_bus ssb_bcm47xx;
EXPORT_SYMBOL(ssb_bcm47xx);
+extern void bcm47xx_pci_init(void);
+
static void bcm47xx_machine_restart(char *command)
{
printk(KERN_ALERT "Please stand by while rebooting the system...\n");
@@ -56,7 +66,7 @@ static void bcm47xx_machine_halt(void)
cpu_relax();
}
-static void str2eaddr(char *str, char *dest)
+static void e_aton(char *str, char *dest)
{
int i = 0;
@@ -73,51 +83,142 @@ static void str2eaddr(char *str, char *d
}
}
-static int bcm47xx_get_invariants(struct ssb_bus *bus,
- struct ssb_init_invariants *iv)
+static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
+{
+ char *s;
+
+ memset(sprom, 0xFF, sizeof(struct ssb_sprom));
+
+ sprom->revision = 1;
+ if ((s = nvram_get("il0macaddr")))
+ e_aton(s, sprom->il0mac);
+ if ((s = nvram_get("et0macaddr")))
+ e_aton(s, sprom->et0mac);
+ if ((s = nvram_get("et1macaddr")))
+ e_aton(s, sprom->et1mac);
+ if ((s = nvram_get("et0phyaddr")))
+ sprom->et0phyaddr = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("et1phyaddr")))
+ sprom->et1phyaddr = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("et0mdcport")))
+ sprom->et0mdcport = !!simple_strtoul(s, NULL, 10);
+ if ((s = nvram_get("et1mdcport")))
+ sprom->et1mdcport = !!simple_strtoul(s, NULL, 10);
+ if ((s = nvram_get("pa0b0")))
+ sprom->pa0b0 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("pa0b1")))
+ sprom->pa0b1 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("pa0b2")))
+ sprom->pa0b2 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("pa1b0")))
+ sprom->pa1b0 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("pa1b1")))
+ sprom->pa1b1 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("pa1b2")))
+ sprom->pa1b2 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("wl0gpio0")))
+ sprom->gpio0 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("wl0gpio1")))
+ sprom->gpio1 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("wl0gpio2")))
+ sprom->gpio2 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("wl0gpio3")))
+ sprom->gpio3 = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("pa0maxpwr")))
+ sprom->maxpwr_bg = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("pa1maxpwr")))
+ sprom->maxpwr_a = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("pa0itssit")))
+ sprom->itssi_bg = simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("pa1itssit")))
+ sprom->itssi_a = simple_strtoul(s, NULL, 0);
+ sprom->boardflags_lo = 0;
+ if ((s = nvram_get("boardflags")))
+ sprom->boardflags_lo = simple_strtoul(s, NULL, 0);
+ sprom->boardflags_hi = 0;
+ if ((s = nvram_get("boardflags2")))
+ sprom->boardflags_hi = simple_strtoul(s, NULL, 0);
+}
+
+static int bcm47xx_get_invariants(struct ssb_bus *bus, struct ssb_init_invariants *iv)
{
- char buf[100];
+ char *s;
+
+ iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
+ if ((s = nvram_get("boardtype")))
+ iv->boardinfo.type = (u16)simple_strtoul(s, NULL, 0);
+ if ((s = nvram_get("boardrev")))
+ iv->boardinfo.rev = (u16)simple_strtoul(s, NULL, 0);
- /* Fill boardinfo structure */
- memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
+ bcm47xx_fill_sprom(&iv->sprom);
- if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0)
- iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
- if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0)
- iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
- if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0)
- iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
-
- /* Fill sprom structure */
- memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
- iv->sprom.revision = 3;
-
- if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
- str2eaddr(buf, iv->sprom.et0mac);
- if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
- str2eaddr(buf, iv->sprom.et1mac);
- if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
- iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 10);
- if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
- iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 10);
- if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
- iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
- if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
- iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
+ if ((s = nvram_get("cardbus")))
+ iv->has_cardbus_slot = !!simple_strtoul(s, NULL, 10);
return 0;
}
void __init plat_mem_setup(void)
{
- int err;
+ int i, err;
+ char *s;
+ struct ssb_mipscore *mcore;
+
+ err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE, bcm47xx_get_invariants);
+ if (err) {
+ const char *msg = "Failed to initialize SSB bus (err %d)\n";
+ printk(msg, err); /* Make sure the message gets out of the box. */
+ panic(msg, err);
+ }
+ mcore = &ssb_bcm47xx.mipscore;
- err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
- bcm47xx_get_invariants);
- if (err)
- panic("Failed to initialize SSB bus (err %d)\n", err);
+ s = nvram_get("kernel_args");
+ if (s && !strncmp(s, "console=ttyS1", 13)) {
+ struct ssb_serial_port port;
+
+ printk("Swapping serial ports!\n");
+ /* swap serial ports */
+ memcpy(&port, &mcore->serial_ports[0], sizeof(port));
+ memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1], sizeof(port));
+ memcpy(&mcore->serial_ports[1], &port, sizeof(port));
+ }
+
+ for (i = 0; i < mcore->nr_serial_ports; i++) {
+ struct ssb_serial_port *port = &(mcore->serial_ports[i]);
+ struct uart_port s;
+
+ memset(&s, 0, sizeof(s));
+ s.line = i;
+ s.mapbase = (unsigned int) port->regs;
+ s.membase = port->regs;
+ s.irq = port->irq + 2;
+ s.uartclk = port->baud_base;
+ s.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ s.iotype = SERIAL_IO_MEM;
+ s.regshift = port->reg_shift;
+
+ early_serial_setup(&s);
+ }
+ printk("Serial init done.\n");
_machine_restart = bcm47xx_machine_restart;
_machine_halt = bcm47xx_machine_halt; _machine_halt = bcm47xx_machine_halt;
pm_power_off = bcm47xx_machine_halt; pm_power_off = bcm47xx_machine_halt;
} }
@ -295,25 +54,3 @@
+ return 0; + return 0;
+} +}
+device_initcall(bcm47xx_register_gpiodev); +device_initcall(bcm47xx_register_gpiodev);
--- a/arch/mips/bcm47xx/time.c
+++ b/arch/mips/bcm47xx/time.c
@@ -22,11 +22,17 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/serial_reg.h>
+#include <linux/interrupt.h>
#include <linux/ssb/ssb.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
#include <asm/time.h>
-#include <bcm47xx.h>
+
+extern struct ssb_bus ssb_bcm47xx;
void __init plat_time_init(void)
{

View File

@ -8,7 +8,7 @@
#include <net/checksum.h> #include <net/checksum.h>
#include <net/ip.h> #include <net/ip.h>
@@ -471,8 +472,9 @@ static void _tw32_flush(struct tg3 *tp, @@ -494,8 +495,9 @@ static void _tw32_flush(struct tg3 *tp,
static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val) static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val)
{ {
tp->write32_mbox(tp, off, val); tp->write32_mbox(tp, off, val);
@ -20,7 +20,7 @@
tp->read32_mbox(tp, off); tp->read32_mbox(tp, off);
} }
@@ -482,7 +484,7 @@ static void tg3_write32_tx_mbox(struct t @@ -505,7 +507,7 @@ static void tg3_write32_tx_mbox(struct t
writel(val, mbox); writel(val, mbox);
if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG)
writel(val, mbox); writel(val, mbox);
@ -29,7 +29,7 @@
readl(mbox); readl(mbox);
} }
@@ -783,7 +785,7 @@ static void tg3_switch_clocks(struct tg3 @@ -807,7 +809,7 @@ static void tg3_switch_clocks(struct tg3
#define PHY_BUSY_LOOPS 5000 #define PHY_BUSY_LOOPS 5000
@ -38,7 +38,7 @@
{ {
u32 frame_val; u32 frame_val;
unsigned int loops; unsigned int loops;
@@ -797,7 +799,7 @@ static int tg3_readphy(struct tg3 *tp, i @@ -821,7 +823,7 @@ static int tg3_readphy(struct tg3 *tp, i
*val = 0x0; *val = 0x0;
@ -47,7 +47,7 @@
MI_COM_PHY_ADDR_MASK); MI_COM_PHY_ADDR_MASK);
frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) & frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
MI_COM_REG_ADDR_MASK); MI_COM_REG_ADDR_MASK);
@@ -832,7 +834,12 @@ static int tg3_readphy(struct tg3 *tp, i @@ -856,7 +858,12 @@ static int tg3_readphy(struct tg3 *tp, i
return ret; return ret;
} }
@ -61,7 +61,7 @@
{ {
u32 frame_val; u32 frame_val;
unsigned int loops; unsigned int loops;
@@ -848,7 +855,7 @@ static int tg3_writephy(struct tg3 *tp, @@ -872,7 +879,7 @@ static int tg3_writephy(struct tg3 *tp,
udelay(80); udelay(80);
} }
@ -70,7 +70,7 @@
MI_COM_PHY_ADDR_MASK); MI_COM_PHY_ADDR_MASK);
frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) & frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
MI_COM_REG_ADDR_MASK); MI_COM_REG_ADDR_MASK);
@@ -881,6 +888,11 @@ static int tg3_writephy(struct tg3 *tp, @@ -905,6 +912,11 @@ static int tg3_writephy(struct tg3 *tp,
return ret; return ret;
} }
@ -82,7 +82,7 @@
static int tg3_bmcr_reset(struct tg3 *tp) static int tg3_bmcr_reset(struct tg3 *tp)
{ {
u32 phy_control; u32 phy_control;
@@ -2389,6 +2401,9 @@ static int tg3_nvram_read(struct tg3 *tp @@ -2411,6 +2423,9 @@ static int tg3_nvram_read(struct tg3 *tp
{ {
int ret; int ret;
@ -92,7 +92,7 @@
if (!(tp->tg3_flags & TG3_FLAG_NVRAM)) if (!(tp->tg3_flags & TG3_FLAG_NVRAM))
return tg3_nvram_read_using_eeprom(tp, offset, val); return tg3_nvram_read_using_eeprom(tp, offset, val);
@@ -2720,8 +2735,10 @@ static int tg3_set_power_state(struct tg @@ -2742,8 +2757,10 @@ static int tg3_set_power_state(struct tg
tg3_frob_aux_power(tp); tg3_frob_aux_power(tp);
/* Workaround for unstable PLL clock */ /* Workaround for unstable PLL clock */
@ -105,7 +105,7 @@
u32 val = tr32(0x7d00); u32 val = tr32(0x7d00);
val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1); val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1);
@@ -3214,6 +3231,14 @@ relink: @@ -3236,6 +3253,14 @@ relink:
tg3_phy_copper_begin(tp); tg3_phy_copper_begin(tp);
@ -120,7 +120,7 @@
tg3_readphy(tp, MII_BMSR, &tmp); tg3_readphy(tp, MII_BMSR, &tmp);
if (!tg3_readphy(tp, MII_BMSR, &tmp) && if (!tg3_readphy(tp, MII_BMSR, &tmp) &&
(tmp & BMSR_LSTATUS)) (tmp & BMSR_LSTATUS))
@@ -6675,6 +6700,11 @@ static int tg3_poll_fw(struct tg3 *tp) @@ -6719,6 +6744,11 @@ static int tg3_poll_fw(struct tg3 *tp)
int i; int i;
u32 val; u32 val;
@ -132,7 +132,7 @@
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
/* Wait up to 20ms for init done. */ /* Wait up to 20ms for init done. */
for (i = 0; i < 200; i++) { for (i = 0; i < 200; i++) {
@@ -6958,6 +6988,14 @@ static int tg3_chip_reset(struct tg3 *tp @@ -7002,6 +7032,14 @@ static int tg3_chip_reset(struct tg3 *tp
tw32(0x5000, 0x400); tw32(0x5000, 0x400);
} }
@ -147,7 +147,7 @@
tw32(GRC_MODE, tp->grc_mode); tw32(GRC_MODE, tp->grc_mode);
if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) { if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) {
@@ -7135,9 +7173,12 @@ static int tg3_halt_cpu(struct tg3 *tp, @@ -7179,9 +7217,12 @@ static int tg3_halt_cpu(struct tg3 *tp,
return -ENODEV; return -ENODEV;
} }
@ -163,7 +163,7 @@
return 0; return 0;
} }
@@ -7199,6 +7240,11 @@ static int tg3_load_5701_a0_firmware_fix @@ -7244,6 +7285,11 @@ static int tg3_load_5701_a0_firmware_fix
const __be32 *fw_data; const __be32 *fw_data;
int err, i; int err, i;
@ -175,7 +175,7 @@
fw_data = (void *)tp->fw->data; fw_data = (void *)tp->fw->data;
/* Firmware blob starts with version numbers, followed by /* Firmware blob starts with version numbers, followed by
@@ -7256,6 +7302,11 @@ static int tg3_load_tso_firmware(struct @@ -7302,6 +7348,11 @@ static int tg3_load_tso_firmware(struct
unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size; unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size;
int err, i; int err, i;
@ -187,7 +187,7 @@
if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
return 0; return 0;
@@ -8380,6 +8431,11 @@ static void tg3_timer(unsigned long __op @@ -8446,6 +8497,11 @@ static void tg3_timer(unsigned long __op
spin_lock(&tp->lock); spin_lock(&tp->lock);
@ -199,7 +199,7 @@
if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) { if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
/* All of this garbage is because when using non-tagged /* All of this garbage is because when using non-tagged
* IRQ status the mailbox/status_block protocol the chip * IRQ status the mailbox/status_block protocol the chip
@@ -10279,6 +10335,11 @@ static int tg3_test_nvram(struct tg3 *tp @@ -10113,6 +10169,11 @@ static int tg3_test_nvram(struct tg3 *tp
if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM)
return 0; return 0;
@ -211,7 +211,7 @@
if (tg3_nvram_read(tp, 0, &magic) != 0) if (tg3_nvram_read(tp, 0, &magic) != 0)
return -EIO; return -EIO;
@@ -11098,7 +11159,7 @@ static int tg3_ioctl(struct net_device * @@ -10932,7 +10993,7 @@ static int tg3_ioctl(struct net_device *
return -EAGAIN; return -EAGAIN;
spin_lock_bh(&tp->lock); spin_lock_bh(&tp->lock);
@ -220,7 +220,7 @@
spin_unlock_bh(&tp->lock); spin_unlock_bh(&tp->lock);
data->val_out = mii_regval; data->val_out = mii_regval;
@@ -11114,7 +11175,7 @@ static int tg3_ioctl(struct net_device * @@ -10948,7 +11009,7 @@ static int tg3_ioctl(struct net_device *
return -EAGAIN; return -EAGAIN;
spin_lock_bh(&tp->lock); spin_lock_bh(&tp->lock);
@ -229,7 +229,7 @@
spin_unlock_bh(&tp->lock); spin_unlock_bh(&tp->lock);
return err; return err;
@@ -11759,6 +11820,12 @@ static void __devinit tg3_get_5717_nvram @@ -11593,6 +11654,12 @@ static void __devinit tg3_get_5717_nvram
/* Chips other than 5700/5701 use the NVRAM for fetching info. */ /* Chips other than 5700/5701 use the NVRAM for fetching info. */
static void __devinit tg3_nvram_init(struct tg3 *tp) static void __devinit tg3_nvram_init(struct tg3 *tp)
{ {
@ -242,7 +242,7 @@
tw32_f(GRC_EEPROM_ADDR, tw32_f(GRC_EEPROM_ADDR,
(EEPROM_ADDR_FSM_RESET | (EEPROM_ADDR_FSM_RESET |
(EEPROM_DEFAULT_CLOCK_PERIOD << (EEPROM_DEFAULT_CLOCK_PERIOD <<
@@ -12020,6 +12087,9 @@ static int tg3_nvram_write_block(struct @@ -11855,6 +11922,9 @@ static int tg3_nvram_write_block(struct
{ {
int ret; int ret;
@ -252,7 +252,7 @@
if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) { if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) {
tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl & tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl &
~GRC_LCLCTRL_GPIO_OUTPUT1); ~GRC_LCLCTRL_GPIO_OUTPUT1);
@@ -13360,6 +13430,11 @@ static int __devinit tg3_get_invariants( @@ -13227,6 +13297,11 @@ static int __devinit tg3_get_invariants(
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701))) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)))
tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG; tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG;
@ -264,7 +264,7 @@
/* Get eeprom hw config before calling tg3_set_power_state(). /* Get eeprom hw config before calling tg3_set_power_state().
* In particular, the TG3_FLG2_IS_NIC flag must be * In particular, the TG3_FLG2_IS_NIC flag must be
* determined before calling tg3_set_power_state() so that * determined before calling tg3_set_power_state() so that
@@ -13753,6 +13828,10 @@ static int __devinit tg3_get_device_addr @@ -13624,6 +13699,10 @@ static int __devinit tg3_get_device_addr
} }
if (!is_valid_ether_addr(&dev->dev_addr[0])) { if (!is_valid_ether_addr(&dev->dev_addr[0])) {
@ -275,7 +275,7 @@
#ifdef CONFIG_SPARC #ifdef CONFIG_SPARC
if (!tg3_get_default_macaddr_sparc(tp)) if (!tg3_get_default_macaddr_sparc(tp))
return 0; return 0;
@@ -14272,6 +14351,7 @@ static char * __devinit tg3_phy_string(s @@ -14144,6 +14223,7 @@ static char * __devinit tg3_phy_string(s
case TG3_PHY_ID_BCM5704: return "5704"; case TG3_PHY_ID_BCM5704: return "5704";
case TG3_PHY_ID_BCM5705: return "5705"; case TG3_PHY_ID_BCM5705: return "5705";
case TG3_PHY_ID_BCM5750: return "5750"; case TG3_PHY_ID_BCM5750: return "5750";
@ -283,7 +283,7 @@
case TG3_PHY_ID_BCM5752: return "5752"; case TG3_PHY_ID_BCM5752: return "5752";
case TG3_PHY_ID_BCM5714: return "5714"; case TG3_PHY_ID_BCM5714: return "5714";
case TG3_PHY_ID_BCM5780: return "5780"; case TG3_PHY_ID_BCM5780: return "5780";
@@ -14481,6 +14561,13 @@ static int __devinit tg3_init_one(struct @@ -14354,6 +14434,13 @@ static int __devinit tg3_init_one(struct
tp->msg_enable = tg3_debug; tp->msg_enable = tg3_debug;
else else
tp->msg_enable = TG3_DEF_MSG_ENABLE; tp->msg_enable = TG3_DEF_MSG_ENABLE;
@ -309,7 +309,7 @@
#define NIC_SRAM_RX_MINI_BUFFER_DESC 0x00001000 #define NIC_SRAM_RX_MINI_BUFFER_DESC 0x00001000
@@ -2930,6 +2933,7 @@ struct tg3 { @@ -2931,6 +2934,7 @@ struct tg3 {
#define TG3_PHY_ID_BCM5704 0x60008190 #define TG3_PHY_ID_BCM5704 0x60008190
#define TG3_PHY_ID_BCM5705 0x600081a0 #define TG3_PHY_ID_BCM5705 0x600081a0
#define TG3_PHY_ID_BCM5750 0x60008180 #define TG3_PHY_ID_BCM5750 0x60008180
@ -317,7 +317,7 @@
#define TG3_PHY_ID_BCM5752 0x60008100 #define TG3_PHY_ID_BCM5752 0x60008100
#define TG3_PHY_ID_BCM5714 0x60008340 #define TG3_PHY_ID_BCM5714 0x60008340
#define TG3_PHY_ID_BCM5780 0x60008350 #define TG3_PHY_ID_BCM5780 0x60008350
@@ -2964,7 +2968,8 @@ struct tg3 { @@ -2965,7 +2969,8 @@ struct tg3 {
(X) == TG3_PHY_ID_BCM5755 || (X) == TG3_PHY_ID_BCM5756 || \ (X) == TG3_PHY_ID_BCM5755 || (X) == TG3_PHY_ID_BCM5756 || \
(X) == TG3_PHY_ID_BCM5906 || (X) == TG3_PHY_ID_BCM5761 || \ (X) == TG3_PHY_ID_BCM5906 || (X) == TG3_PHY_ID_BCM5761 || \
(X) == TG3_PHY_ID_BCM5718C || (X) == TG3_PHY_ID_BCM5718S || \ (X) == TG3_PHY_ID_BCM5718C || (X) == TG3_PHY_ID_BCM5718S || \

View File

@ -1,108 +0,0 @@
--- a/arch/mips/bcm47xx/prom.c
+++ b/arch/mips/bcm47xx/prom.c
@@ -32,6 +32,7 @@
#include <asm/fw/cfe/cfe_error.h>
static int cfe_cons_handle;
+static void (* __prom_putchar)(char c);
const char *get_system_type(void)
{
@@ -40,65 +41,40 @@ const char *get_system_type(void)
void prom_putchar(char c)
{
+ if (__prom_putchar)
+ __prom_putchar(c);
+}
+
+void prom_putchar_cfe(char c)
+{
while (cfe_write(cfe_cons_handle, &c, 1) == 0)
;
}
-static __init void prom_init_cfe(void)
+static __init int prom_init_cfe(void)
{
uint32_t cfe_ept;
uint32_t cfe_handle;
uint32_t cfe_eptseal;
- int argc = fw_arg0;
- char **envp = (char **) fw_arg2;
- int *prom_vec = (int *) fw_arg3;
-
- /*
- * Check if a loader was used; if NOT, the 4 arguments are
- * what CFE gives us (handle, 0, EPT and EPTSEAL)
- */
- if (argc < 0) {
- cfe_handle = (uint32_t)argc;
- cfe_ept = (uint32_t)envp;
- cfe_eptseal = (uint32_t)prom_vec;
- } else {
- if ((int)prom_vec < 0) {
- /*
- * Old loader; all it gives us is the handle,
- * so use the "known" entrypoint and assume
- * the seal.
- */
- cfe_handle = (uint32_t)prom_vec;
- cfe_ept = 0xBFC00500;
- cfe_eptseal = CFE_EPTSEAL;
- } else {
- /*
- * Newer loaders bundle the handle/ept/eptseal
- * Note: prom_vec is in the loader's useg
- * which is still alive in the TLB.
- */
- cfe_handle = prom_vec[0];
- cfe_ept = prom_vec[2];
- cfe_eptseal = prom_vec[3];
- }
- }
- if (cfe_eptseal != CFE_EPTSEAL) {
- /* too early for panic to do any good */
- printk(KERN_ERR "CFE's entrypoint seal doesn't match.");
- while (1) ;
- }
+ cfe_eptseal = (uint32_t) fw_arg3;
+ cfe_handle = (uint32_t) fw_arg0;
+ cfe_ept = (uint32_t) fw_arg2;
+
+ if (cfe_eptseal != CFE_EPTSEAL)
+ return -1;
cfe_init(cfe_handle, cfe_ept);
+ return 0;
}
-static __init void prom_init_console(void)
+static __init void prom_init_console_cfe(void)
{
/* Initialize CFE console */
cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
}
-static __init void prom_init_cmdline(void)
+static __init void prom_init_cmdline_cfe(void)
{
static char buf[COMMAND_LINE_SIZE] __initdata;
@@ -160,9 +136,12 @@ static __init void prom_init_mem(void)
void __init prom_init(void)
{
- prom_init_cfe();
- prom_init_console();
- prom_init_cmdline();
+ if (prom_init_cfe() == 0) {
+ //prom_init_console_cfe();
+ //prom_init_cmdline_cfe();
+ __prom_putchar = prom_putchar_cfe;
+ }
+
prom_init_mem();
}

View File

@ -4,8 +4,8 @@
# under Linux. # under Linux.
# #
-obj-y := cfe_env.o gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o -obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
+obj-y := cfe_env.o gpio.o irq.o nvram.o prom.o serial.o setup.o time.o +obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o
--- a/arch/mips/bcm47xx/wgt634u.c --- a/arch/mips/bcm47xx/wgt634u.c
+++ /dev/null +++ /dev/null
@@ -1,166 +0,0 @@ @@ -1,166 +0,0 @@

View File

@ -1,10 +0,0 @@
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -65,7 +65,6 @@ config BCM47XX
select SSB_B43_PCI_BRIDGE if PCI
select SSB_PCICORE_HOSTMODE if PCI
select GENERIC_GPIO
- select SYS_HAS_EARLY_PRINTK
select CFE
help
Support for BCM47XX based boards

View File

@ -1,6 +1,6 @@
--- a/drivers/pcmcia/yenta_socket.c --- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c
@@ -924,6 +924,8 @@ static unsigned int yenta_probe_irq(stru @@ -922,6 +922,8 @@ static unsigned int yenta_probe_irq(stru
* Probe for usable interrupts using the force * Probe for usable interrupts using the force
* register to generate bogus card status events. * register to generate bogus card status events.
*/ */
@ -9,7 +9,7 @@
cb_writel(socket, CB_SOCKET_EVENT, -1); cb_writel(socket, CB_SOCKET_EVENT, -1);
cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
reg = exca_readb(socket, I365_CSCINT); reg = exca_readb(socket, I365_CSCINT);
@@ -939,6 +941,7 @@ static unsigned int yenta_probe_irq(stru @@ -937,6 +939,7 @@ static unsigned int yenta_probe_irq(stru
} }
cb_writel(socket, CB_SOCKET_MASK, 0); cb_writel(socket, CB_SOCKET_MASK, 0);
exca_writeb(socket, I365_CSCINT, reg); exca_writeb(socket, I365_CSCINT, reg);
@ -17,7 +17,7 @@
mask = probe_irq_mask(val) & 0xffff; mask = probe_irq_mask(val) & 0xffff;
@@ -1022,6 +1025,10 @@ static void yenta_get_socket_capabilitie @@ -1021,6 +1024,10 @@ static void yenta_get_socket_capabilitie
else else
socket->socket.irq_mask = 0; socket->socket.irq_mask = 0;
@ -28,7 +28,7 @@
dev_printk(KERN_INFO, &socket->dev->dev, dev_printk(KERN_INFO, &socket->dev->dev,
"ISA IRQ mask 0x%04x, PCI irq %d\n", "ISA IRQ mask 0x%04x, PCI irq %d\n",
socket->socket.irq_mask, socket->cb_irq); socket->socket.irq_mask, socket->cb_irq);
@@ -1260,6 +1267,15 @@ static int __devinit yenta_probe(struct @@ -1259,6 +1266,15 @@ static int __devinit yenta_probe(struct
dev_printk(KERN_INFO, &dev->dev, dev_printk(KERN_INFO, &dev->dev,
"Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE)); "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));

View File

@ -1,16 +1,15 @@
--- a/arch/mips/bcm47xx/nvram.c --- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c
@@ -29,7 +29,9 @@ @@ -20,7 +20,8 @@
#define MB * 1048576 #include <asm/mach-bcm47xx/nvram.h>
extern struct ssb_bus ssb_bcm47xx; #include <asm/mach-bcm47xx/bcm47xx.h>
-static char nvram_buf[NVRAM_SPACE]; -static char nvram_buf[NVRAM_SPACE];
+char nvram_buf[NVRAM_SPACE]; +char nvram_buf[NVRAM_SPACE];
+EXPORT_SYMBOL(nvram_buf); +EXPORT_SYMBOL(nvram_buf);
+
static int cfe_env;
extern char *cfe_env_get(char *nv_buf, const char *name);
/* Probe for NVRAM header */
static void __init early_nvram_init(void)
--- a/arch/mips/mm/cache.c --- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c
@@ -52,6 +52,7 @@ void (*_dma_cache_wback)(unsigned long s @@ -52,6 +52,7 @@ void (*_dma_cache_wback)(unsigned long s

View File

@ -1,15 +1,380 @@
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -135,7 +135,6 @@ static void b44_init_rings(struct b44 *)
static void b44_init_hw(struct b44 *, int);
-static int dma_desc_align_mask;
static int dma_desc_sync_size;
static int instance;
@@ -150,9 +149,8 @@ static inline void b44_sync_dma_desc_for
unsigned long offset,
enum dma_data_direction dir)
{
- ssb_dma_sync_single_range_for_device(sdev, dma_base,
- offset & dma_desc_align_mask,
- dma_desc_sync_size, dir);
+ dma_sync_single_for_device(sdev->dma_dev, dma_base + offset,
+ dma_desc_sync_size, dir);
}
static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev,
@@ -160,9 +158,8 @@ static inline void b44_sync_dma_desc_for
unsigned long offset,
enum dma_data_direction dir)
{
- ssb_dma_sync_single_range_for_cpu(sdev, dma_base,
- offset & dma_desc_align_mask,
- dma_desc_sync_size, dir);
+ dma_sync_single_for_cpu(sdev->dma_dev, dma_base + offset,
+ dma_desc_sync_size, dir);
}
static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
@@ -608,10 +605,10 @@ static void b44_tx(struct b44 *bp)
BUG_ON(skb == NULL);
- ssb_dma_unmap_single(bp->sdev,
- rp->mapping,
- skb->len,
- DMA_TO_DEVICE);
+ dma_unmap_single(bp->sdev->dma_dev,
+ rp->mapping,
+ skb->len,
+ DMA_TO_DEVICE);
rp->skb = NULL;
dev_kfree_skb_irq(skb);
}
@@ -648,29 +645,29 @@ static int b44_alloc_rx_skb(struct b44 *
if (skb == NULL)
return -ENOMEM;
- mapping = ssb_dma_map_single(bp->sdev, skb->data,
- RX_PKT_BUF_SZ,
- DMA_FROM_DEVICE);
+ mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
+ RX_PKT_BUF_SZ,
+ DMA_FROM_DEVICE);
/* Hardware bug work-around, the chip is unable to do PCI DMA
to/from anything above 1GB :-( */
- if (ssb_dma_mapping_error(bp->sdev, mapping) ||
+ if (dma_mapping_error(bp->sdev->dma_dev, mapping) ||
mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
/* Sigh... */
- if (!ssb_dma_mapping_error(bp->sdev, mapping))
- ssb_dma_unmap_single(bp->sdev, mapping,
+ if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
+ dma_unmap_single(bp->sdev->dma_dev, mapping,
RX_PKT_BUF_SZ, DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
if (skb == NULL)
return -ENOMEM;
- mapping = ssb_dma_map_single(bp->sdev, skb->data,
- RX_PKT_BUF_SZ,
- DMA_FROM_DEVICE);
- if (ssb_dma_mapping_error(bp->sdev, mapping) ||
- mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
- if (!ssb_dma_mapping_error(bp->sdev, mapping))
- ssb_dma_unmap_single(bp->sdev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
+ mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
+ RX_PKT_BUF_SZ,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(bp->sdev->dma_dev, mapping) ||
+ mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
+ if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
+ dma_unmap_single(bp->sdev->dma_dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
return -ENOMEM;
}
@@ -745,9 +742,9 @@ static void b44_recycle_rx(struct b44 *b
dest_idx * sizeof(*dest_desc),
DMA_BIDIRECTIONAL);
- ssb_dma_sync_single_for_device(bp->sdev, dest_map->mapping,
- RX_PKT_BUF_SZ,
- DMA_FROM_DEVICE);
+ dma_sync_single_for_device(bp->sdev->dma_dev, dest_map->mapping,
+ RX_PKT_BUF_SZ,
+ DMA_FROM_DEVICE);
}
static int b44_rx(struct b44 *bp, int budget)
@@ -767,9 +764,9 @@ static int b44_rx(struct b44 *bp, int bu
struct rx_header *rh;
u16 len;
- ssb_dma_sync_single_for_cpu(bp->sdev, map,
- RX_PKT_BUF_SZ,
- DMA_FROM_DEVICE);
+ dma_sync_single_for_cpu(bp->sdev->dma_dev, map,
+ RX_PKT_BUF_SZ,
+ DMA_FROM_DEVICE);
rh = (struct rx_header *) skb->data;
len = le16_to_cpu(rh->len);
if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) ||
@@ -801,8 +798,8 @@ static int b44_rx(struct b44 *bp, int bu
skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod);
if (skb_size < 0)
goto drop_it;
- ssb_dma_unmap_single(bp->sdev, map,
- skb_size, DMA_FROM_DEVICE);
+ dma_unmap_single(bp->sdev->dma_dev, map,
+ skb_size, DMA_FROM_DEVICE);
/* Leave out rx_header */
skb_put(skb, len + RX_PKT_OFFSET);
skb_pull(skb, RX_PKT_OFFSET);
@@ -954,24 +951,24 @@ static netdev_tx_t b44_start_xmit(struct
goto err_out;
}
- mapping = ssb_dma_map_single(bp->sdev, skb->data, len, DMA_TO_DEVICE);
- if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
+ mapping = dma_map_single(bp->sdev->dma_dev, skb->data, len, DMA_TO_DEVICE);
+ if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
struct sk_buff *bounce_skb;
/* Chip can't handle DMA to/from >1GB, use bounce buffer */
- if (!ssb_dma_mapping_error(bp->sdev, mapping))
- ssb_dma_unmap_single(bp->sdev, mapping, len,
+ if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
+ dma_unmap_single(bp->sdev->dma_dev, mapping, len,
DMA_TO_DEVICE);
bounce_skb = __netdev_alloc_skb(dev, len, GFP_ATOMIC | GFP_DMA);
if (!bounce_skb)
goto err_out;
- mapping = ssb_dma_map_single(bp->sdev, bounce_skb->data,
- len, DMA_TO_DEVICE);
- if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
- if (!ssb_dma_mapping_error(bp->sdev, mapping))
- ssb_dma_unmap_single(bp->sdev, mapping,
+ mapping = dma_map_single(bp->sdev->dma_dev, bounce_skb->data,
+ len, DMA_TO_DEVICE);
+ if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
+ if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
+ dma_unmap_single(bp->sdev->dma_dev, mapping,
len, DMA_TO_DEVICE);
dev_kfree_skb_any(bounce_skb);
goto err_out;
@@ -1014,8 +1011,6 @@ static netdev_tx_t b44_start_xmit(struct
if (TX_BUFFS_AVAIL(bp) < 1)
netif_stop_queue(dev);
- dev->trans_start = jiffies;
-
out_unlock:
spin_unlock_irqrestore(&bp->lock, flags);
@@ -1070,8 +1065,8 @@ static void b44_free_rings(struct b44 *b
if (rp->skb == NULL)
continue;
- ssb_dma_unmap_single(bp->sdev, rp->mapping, RX_PKT_BUF_SZ,
- DMA_FROM_DEVICE);
+ dma_unmap_single(bp->sdev->dma_dev, rp->mapping, RX_PKT_BUF_SZ,
+ DMA_FROM_DEVICE);
dev_kfree_skb_any(rp->skb);
rp->skb = NULL;
}
@@ -1082,8 +1077,8 @@ static void b44_free_rings(struct b44 *b
if (rp->skb == NULL)
continue;
- ssb_dma_unmap_single(bp->sdev, rp->mapping, rp->skb->len,
- DMA_TO_DEVICE);
+ dma_unmap_single(bp->sdev->dma_dev, rp->mapping, rp->skb->len,
+ DMA_TO_DEVICE);
dev_kfree_skb_any(rp->skb);
rp->skb = NULL;
}
@@ -1105,14 +1100,12 @@ static void b44_init_rings(struct b44 *b
memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
if (bp->flags & B44_FLAG_RX_RING_HACK)
- ssb_dma_sync_single_for_device(bp->sdev, bp->rx_ring_dma,
- DMA_TABLE_BYTES,
- DMA_BIDIRECTIONAL);
+ dma_sync_single_for_device(bp->sdev->dma_dev, bp->rx_ring_dma,
+ DMA_TABLE_BYTES, DMA_BIDIRECTIONAL);
if (bp->flags & B44_FLAG_TX_RING_HACK)
- ssb_dma_sync_single_for_device(bp->sdev, bp->tx_ring_dma,
- DMA_TABLE_BYTES,
- DMA_TO_DEVICE);
+ dma_sync_single_for_device(bp->sdev->dma_dev, bp->tx_ring_dma,
+ DMA_TABLE_BYTES, DMA_TO_DEVICE);
for (i = 0; i < bp->rx_pending; i++) {
if (b44_alloc_rx_skb(bp, -1, i) < 0)
@@ -1132,27 +1125,23 @@ static void b44_free_consistent(struct b
bp->tx_buffers = NULL;
if (bp->rx_ring) {
if (bp->flags & B44_FLAG_RX_RING_HACK) {
- ssb_dma_unmap_single(bp->sdev, bp->rx_ring_dma,
- DMA_TABLE_BYTES,
- DMA_BIDIRECTIONAL);
+ dma_unmap_single(bp->sdev->dma_dev, bp->rx_ring_dma,
+ DMA_TABLE_BYTES, DMA_BIDIRECTIONAL);
kfree(bp->rx_ring);
} else
- ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES,
- bp->rx_ring, bp->rx_ring_dma,
- GFP_KERNEL);
+ dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
+ bp->rx_ring, bp->rx_ring_dma);
bp->rx_ring = NULL;
bp->flags &= ~B44_FLAG_RX_RING_HACK;
}
if (bp->tx_ring) {
if (bp->flags & B44_FLAG_TX_RING_HACK) {
- ssb_dma_unmap_single(bp->sdev, bp->tx_ring_dma,
- DMA_TABLE_BYTES,
- DMA_TO_DEVICE);
+ dma_unmap_single(bp->sdev->dma_dev, bp->tx_ring_dma,
+ DMA_TABLE_BYTES, DMA_TO_DEVICE);
kfree(bp->tx_ring);
} else
- ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES,
- bp->tx_ring, bp->tx_ring_dma,
- GFP_KERNEL);
+ dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
+ bp->tx_ring, bp->tx_ring_dma);
bp->tx_ring = NULL;
bp->flags &= ~B44_FLAG_TX_RING_HACK;
}
@@ -1177,7 +1166,8 @@ static int b44_alloc_consistent(struct b
goto out_err;
size = DMA_TABLE_BYTES;
- bp->rx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->rx_ring_dma, gfp);
+ bp->rx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size,
+ &bp->rx_ring_dma, gfp);
if (!bp->rx_ring) {
/* Allocation may have failed due to pci_alloc_consistent
insisting on use of GFP_DMA, which is more restrictive
@@ -1189,11 +1179,11 @@ static int b44_alloc_consistent(struct b
if (!rx_ring)
goto out_err;
- rx_ring_dma = ssb_dma_map_single(bp->sdev, rx_ring,
- DMA_TABLE_BYTES,
- DMA_BIDIRECTIONAL);
+ rx_ring_dma = dma_map_single(bp->sdev->dma_dev, rx_ring,
+ DMA_TABLE_BYTES,
+ DMA_BIDIRECTIONAL);
- if (ssb_dma_mapping_error(bp->sdev, rx_ring_dma) ||
+ if (dma_mapping_error(bp->sdev->dma_dev, rx_ring_dma) ||
rx_ring_dma + size > DMA_BIT_MASK(30)) {
kfree(rx_ring);
goto out_err;
@@ -1204,7 +1194,8 @@ static int b44_alloc_consistent(struct b
bp->flags |= B44_FLAG_RX_RING_HACK;
}
- bp->tx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->tx_ring_dma, gfp);
+ bp->tx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size,
+ &bp->tx_ring_dma, gfp);
if (!bp->tx_ring) {
/* Allocation may have failed due to ssb_dma_alloc_consistent
insisting on use of GFP_DMA, which is more restrictive
@@ -1216,11 +1207,11 @@ static int b44_alloc_consistent(struct b
if (!tx_ring)
goto out_err;
- tx_ring_dma = ssb_dma_map_single(bp->sdev, tx_ring,
- DMA_TABLE_BYTES,
- DMA_TO_DEVICE);
+ tx_ring_dma = dma_map_single(bp->sdev->dma_dev, tx_ring,
+ DMA_TABLE_BYTES,
+ DMA_TO_DEVICE);
- if (ssb_dma_mapping_error(bp->sdev, tx_ring_dma) ||
+ if (dma_mapping_error(bp->sdev->dma_dev, tx_ring_dma) ||
tx_ring_dma + size > DMA_BIT_MASK(30)) {
kfree(tx_ring);
goto out_err;
@@ -2178,12 +2169,14 @@ static int __devinit b44_init_one(struct
"Failed to powerup the bus\n");
goto err_out_free_dev;
}
- err = ssb_dma_set_mask(sdev, DMA_BIT_MASK(30));
- if (err) {
+
+ if (dma_set_mask(sdev->dma_dev, DMA_BIT_MASK(30)) ||
+ dma_set_coherent_mask(sdev->dma_dev, DMA_BIT_MASK(30))) {
dev_err(sdev->dev,
"Required 30BIT DMA mask unsupported by the system\n");
goto err_out_powerdown;
}
+
err = b44_get_invariants(bp);
if (err) {
dev_err(sdev->dev,
@@ -2346,7 +2339,6 @@ static int __init b44_init(void)
int err;
/* Setup paramaters for syncing RX/TX DMA descriptors */
- dma_desc_align_mask = ~(dma_desc_align_size - 1);
dma_desc_sync_size = max_t(unsigned int, dma_desc_align_size, sizeof(struct dma_desc));
err = b44_pci_init();
--- a/drivers/ssb/driver_chipcommon.c --- a/drivers/ssb/driver_chipcommon.c
+++ b/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c
@@ -233,6 +233,8 @@ void ssb_chipcommon_init(struct ssb_chip @@ -209,6 +209,24 @@ static void chipco_powercontrol_init(str
}
}
+/* http://bcm-v4.sipsolutions.net/802.11/PmuFastPwrupDelay */
+static u16 pmu_fast_powerup_delay(struct ssb_chipcommon *cc)
+{
+ struct ssb_bus *bus = cc->dev->bus;
+
+ switch (bus->chip_id) {
+ case 0x4312:
+ case 0x4322:
+ case 0x4328:
+ return 7000;
+ case 0x4325:
+ /* TODO: */
+ default:
+ return 15000;
+ }
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/ClkctlFastPwrupDelay */
static void calc_fast_powerup_delay(struct ssb_chipcommon *cc)
{
struct ssb_bus *bus = cc->dev->bus;
@@ -218,6 +236,12 @@ static void calc_fast_powerup_delay(stru
if (bus->bustype != SSB_BUSTYPE_PCI)
return;
+
+ if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
+ cc->fast_pwrup_delay = pmu_fast_powerup_delay(cc);
+ return;
+ }
+
if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL))
return;
@@ -233,6 +257,9 @@ void ssb_chipcommon_init(struct ssb_chip
{ {
if (!cc->dev) if (!cc->dev)
return; /* We don't have a ChipCommon */ return; /* We don't have a ChipCommon */
+ if (cc->dev->id.revision >= 11) + if (cc->dev->id.revision >= 11)
+ cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); + cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT);
+ ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status);
ssb_pmu_init(cc); ssb_pmu_init(cc);
chipco_powercontrol_init(cc); chipco_powercontrol_init(cc);
ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
@@ -370,6 +372,7 @@ u32 ssb_chipco_gpio_control(struct ssb_c @@ -370,6 +397,7 @@ u32 ssb_chipco_gpio_control(struct ssb_c
{ {
return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value); return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value);
} }
@ -17,9 +382,66 @@
u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value) u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value)
{ {
--- a/drivers/ssb/driver_chipcommon_pmu.c
+++ b/drivers/ssb/driver_chipcommon_pmu.c
@@ -502,9 +502,9 @@ static void ssb_pmu_resources_init(struc
chipco_write32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, max_msk);
}
+/* http://bcm-v4.sipsolutions.net/802.11/SSB/PmuInit */
void ssb_pmu_init(struct ssb_chipcommon *cc)
{
- struct ssb_bus *bus = cc->dev->bus;
u32 pmucap;
if (!(cc->capabilities & SSB_CHIPCO_CAP_PMU))
@@ -516,15 +516,12 @@ void ssb_pmu_init(struct ssb_chipcommon
ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n",
cc->pmu.rev, pmucap);
- if (cc->pmu.rev >= 1) {
- if ((bus->chip_id == 0x4325) && (bus->chip_rev < 2)) {
- chipco_mask32(cc, SSB_CHIPCO_PMU_CTL,
- ~SSB_CHIPCO_PMU_CTL_NOILPONW);
- } else {
- chipco_set32(cc, SSB_CHIPCO_PMU_CTL,
- SSB_CHIPCO_PMU_CTL_NOILPONW);
- }
- }
+ if (cc->pmu.rev == 1)
+ chipco_mask32(cc, SSB_CHIPCO_PMU_CTL,
+ ~SSB_CHIPCO_PMU_CTL_NOILPONW);
+ else
+ chipco_set32(cc, SSB_CHIPCO_PMU_CTL,
+ SSB_CHIPCO_PMU_CTL_NOILPONW);
ssb_pmu_pll_init(cc);
ssb_pmu_resources_init(cc);
}
--- a/drivers/ssb/main.c --- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c +++ b/drivers/ssb/main.c
@@ -834,6 +834,9 @@ int ssb_bus_pcibus_register(struct ssb_b @@ -486,11 +486,12 @@ static int ssb_devices_register(struct s
#ifdef CONFIG_SSB_PCIHOST
sdev->irq = bus->host_pci->irq;
dev->parent = &bus->host_pci->dev;
+ sdev->dma_dev = dev->parent;
#endif
break;
case SSB_BUSTYPE_PCMCIA:
#ifdef CONFIG_SSB_PCMCIAHOST
- sdev->irq = bus->host_pcmcia->irq.AssignedIRQ;
+ sdev->irq = bus->host_pcmcia->irq;
dev->parent = &bus->host_pcmcia->dev;
#endif
break;
@@ -501,6 +502,7 @@ static int ssb_devices_register(struct s
break;
case SSB_BUSTYPE_SSB:
dev->dma_mask = &dev->coherent_dma_mask;
+ sdev->dma_dev = dev;
break;
}
@@ -834,6 +836,9 @@ int ssb_bus_pcibus_register(struct ssb_b
if (!err) { if (!err) {
ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on " ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on "
"PCI device %s\n", dev_name(&host_pci->dev)); "PCI device %s\n", dev_name(&host_pci->dev));
@ -29,6 +451,87 @@
} }
return err; return err;
@@ -1223,80 +1228,6 @@ u32 ssb_dma_translation(struct ssb_devic
}
EXPORT_SYMBOL(ssb_dma_translation);
-int ssb_dma_set_mask(struct ssb_device *dev, u64 mask)
-{
-#ifdef CONFIG_SSB_PCIHOST
- int err;
-#endif
-
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- err = pci_set_dma_mask(dev->bus->host_pci, mask);
- if (err)
- return err;
- err = pci_set_consistent_dma_mask(dev->bus->host_pci, mask);
- return err;
-#endif
- case SSB_BUSTYPE_SSB:
- return dma_set_mask(dev->dev, mask);
- default:
- __ssb_dma_not_implemented(dev);
- }
- return -ENOSYS;
-}
-EXPORT_SYMBOL(ssb_dma_set_mask);
-
-void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp_flags)
-{
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- if (gfp_flags & GFP_DMA) {
- /* Workaround: The PCI API does not support passing
- * a GFP flag. */
- return dma_alloc_coherent(&dev->bus->host_pci->dev,
- size, dma_handle, gfp_flags);
- }
- return pci_alloc_consistent(dev->bus->host_pci, size, dma_handle);
-#endif
- case SSB_BUSTYPE_SSB:
- return dma_alloc_coherent(dev->dev, size, dma_handle, gfp_flags);
- default:
- __ssb_dma_not_implemented(dev);
- }
- return NULL;
-}
-EXPORT_SYMBOL(ssb_dma_alloc_consistent);
-
-void ssb_dma_free_consistent(struct ssb_device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle,
- gfp_t gfp_flags)
-{
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- if (gfp_flags & GFP_DMA) {
- /* Workaround: The PCI API does not support passing
- * a GFP flag. */
- dma_free_coherent(&dev->bus->host_pci->dev,
- size, vaddr, dma_handle);
- return;
- }
- pci_free_consistent(dev->bus->host_pci, size,
- vaddr, dma_handle);
- return;
-#endif
- case SSB_BUSTYPE_SSB:
- dma_free_coherent(dev->dev, size, vaddr, dma_handle);
- return;
- default:
- __ssb_dma_not_implemented(dev);
- }
-}
-EXPORT_SYMBOL(ssb_dma_free_consistent);
-
int ssb_bus_may_powerdown(struct ssb_bus *bus)
{
struct ssb_chipcommon *cc;
--- a/drivers/ssb/pci.c --- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c
@@ -168,7 +168,7 @@ err_pci: @@ -168,7 +168,7 @@ err_pci:
@ -58,7 +561,7 @@
mmiowb(); mmiowb();
msleep(20); msleep(20);
} }
@@ -621,6 +621,14 @@ static int ssb_pci_sprom_get(struct ssb_ @@ -621,6 +621,28 @@ static int ssb_pci_sprom_get(struct ssb_
int err = -ENOMEM; int err = -ENOMEM;
u16 *buf; u16 *buf;
@ -66,16 +569,30 @@
+ ssb_printk(KERN_ERR PFX "No SPROM available!\n"); + ssb_printk(KERN_ERR PFX "No SPROM available!\n");
+ return -ENODEV; + return -ENODEV;
+ } + }
+ + if (bus->chipco.dev) { /* can be unavailible! */
+ bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ? + /*
+ SSB_SPROM_BASE1 : SSB_SPROM_BASE31; + * get SPROM offset: SSB_SPROM_BASE1 except for
+ * chipcommon rev >= 31 or chip ID is 0x4312 and
+ * chipcommon status & 3 == 2
+ */
+ if (bus->chipco.dev->id.revision >= 31)
+ bus->sprom_offset = SSB_SPROM_BASE31;
+ else if (bus->chip_id == 0x4312 &&
+ (bus->chipco.status & 0x03) == 2)
+ bus->sprom_offset = SSB_SPROM_BASE31;
+ else
+ bus->sprom_offset = SSB_SPROM_BASE1;
+ } else {
+ bus->sprom_offset = SSB_SPROM_BASE1;
+ }
+ ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
+ +
buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
if (!buf) if (!buf)
goto out; goto out;
--- a/drivers/ssb/sprom.c --- a/drivers/ssb/sprom.c
+++ b/drivers/ssb/sprom.c +++ b/drivers/ssb/sprom.c
@@ -176,3 +176,17 @@ const struct ssb_sprom *ssb_get_fallback @@ -176,3 +176,18 @@ const struct ssb_sprom *ssb_get_fallback
{ {
return fallback_sprom; return fallback_sprom;
} }
@ -88,6 +605,7 @@
+ /* this routine differs from specs as we do not access SPROM directly + /* this routine differs from specs as we do not access SPROM directly
+ on PCMCIA */ + on PCMCIA */
+ if (bus->bustype == SSB_BUSTYPE_PCI && + if (bus->bustype == SSB_BUSTYPE_PCI &&
+ bus->chipco.dev && /* can be unavailible! */
+ bus->chipco.dev->id.revision >= 31) + bus->chipco.dev->id.revision >= 31)
+ return bus->chipco.capabilities & SSB_CHIPCO_CAP_SPROM; + return bus->chipco.capabilities & SSB_CHIPCO_CAP_SPROM;
+ +
@ -95,6 +613,15 @@
+} +}
--- a/include/linux/ssb/ssb.h --- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h
@@ -167,7 +167,7 @@ struct ssb_device {
* is an optimization. */
const struct ssb_bus_ops *ops;
- struct device *dev;
+ struct device *dev, *dma_dev;
struct ssb_bus *bus;
struct ssb_device_id id;
@@ -305,6 +305,7 @@ struct ssb_bus { @@ -305,6 +305,7 @@ struct ssb_bus {
/* ID information about the Chip. */ /* ID information about the Chip. */
u16 chip_id; u16 chip_id;
@ -113,6 +640,177 @@
/* Set a fallback SPROM. /* Set a fallback SPROM.
* See kdoc at the function definition for complete documentation. */ * See kdoc at the function definition for complete documentation. */
extern int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom); extern int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom);
@@ -466,14 +470,6 @@ extern u32 ssb_dma_translation(struct ss
#define SSB_DMA_TRANSLATION_MASK 0xC0000000
#define SSB_DMA_TRANSLATION_SHIFT 30
-extern int ssb_dma_set_mask(struct ssb_device *dev, u64 mask);
-
-extern void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp_flags);
-extern void ssb_dma_free_consistent(struct ssb_device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle,
- gfp_t gfp_flags);
-
static inline void __cold __ssb_dma_not_implemented(struct ssb_device *dev)
{
#ifdef CONFIG_SSB_DEBUG
@@ -482,155 +478,6 @@ static inline void __cold __ssb_dma_not_
#endif /* DEBUG */
}
-static inline int ssb_dma_mapping_error(struct ssb_device *dev, dma_addr_t addr)
-{
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- return pci_dma_mapping_error(dev->bus->host_pci, addr);
-#endif
- break;
- case SSB_BUSTYPE_SSB:
- return dma_mapping_error(dev->dev, addr);
- default:
- break;
- }
- __ssb_dma_not_implemented(dev);
- return -ENOSYS;
-}
-
-static inline dma_addr_t ssb_dma_map_single(struct ssb_device *dev, void *p,
- size_t size, enum dma_data_direction dir)
-{
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- return pci_map_single(dev->bus->host_pci, p, size, dir);
-#endif
- break;
- case SSB_BUSTYPE_SSB:
- return dma_map_single(dev->dev, p, size, dir);
- default:
- break;
- }
- __ssb_dma_not_implemented(dev);
- return 0;
-}
-
-static inline void ssb_dma_unmap_single(struct ssb_device *dev, dma_addr_t dma_addr,
- size_t size, enum dma_data_direction dir)
-{
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- pci_unmap_single(dev->bus->host_pci, dma_addr, size, dir);
- return;
-#endif
- break;
- case SSB_BUSTYPE_SSB:
- dma_unmap_single(dev->dev, dma_addr, size, dir);
- return;
- default:
- break;
- }
- __ssb_dma_not_implemented(dev);
-}
-
-static inline void ssb_dma_sync_single_for_cpu(struct ssb_device *dev,
- dma_addr_t dma_addr,
- size_t size,
- enum dma_data_direction dir)
-{
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- pci_dma_sync_single_for_cpu(dev->bus->host_pci, dma_addr,
- size, dir);
- return;
-#endif
- break;
- case SSB_BUSTYPE_SSB:
- dma_sync_single_for_cpu(dev->dev, dma_addr, size, dir);
- return;
- default:
- break;
- }
- __ssb_dma_not_implemented(dev);
-}
-
-static inline void ssb_dma_sync_single_for_device(struct ssb_device *dev,
- dma_addr_t dma_addr,
- size_t size,
- enum dma_data_direction dir)
-{
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- pci_dma_sync_single_for_device(dev->bus->host_pci, dma_addr,
- size, dir);
- return;
-#endif
- break;
- case SSB_BUSTYPE_SSB:
- dma_sync_single_for_device(dev->dev, dma_addr, size, dir);
- return;
- default:
- break;
- }
- __ssb_dma_not_implemented(dev);
-}
-
-static inline void ssb_dma_sync_single_range_for_cpu(struct ssb_device *dev,
- dma_addr_t dma_addr,
- unsigned long offset,
- size_t size,
- enum dma_data_direction dir)
-{
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- /* Just sync everything. That's all the PCI API can do. */
- pci_dma_sync_single_for_cpu(dev->bus->host_pci, dma_addr,
- offset + size, dir);
- return;
-#endif
- break;
- case SSB_BUSTYPE_SSB:
- dma_sync_single_range_for_cpu(dev->dev, dma_addr, offset,
- size, dir);
- return;
- default:
- break;
- }
- __ssb_dma_not_implemented(dev);
-}
-
-static inline void ssb_dma_sync_single_range_for_device(struct ssb_device *dev,
- dma_addr_t dma_addr,
- unsigned long offset,
- size_t size,
- enum dma_data_direction dir)
-{
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- /* Just sync everything. That's all the PCI API can do. */
- pci_dma_sync_single_for_device(dev->bus->host_pci, dma_addr,
- offset + size, dir);
- return;
-#endif
- break;
- case SSB_BUSTYPE_SSB:
- dma_sync_single_range_for_device(dev->dev, dma_addr, offset,
- size, dir);
- return;
- default:
- break;
- }
- __ssb_dma_not_implemented(dev);
-}
-
-
#ifdef CONFIG_SSB_PCIHOST
/* PCI-host wrapper driver */
extern int ssb_pcihost_register(struct pci_driver *driver);
--- a/include/linux/ssb/ssb_driver_chipcommon.h --- a/include/linux/ssb/ssb_driver_chipcommon.h
+++ b/include/linux/ssb/ssb_driver_chipcommon.h +++ b/include/linux/ssb/ssb_driver_chipcommon.h
@@ -53,6 +53,7 @@ @@ -53,6 +53,7 @@

View File

@ -1,52 +0,0 @@
From: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Add dma_dev, a pointer to struct device, to struct ssb_device. We pass it
to the generic DMA API with SSB_BUSTYPE_PCI and SSB_BUSTYPE_SSB.
ssb_devices_register() sets up it properly.
This is preparation for replacing the ssb bus specific DMA API (ssb_dma_*)
with the generic DMA API.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Acked-by: Michael Buesch <mb@bu3sch.de>
Cc: Gary Zambrano <zambrano@broadcom.com>
Cc: Stefano Brivio <stefano.brivio@polimi.it>
Cc: Larry Finger <Larry.Finger@lwfinger.net>
Cc: John W. Linville <linville@tuxdriver.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/ssb/main.c | 2 ++
include/linux/ssb/ssb.h | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -486,6 +486,7 @@ static int ssb_devices_register(struct s
#ifdef CONFIG_SSB_PCIHOST
sdev->irq = bus->host_pci->irq;
dev->parent = &bus->host_pci->dev;
+ sdev->dma_dev = dev->parent;
#endif
break;
case SSB_BUSTYPE_PCMCIA:
@@ -501,6 +502,7 @@ static int ssb_devices_register(struct s
break;
case SSB_BUSTYPE_SSB:
dev->dma_mask = &dev->coherent_dma_mask;
+ sdev->dma_dev = dev;
break;
}
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -167,7 +167,7 @@ struct ssb_device {
* is an optimization. */
const struct ssb_bus_ops *ops;
- struct device *dev;
+ struct device *dev, *dma_dev;
struct ssb_bus *bus;
struct ssb_device_id id;

View File

@ -0,0 +1,708 @@
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -135,7 +135,6 @@ static void b44_init_rings(struct b44 *)
static void b44_init_hw(struct b44 *, int);
-static int dma_desc_align_mask;
static int dma_desc_sync_size;
static int instance;
@@ -150,9 +149,8 @@ static inline void b44_sync_dma_desc_for
unsigned long offset,
enum dma_data_direction dir)
{
- ssb_dma_sync_single_range_for_device(sdev, dma_base,
- offset & dma_desc_align_mask,
- dma_desc_sync_size, dir);
+ dma_sync_single_for_device(sdev->dma_dev, dma_base + offset,
+ dma_desc_sync_size, dir);
}
static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev,
@@ -160,9 +158,8 @@ static inline void b44_sync_dma_desc_for
unsigned long offset,
enum dma_data_direction dir)
{
- ssb_dma_sync_single_range_for_cpu(sdev, dma_base,
- offset & dma_desc_align_mask,
- dma_desc_sync_size, dir);
+ dma_sync_single_for_cpu(sdev->dma_dev, dma_base + offset,
+ dma_desc_sync_size, dir);
}
static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
@@ -608,10 +605,10 @@ static void b44_tx(struct b44 *bp)
BUG_ON(skb == NULL);
- ssb_dma_unmap_single(bp->sdev,
- rp->mapping,
- skb->len,
- DMA_TO_DEVICE);
+ dma_unmap_single(bp->sdev->dma_dev,
+ rp->mapping,
+ skb->len,
+ DMA_TO_DEVICE);
rp->skb = NULL;
dev_kfree_skb_irq(skb);
}
@@ -648,29 +645,29 @@ static int b44_alloc_rx_skb(struct b44 *
if (skb == NULL)
return -ENOMEM;
- mapping = ssb_dma_map_single(bp->sdev, skb->data,
- RX_PKT_BUF_SZ,
- DMA_FROM_DEVICE);
+ mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
+ RX_PKT_BUF_SZ,
+ DMA_FROM_DEVICE);
/* Hardware bug work-around, the chip is unable to do PCI DMA
to/from anything above 1GB :-( */
- if (ssb_dma_mapping_error(bp->sdev, mapping) ||
+ if (dma_mapping_error(bp->sdev->dma_dev, mapping) ||
mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
/* Sigh... */
- if (!ssb_dma_mapping_error(bp->sdev, mapping))
- ssb_dma_unmap_single(bp->sdev, mapping,
+ if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
+ dma_unmap_single(bp->sdev->dma_dev, mapping,
RX_PKT_BUF_SZ, DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
if (skb == NULL)
return -ENOMEM;
- mapping = ssb_dma_map_single(bp->sdev, skb->data,
- RX_PKT_BUF_SZ,
- DMA_FROM_DEVICE);
- if (ssb_dma_mapping_error(bp->sdev, mapping) ||
- mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
- if (!ssb_dma_mapping_error(bp->sdev, mapping))
- ssb_dma_unmap_single(bp->sdev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
+ mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
+ RX_PKT_BUF_SZ,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(bp->sdev->dma_dev, mapping) ||
+ mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
+ if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
+ dma_unmap_single(bp->sdev->dma_dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
return -ENOMEM;
}
@@ -745,9 +742,9 @@ static void b44_recycle_rx(struct b44 *b
dest_idx * sizeof(*dest_desc),
DMA_BIDIRECTIONAL);
- ssb_dma_sync_single_for_device(bp->sdev, dest_map->mapping,
- RX_PKT_BUF_SZ,
- DMA_FROM_DEVICE);
+ dma_sync_single_for_device(bp->sdev->dma_dev, dest_map->mapping,
+ RX_PKT_BUF_SZ,
+ DMA_FROM_DEVICE);
}
static int b44_rx(struct b44 *bp, int budget)
@@ -767,9 +764,9 @@ static int b44_rx(struct b44 *bp, int bu
struct rx_header *rh;
u16 len;
- ssb_dma_sync_single_for_cpu(bp->sdev, map,
- RX_PKT_BUF_SZ,
- DMA_FROM_DEVICE);
+ dma_sync_single_for_cpu(bp->sdev->dma_dev, map,
+ RX_PKT_BUF_SZ,
+ DMA_FROM_DEVICE);
rh = (struct rx_header *) skb->data;
len = le16_to_cpu(rh->len);
if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) ||
@@ -801,8 +798,8 @@ static int b44_rx(struct b44 *bp, int bu
skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod);
if (skb_size < 0)
goto drop_it;
- ssb_dma_unmap_single(bp->sdev, map,
- skb_size, DMA_FROM_DEVICE);
+ dma_unmap_single(bp->sdev->dma_dev, map,
+ skb_size, DMA_FROM_DEVICE);
/* Leave out rx_header */
skb_put(skb, len + RX_PKT_OFFSET);
skb_pull(skb, RX_PKT_OFFSET);
@@ -954,24 +951,24 @@ static netdev_tx_t b44_start_xmit(struct
goto err_out;
}
- mapping = ssb_dma_map_single(bp->sdev, skb->data, len, DMA_TO_DEVICE);
- if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
+ mapping = dma_map_single(bp->sdev->dma_dev, skb->data, len, DMA_TO_DEVICE);
+ if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
struct sk_buff *bounce_skb;
/* Chip can't handle DMA to/from >1GB, use bounce buffer */
- if (!ssb_dma_mapping_error(bp->sdev, mapping))
- ssb_dma_unmap_single(bp->sdev, mapping, len,
+ if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
+ dma_unmap_single(bp->sdev->dma_dev, mapping, len,
DMA_TO_DEVICE);
bounce_skb = __netdev_alloc_skb(dev, len, GFP_ATOMIC | GFP_DMA);
if (!bounce_skb)
goto err_out;
- mapping = ssb_dma_map_single(bp->sdev, bounce_skb->data,
- len, DMA_TO_DEVICE);
- if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
- if (!ssb_dma_mapping_error(bp->sdev, mapping))
- ssb_dma_unmap_single(bp->sdev, mapping,
+ mapping = dma_map_single(bp->sdev->dma_dev, bounce_skb->data,
+ len, DMA_TO_DEVICE);
+ if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
+ if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
+ dma_unmap_single(bp->sdev->dma_dev, mapping,
len, DMA_TO_DEVICE);
dev_kfree_skb_any(bounce_skb);
goto err_out;
@@ -1068,8 +1065,8 @@ static void b44_free_rings(struct b44 *b
if (rp->skb == NULL)
continue;
- ssb_dma_unmap_single(bp->sdev, rp->mapping, RX_PKT_BUF_SZ,
- DMA_FROM_DEVICE);
+ dma_unmap_single(bp->sdev->dma_dev, rp->mapping, RX_PKT_BUF_SZ,
+ DMA_FROM_DEVICE);
dev_kfree_skb_any(rp->skb);
rp->skb = NULL;
}
@@ -1080,8 +1077,8 @@ static void b44_free_rings(struct b44 *b
if (rp->skb == NULL)
continue;
- ssb_dma_unmap_single(bp->sdev, rp->mapping, rp->skb->len,
- DMA_TO_DEVICE);
+ dma_unmap_single(bp->sdev->dma_dev, rp->mapping, rp->skb->len,
+ DMA_TO_DEVICE);
dev_kfree_skb_any(rp->skb);
rp->skb = NULL;
}
@@ -1103,14 +1100,12 @@ static void b44_init_rings(struct b44 *b
memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
if (bp->flags & B44_FLAG_RX_RING_HACK)
- ssb_dma_sync_single_for_device(bp->sdev, bp->rx_ring_dma,
- DMA_TABLE_BYTES,
- DMA_BIDIRECTIONAL);
+ dma_sync_single_for_device(bp->sdev->dma_dev, bp->rx_ring_dma,
+ DMA_TABLE_BYTES, DMA_BIDIRECTIONAL);
if (bp->flags & B44_FLAG_TX_RING_HACK)
- ssb_dma_sync_single_for_device(bp->sdev, bp->tx_ring_dma,
- DMA_TABLE_BYTES,
- DMA_TO_DEVICE);
+ dma_sync_single_for_device(bp->sdev->dma_dev, bp->tx_ring_dma,
+ DMA_TABLE_BYTES, DMA_TO_DEVICE);
for (i = 0; i < bp->rx_pending; i++) {
if (b44_alloc_rx_skb(bp, -1, i) < 0)
@@ -1130,27 +1125,23 @@ static void b44_free_consistent(struct b
bp->tx_buffers = NULL;
if (bp->rx_ring) {
if (bp->flags & B44_FLAG_RX_RING_HACK) {
- ssb_dma_unmap_single(bp->sdev, bp->rx_ring_dma,
- DMA_TABLE_BYTES,
- DMA_BIDIRECTIONAL);
+ dma_unmap_single(bp->sdev->dma_dev, bp->rx_ring_dma,
+ DMA_TABLE_BYTES, DMA_BIDIRECTIONAL);
kfree(bp->rx_ring);
} else
- ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES,
- bp->rx_ring, bp->rx_ring_dma,
- GFP_KERNEL);
+ dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
+ bp->rx_ring, bp->rx_ring_dma);
bp->rx_ring = NULL;
bp->flags &= ~B44_FLAG_RX_RING_HACK;
}
if (bp->tx_ring) {
if (bp->flags & B44_FLAG_TX_RING_HACK) {
- ssb_dma_unmap_single(bp->sdev, bp->tx_ring_dma,
- DMA_TABLE_BYTES,
- DMA_TO_DEVICE);
+ dma_unmap_single(bp->sdev->dma_dev, bp->tx_ring_dma,
+ DMA_TABLE_BYTES, DMA_TO_DEVICE);
kfree(bp->tx_ring);
} else
- ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES,
- bp->tx_ring, bp->tx_ring_dma,
- GFP_KERNEL);
+ dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
+ bp->tx_ring, bp->tx_ring_dma);
bp->tx_ring = NULL;
bp->flags &= ~B44_FLAG_TX_RING_HACK;
}
@@ -1175,7 +1166,8 @@ static int b44_alloc_consistent(struct b
goto out_err;
size = DMA_TABLE_BYTES;
- bp->rx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->rx_ring_dma, gfp);
+ bp->rx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size,
+ &bp->rx_ring_dma, gfp);
if (!bp->rx_ring) {
/* Allocation may have failed due to pci_alloc_consistent
insisting on use of GFP_DMA, which is more restrictive
@@ -1187,11 +1179,11 @@ static int b44_alloc_consistent(struct b
if (!rx_ring)
goto out_err;
- rx_ring_dma = ssb_dma_map_single(bp->sdev, rx_ring,
- DMA_TABLE_BYTES,
- DMA_BIDIRECTIONAL);
+ rx_ring_dma = dma_map_single(bp->sdev->dma_dev, rx_ring,
+ DMA_TABLE_BYTES,
+ DMA_BIDIRECTIONAL);
- if (ssb_dma_mapping_error(bp->sdev, rx_ring_dma) ||
+ if (dma_mapping_error(bp->sdev->dma_dev, rx_ring_dma) ||
rx_ring_dma + size > DMA_BIT_MASK(30)) {
kfree(rx_ring);
goto out_err;
@@ -1202,7 +1194,8 @@ static int b44_alloc_consistent(struct b
bp->flags |= B44_FLAG_RX_RING_HACK;
}
- bp->tx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->tx_ring_dma, gfp);
+ bp->tx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size,
+ &bp->tx_ring_dma, gfp);
if (!bp->tx_ring) {
/* Allocation may have failed due to ssb_dma_alloc_consistent
insisting on use of GFP_DMA, which is more restrictive
@@ -1214,11 +1207,11 @@ static int b44_alloc_consistent(struct b
if (!tx_ring)
goto out_err;
- tx_ring_dma = ssb_dma_map_single(bp->sdev, tx_ring,
- DMA_TABLE_BYTES,
- DMA_TO_DEVICE);
+ tx_ring_dma = dma_map_single(bp->sdev->dma_dev, tx_ring,
+ DMA_TABLE_BYTES,
+ DMA_TO_DEVICE);
- if (ssb_dma_mapping_error(bp->sdev, tx_ring_dma) ||
+ if (dma_mapping_error(bp->sdev->dma_dev, tx_ring_dma) ||
tx_ring_dma + size > DMA_BIT_MASK(30)) {
kfree(tx_ring);
goto out_err;
@@ -2176,12 +2169,14 @@ static int __devinit b44_init_one(struct
"Failed to powerup the bus\n");
goto err_out_free_dev;
}
- err = ssb_dma_set_mask(sdev, DMA_BIT_MASK(30));
- if (err) {
+
+ if (dma_set_mask(sdev->dma_dev, DMA_BIT_MASK(30)) ||
+ dma_set_coherent_mask(sdev->dma_dev, DMA_BIT_MASK(30))) {
dev_err(sdev->dev,
"Required 30BIT DMA mask unsupported by the system\n");
goto err_out_powerdown;
}
+
err = b44_get_invariants(bp);
if (err) {
dev_err(sdev->dev,
@@ -2344,7 +2339,6 @@ static int __init b44_init(void)
int err;
/* Setup paramaters for syncing RX/TX DMA descriptors */
- dma_desc_align_mask = ~(dma_desc_align_size - 1);
dma_desc_sync_size = max_t(unsigned int, dma_desc_align_size, sizeof(struct dma_desc));
err = b44_pci_init();
--- a/drivers/ssb/driver_chipcommon.c
+++ b/drivers/ssb/driver_chipcommon.c
@@ -209,6 +209,24 @@ static void chipco_powercontrol_init(str
}
}
+/* http://bcm-v4.sipsolutions.net/802.11/PmuFastPwrupDelay */
+static u16 pmu_fast_powerup_delay(struct ssb_chipcommon *cc)
+{
+ struct ssb_bus *bus = cc->dev->bus;
+
+ switch (bus->chip_id) {
+ case 0x4312:
+ case 0x4322:
+ case 0x4328:
+ return 7000;
+ case 0x4325:
+ /* TODO: */
+ default:
+ return 15000;
+ }
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/ClkctlFastPwrupDelay */
static void calc_fast_powerup_delay(struct ssb_chipcommon *cc)
{
struct ssb_bus *bus = cc->dev->bus;
@@ -218,6 +236,12 @@ static void calc_fast_powerup_delay(stru
if (bus->bustype != SSB_BUSTYPE_PCI)
return;
+
+ if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
+ cc->fast_pwrup_delay = pmu_fast_powerup_delay(cc);
+ return;
+ }
+
if (!(cc->capabilities & SSB_CHIPCO_CAP_PCTL))
return;
@@ -235,6 +259,7 @@ void ssb_chipcommon_init(struct ssb_chip
return; /* We don't have a ChipCommon */
if (cc->dev->id.revision >= 11)
cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT);
+ ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status);
ssb_pmu_init(cc);
chipco_powercontrol_init(cc);
ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
--- a/drivers/ssb/driver_chipcommon_pmu.c
+++ b/drivers/ssb/driver_chipcommon_pmu.c
@@ -502,9 +502,9 @@ static void ssb_pmu_resources_init(struc
chipco_write32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, max_msk);
}
+/* http://bcm-v4.sipsolutions.net/802.11/SSB/PmuInit */
void ssb_pmu_init(struct ssb_chipcommon *cc)
{
- struct ssb_bus *bus = cc->dev->bus;
u32 pmucap;
if (!(cc->capabilities & SSB_CHIPCO_CAP_PMU))
@@ -516,15 +516,12 @@ void ssb_pmu_init(struct ssb_chipcommon
ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n",
cc->pmu.rev, pmucap);
- if (cc->pmu.rev >= 1) {
- if ((bus->chip_id == 0x4325) && (bus->chip_rev < 2)) {
- chipco_mask32(cc, SSB_CHIPCO_PMU_CTL,
- ~SSB_CHIPCO_PMU_CTL_NOILPONW);
- } else {
- chipco_set32(cc, SSB_CHIPCO_PMU_CTL,
- SSB_CHIPCO_PMU_CTL_NOILPONW);
- }
- }
+ if (cc->pmu.rev == 1)
+ chipco_mask32(cc, SSB_CHIPCO_PMU_CTL,
+ ~SSB_CHIPCO_PMU_CTL_NOILPONW);
+ else
+ chipco_set32(cc, SSB_CHIPCO_PMU_CTL,
+ SSB_CHIPCO_PMU_CTL_NOILPONW);
ssb_pmu_pll_init(cc);
ssb_pmu_resources_init(cc);
}
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -486,6 +486,7 @@ static int ssb_devices_register(struct s
#ifdef CONFIG_SSB_PCIHOST
sdev->irq = bus->host_pci->irq;
dev->parent = &bus->host_pci->dev;
+ sdev->dma_dev = dev->parent;
#endif
break;
case SSB_BUSTYPE_PCMCIA:
@@ -501,6 +502,7 @@ static int ssb_devices_register(struct s
break;
case SSB_BUSTYPE_SSB:
dev->dma_mask = &dev->coherent_dma_mask;
+ sdev->dma_dev = dev;
break;
}
@@ -1226,80 +1228,6 @@ u32 ssb_dma_translation(struct ssb_devic
}
EXPORT_SYMBOL(ssb_dma_translation);
-int ssb_dma_set_mask(struct ssb_device *dev, u64 mask)
-{
-#ifdef CONFIG_SSB_PCIHOST
- int err;
-#endif
-
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- err = pci_set_dma_mask(dev->bus->host_pci, mask);
- if (err)
- return err;
- err = pci_set_consistent_dma_mask(dev->bus->host_pci, mask);
- return err;
-#endif
- case SSB_BUSTYPE_SSB:
- return dma_set_mask(dev->dev, mask);
- default:
- __ssb_dma_not_implemented(dev);
- }
- return -ENOSYS;
-}
-EXPORT_SYMBOL(ssb_dma_set_mask);
-
-void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp_flags)
-{
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- if (gfp_flags & GFP_DMA) {
- /* Workaround: The PCI API does not support passing
- * a GFP flag. */
- return dma_alloc_coherent(&dev->bus->host_pci->dev,
- size, dma_handle, gfp_flags);
- }
- return pci_alloc_consistent(dev->bus->host_pci, size, dma_handle);
-#endif
- case SSB_BUSTYPE_SSB:
- return dma_alloc_coherent(dev->dev, size, dma_handle, gfp_flags);
- default:
- __ssb_dma_not_implemented(dev);
- }
- return NULL;
-}
-EXPORT_SYMBOL(ssb_dma_alloc_consistent);
-
-void ssb_dma_free_consistent(struct ssb_device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle,
- gfp_t gfp_flags)
-{
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- if (gfp_flags & GFP_DMA) {
- /* Workaround: The PCI API does not support passing
- * a GFP flag. */
- dma_free_coherent(&dev->bus->host_pci->dev,
- size, vaddr, dma_handle);
- return;
- }
- pci_free_consistent(dev->bus->host_pci, size,
- vaddr, dma_handle);
- return;
-#endif
- case SSB_BUSTYPE_SSB:
- dma_free_coherent(dev->dev, size, vaddr, dma_handle);
- return;
- default:
- __ssb_dma_not_implemented(dev);
- }
-}
-EXPORT_SYMBOL(ssb_dma_free_consistent);
-
int ssb_bus_may_powerdown(struct ssb_bus *bus)
{
struct ssb_chipcommon *cc;
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -626,11 +626,22 @@ static int ssb_pci_sprom_get(struct ssb_
return -ENODEV;
}
if (bus->chipco.dev) { /* can be unavailible! */
- bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ?
- SSB_SPROM_BASE1 : SSB_SPROM_BASE31;
+ /*
+ * get SPROM offset: SSB_SPROM_BASE1 except for
+ * chipcommon rev >= 31 or chip ID is 0x4312 and
+ * chipcommon status & 3 == 2
+ */
+ if (bus->chipco.dev->id.revision >= 31)
+ bus->sprom_offset = SSB_SPROM_BASE31;
+ else if (bus->chip_id == 0x4312 &&
+ (bus->chipco.status & 0x03) == 2)
+ bus->sprom_offset = SSB_SPROM_BASE31;
+ else
+ bus->sprom_offset = SSB_SPROM_BASE1;
} else {
bus->sprom_offset = SSB_SPROM_BASE1;
}
+ ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
if (!buf)
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -167,7 +167,7 @@ struct ssb_device {
* is an optimization. */
const struct ssb_bus_ops *ops;
- struct device *dev;
+ struct device *dev, *dma_dev;
struct ssb_bus *bus;
struct ssb_device_id id;
@@ -470,14 +470,6 @@ extern u32 ssb_dma_translation(struct ss
#define SSB_DMA_TRANSLATION_MASK 0xC0000000
#define SSB_DMA_TRANSLATION_SHIFT 30
-extern int ssb_dma_set_mask(struct ssb_device *dev, u64 mask);
-
-extern void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp_flags);
-extern void ssb_dma_free_consistent(struct ssb_device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle,
- gfp_t gfp_flags);
-
static inline void __cold __ssb_dma_not_implemented(struct ssb_device *dev)
{
#ifdef CONFIG_SSB_DEBUG
@@ -486,155 +478,6 @@ static inline void __cold __ssb_dma_not_
#endif /* DEBUG */
}
-static inline int ssb_dma_mapping_error(struct ssb_device *dev, dma_addr_t addr)
-{
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- return pci_dma_mapping_error(dev->bus->host_pci, addr);
-#endif
- break;
- case SSB_BUSTYPE_SSB:
- return dma_mapping_error(dev->dev, addr);
- default:
- break;
- }
- __ssb_dma_not_implemented(dev);
- return -ENOSYS;
-}
-
-static inline dma_addr_t ssb_dma_map_single(struct ssb_device *dev, void *p,
- size_t size, enum dma_data_direction dir)
-{
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- return pci_map_single(dev->bus->host_pci, p, size, dir);
-#endif
- break;
- case SSB_BUSTYPE_SSB:
- return dma_map_single(dev->dev, p, size, dir);
- default:
- break;
- }
- __ssb_dma_not_implemented(dev);
- return 0;
-}
-
-static inline void ssb_dma_unmap_single(struct ssb_device *dev, dma_addr_t dma_addr,
- size_t size, enum dma_data_direction dir)
-{
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- pci_unmap_single(dev->bus->host_pci, dma_addr, size, dir);
- return;
-#endif
- break;
- case SSB_BUSTYPE_SSB:
- dma_unmap_single(dev->dev, dma_addr, size, dir);
- return;
- default:
- break;
- }
- __ssb_dma_not_implemented(dev);
-}
-
-static inline void ssb_dma_sync_single_for_cpu(struct ssb_device *dev,
- dma_addr_t dma_addr,
- size_t size,
- enum dma_data_direction dir)
-{
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- pci_dma_sync_single_for_cpu(dev->bus->host_pci, dma_addr,
- size, dir);
- return;
-#endif
- break;
- case SSB_BUSTYPE_SSB:
- dma_sync_single_for_cpu(dev->dev, dma_addr, size, dir);
- return;
- default:
- break;
- }
- __ssb_dma_not_implemented(dev);
-}
-
-static inline void ssb_dma_sync_single_for_device(struct ssb_device *dev,
- dma_addr_t dma_addr,
- size_t size,
- enum dma_data_direction dir)
-{
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- pci_dma_sync_single_for_device(dev->bus->host_pci, dma_addr,
- size, dir);
- return;
-#endif
- break;
- case SSB_BUSTYPE_SSB:
- dma_sync_single_for_device(dev->dev, dma_addr, size, dir);
- return;
- default:
- break;
- }
- __ssb_dma_not_implemented(dev);
-}
-
-static inline void ssb_dma_sync_single_range_for_cpu(struct ssb_device *dev,
- dma_addr_t dma_addr,
- unsigned long offset,
- size_t size,
- enum dma_data_direction dir)
-{
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- /* Just sync everything. That's all the PCI API can do. */
- pci_dma_sync_single_for_cpu(dev->bus->host_pci, dma_addr,
- offset + size, dir);
- return;
-#endif
- break;
- case SSB_BUSTYPE_SSB:
- dma_sync_single_range_for_cpu(dev->dev, dma_addr, offset,
- size, dir);
- return;
- default:
- break;
- }
- __ssb_dma_not_implemented(dev);
-}
-
-static inline void ssb_dma_sync_single_range_for_device(struct ssb_device *dev,
- dma_addr_t dma_addr,
- unsigned long offset,
- size_t size,
- enum dma_data_direction dir)
-{
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
- /* Just sync everything. That's all the PCI API can do. */
- pci_dma_sync_single_for_device(dev->bus->host_pci, dma_addr,
- offset + size, dir);
- return;
-#endif
- break;
- case SSB_BUSTYPE_SSB:
- dma_sync_single_range_for_device(dev->dev, dma_addr, offset,
- size, dir);
- return;
- default:
- break;
- }
- __ssb_dma_not_implemented(dev);
-}
-
-
#ifdef CONFIG_SSB_PCIHOST
/* PCI-host wrapper driver */
extern int ssb_pcihost_register(struct pci_driver *driver);

View File

@ -1,52 +0,0 @@
From: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Add dma_dev, a pointer to struct device, to struct ssb_device. We pass it
to the generic DMA API with SSB_BUSTYPE_PCI and SSB_BUSTYPE_SSB.
ssb_devices_register() sets up it properly.
This is preparation for replacing the ssb bus specific DMA API (ssb_dma_*)
with the generic DMA API.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Acked-by: Michael Buesch <mb@bu3sch.de>
Cc: Gary Zambrano <zambrano@broadcom.com>
Cc: Stefano Brivio <stefano.brivio@polimi.it>
Cc: Larry Finger <Larry.Finger@lwfinger.net>
Cc: John W. Linville <linville@tuxdriver.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/ssb/main.c | 2 ++
include/linux/ssb/ssb.h | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -486,6 +486,7 @@ static int ssb_devices_register(struct s
#ifdef CONFIG_SSB_PCIHOST
sdev->irq = bus->host_pci->irq;
dev->parent = &bus->host_pci->dev;
+ sdev->dma_dev = dev->parent;
#endif
break;
case SSB_BUSTYPE_PCMCIA:
@@ -501,6 +502,7 @@ static int ssb_devices_register(struct s
break;
case SSB_BUSTYPE_SSB:
dev->dma_mask = &dev->coherent_dma_mask;
+ sdev->dma_dev = dev;
break;
}
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -167,7 +167,7 @@ struct ssb_device {
* is an optimization. */
const struct ssb_bus_ops *ops;
- struct device *dev;
+ struct device *dev, *dma_dev;
struct ssb_bus *bus;
struct ssb_device_id id;