mirror of https://github.com/hak5/openwrt-owl.git
brcm47xx: update bcma and ssb to master-2011-07-21
* add new patches for bcm4716 SoC * add support for serial flash on bcma bus SVN-Revision: 27723owl
parent
39f491e479
commit
b988168906
|
@ -18,6 +18,7 @@ CONFIG_BCM47XX_BCMA=y
|
|||
CONFIG_BCM47XX_SSB=y
|
||||
CONFIG_BCM47XX_WDT=y
|
||||
CONFIG_BCMA=y
|
||||
CONFIG_BCMA_BLOCKIO=y
|
||||
CONFIG_BCMA_DEBUG=y
|
||||
CONFIG_BCMA_DRIVER_MIPS=y
|
||||
CONFIG_BCMA_DRIVER_PCI_HOSTMODE=y
|
||||
|
@ -25,6 +26,7 @@ CONFIG_BCMA_HOST_PCI=y
|
|||
CONFIG_BCMA_HOST_PCI_POSSIBLE=y
|
||||
CONFIG_BCMA_HOST_SOC=y
|
||||
CONFIG_BCMA_POSSIBLE=y
|
||||
CONFIG_BCMA_SFLASH=y
|
||||
# CONFIG_BRCMUTIL is not set
|
||||
# CONFIG_BSD_PROCESS_ACCT is not set
|
||||
# CONFIG_BUG is not set
|
||||
|
@ -93,7 +95,9 @@ CONFIG_MIPS=y
|
|||
CONFIG_MIPS_L1_CACHE_SHIFT=5
|
||||
# CONFIG_MIPS_MACHINE is not set
|
||||
CONFIG_MIPS_MT_DISABLED=y
|
||||
CONFIG_MTD_BCM47XX=y
|
||||
CONFIG_MTD_BCM47XX_PARTS=y
|
||||
CONFIG_MTD_BCM47XX_PFLASH=y
|
||||
CONFIG_MTD_BCM47XX_SFLASH=y
|
||||
CONFIG_NEED_DMA_MAP_STATE=y
|
||||
CONFIG_NEED_PER_CPU_KM=y
|
||||
CONFIG_NO_HZ=y
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
--- a/drivers/ssb/driver_pcicore.c
|
||||
+++ b/drivers/ssb/driver_pcicore.c
|
||||
@@ -412,16 +412,6 @@ static int __devinit pcicore_is_in_hostm
|
||||
* Workarounds.
|
||||
**************************************************/
|
||||
|
||||
-static void __devinit ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc)
|
||||
-{
|
||||
- u16 tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(0));
|
||||
- if (((tmp & 0xF000) >> 12) != pc->dev->core_index) {
|
||||
- tmp &= ~0xF000;
|
||||
- tmp |= (pc->dev->core_index << 12);
|
||||
- pcicore_write16(pc, SSB_PCICORE_SPROM(0), tmp);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
static u8 ssb_pcicore_polarity_workaround(struct ssb_pcicore *pc)
|
||||
{
|
||||
return (ssb_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80;
|
||||
@@ -529,8 +519,6 @@ void __devinit ssb_pcicore_init(struct s
|
||||
if (!ssb_device_is_enabled(dev))
|
||||
ssb_device_enable(dev, 0);
|
||||
|
||||
- ssb_pcicore_fix_sprom_core_index(pc);
|
||||
-
|
||||
#ifdef CONFIG_SSB_PCICORE_HOSTMODE
|
||||
pc->hostmode = pcicore_is_in_hostmode(pc);
|
||||
if (pc->hostmode)
|
|
@ -25,7 +25,7 @@
|
|||
ssb_printk(KERN_ERR PFX
|
||||
--- a/include/linux/ssb/ssb.h
|
||||
+++ b/include/linux/ssb/ssb.h
|
||||
@@ -155,9 +155,16 @@ struct ssb_bus_ops {
|
||||
@@ -157,9 +157,16 @@ struct ssb_bus_ops {
|
||||
#define SSB_DEV_MINI_MACPHY 0x823
|
||||
#define SSB_DEV_ARM_1176 0x824
|
||||
#define SSB_DEV_ARM_7TDMI 0x825
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
From c4fb5adbe45b3a1cfc509a64bb92429ab0d6fc37 Mon Sep 17 00:00:00 2001
|
||||
From e6defe46ea936ebb309c9cab4f7fd14bdc0c5416 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sat, 11 Jun 2011 16:47:38 +0200
|
||||
Subject: [PATCH 01/14] bcma: move parsing of EEPROM into own function.
|
||||
Subject: [PATCH 01/22] bcma: move parsing of EEPROM into own function.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Move the parsing of the EEPROM data in scan function for one core into
|
||||
an own function. Now we are able to use it in some other scan function
|
||||
as well.
|
||||
|
||||
Acked-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/scan.c | 230 ++++++++++++++++++++++++++-------------------------
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
From dd6cbe9b9e2ae563659b34184f4cd9d905dc90d5 Mon Sep 17 00:00:00 2001
|
||||
From 47b0447e18f72724caf57ba7e4573e309fb2bfae Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sat, 18 Jun 2011 11:55:47 +0200
|
||||
Subject: [PATCH 02/14] bcma: move initializing of struct bcma_bus to own function.
|
||||
Subject: [PATCH 02/22] bcma: move initializing of struct bcma_bus to own function.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This makes it possible to use this code in some other method.
|
||||
|
||||
Acked-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/scan.c | 17 +++++++++++------
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
From 9a920f4d8eed485f7b73e9b13dab0e49c64d3ff8 Mon Sep 17 00:00:00 2001
|
||||
From beb36a1a49227ca6c5778a667aefc8cd3fd56a4f Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sat, 18 Jun 2011 14:30:55 +0200
|
||||
Subject: [PATCH 03/14] bcma: add functions to scan cores needed on SoCs
|
||||
Subject: [PATCH 03/22] bcma: add functions to scan cores needed on SoCs
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The chip common and mips core have to be setup early in the boot
|
||||
process to get the cpu clock.
|
||||
|
@ -10,17 +13,19 @@ data and searches for the chip common and mips core and initializes
|
|||
chip common. After that was done and the kernel is out of early boot we
|
||||
just have to run bcma_bus_register() and it will search for the other
|
||||
cores, initialize and register them.
|
||||
The cores are getting the same numbers as before.
|
||||
|
||||
Acked-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/bcma_private.h | 7 ++
|
||||
drivers/bcma/driver_chipcommon.c | 5 ++
|
||||
drivers/bcma/driver_pci.c | 3 +
|
||||
drivers/bcma/main.c | 45 +++++++++++++
|
||||
drivers/bcma/driver_pci.c | 5 ++
|
||||
drivers/bcma/main.c | 46 +++++++++++++
|
||||
drivers/bcma/scan.c | 95 +++++++++++++++++++++++++--
|
||||
include/linux/bcma/bcma.h | 1 +
|
||||
include/linux/bcma/bcma_driver_chipcommon.h | 1 +
|
||||
7 files changed, 151 insertions(+), 6 deletions(-)
|
||||
7 files changed, 154 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/bcma/bcma_private.h
|
||||
+++ b/drivers/bcma/bcma_private.h
|
||||
|
@ -43,20 +48,20 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
int bcma_sprom_get(struct bcma_bus *bus);
|
||||
--- a/drivers/bcma/driver_chipcommon.c
|
||||
+++ b/drivers/bcma/driver_chipcommon.c
|
||||
@@ -23,6 +23,9 @@ static inline u32 bcma_cc_write32_masked
|
||||
@@ -26,6 +26,9 @@ void bcma_core_chipcommon_init(struct bc
|
||||
u32 leddc_on = 10;
|
||||
u32 leddc_off = 90;
|
||||
|
||||
void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
+ if (cc->setup_done)
|
||||
+ return;
|
||||
+
|
||||
if (cc->core->id.rev >= 11)
|
||||
cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
|
||||
cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
|
||||
@@ -38,6 +41,8 @@ void bcma_core_chipcommon_init(struct bc
|
||||
bcma_pmu_init(cc);
|
||||
if (cc->capabilities & BCMA_CC_CAP_PCTL)
|
||||
pr_err("Power control not implemented!\n");
|
||||
@@ -52,6 +55,8 @@ void bcma_core_chipcommon_init(struct bc
|
||||
((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
|
||||
(leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
|
||||
}
|
||||
+
|
||||
+ cc->setup_done = true;
|
||||
}
|
||||
|
@ -64,20 +69,28 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
|
||||
--- a/drivers/bcma/driver_pci.c
|
||||
+++ b/drivers/bcma/driver_pci.c
|
||||
@@ -159,7 +159,10 @@ static void bcma_pcicore_serdes_workarou
|
||||
@@ -187,6 +187,9 @@ static bool bcma_core_pci_is_in_hostmode
|
||||
|
||||
void bcma_core_pci_init(struct bcma_drv_pci *pc)
|
||||
{
|
||||
+ if (pc->setup_done)
|
||||
+ return;
|
||||
bcma_pcicore_serdes_workaround(pc);
|
||||
+
|
||||
if (bcma_core_pci_is_in_hostmode(pc)) {
|
||||
#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
|
||||
bcma_core_pci_hostmode_init(pc);
|
||||
@@ -196,6 +199,8 @@ void bcma_core_pci_init(struct bcma_drv_
|
||||
} else {
|
||||
bcma_core_pci_clientmode_init(pc);
|
||||
}
|
||||
+
|
||||
+ pc->setup_done = true;
|
||||
}
|
||||
|
||||
int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
|
||||
--- a/drivers/bcma/main.c
|
||||
+++ b/drivers/bcma/main.c
|
||||
@@ -167,6 +167,51 @@ void bcma_bus_unregister(struct bcma_bus
|
||||
@@ -169,6 +169,52 @@ void bcma_bus_unregister(struct bcma_bus
|
||||
bcma_unregister_cores(bus);
|
||||
}
|
||||
|
||||
|
@ -96,7 +109,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+ match.class = BCMA_CL_SIM;
|
||||
+ match.rev = BCMA_ANY_REV;
|
||||
+
|
||||
+ /* Scan for devices (cores) */
|
||||
+ /* Scan for chip common core */
|
||||
+ err = bcma_bus_scan_early(bus, &match, core_cc);
|
||||
+ if (err) {
|
||||
+ pr_err("Failed to scan for common core: %d\n", err);
|
||||
|
@ -108,6 +121,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+ match.class = BCMA_CL_SIM;
|
||||
+ match.rev = BCMA_ANY_REV;
|
||||
+
|
||||
+ /* Scan for mips core */
|
||||
+ err = bcma_bus_scan_early(bus, &match, core_mips);
|
||||
+ if (err) {
|
||||
+ pr_err("Failed to scan for mips core: %d\n", err);
|
||||
|
@ -287,7 +301,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+}
|
||||
--- a/include/linux/bcma/bcma.h
|
||||
+++ b/include/linux/bcma/bcma.h
|
||||
@@ -185,6 +185,7 @@ struct bcma_bus {
|
||||
@@ -190,6 +190,7 @@ struct bcma_bus {
|
||||
struct bcma_device *mapped_core;
|
||||
struct list_head cores;
|
||||
u8 nr_cores;
|
||||
|
@ -297,7 +311,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
struct bcma_drv_pci drv_pci;
|
||||
--- a/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
@@ -259,6 +259,7 @@ struct bcma_drv_cc {
|
||||
@@ -252,6 +252,7 @@ struct bcma_drv_cc {
|
||||
u32 status;
|
||||
u32 capabilities;
|
||||
u32 capabilities_ext;
|
||||
|
|
|
@ -1,44 +1,50 @@
|
|||
From a807b2fb233af60028ed38ba237953bcffdf33e9 Mon Sep 17 00:00:00 2001
|
||||
From 22573303ad477fa07c948a9944e9c18fea9af724 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sat, 18 Jun 2011 14:31:53 +0200
|
||||
Subject: [PATCH 04/14] bcma: add SOC bus
|
||||
Subject: [PATCH 04/22] bcma: add SOC bus
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This patch adds support for using bcma on an embedded bus. An embedded
|
||||
system like the bcm4716 could register this bus and it searches for the
|
||||
bcma cores then.
|
||||
This patch adds support for using bcma on a Broadcom SoC as the system
|
||||
bus. An SoC like the bcm4716 could register this bus and use it to
|
||||
searches for the bcma cores and register the devices on this bus.
|
||||
|
||||
BCMA_HOSTTYPE_NONE was intended for SoCs at first but BCMA_HOSTTYPE_SOC
|
||||
is a better name.
|
||||
|
||||
Acked-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/Kconfig | 5 +
|
||||
drivers/bcma/Kconfig | 4 +
|
||||
drivers/bcma/Makefile | 1 +
|
||||
drivers/bcma/host_soc.c | 178 +++++++++++++++++++++++++++++++++++++++++
|
||||
drivers/bcma/main.c | 1 +
|
||||
drivers/bcma/scan.c | 24 +++++-
|
||||
include/linux/bcma/bcma.h | 4 +
|
||||
drivers/bcma/host_soc.c | 183 +++++++++++++++++++++++++++++++++++++++++
|
||||
drivers/bcma/main.c | 6 +-
|
||||
drivers/bcma/scan.c | 42 ++++++++-
|
||||
include/linux/bcma/bcma.h | 5 +-
|
||||
include/linux/bcma/bcma_soc.h | 16 ++++
|
||||
7 files changed, 227 insertions(+), 2 deletions(-)
|
||||
7 files changed, 250 insertions(+), 7 deletions(-)
|
||||
create mode 100644 drivers/bcma/host_soc.c
|
||||
create mode 100644 include/linux/bcma/bcma_soc.h
|
||||
|
||||
--- a/drivers/bcma/Kconfig
|
||||
+++ b/drivers/bcma/Kconfig
|
||||
@@ -27,6 +27,11 @@ config BCMA_HOST_PCI
|
||||
bool "Support for BCMA on PCI-host bus"
|
||||
depends on BCMA_HOST_PCI_POSSIBLE
|
||||
@@ -34,6 +34,10 @@ config BCMA_DRIVER_PCI_HOSTMODE
|
||||
help
|
||||
PCI core hostmode operation (external PCI bus).
|
||||
|
||||
+config BCMA_HOST_SOC
|
||||
+ bool
|
||||
+ depends on BCMA && MIPS
|
||||
+ default n
|
||||
+
|
||||
config BCMA_DEBUG
|
||||
bool "BCMA debugging"
|
||||
depends on BCMA
|
||||
--- a/drivers/bcma/Makefile
|
||||
+++ b/drivers/bcma/Makefile
|
||||
@@ -2,6 +2,7 @@ bcma-y += main.o scan.o core.o sprom
|
||||
bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
|
||||
@@ -3,6 +3,7 @@ bcma-y += driver_chipcommon.o driver
|
||||
bcma-y += driver_pci.o
|
||||
bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
|
||||
bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
|
||||
+bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o
|
||||
obj-$(CONFIG_BCMA) += bcma.o
|
||||
|
@ -46,7 +52,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG
|
||||
--- /dev/null
|
||||
+++ b/drivers/bcma/host_soc.c
|
||||
@@ -0,0 +1,178 @@
|
||||
@@ -0,0 +1,183 @@
|
||||
+/*
|
||||
+ * Broadcom specific AMBA
|
||||
+ * System on Chip (SoC) Host
|
||||
|
@ -210,11 +216,12 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+int __init bcma_host_soc_register(struct bcma_soc *soc)
|
||||
+{
|
||||
+ struct bcma_bus *bus = &soc->bus;
|
||||
+ int err;
|
||||
+
|
||||
+ /* iomap only first core. We have to read some register on this core
|
||||
+ * to scan the bus.
|
||||
+ */
|
||||
+ bus->mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
|
||||
+ bus->mmio = ioremap_nocache(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
|
||||
+ if (!bus->mmio)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
|
@ -223,13 +230,30 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+ bus->ops = &bcma_host_soc_ops;
|
||||
+
|
||||
+ /* Register */
|
||||
+ return bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips);
|
||||
+ err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips);
|
||||
+ if (err)
|
||||
+ iounmap(bus->mmio);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
--- a/drivers/bcma/main.c
|
||||
+++ b/drivers/bcma/main.c
|
||||
@@ -95,6 +95,7 @@ static int bcma_register_cores(struct bc
|
||||
@@ -66,6 +66,10 @@ static struct bcma_device *bcma_find_cor
|
||||
static void bcma_release_core_dev(struct device *dev)
|
||||
{
|
||||
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
|
||||
+ if (core->io_addr)
|
||||
+ iounmap(core->io_addr);
|
||||
+ if (core->io_wrap)
|
||||
+ iounmap(core->io_wrap);
|
||||
kfree(core);
|
||||
}
|
||||
|
||||
@@ -93,8 +97,8 @@ static int bcma_register_cores(struct bc
|
||||
core->dma_dev = &bus->host_pci->dev;
|
||||
core->irq = bus->host_pci->irq;
|
||||
break;
|
||||
case BCMA_HOSTTYPE_NONE:
|
||||
- case BCMA_HOSTTYPE_NONE:
|
||||
case BCMA_HOSTTYPE_SDIO:
|
||||
+ case BCMA_HOSTTYPE_SOC:
|
||||
break;
|
||||
|
@ -237,62 +261,99 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
|
||||
--- a/drivers/bcma/scan.c
|
||||
+++ b/drivers/bcma/scan.c
|
||||
@@ -337,6 +337,14 @@ static int bcma_get_next_core(struct bcm
|
||||
@@ -337,6 +337,16 @@ static int bcma_get_next_core(struct bcm
|
||||
}
|
||||
}
|
||||
}
|
||||
+ if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
|
||||
+ core->io_addr = ioremap(core->addr, BCMA_CORE_SIZE);
|
||||
+ core->io_addr = ioremap_nocache(core->addr, BCMA_CORE_SIZE);
|
||||
+ if (!core->io_addr)
|
||||
+ return -ENOMEM;
|
||||
+ core->io_wrap = ioremap(core->wrap, BCMA_CORE_SIZE);
|
||||
+ if (!core->io_wrap)
|
||||
+ core->io_wrap = ioremap_nocache(core->wrap, BCMA_CORE_SIZE);
|
||||
+ if (!core->io_wrap) {
|
||||
+ iounmap(core->io_addr);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ }
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -369,7 +377,13 @@ int bcma_bus_scan(struct bcma_bus *bus)
|
||||
@@ -369,7 +379,14 @@ int bcma_bus_scan(struct bcma_bus *bus)
|
||||
bcma_init_bus(bus);
|
||||
|
||||
erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
|
||||
- eromptr = bus->mmio;
|
||||
+ if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
|
||||
+ eromptr = ioremap(erombase, BCMA_CORE_SIZE);
|
||||
+ eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
|
||||
+ if (!eromptr)
|
||||
+ return -ENOMEM;
|
||||
+ } else
|
||||
+ } else {
|
||||
+ eromptr = bus->mmio;
|
||||
+ }
|
||||
+
|
||||
eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
|
||||
|
||||
bcma_scan_switch_core(bus, erombase);
|
||||
@@ -417,7 +431,13 @@ int __init bcma_bus_scan_early(struct bc
|
||||
int err, core_num = 0;
|
||||
@@ -404,6 +421,9 @@ int bcma_bus_scan(struct bcma_bus *bus)
|
||||
list_add(&core->list, &bus->cores);
|
||||
}
|
||||
|
||||
+ if (bus->hosttype == BCMA_HOSTTYPE_SOC)
|
||||
+ iounmap(eromptr);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -414,10 +434,18 @@ int __init bcma_bus_scan_early(struct bc
|
||||
u32 erombase;
|
||||
u32 __iomem *eromptr, *eromend;
|
||||
|
||||
- int err, core_num = 0;
|
||||
+ int err = -ENODEV;
|
||||
+ int core_num = 0;
|
||||
|
||||
erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
|
||||
- eromptr = bus->mmio;
|
||||
+ if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
|
||||
+ eromptr = ioremap(erombase, BCMA_CORE_SIZE);
|
||||
+ eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
|
||||
+ if (!eromptr)
|
||||
+ return -ENOMEM;
|
||||
+ } else
|
||||
+ } else {
|
||||
+ eromptr = bus->mmio;
|
||||
+ }
|
||||
+
|
||||
eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
|
||||
|
||||
bcma_scan_switch_core(bus, erombase);
|
||||
@@ -447,8 +475,12 @@ int __init bcma_bus_scan_early(struct bc
|
||||
core->id.class);
|
||||
|
||||
list_add(&core->list, &bus->cores);
|
||||
- return 0;
|
||||
+ err = 0;
|
||||
+ break;
|
||||
}
|
||||
|
||||
- return -ENODEV;
|
||||
+ if (bus->hosttype == BCMA_HOSTTYPE_SOC)
|
||||
+ iounmap(eromptr);
|
||||
+
|
||||
+ return err;
|
||||
}
|
||||
--- a/include/linux/bcma/bcma.h
|
||||
+++ b/include/linux/bcma/bcma.h
|
||||
@@ -17,6 +17,7 @@ enum bcma_hosttype {
|
||||
BCMA_HOSTTYPE_NONE,
|
||||
@@ -14,9 +14,9 @@ struct bcma_device;
|
||||
struct bcma_bus;
|
||||
|
||||
enum bcma_hosttype {
|
||||
- BCMA_HOSTTYPE_NONE,
|
||||
BCMA_HOSTTYPE_PCI,
|
||||
BCMA_HOSTTYPE_SDIO,
|
||||
+ BCMA_HOSTTYPE_SOC,
|
||||
};
|
||||
|
||||
struct bcma_chipinfo {
|
||||
@@ -133,6 +134,9 @@ struct bcma_device {
|
||||
@@ -138,6 +138,9 @@ struct bcma_device {
|
||||
u32 addr;
|
||||
u32 wrap;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
From 0a1a5fd8aab864e7b531ab88fd317ff7278d884d Mon Sep 17 00:00:00 2001
|
||||
From 5961a1401605cd1941d5260a03b1dc2e8ae80619 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Mon, 6 Jun 2011 00:07:32 +0200
|
||||
Subject: [PATCH 05/14] bcma: add mips driver
|
||||
Subject: [PATCH 05/22] bcma: add mips driver
|
||||
|
||||
This adds a mips driver to bcma. This is only found on embedded
|
||||
devices. For now the driver just initializes the irqs used on this
|
||||
|
@ -9,51 +9,49 @@ system.
|
|||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/Kconfig | 11 ++-
|
||||
drivers/bcma/Kconfig | 9 +
|
||||
drivers/bcma/Makefile | 1 +
|
||||
drivers/bcma/driver_mips.c | 234 +++++++++++++++++++++++++++++++++
|
||||
drivers/bcma/main.c | 19 +++
|
||||
include/linux/bcma/bcma.h | 2 +
|
||||
include/linux/bcma/bcma_driver_mips.h | 49 +++++++
|
||||
6 files changed, 315 insertions(+), 1 deletions(-)
|
||||
drivers/bcma/driver_mips.c | 243 +++++++++++++++++++++++++++
|
||||
drivers/bcma/main.c | 15 ++
|
||||
include/linux/bcma/bcma.h | 3 +
|
||||
include/linux/bcma/bcma_driver_chipcommon.h | 13 ++
|
||||
include/linux/bcma/bcma_driver_mips.h | 49 ++++++
|
||||
7 files changed, 333 insertions(+), 0 deletions(-)
|
||||
create mode 100644 drivers/bcma/driver_mips.c
|
||||
create mode 100644 include/linux/bcma/bcma_driver_mips.h
|
||||
|
||||
--- a/drivers/bcma/Kconfig
|
||||
+++ b/drivers/bcma/Kconfig
|
||||
@@ -29,9 +29,18 @@ config BCMA_HOST_PCI
|
||||
@@ -36,7 +36,16 @@ config BCMA_DRIVER_PCI_HOSTMODE
|
||||
|
||||
config BCMA_HOST_SOC
|
||||
bool
|
||||
- depends on BCMA && MIPS
|
||||
+ depends on BCMA_DRIVER_MIPS
|
||||
default n
|
||||
|
||||
+
|
||||
+config BCMA_DRIVER_MIPS
|
||||
+ bool "BCMA Broadcom MIPS core driver"
|
||||
+ depends on BCMA && MIPS
|
||||
depends on BCMA && MIPS
|
||||
+ help
|
||||
+ Driver for the Broadcom MIPS core attached to Broadcom specific
|
||||
+ Advanced Microcontroller Bus.
|
||||
+
|
||||
+ If unsure, say N
|
||||
+
|
||||
|
||||
config BCMA_DEBUG
|
||||
bool "BCMA debugging"
|
||||
depends on BCMA
|
||||
--- a/drivers/bcma/Makefile
|
||||
+++ b/drivers/bcma/Makefile
|
||||
@@ -1,6 +1,7 @@
|
||||
bcma-y += main.o scan.o core.o sprom.o
|
||||
@@ -2,6 +2,7 @@ bcma-y += main.o scan.o core.o sprom
|
||||
bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
|
||||
bcma-y += driver_pci.o
|
||||
bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
|
||||
+bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o
|
||||
bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
|
||||
bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o
|
||||
obj-$(CONFIG_BCMA) += bcma.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/bcma/driver_mips.c
|
||||
@@ -0,0 +1,234 @@
|
||||
@@ -0,0 +1,243 @@
|
||||
+/*
|
||||
+ * Broadcom specific AMBA
|
||||
+ * Broadcom MIPS32 74K core driver
|
||||
|
@ -75,13 +73,22 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+#include <linux/serial_reg.h>
|
||||
+#include <linux/time.h>
|
||||
+
|
||||
+/* The 47162a0 hangs when reading its registers */
|
||||
+/* The 47162a0 hangs when reading MIPS DMP registers registers */
|
||||
+static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
|
||||
+{
|
||||
+ return dev->bus->chipinfo.id == 47162 && dev->bus->chipinfo.rev == 0 &&
|
||||
+ dev->id.id == BCMA_CORE_MIPS_74K;
|
||||
+}
|
||||
+
|
||||
+/* The 5357b0 hangs when reading USB20H DMP registers */
|
||||
+static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev)
|
||||
+{
|
||||
+ return (dev->bus->chipinfo.id == 0x5357 ||
|
||||
+ dev->bus->chipinfo.id == 0x4749) &&
|
||||
+ dev->bus->chipinfo.pkg == 11 &&
|
||||
+ dev->id.id == BCMA_CORE_USB20_HOST;
|
||||
+}
|
||||
+
|
||||
+static inline u32 mips_read32(struct bcma_drv_mips *mcore,
|
||||
+ u16 offset)
|
||||
+{
|
||||
|
@ -117,15 +124,15 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+
|
||||
+ if (bcma_core_mips_bcm47162a0_quirk(dev))
|
||||
+ return dev->core_index;
|
||||
+ if (bcma_core_mips_bcm5357b0_quirk(dev))
|
||||
+ return dev->core_index;
|
||||
+ flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
|
||||
+
|
||||
+ return flag & 0x1F;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* Get the MIPS IRQ assignment for a specified device.
|
||||
+ * If unassigned, 0 is returned.
|
||||
+ * If disabled, 5 is returned.
|
||||
+ */
|
||||
+unsigned int bcma_core_mips_irq(struct bcma_device *dev)
|
||||
+{
|
||||
|
@ -217,24 +224,24 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+{
|
||||
+ struct bcma_bus *bus = mcore->core->bus;
|
||||
+
|
||||
+ mcore->flash_buswidth = 2;
|
||||
+ if (bus->drv_cc.core) {
|
||||
+ mcore->flash_window = 0x1c000000;
|
||||
+ mcore->flash_window_size = 0x02000000;
|
||||
+ switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
|
||||
+ case BCMA_CC_FLASHT_STSER:
|
||||
+ case BCMA_CC_FLASHT_ATSER:
|
||||
+ pr_err("Serial flash not supported.\n");
|
||||
+ break;
|
||||
+ case BCMA_CC_FLASHT_PARA:
|
||||
+ pr_info("found parallel flash.\n");
|
||||
+ bus->drv_cc.pflash.window = 0x1c000000;
|
||||
+ bus->drv_cc.pflash.window_size = 0x02000000;
|
||||
+
|
||||
+ if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) &
|
||||
+ BCMA_CC_OTPS) == 0)
|
||||
+ mcore->flash_buswidth = 1;
|
||||
+ BCMA_CC_FLASH_CFG_DS) == 0)
|
||||
+ bus->drv_cc.pflash.buswidth = 1;
|
||||
+ else
|
||||
+ bus->drv_cc.pflash.buswidth = 2;
|
||||
+ break;
|
||||
+ }
|
||||
+ } else {
|
||||
+ mcore->flash_window = 0x1fc00000;
|
||||
+ mcore->flash_window_size = 0x00400000;
|
||||
+ default:
|
||||
+ pr_err("flash not supported.\n");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
|
@ -290,7 +297,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+}
|
||||
--- a/drivers/bcma/main.c
|
||||
+++ b/drivers/bcma/main.c
|
||||
@@ -80,6 +80,7 @@ static int bcma_register_cores(struct bc
|
||||
@@ -84,6 +84,7 @@ static int bcma_register_cores(struct bc
|
||||
case BCMA_CORE_CHIPCOMMON:
|
||||
case BCMA_CORE_PCI:
|
||||
case BCMA_CORE_PCIE:
|
||||
|
@ -298,34 +305,30 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
continue;
|
||||
}
|
||||
|
||||
@@ -141,6 +142,15 @@ int bcma_bus_register(struct bcma_bus *b
|
||||
@@ -144,6 +145,13 @@ int bcma_bus_register(struct bcma_bus *b
|
||||
bcma_core_chipcommon_init(&bus->drv_cc);
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
+ /* Init MIPS core */
|
||||
+ core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
|
||||
+ if (core) {
|
||||
+ bus->drv_mips.core = core;
|
||||
+ bcma_core_mips_init(&bus->drv_mips);
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
/* Init PCIE core */
|
||||
core = bcma_find_core(bus, BCMA_CORE_PCIE);
|
||||
if (core) {
|
||||
@@ -208,6 +218,15 @@ int __init bcma_bus_early_register(struc
|
||||
@@ -214,6 +222,13 @@ int __init bcma_bus_early_register(struc
|
||||
bcma_core_chipcommon_init(&bus->drv_cc);
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
+ /* Init MIPS core */
|
||||
+ core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
|
||||
+ if (core) {
|
||||
+ bus->drv_mips.core = core;
|
||||
+ bcma_core_mips_init(&bus->drv_mips);
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
pr_info("Early bus registered\n");
|
||||
|
||||
|
@ -340,7 +343,15 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
#include <linux/ssb/ssb.h> /* SPROM sharing */
|
||||
|
||||
#include "bcma_regs.h"
|
||||
@@ -193,6 +194,7 @@ struct bcma_bus {
|
||||
@@ -130,6 +131,7 @@ struct bcma_device {
|
||||
|
||||
struct device dev;
|
||||
struct device *dma_dev;
|
||||
+
|
||||
unsigned int irq;
|
||||
bool dev_registered;
|
||||
|
||||
@@ -197,6 +199,7 @@ struct bcma_bus {
|
||||
|
||||
struct bcma_drv_cc drv_cc;
|
||||
struct bcma_drv_pci drv_pci;
|
||||
|
@ -348,6 +359,49 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
|
||||
/* We decided to share SPROM struct with SSB as long as we do not need
|
||||
* any hacks for BCMA. This simplifies drivers code. */
|
||||
--- a/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
@@ -24,6 +24,7 @@
|
||||
#define BCMA_CC_FLASHT_NONE 0x00000000 /* No flash */
|
||||
#define BCMA_CC_FLASHT_STSER 0x00000100 /* ST serial flash */
|
||||
#define BCMA_CC_FLASHT_ATSER 0x00000200 /* Atmel serial flash */
|
||||
+#define BCMA_CC_FLASHT_NFLASH 0x00000200
|
||||
#define BCMA_CC_FLASHT_PARA 0x00000700 /* Parallel flash */
|
||||
#define BCMA_CC_CAP_PLLT 0x00038000 /* PLL Type */
|
||||
#define BCMA_PLLTYPE_NONE 0x00000000
|
||||
@@ -178,6 +179,7 @@
|
||||
#define BCMA_CC_PROG_CFG 0x0120
|
||||
#define BCMA_CC_PROG_WAITCNT 0x0124
|
||||
#define BCMA_CC_FLASH_CFG 0x0128
|
||||
+#define BCMA_CC_FLASH_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */
|
||||
#define BCMA_CC_FLASH_WAITCNT 0x012C
|
||||
/* 0x1E0 is defined as shared BCMA_CLKCTLST */
|
||||
#define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */
|
||||
@@ -247,6 +249,14 @@ struct bcma_chipcommon_pmu {
|
||||
u32 crystalfreq; /* The active crystal frequency (in kHz) */
|
||||
};
|
||||
|
||||
+#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
+struct bcma_pflash {
|
||||
+ u8 buswidth;
|
||||
+ u32 window;
|
||||
+ u32 window_size;
|
||||
+};
|
||||
+#endif /* CONFIG_BCMA_DRIVER_MIPS */
|
||||
+
|
||||
struct bcma_drv_cc {
|
||||
struct bcma_device *core;
|
||||
u32 status;
|
||||
@@ -256,6 +266,9 @@ struct bcma_drv_cc {
|
||||
/* Fast Powerup Delay constant */
|
||||
u16 fast_pwrup_delay;
|
||||
struct bcma_chipcommon_pmu pmu;
|
||||
+#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
+ struct bcma_pflash pflash;
|
||||
+#endif /* CONFIG_BCMA_DRIVER_MIPS */
|
||||
};
|
||||
|
||||
/* Register access */
|
||||
--- /dev/null
|
||||
+++ b/include/linux/bcma/bcma_driver_mips.h
|
||||
@@ -0,0 +1,49 @@
|
||||
|
@ -389,13 +443,13 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+ struct bcma_device *core;
|
||||
+ u8 setup_done:1;
|
||||
+ unsigned int assigned_irqs;
|
||||
+
|
||||
+ u8 flash_buswidth;
|
||||
+ u32 flash_window;
|
||||
+ u32 flash_window_size;
|
||||
+};
|
||||
+
|
||||
+#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
+extern void bcma_core_mips_init(struct bcma_drv_mips *mcore);
|
||||
+#else
|
||||
+static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { }
|
||||
+#endif
|
||||
+
|
||||
+extern unsigned int bcma_core_mips_irq(struct bcma_device *dev);
|
||||
+
|
||||
|
|
|
@ -1,63 +1,55 @@
|
|||
From b7c100827012ba588089807475affe0c69a3f817 Mon Sep 17 00:00:00 2001
|
||||
From 5088e81ecc5c953df7de84eeedd0817326bc4be4 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Mon, 6 Jun 2011 00:07:33 +0200
|
||||
Subject: [PATCH 06/14] bcma: add serial console support
|
||||
Subject: [PATCH 06/22] bcma: add serial console support
|
||||
|
||||
This adds support for serial console to bcma, when operating on an
|
||||
embedded device.
|
||||
This adds support for serial console to bcma, when operating on an SoC.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/bcma_private.h | 6 +++
|
||||
drivers/bcma/driver_chipcommon.c | 64 +++++++++++++++++++++++++++++++++
|
||||
drivers/bcma/driver_mips.c | 9 +++++
|
||||
include/linux/bcma/bcma_driver_mips.h | 11 ++++++
|
||||
4 files changed, 90 insertions(+), 0 deletions(-)
|
||||
drivers/bcma/bcma_private.h | 8 ++++
|
||||
drivers/bcma/driver_chipcommon.c | 48 +++++++++++++++++++++++++++
|
||||
drivers/bcma/driver_chipcommon_pmu.c | 26 ++++++++++++++
|
||||
drivers/bcma/driver_mips.c | 1 +
|
||||
include/linux/bcma/bcma_driver_chipcommon.h | 14 ++++++++
|
||||
5 files changed, 97 insertions(+), 0 deletions(-)
|
||||
|
||||
--- a/drivers/bcma/bcma_private.h
|
||||
+++ b/drivers/bcma/bcma_private.h
|
||||
@@ -29,6 +29,12 @@ void bcma_init_bus(struct bcma_bus *bus)
|
||||
@@ -29,6 +29,14 @@ void bcma_init_bus(struct bcma_bus *bus)
|
||||
/* sprom.c */
|
||||
int bcma_sprom_get(struct bcma_bus *bus);
|
||||
|
||||
+/* driver_chipcommon.c */
|
||||
+#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
+extern int bcma_chipco_serial_init(struct bcma_drv_cc *cc,
|
||||
+ struct bcma_drv_mips_serial_port *ports);
|
||||
+void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
|
||||
+#endif /* CONFIG_BCMA_DRIVER_MIPS */
|
||||
+
|
||||
+/* driver_chipcommon_pmu.c */
|
||||
+u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc);
|
||||
+
|
||||
#ifdef CONFIG_BCMA_HOST_PCI
|
||||
/* host_pci.c */
|
||||
extern int __init bcma_host_pci_init(void);
|
||||
--- a/drivers/bcma/driver_chipcommon.c
|
||||
+++ b/drivers/bcma/driver_chipcommon.c
|
||||
@@ -92,3 +92,67 @@ u32 bcma_chipco_gpio_polarity(struct bcm
|
||||
@@ -106,3 +106,51 @@ u32 bcma_chipco_gpio_polarity(struct bcm
|
||||
{
|
||||
return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
|
||||
}
|
||||
+
|
||||
+#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
+int bcma_chipco_serial_init(struct bcma_drv_cc *cc,
|
||||
+ struct bcma_drv_mips_serial_port *ports)
|
||||
+void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
|
||||
+{
|
||||
+ int nr_ports = 0;
|
||||
+ u32 plltype;
|
||||
+ unsigned int irq;
|
||||
+ u32 baud_base, div;
|
||||
+ u32 i, n;
|
||||
+ u32 baud_base;
|
||||
+ u32 i;
|
||||
+ unsigned int ccrev = cc->core->id.rev;
|
||||
+ struct bcma_serial_port *ports = cc->serial_ports;
|
||||
+
|
||||
+ plltype = (cc->capabilities & BCMA_CC_CAP_PLLT);
|
||||
+ irq = bcma_core_mips_irq(cc->core);
|
||||
+
|
||||
+ if ((ccrev >= 11) && (ccrev != 15) && (ccrev != 20)) {
|
||||
+ if (ccrev >= 11 && ccrev != 15) {
|
||||
+ /* Fixed ALP clock */
|
||||
+ baud_base = 20000000;
|
||||
+ if (cc->capabilities & BCMA_CC_CAP_PMU) {
|
||||
+ /* FIXME: baud_base is different for devices with a PMU */
|
||||
+ WARN_ON(1);
|
||||
+ }
|
||||
+ div = 1;
|
||||
+ baud_base = bcma_pmu_alp_clock(cc);
|
||||
+ if (ccrev >= 21) {
|
||||
+ /* Turn off UART clock before switching clocksource. */
|
||||
+ bcma_cc_write32(cc, BCMA_CC_CORECTL,
|
||||
|
@ -74,78 +66,101 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+ bcma_cc_read32(cc, BCMA_CC_CORECTL)
|
||||
+ | BCMA_CC_CORECTL_UARTCLKEN);
|
||||
+ }
|
||||
+ } else
|
||||
+ } else {
|
||||
+ pr_err("serial not supported on this device ccrev: 0x%x\n",
|
||||
+ ccrev);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ irq = bcma_core_mips_irq(cc->core);
|
||||
+
|
||||
+ /* Determine the registers of the UARTs */
|
||||
+ n = (cc->capabilities & BCMA_CC_CAP_NRUART);
|
||||
+ for (i = 0; i < n; i++) {
|
||||
+ void __iomem *cc_mmio;
|
||||
+ void __iomem *uart_regs;
|
||||
+
|
||||
+ cc_mmio = cc->core->bus->mmio +
|
||||
+ (cc->core->core_index * BCMA_CORE_SIZE);
|
||||
+ uart_regs = cc_mmio + BCMA_CC_UART0_DATA;
|
||||
+ uart_regs += (i * 256);
|
||||
+
|
||||
+ nr_ports++;
|
||||
+ ports[i].regs = uart_regs;
|
||||
+ cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
|
||||
+ for (i = 0; i < cc->nr_serial_ports; i++) {
|
||||
+ ports[i].regs = cc->core->io_addr + BCMA_CC_UART0_DATA +
|
||||
+ (i * 256);
|
||||
+ ports[i].irq = irq;
|
||||
+ ports[i].baud_base = baud_base;
|
||||
+ ports[i].reg_shift = 0;
|
||||
+ }
|
||||
+
|
||||
+ return nr_ports;
|
||||
+}
|
||||
+#endif /* CONFIG_BCMA_DRIVER_MIPS */
|
||||
--- a/drivers/bcma/driver_chipcommon_pmu.c
|
||||
+++ b/drivers/bcma/driver_chipcommon_pmu.c
|
||||
@@ -136,3 +136,29 @@ void bcma_pmu_init(struct bcma_drv_cc *c
|
||||
bcma_pmu_swreg_init(cc);
|
||||
bcma_pmu_workarounds(cc);
|
||||
}
|
||||
+
|
||||
+u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc)
|
||||
+{
|
||||
+ struct bcma_bus *bus = cc->core->bus;
|
||||
+
|
||||
+ switch (bus->chipinfo.id) {
|
||||
+ case 0x4716:
|
||||
+ case 0x4748:
|
||||
+ case 47162:
|
||||
+ case 0x4313:
|
||||
+ case 0x5357:
|
||||
+ case 0x4749:
|
||||
+ case 53572:
|
||||
+ /* always 20Mhz */
|
||||
+ return 20000 * 1000;
|
||||
+ case 0x5356:
|
||||
+ case 0x5300:
|
||||
+ /* always 25Mhz */
|
||||
+ return 25000 * 1000;
|
||||
+ default:
|
||||
+ pr_warn("No ALP clock specified for %04X device, "
|
||||
+ "pmu rev. %d, using default %d Hz\n",
|
||||
+ bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
|
||||
+ }
|
||||
+ return BCMA_CC_PMU_ALP_CLOCK;
|
||||
+}
|
||||
--- a/drivers/bcma/driver_mips.c
|
||||
+++ b/drivers/bcma/driver_mips.c
|
||||
@@ -157,6 +157,14 @@ static void bcma_core_mips_dump_irq(stru
|
||||
}
|
||||
}
|
||||
|
||||
+static void bcma_core_mips_serial_init(struct bcma_drv_mips *mcore)
|
||||
+{
|
||||
+ struct bcma_bus *bus = mcore->core->bus;
|
||||
+
|
||||
+ mcore->nr_serial_ports = bcma_chipco_serial_init(&bus->drv_cc,
|
||||
+ mcore->serial_ports);
|
||||
+}
|
||||
+
|
||||
static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
|
||||
{
|
||||
struct bcma_bus *bus = mcore->core->bus;
|
||||
@@ -229,6 +237,7 @@ void bcma_core_mips_init(struct bcma_drv
|
||||
@@ -238,6 +238,7 @@ void bcma_core_mips_init(struct bcma_drv
|
||||
if (mcore->setup_done)
|
||||
return;
|
||||
|
||||
+ bcma_core_mips_serial_init(mcore);
|
||||
+ bcma_chipco_serial_init(&bus->drv_cc);
|
||||
bcma_core_mips_flash_detect(mcore);
|
||||
mcore->setup_done = true;
|
||||
}
|
||||
--- a/include/linux/bcma/bcma_driver_mips.h
|
||||
+++ b/include/linux/bcma/bcma_driver_mips.h
|
||||
@@ -32,11 +32,22 @@
|
||||
--- a/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
@@ -241,6 +241,9 @@
|
||||
#define BCMA_CC_SPROM 0x0800 /* SPROM beginning */
|
||||
#define BCMA_CC_SPROM_PCIE6 0x0830 /* SPROM beginning on PCIe rev >= 6 */
|
||||
|
||||
struct bcma_device;
|
||||
|
||||
+struct bcma_drv_mips_serial_port {
|
||||
+/* ALP clock on pre-PMU chips */
|
||||
+#define BCMA_CC_PMU_ALP_CLOCK 20000000
|
||||
+
|
||||
/* Data for the PMU, if available.
|
||||
* Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
|
||||
*/
|
||||
@@ -255,6 +258,14 @@ struct bcma_pflash {
|
||||
u32 window;
|
||||
u32 window_size;
|
||||
};
|
||||
+
|
||||
+struct bcma_serial_port {
|
||||
+ void *regs;
|
||||
+ unsigned long clockspeed;
|
||||
+ unsigned int irq;
|
||||
+ unsigned int baud_base;
|
||||
+ unsigned int reg_shift;
|
||||
+};
|
||||
+
|
||||
struct bcma_drv_mips {
|
||||
struct bcma_device *core;
|
||||
u8 setup_done:1;
|
||||
unsigned int assigned_irqs;
|
||||
#endif /* CONFIG_BCMA_DRIVER_MIPS */
|
||||
|
||||
+ int nr_serial_ports;
|
||||
+ struct bcma_drv_mips_serial_port serial_ports[4];
|
||||
struct bcma_drv_cc {
|
||||
@@ -268,6 +279,9 @@ struct bcma_drv_cc {
|
||||
struct bcma_chipcommon_pmu pmu;
|
||||
#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
struct bcma_pflash pflash;
|
||||
+
|
||||
u8 flash_buswidth;
|
||||
u32 flash_window;
|
||||
u32 flash_window_size;
|
||||
+ int nr_serial_ports;
|
||||
+ struct bcma_serial_port serial_ports[4];
|
||||
#endif /* CONFIG_BCMA_DRIVER_MIPS */
|
||||
};
|
||||
|
||||
|
|
|
@ -1,32 +1,30 @@
|
|||
From 257d5fe12600f08df764cac0abc17bef7b6fae9b Mon Sep 17 00:00:00 2001
|
||||
From e993e8342e660f29a048be872522eedabaa177e1 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sun, 19 Jun 2011 17:51:30 +0200
|
||||
Subject: [PATCH 07/14] bcma: get CPU clock
|
||||
Date: Sat, 16 Jul 2011 15:19:38 +0200
|
||||
Subject: [PATCH 07/22] bcma: get CPU clock
|
||||
|
||||
Add method to return the clock of the CPU. This is needed by the arch
|
||||
code to calculate the mips_hpt_frequency.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/bcma_private.h | 3 +
|
||||
drivers/bcma/driver_chipcommon_pmu.c | 87 +++++++++++++++++++++++++++
|
||||
drivers/bcma/driver_mips.c | 12 ++++
|
||||
include/linux/bcma/bcma_driver_chipcommon.h | 35 +++++++++++
|
||||
include/linux/bcma/bcma_driver_mips.h | 1 +
|
||||
5 files changed, 138 insertions(+), 0 deletions(-)
|
||||
drivers/bcma/bcma_private.h | 1 +
|
||||
drivers/bcma/driver_chipcommon_pmu.c | 107 +++++++++++++++++++++++++++
|
||||
drivers/bcma/driver_mips.c | 12 +++
|
||||
include/linux/bcma/bcma_driver_chipcommon.h | 39 ++++++++++
|
||||
include/linux/bcma/bcma_driver_mips.h | 2 +
|
||||
5 files changed, 161 insertions(+), 0 deletions(-)
|
||||
|
||||
--- a/drivers/bcma/bcma_private.h
|
||||
+++ b/drivers/bcma/bcma_private.h
|
||||
@@ -29,6 +29,9 @@ void bcma_init_bus(struct bcma_bus *bus)
|
||||
/* sprom.c */
|
||||
int bcma_sprom_get(struct bcma_bus *bus);
|
||||
@@ -36,6 +36,7 @@ void bcma_chipco_serial_init(struct bcma
|
||||
|
||||
+/* driver_chipcommon_pmu.c */
|
||||
+extern u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
|
||||
+
|
||||
/* driver_chipcommon.c */
|
||||
#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
extern int bcma_chipco_serial_init(struct bcma_drv_cc *cc,
|
||||
/* driver_chipcommon_pmu.c */
|
||||
u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc);
|
||||
+u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
|
||||
|
||||
#ifdef CONFIG_BCMA_HOST_PCI
|
||||
/* host_pci.c */
|
||||
--- a/drivers/bcma/driver_chipcommon_pmu.c
|
||||
+++ b/drivers/bcma/driver_chipcommon_pmu.c
|
||||
@@ -11,6 +11,13 @@
|
||||
|
@ -43,28 +41,10 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
|
||||
u32 offset, u32 mask, u32 set)
|
||||
{
|
||||
@@ -136,3 +143,83 @@ void bcma_pmu_init(struct bcma_drv_cc *c
|
||||
bcma_pmu_swreg_init(cc);
|
||||
bcma_pmu_workarounds(cc);
|
||||
@@ -162,3 +169,103 @@ u32 bcma_pmu_alp_clock(struct bcma_drv_c
|
||||
}
|
||||
return BCMA_CC_PMU_ALP_CLOCK;
|
||||
}
|
||||
+
|
||||
+static u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc)
|
||||
+{
|
||||
+ struct bcma_bus *bus = cc->core->bus;
|
||||
+
|
||||
+ switch (bus->chipinfo.id) {
|
||||
+ case 0x4716:
|
||||
+ case 0x4748:
|
||||
+ case 47162:
|
||||
+ /* always 20Mhz */
|
||||
+ return 20000 * 1000;
|
||||
+ default:
|
||||
+ pr_warn("No ALP clock specified for %04X device, "
|
||||
+ "pmu rev. %d, using default %d Hz\n",
|
||||
+ bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
|
||||
+ }
|
||||
+ return BCMA_CC_PMU_ALP_CLOCK;
|
||||
+}
|
||||
+
|
||||
+/* Find the output of the "m" pll divider given pll controls that start with
|
||||
+ * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
|
||||
|
@ -72,10 +52,18 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
|
||||
+{
|
||||
+ u32 tmp, div, ndiv, p1, p2, fc;
|
||||
+ struct bcma_bus *bus = cc->core->bus;
|
||||
+
|
||||
+ BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0));
|
||||
+
|
||||
+ BUG_ON(!m || m > 4);
|
||||
+
|
||||
+ BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0));
|
||||
+ if (bus->chipinfo.id == 0x5357 || bus->chipinfo.id == 0x4749) {
|
||||
+ /* Detect failure in clock setting */
|
||||
+ tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
|
||||
+ if (tmp & 0x40000)
|
||||
+ return 133 * 1000000;
|
||||
+ }
|
||||
+
|
||||
+ tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_P1P2_OFF);
|
||||
+ p1 = (tmp & BCMA_CC_PPL_P1_MASK) >> BCMA_CC_PPL_P1_SHIFT;
|
||||
|
@ -107,6 +95,18 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+ case 47162:
|
||||
+ return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
|
||||
+ BCMA_CC_PMU5_MAINPLL_SSB);
|
||||
+ case 0x5356:
|
||||
+ return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
|
||||
+ BCMA_CC_PMU5_MAINPLL_SSB);
|
||||
+ case 0x5357:
|
||||
+ case 0x4749:
|
||||
+ return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
|
||||
+ BCMA_CC_PMU5_MAINPLL_SSB);
|
||||
+ case 0x5300:
|
||||
+ return bcma_pmu_clock(cc, BCMA_CC_PMU4706_MAINPLL_PLL0,
|
||||
+ BCMA_CC_PMU5_MAINPLL_SSB);
|
||||
+ case 53572:
|
||||
+ return 75000000;
|
||||
+ default:
|
||||
+ pr_warn("No backplane clock specified for %04X device, "
|
||||
+ "pmu rev. %d, using default %d Hz\n",
|
||||
|
@ -120,16 +120,34 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+{
|
||||
+ struct bcma_bus *bus = cc->core->bus;
|
||||
+
|
||||
+ if ((cc->pmu.rev == 5 || cc->pmu.rev == 6 || cc->pmu.rev == 7) &&
|
||||
+ (bus->chipinfo.id != 0x4319))
|
||||
+ return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
|
||||
+ BCMA_CC_PMU5_MAINPLL_CPU);
|
||||
+ if (bus->chipinfo.id == 53572)
|
||||
+ return 300000000;
|
||||
+
|
||||
+ if (cc->pmu.rev >= 5) {
|
||||
+ u32 pll;
|
||||
+ switch (bus->chipinfo.id) {
|
||||
+ case 0x5356:
|
||||
+ pll = BCMA_CC_PMU5356_MAINPLL_PLL0;
|
||||
+ break;
|
||||
+ case 0x5357:
|
||||
+ case 0x4749:
|
||||
+ pll = BCMA_CC_PMU5357_MAINPLL_PLL0;
|
||||
+ break;
|
||||
+ default:
|
||||
+ pll = BCMA_CC_PMU4716_MAINPLL_PLL0;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* TODO: if (bus->chipinfo.id == 0x5300)
|
||||
+ return si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU); */
|
||||
+ return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
|
||||
+ }
|
||||
+
|
||||
+ return bcma_pmu_get_clockcontrol(cc);
|
||||
+}
|
||||
--- a/drivers/bcma/driver_mips.c
|
||||
+++ b/drivers/bcma/driver_mips.c
|
||||
@@ -157,6 +157,18 @@ static void bcma_core_mips_dump_irq(stru
|
||||
@@ -166,6 +166,18 @@ static void bcma_core_mips_dump_irq(stru
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,14 +163,14 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+}
|
||||
+EXPORT_SYMBOL(bcma_cpu_clock);
|
||||
+
|
||||
static void bcma_core_mips_serial_init(struct bcma_drv_mips *mcore)
|
||||
static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
|
||||
{
|
||||
struct bcma_bus *bus = mcore->core->bus;
|
||||
--- a/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
@@ -246,6 +246,41 @@
|
||||
#define BCMA_CC_PLLCTL_DATA 0x0664
|
||||
#define BCMA_CC_SPROM 0x0830 /* SPROM beginning */
|
||||
@@ -241,8 +241,47 @@
|
||||
#define BCMA_CC_SPROM 0x0800 /* SPROM beginning */
|
||||
#define BCMA_CC_SPROM_PCIE6 0x0830 /* SPROM beginning on PCIe rev >= 6 */
|
||||
|
||||
+/* Divider allocation in 4716/47162/5356 */
|
||||
+#define BCMA_CC_PMU5_MAINPLL_CPU 1
|
||||
|
@ -162,8 +180,15 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+/* PLL usage in 4716/47162 */
|
||||
+#define BCMA_CC_PMU4716_MAINPLL_PLL0 12
|
||||
+
|
||||
+/* ALP clock on pre-PMU chips */
|
||||
+#define BCMA_CC_PMU_ALP_CLOCK 20000000
|
||||
+/* PLL usage in 5356/5357 */
|
||||
+#define BCMA_CC_PMU5356_MAINPLL_PLL0 0
|
||||
+#define BCMA_CC_PMU5357_MAINPLL_PLL0 0
|
||||
+
|
||||
+/* 4706 PMU */
|
||||
+#define BCMA_CC_PMU4706_MAINPLL_PLL0 0
|
||||
+
|
||||
/* ALP clock on pre-PMU chips */
|
||||
#define BCMA_CC_PMU_ALP_CLOCK 20000000
|
||||
+/* HT clock for systems with PMU-enabled chipcommon */
|
||||
+#define BCMA_CC_PMU_HT_CLOCK 80000000
|
||||
+
|
||||
|
@ -188,17 +213,17 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+#define BCMA_CC_PPL_PLLCTL_OFF 4
|
||||
+#define BCMA_CC_PPL_PCHI_OFF 5
|
||||
+#define BCMA_CC_PPL_PCHI_MASK 0x0000003f
|
||||
+
|
||||
|
||||
/* Data for the PMU, if available.
|
||||
* Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
|
||||
*/
|
||||
--- a/include/linux/bcma/bcma_driver_mips.h
|
||||
+++ b/include/linux/bcma/bcma_driver_mips.h
|
||||
@@ -54,6 +54,7 @@ struct bcma_drv_mips {
|
||||
};
|
||||
@@ -44,6 +44,8 @@ extern void bcma_core_mips_init(struct b
|
||||
static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { }
|
||||
#endif
|
||||
|
||||
extern void bcma_core_mips_init(struct bcma_drv_mips *mcore);
|
||||
+extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore);
|
||||
|
||||
+
|
||||
extern unsigned int bcma_core_mips_irq(struct bcma_device *dev);
|
||||
|
||||
#endif /* LINUX_BCMA_DRIVER_MIPS_H_ */
|
||||
|
|
|
@ -1,24 +1,26 @@
|
|||
From c0886db6357de20fba4f7c0602eceefba3ad343b Mon Sep 17 00:00:00 2001
|
||||
From 1db44bc4e7d5abb2966154ac57d1f035dc3e4ec1 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Mon, 6 Jun 2011 00:07:36 +0200
|
||||
Subject: [PATCH 10/14] bcm47xx: prepare to support different buses
|
||||
Subject: [PATCH 08/22] bcm47xx: prepare to support different buses
|
||||
|
||||
The ssb bus is not hod directly any more. there is now a union which
|
||||
contains all the supported buses, now just ssb. As just one system bus
|
||||
can be used at a time the union does not cause any problems.
|
||||
Prepare bcm47xx to support different System buses. Before adding
|
||||
support for bcma it should be possible to build bcm47xx without the
|
||||
need of ssb. With this patch bcm47xx does not directly contain a
|
||||
ssb_bus, but a union contain all the supported system buses. As a SoC
|
||||
just uses one system bus a union is a good choice.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
arch/mips/bcm47xx/gpio.c | 56 ++++++++++++++++----------
|
||||
arch/mips/bcm47xx/nvram.c | 15 +++++--
|
||||
arch/mips/bcm47xx/serial.c | 13 +++++-
|
||||
arch/mips/bcm47xx/setup.c | 32 +++++++++++---
|
||||
arch/mips/bcm47xx/setup.c | 33 ++++++++++++---
|
||||
arch/mips/bcm47xx/time.c | 9 +++-
|
||||
arch/mips/bcm47xx/wgt634u.c | 13 ++++--
|
||||
arch/mips/bcm47xx/wgt634u.c | 14 ++++--
|
||||
arch/mips/include/asm/mach-bcm47xx/bcm47xx.h | 14 ++++++-
|
||||
arch/mips/include/asm/mach-bcm47xx/gpio.h | 55 ++++++++++++++++++-------
|
||||
drivers/watchdog/bcm47xx_wdt.c | 12 +++++-
|
||||
9 files changed, 158 insertions(+), 61 deletions(-)
|
||||
9 files changed, 160 insertions(+), 61 deletions(-)
|
||||
|
||||
--- a/arch/mips/bcm47xx/gpio.c
|
||||
+++ b/arch/mips/bcm47xx/gpio.c
|
||||
|
@ -277,15 +279,17 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
SSB_CHIPCO_IRQ_GPIO))
|
||||
return IRQ_NONE;
|
||||
|
||||
@@ -133,21 +133,24 @@ static int __init wgt634u_init(void)
|
||||
@@ -132,22 +132,26 @@ static int __init wgt634u_init(void)
|
||||
* machine. Use the MAC address as an heuristic. Netgear Inc. has
|
||||
* been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx.
|
||||
*/
|
||||
+ u8 *et0mac;
|
||||
|
||||
- u8 *et0mac = ssb_bcm47xx.sprom.et0mac;
|
||||
+ if (bcm47xx_active_bus_type != BCM47XX_BUS_TYPE_SSB)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ u8 *et0mac = bcm47xx_bus.ssb.sprom.et0mac;
|
||||
+ et0mac = bcm47xx_bus.ssb.sprom.et0mac;
|
||||
|
||||
if (et0mac[0] == 0x00 &&
|
||||
((et0mac[1] == 0x09 && et0mac[2] == 0x5b) ||
|
|
@ -1,140 +0,0 @@
|
|||
From f93062e72447b4a4a51afbe33ea086ce8c922587 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sun, 19 Jun 2011 17:52:09 +0200
|
||||
Subject: [PATCH 08/14] bcma: add pci(e) host mode
|
||||
|
||||
This adds some stub for a pci(e) host controller. This controller is
|
||||
found on some embedded devices to attach other chips.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/Kconfig | 6 ++++
|
||||
drivers/bcma/Makefile | 1 +
|
||||
drivers/bcma/bcma_private.h | 6 ++++
|
||||
drivers/bcma/driver_pci.c | 14 ++++++++++-
|
||||
drivers/bcma/driver_pci_host.c | 43 ++++++++++++++++++++++++++++++++++
|
||||
include/linux/bcma/bcma_driver_pci.h | 1 +
|
||||
6 files changed, 70 insertions(+), 1 deletions(-)
|
||||
create mode 100644 drivers/bcma/driver_pci_host.c
|
||||
|
||||
--- a/drivers/bcma/Kconfig
|
||||
+++ b/drivers/bcma/Kconfig
|
||||
@@ -32,6 +32,12 @@ config BCMA_HOST_SOC
|
||||
depends on BCMA_DRIVER_MIPS
|
||||
default n
|
||||
|
||||
+config BCMA_DRIVER_PCI_HOSTMODE
|
||||
+ bool "Hostmode support for BCMA PCI core"
|
||||
+ depends on BCMA_DRIVER_MIPS
|
||||
+ help
|
||||
+ PCIcore hostmode operation (external PCI bus).
|
||||
+
|
||||
config BCMA_DRIVER_MIPS
|
||||
bool "BCMA Broadcom MIPS core driver"
|
||||
depends on BCMA && MIPS
|
||||
--- a/drivers/bcma/Makefile
|
||||
+++ b/drivers/bcma/Makefile
|
||||
@@ -1,6 +1,7 @@
|
||||
bcma-y += main.o scan.o core.o sprom.o
|
||||
bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
|
||||
bcma-y += driver_pci.o
|
||||
+bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
|
||||
bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o
|
||||
bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
|
||||
bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o
|
||||
--- a/drivers/bcma/bcma_private.h
|
||||
+++ b/drivers/bcma/bcma_private.h
|
||||
@@ -38,6 +38,12 @@ extern int bcma_chipco_serial_init(struc
|
||||
struct bcma_drv_mips_serial_port *ports);
|
||||
#endif /* CONFIG_BCMA_DRIVER_MIPS */
|
||||
|
||||
+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
|
||||
+/* driver_pci_host.c */
|
||||
+int bcma_core_pci_in_hostmode(struct bcma_drv_pci *pc);
|
||||
+void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
|
||||
+#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
|
||||
+
|
||||
#ifdef CONFIG_BCMA_HOST_PCI
|
||||
/* host_pci.c */
|
||||
extern int __init bcma_host_pci_init(void);
|
||||
--- a/drivers/bcma/driver_pci.c
|
||||
+++ b/drivers/bcma/driver_pci.c
|
||||
@@ -159,9 +159,21 @@ static void bcma_pcicore_serdes_workarou
|
||||
|
||||
void bcma_core_pci_init(struct bcma_drv_pci *pc)
|
||||
{
|
||||
+ struct bcma_device *core = pc->core;
|
||||
+
|
||||
if (pc->setup_done)
|
||||
return;
|
||||
- bcma_pcicore_serdes_workaround(pc);
|
||||
+
|
||||
+ if (!bcma_core_is_enabled(core))
|
||||
+ bcma_core_enable(core, 0);
|
||||
+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
|
||||
+ pc->hostmode = bcma_core_pci_in_hostmode(pc);
|
||||
+ if (pc->hostmode)
|
||||
+ bcma_core_pci_hostmode_init(pc);
|
||||
+#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
|
||||
+ if (!pc->hostmode)
|
||||
+ bcma_pcicore_serdes_workaround(pc);
|
||||
+
|
||||
pc->setup_done = true;
|
||||
}
|
||||
|
||||
--- /dev/null
|
||||
+++ b/drivers/bcma/driver_pci_host.c
|
||||
@@ -0,0 +1,43 @@
|
||||
+/*
|
||||
+ * Broadcom specific AMBA
|
||||
+ * PCI Host mode
|
||||
+ *
|
||||
+ * Copyright 2005, Broadcom Corporation
|
||||
+ *
|
||||
+ * Licensed under the GNU/GPL. See COPYING for details.
|
||||
+ */
|
||||
+
|
||||
+#include "bcma_private.h"
|
||||
+#include <linux/bcma/bcma.h>
|
||||
+
|
||||
+#include <asm/paccess.h>
|
||||
+/* Probe a 32bit value on the bus and catch bus exceptions.
|
||||
+ * Returns nonzero on a bus exception.
|
||||
+ * This is MIPS specific */
|
||||
+#define mips_busprobe32(val, addr) get_dbe((val), ((u32 *)(addr)))
|
||||
+
|
||||
+
|
||||
+void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
|
||||
+{
|
||||
+ /* TODO: implement PCI host mode */
|
||||
+}
|
||||
+
|
||||
+int bcma_core_pci_in_hostmode(struct bcma_drv_pci *pc)
|
||||
+{
|
||||
+ struct bcma_bus *bus = pc->core->bus;
|
||||
+ u16 chipid_top;
|
||||
+ u32 tmp;
|
||||
+
|
||||
+ chipid_top = (bus->chipinfo.id & 0xFF00);
|
||||
+ if (chipid_top != 0x4700 &&
|
||||
+ chipid_top != 0x5300)
|
||||
+ return 0;
|
||||
+
|
||||
+/* TODO: add when sprom is available
|
||||
+ * if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI)
|
||||
+ * return 0;
|
||||
+ */
|
||||
+
|
||||
+ return !mips_busprobe32(tmp, (bus->mmio + (pc->core->core_index *
|
||||
+ BCMA_CORE_SIZE)));
|
||||
+}
|
||||
--- a/include/linux/bcma/bcma_driver_pci.h
|
||||
+++ b/include/linux/bcma/bcma_driver_pci.h
|
||||
@@ -78,6 +78,7 @@ struct pci_dev;
|
||||
struct bcma_drv_pci {
|
||||
struct bcma_device *core;
|
||||
u8 setup_done:1;
|
||||
+ u8 hostmode:1;
|
||||
};
|
||||
|
||||
/* Register access */
|
|
@ -1,7 +1,7 @@
|
|||
From 82d03f33ba3e41511e56bd6ae5ae93b3b1bd0b63 Mon Sep 17 00:00:00 2001
|
||||
From 1f25ff1b0bb5a8deae3aba2ea9c58f9b83f367bb Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Wed, 22 Jun 2011 22:16:35 +0200
|
||||
Subject: [PATCH 11/14] bcm47xx: make it possible to build bcm47xx without ssb.
|
||||
Subject: [PATCH 09/22] bcm47xx: make it possible to build bcm47xx without ssb.
|
||||
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
|
@ -63,9 +63,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+ select SSB_PCICORE_HOSTMODE if PCI
|
||||
+ default y
|
||||
+ help
|
||||
+ Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support bus.
|
||||
+ Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support.
|
||||
+
|
||||
+ This will generate an image with support for SSB and MIPS32 R2 instruction set.
|
||||
+ This will generate an image with support for SSB and MIPS32 R1 instruction set.
|
||||
+
|
||||
+endif
|
||||
--- a/arch/mips/bcm47xx/Makefile
|
|
@ -1,37 +0,0 @@
|
|||
From 5972feafaa3c71c1497b4ef4101b3c6855b7b64e Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sun, 19 Jun 2011 19:14:11 +0200
|
||||
Subject: [PATCH 09/14] bcma: add check if sprom is available before accessing it.
|
||||
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/main.c | 4 +++-
|
||||
drivers/bcma/sprom.c | 3 +++
|
||||
2 files changed, 6 insertions(+), 1 deletions(-)
|
||||
|
||||
--- a/drivers/bcma/main.c
|
||||
+++ b/drivers/bcma/main.c
|
||||
@@ -160,7 +160,9 @@ int bcma_bus_register(struct bcma_bus *b
|
||||
|
||||
/* Try to get SPROM */
|
||||
err = bcma_sprom_get(bus);
|
||||
- if (err) {
|
||||
+ if (err == -ENOENT) {
|
||||
+ pr_err("No SPROM available\n");
|
||||
+ } else if (err) {
|
||||
pr_err("Failed to get SPROM: %d\n", err);
|
||||
return -ENOENT;
|
||||
}
|
||||
--- a/drivers/bcma/sprom.c
|
||||
+++ b/drivers/bcma/sprom.c
|
||||
@@ -143,6 +143,9 @@ int bcma_sprom_get(struct bcma_bus *bus)
|
||||
if (!bus->drv_cc.core)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
+ if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
|
||||
+ return -ENOENT;
|
||||
+
|
||||
sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
|
||||
GFP_KERNEL);
|
||||
if (!sprom)
|
|
@ -1,7 +1,7 @@
|
|||
From 0b7b4817579b5b283e48b96de24b7b2c1a861644 Mon Sep 17 00:00:00 2001
|
||||
From 27aa4f76cfe54b6ce3bf98f4d5fd70ab1f60071f Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Mon, 6 Jun 2011 00:07:37 +0200
|
||||
Subject: [PATCH 12/14] bcm47xx: add support for bcma bus
|
||||
Subject: [PATCH 10/22] bcm47xx: add support for bcma bus
|
||||
|
||||
This patch add support for the bcma bus. Broadcom uses only Mips 74K
|
||||
CPUs on the new SoC and on the old ons using ssb bus there are no Mips
|
||||
|
@ -24,10 +24,10 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+++ b/arch/mips/bcm47xx/Kconfig
|
||||
@@ -15,4 +15,17 @@ config BCM47XX_SSB
|
||||
|
||||
This will generate an image with support for SSB and MIPS32 R2 instruction set.
|
||||
This will generate an image with support for SSB and MIPS32 R1 instruction set.
|
||||
|
||||
+config BCM47XX_BCMA
|
||||
+ bool "SSB Support for Broadcom BCM47XX"
|
||||
+ bool "BCMA Support for Broadcom BCM47XX"
|
||||
+ select SYS_HAS_CPU_MIPS32_R2
|
||||
+ select BCMA
|
||||
+ select BCMA_HOST_SOC
|
||||
|
@ -48,7 +48,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
#endif
|
||||
+#ifdef CONFIG_BCM47XX_BCMA
|
||||
+ case BCM47XX_BUS_TYPE_BCMA:
|
||||
+ if ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES)
|
||||
+ if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (test_and_set_bit(gpio, gpio_in_use))
|
||||
|
@ -65,7 +65,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
#endif
|
||||
+#ifdef CONFIG_BCM47XX_BCMA
|
||||
+ case BCM47XX_BUS_TYPE_BCMA:
|
||||
+ if ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES)
|
||||
+ if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
|
||||
+ return;
|
||||
+
|
||||
+ clear_bit(gpio, gpio_in_use);
|
||||
|
@ -92,7 +92,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
struct ssb_mipscore *mcore_ssb;
|
||||
#endif
|
||||
+#ifdef CONFIG_BCM47XX_BCMA
|
||||
+ struct bcma_drv_mips *mcore_bcma;
|
||||
+ struct bcma_drv_cc *bcma_cc;
|
||||
+#endif
|
||||
struct nvram_header *header;
|
||||
int i;
|
||||
|
@ -103,9 +103,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
#endif
|
||||
+#ifdef CONFIG_BCM47XX_BCMA
|
||||
+ case BCM47XX_BUS_TYPE_BCMA:
|
||||
+ mcore_bcma = &bcm47xx_bus.bcma.bus.drv_mips;
|
||||
+ base = mcore_bcma->flash_window;
|
||||
+ lim = mcore_bcma->flash_window_size;
|
||||
+ bcma_cc = &bcm47xx_bus.bcma.bus.drv_cc;
|
||||
+ base = bcma_cc->pflash.window;
|
||||
+ lim = bcma_cc->pflash.window_size;
|
||||
+ break;
|
||||
+#endif
|
||||
}
|
||||
|
@ -121,14 +121,14 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
+static int __init uart8250_init_bcma(void)
|
||||
+{
|
||||
+ int i;
|
||||
+ struct bcma_drv_mips *mcore = &(bcm47xx_bus.bcma.bus.drv_mips);
|
||||
+ struct bcma_drv_cc *cc = &(bcm47xx_bus.bcma.bus.drv_cc);
|
||||
+
|
||||
+ memset(&uart8250_data, 0, sizeof(uart8250_data));
|
||||
+
|
||||
+ for (i = 0; i < mcore->nr_serial_ports; i++) {
|
||||
+ for (i = 0; i < cc->nr_serial_ports; i++) {
|
||||
+ struct plat_serial8250_port *p = &(uart8250_data[i]);
|
||||
+ struct bcma_drv_mips_serial_port *bcma_port;
|
||||
+ bcma_port = &(mcore->serial_ports[i]);
|
||||
+ struct bcma_serial_port *bcma_port;
|
||||
+ bcma_port = &(cc->serial_ports[i]);
|
||||
+
|
||||
+ p->mapbase = (unsigned int) bcma_port->regs;
|
||||
+ p->membase = (void *) bcma_port->regs;
|
|
@ -1,7 +1,7 @@
|
|||
From 360eb82fd303ac24590a1b99ad1866162f6b0171 Mon Sep 17 00:00:00 2001
|
||||
From a277b0b02837a167a5766c048dedef8dfc2fb707 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Mon, 6 Jun 2011 00:07:38 +0200
|
||||
Subject: [PATCH 13/14] bcm47xx: fix irq assignment for new SoCs.
|
||||
Subject: [PATCH 11/22] bcm47xx: fix irq assignment for new SoCs.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
|
@ -0,0 +1,166 @@
|
|||
From a1d9c96a6c9b37b26dc1149706f3061b57a62b50 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sun, 17 Jul 2011 14:51:47 +0200
|
||||
Subject: [PATCH 12/22] bcma: move parallel flash into a union
|
||||
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
arch/mips/bcm47xx/nvram.c | 7 ++-
|
||||
drivers/bcma/driver_mips.c | 9 ++--
|
||||
include/linux/bcma/bcma_driver_chipcommon.h | 75 ++++++++++++++++++++++++++-
|
||||
3 files changed, 84 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/arch/mips/bcm47xx/nvram.c
|
||||
+++ b/arch/mips/bcm47xx/nvram.c
|
||||
@@ -50,8 +50,11 @@ static void early_nvram_init(void)
|
||||
#ifdef CONFIG_BCM47XX_BCMA
|
||||
case BCM47XX_BUS_TYPE_BCMA:
|
||||
bcma_cc = &bcm47xx_bus.bcma.bus.drv_cc;
|
||||
- base = bcma_cc->pflash.window;
|
||||
- lim = bcma_cc->pflash.window_size;
|
||||
+ if (bcma_cc->flash_type != BCMA_PFLASH)
|
||||
+ return;
|
||||
+
|
||||
+ base = bcma_cc->flash.pflash.window;
|
||||
+ lim = bcma_cc->flash.pflash.window_size;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
--- a/drivers/bcma/driver_mips.c
|
||||
+++ b/drivers/bcma/driver_mips.c
|
||||
@@ -189,14 +189,15 @@ static void bcma_core_mips_flash_detect(
|
||||
break;
|
||||
case BCMA_CC_FLASHT_PARA:
|
||||
pr_info("found parallel flash.\n");
|
||||
- bus->drv_cc.pflash.window = 0x1c000000;
|
||||
- bus->drv_cc.pflash.window_size = 0x02000000;
|
||||
+ bus->drv_cc.flash_type = BCMA_PFLASH;
|
||||
+ bus->drv_cc.flash.pflash.window = 0x1c000000;
|
||||
+ bus->drv_cc.flash.pflash.window_size = 0x02000000;
|
||||
|
||||
if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) &
|
||||
BCMA_CC_FLASH_CFG_DS) == 0)
|
||||
- bus->drv_cc.pflash.buswidth = 1;
|
||||
+ bus->drv_cc.flash.pflash.buswidth = 1;
|
||||
else
|
||||
- bus->drv_cc.pflash.buswidth = 2;
|
||||
+ bus->drv_cc.flash.pflash.buswidth = 2;
|
||||
break;
|
||||
default:
|
||||
pr_err("flash not supported.\n");
|
||||
--- a/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
@@ -108,10 +108,68 @@
|
||||
#define BCMA_CC_JCTL_EXT_EN 2 /* Enable external targets */
|
||||
#define BCMA_CC_JCTL_EN 1 /* Enable Jtag master */
|
||||
#define BCMA_CC_FLASHCTL 0x0040
|
||||
+
|
||||
+/* Start/busy bit in flashcontrol */
|
||||
+#define BCMA_CC_FLASHCTL_OPCODE 0x000000ff
|
||||
+#define BCMA_CC_FLASHCTL_ACTION 0x00000700
|
||||
+#define BCMA_CC_FLASHCTL_CS_ACTIVE 0x00001000 /* Chip Select Active, rev >= 20 */
|
||||
#define BCMA_CC_FLASHCTL_START 0x80000000
|
||||
#define BCMA_CC_FLASHCTL_BUSY BCMA_CC_FLASHCTL_START
|
||||
+
|
||||
+/* flashcontrol action+opcodes for ST flashes */
|
||||
+#define BCMA_CC_FLASHCTL_ST_WREN 0x0006 /* Write Enable */
|
||||
+#define BCMA_CC_FLASHCTL_ST_WRDIS 0x0004 /* Write Disable */
|
||||
+#define BCMA_CC_FLASHCTL_ST_RDSR 0x0105 /* Read Status Register */
|
||||
+#define BCMA_CC_FLASHCTL_ST_WRSR 0x0101 /* Write Status Register */
|
||||
+#define BCMA_CC_FLASHCTL_ST_READ 0x0303 /* Read Data Bytes */
|
||||
+#define BCMA_CC_FLASHCTL_ST_PP 0x0302 /* Page Program */
|
||||
+#define BCMA_CC_FLASHCTL_ST_SE 0x02d8 /* Sector Erase */
|
||||
+#define BCMA_CC_FLASHCTL_ST_BE 0x00c7 /* Bulk Erase */
|
||||
+#define BCMA_CC_FLASHCTL_ST_DP 0x00b9 /* Deep Power-down */
|
||||
+#define BCMA_CC_FLASHCTL_ST_RES 0x03ab /* Read Electronic Signature */
|
||||
+#define BCMA_CC_FLASHCTL_ST_CSA 0x1000 /* Keep chip select asserted */
|
||||
+#define BCMA_CC_FLASHCTL_ST_SSE 0x0220 /* Sub-sector Erase */
|
||||
+
|
||||
+
|
||||
+/* flashcontrol action+opcodes for Atmel flashes */
|
||||
+#define BCMA_CC_FLASHCTL_AT_READ 0x07e8
|
||||
+#define BCMA_CC_FLASHCTL_AT_PAGE_READ 0x07d2
|
||||
+#define BCMA_CC_FLASHCTL_AT_BUF1_READ
|
||||
+#define BCMA_CC_FLASHCTL_AT_BUF2_READ
|
||||
+#define BCMA_CC_FLASHCTL_AT_STATUS 0x01d7
|
||||
+#define BCMA_CC_FLASHCTL_AT_BUF1_WRITE 0x0384
|
||||
+#define BCMA_CC_FLASHCTL_AT_BUF2_WRITE 0x0387
|
||||
+#define BCMA_CC_FLASHCTL_AT_BUF1_ERASE_PROGRAM 0x0283
|
||||
+#define BCMA_CC_FLASHCTL_AT_BUF2_ERASE_PROGRAM 0x0286
|
||||
+#define BCMA_CC_FLASHCTL_AT_BUF1_PROGRAM 0x0288
|
||||
+#define BCMA_CC_FLASHCTL_AT_BUF2_PROGRAM 0x0289
|
||||
+#define BCMA_CC_FLASHCTL_AT_PAGE_ERASE 0x0281
|
||||
+#define BCMA_CC_FLASHCTL_AT_BLOCK_ERASE 0x0250
|
||||
+#define BCMA_CC_FLASHCTL_AT_BUF1_WRITE_ERASE_PROGRAM 0x0382
|
||||
+#define BCMA_CC_FLASHCTL_AT_BUF2_WRITE_ERASE_PROGRAM 0x0385
|
||||
+#define BCMA_CC_FLASHCTL_AT_BUF1_LOAD 0x0253
|
||||
+#define BCMA_CC_FLASHCTL_AT_BUF2_LOAD 0x0255
|
||||
+#define BCMA_CC_FLASHCTL_AT_BUF1_COMPARE 0x0260
|
||||
+#define BCMA_CC_FLASHCTL_AT_BUF2_COMPARE 0x0261
|
||||
+#define BCMA_CC_FLASHCTL_AT_BUF1_REPROGRAM 0x0258
|
||||
+#define BCMA_CC_FLASHCTL_AT_BUF2_REPROGRAM 0x0259
|
||||
+
|
||||
#define BCMA_CC_FLASHADDR 0x0044
|
||||
#define BCMA_CC_FLASHDATA 0x0048
|
||||
+
|
||||
+/* Status register bits for ST flashes */
|
||||
+#define BCMA_CC_FLASHDATA_ST_WIP 0x01 /* Write In Progress */
|
||||
+#define BCMA_CC_FLASHDATA_ST_WEL 0x02 /* Write Enable Latch */
|
||||
+#define BCMA_CC_FLASHDATA_ST_BP_MASK 0x1c /* Block Protect */
|
||||
+#define BCMA_CC_FLASHDATA_ST_BP_SHIFT 2
|
||||
+#define BCMA_CC_FLASHDATA_ST_SRWD 0x80 /* Status Register Write Disable */
|
||||
+
|
||||
+/* Status register bits for Atmel flashes */
|
||||
+#define BCMA_CC_FLASHDATA_AT_READY 0x80
|
||||
+#define BCMA_CC_FLASHDATA_AT_MISMATCH 0x40
|
||||
+#define BCMA_CC_FLASHDATA_AT_ID_MASK 0x38
|
||||
+#define BCMA_CC_FLASHDATA_AT_ID_SHIFT 3
|
||||
+
|
||||
#define BCMA_CC_BCAST_ADDR 0x0050
|
||||
#define BCMA_CC_BCAST_DATA 0x0054
|
||||
#define BCMA_CC_GPIOPULLUP 0x0058 /* Rev >= 20 only */
|
||||
@@ -283,6 +341,12 @@
|
||||
#define BCMA_CC_PPL_PCHI_OFF 5
|
||||
#define BCMA_CC_PPL_PCHI_MASK 0x0000003f
|
||||
|
||||
+#define BCMA_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */
|
||||
+#define BCMA_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */
|
||||
+#define BCMA_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */
|
||||
+#define BCMA_FLASH1_SZ 0x00400000 /* MIPS Size of Flash Region 1 */
|
||||
+
|
||||
+
|
||||
/* Data for the PMU, if available.
|
||||
* Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
|
||||
*/
|
||||
@@ -292,12 +356,20 @@ struct bcma_chipcommon_pmu {
|
||||
};
|
||||
|
||||
#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
+enum bcma_flash_type {
|
||||
+ BCMA_PFLASH,
|
||||
+};
|
||||
+
|
||||
struct bcma_pflash {
|
||||
u8 buswidth;
|
||||
u32 window;
|
||||
u32 window_size;
|
||||
};
|
||||
|
||||
+union bcma_flash {
|
||||
+ struct bcma_pflash pflash;
|
||||
+};
|
||||
+
|
||||
struct bcma_serial_port {
|
||||
void *regs;
|
||||
unsigned long clockspeed;
|
||||
@@ -317,7 +389,8 @@ struct bcma_drv_cc {
|
||||
u16 fast_pwrup_delay;
|
||||
struct bcma_chipcommon_pmu pmu;
|
||||
#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
- struct bcma_pflash pflash;
|
||||
+ enum bcma_flash_type flash_type;
|
||||
+ union bcma_flash flash;
|
||||
|
||||
int nr_serial_ports;
|
||||
struct bcma_serial_port serial_ports[4];
|
|
@ -0,0 +1,675 @@
|
|||
From b5be6e3037650ff5615cb869f1972dea5a49bcb6 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sun, 17 Jul 2011 14:53:07 +0200
|
||||
Subject: [PATCH 13/22] bcma: add serial flash support to bcma
|
||||
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/Kconfig | 5 +
|
||||
drivers/bcma/Makefile | 1 +
|
||||
drivers/bcma/bcma_private.h | 5 +
|
||||
drivers/bcma/driver_chipcommon_sflash.c | 554 +++++++++++++++++++++++++++
|
||||
drivers/bcma/driver_mips.c | 8 +-
|
||||
include/linux/bcma/bcma_driver_chipcommon.h | 24 ++
|
||||
6 files changed, 596 insertions(+), 1 deletions(-)
|
||||
create mode 100644 drivers/bcma/driver_chipcommon_sflash.c
|
||||
|
||||
--- a/drivers/bcma/Kconfig
|
||||
+++ b/drivers/bcma/Kconfig
|
||||
@@ -38,6 +38,11 @@ config BCMA_HOST_SOC
|
||||
bool
|
||||
depends on BCMA_DRIVER_MIPS
|
||||
|
||||
+config BCMA_SFLASH
|
||||
+ bool
|
||||
+ depends on BCMA_DRIVER_MIPS
|
||||
+ default y
|
||||
+
|
||||
config BCMA_DRIVER_MIPS
|
||||
bool "BCMA Broadcom MIPS core driver"
|
||||
depends on BCMA && MIPS
|
||||
--- a/drivers/bcma/Makefile
|
||||
+++ b/drivers/bcma/Makefile
|
||||
@@ -1,5 +1,6 @@
|
||||
bcma-y += main.o scan.o core.o sprom.o
|
||||
bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
|
||||
+bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o
|
||||
bcma-y += driver_pci.o
|
||||
bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
|
||||
bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o
|
||||
--- a/drivers/bcma/bcma_private.h
|
||||
+++ b/drivers/bcma/bcma_private.h
|
||||
@@ -38,6 +38,11 @@ void bcma_chipco_serial_init(struct bcma
|
||||
u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc);
|
||||
u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
|
||||
|
||||
+#ifdef CONFIG_BCMA_SFLASH
|
||||
+/* driver_chipcommon_sflash.c */
|
||||
+int bcma_sflash_init(struct bcma_drv_cc *cc);
|
||||
+#endif /* CONFIG_BCMA_SFLASH */
|
||||
+
|
||||
#ifdef CONFIG_BCMA_HOST_PCI
|
||||
/* host_pci.c */
|
||||
extern int __init bcma_host_pci_init(void);
|
||||
--- /dev/null
|
||||
+++ b/drivers/bcma/driver_chipcommon_sflash.c
|
||||
@@ -0,0 +1,554 @@
|
||||
+/*
|
||||
+ * Broadcom SiliconBackplane chipcommon serial flash interface
|
||||
+ *
|
||||
+ * Copyright 2011, Jonas Gorski <jonas.gorski@gmail.com>
|
||||
+ * Copyright 2010, Broadcom Corporation
|
||||
+ *
|
||||
+ * Licensed under the GNU/GPL. See COPYING for details.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/bcma/bcma.h>
|
||||
+#include <linux/bcma/bcma_driver_chipcommon.h>
|
||||
+#include <linux/delay.h>
|
||||
+
|
||||
+#include "bcma_private.h"
|
||||
+
|
||||
+#define NUM_RETRIES 3
|
||||
+
|
||||
+
|
||||
+/* Issue a serial flash command */
|
||||
+static inline void bcma_sflash_cmd(struct bcma_drv_cc *cc, u32 opcode)
|
||||
+{
|
||||
+ bcma_cc_write32(cc, BCMA_CC_FLASHCTL,
|
||||
+ BCMA_CC_FLASHCTL_START | opcode);
|
||||
+ while (bcma_cc_read32(cc, BCMA_CC_FLASHCTL)
|
||||
+ & BCMA_CC_FLASHCTL_BUSY);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static inline void bcma_sflash_write_u8(struct bcma_drv_cc *cc,
|
||||
+ u32 offset, u8 byte)
|
||||
+{
|
||||
+ bcma_cc_write32(cc, BCMA_CC_FLASHADDR, offset);
|
||||
+ bcma_cc_write32(cc, BCMA_CC_FLASHDATA, byte);
|
||||
+}
|
||||
+
|
||||
+/* Initialize serial flash access */
|
||||
+int bcma_sflash_init(struct bcma_drv_cc *cc)
|
||||
+{
|
||||
+ u32 id, id2;
|
||||
+
|
||||
+ memset(&cc->flash.sflash, 0, sizeof(struct bcma_sflash));
|
||||
+
|
||||
+ switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
|
||||
+ case BCMA_CC_FLASHT_STSER:
|
||||
+ /* Probe for ST chips */
|
||||
+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_DP);
|
||||
+ bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 0);
|
||||
+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES);
|
||||
+ id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA);
|
||||
+ cc->flash.sflash.blocksize = 64 * 1024;
|
||||
+ switch (id) {
|
||||
+ case 0x11:
|
||||
+ /* ST M25P20 2 Mbit Serial Flash */
|
||||
+ cc->flash.sflash.numblocks = 4;
|
||||
+ break;
|
||||
+ case 0x12:
|
||||
+ /* ST M25P40 4 Mbit Serial Flash */
|
||||
+ cc->flash.sflash.numblocks = 8;
|
||||
+ break;
|
||||
+ case 0x13:
|
||||
+ /* ST M25P80 8 Mbit Serial Flash */
|
||||
+ cc->flash.sflash.numblocks = 16;
|
||||
+ break;
|
||||
+ case 0x14:
|
||||
+ /* ST M25P16 16 Mbit Serial Flash */
|
||||
+ cc->flash.sflash.numblocks = 32;
|
||||
+ break;
|
||||
+ case 0x15:
|
||||
+ /* ST M25P32 32 Mbit Serial Flash */
|
||||
+ cc->flash.sflash.numblocks = 64;
|
||||
+ break;
|
||||
+ case 0x16:
|
||||
+ /* ST M25P64 64 Mbit Serial Flash */
|
||||
+ cc->flash.sflash.numblocks = 128;
|
||||
+ break;
|
||||
+ case 0x17:
|
||||
+ /* ST M25FL128 128 Mbit Serial Flash */
|
||||
+ cc->flash.sflash.numblocks = 256;
|
||||
+ break;
|
||||
+ case 0xbf:
|
||||
+ /* All of the following flashes are SST with
|
||||
+ * 4KB subsectors. Others should be added but
|
||||
+ * We'll have to revamp the way we identify them
|
||||
+ * since RES is not eough to disambiguate them.
|
||||
+ */
|
||||
+ cc->flash.sflash.blocksize = 4 * 1024;
|
||||
+ bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 1);
|
||||
+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES);
|
||||
+ id2 = bcma_cc_read32(cc, BCMA_CC_FLASHDATA);
|
||||
+ switch (id2) {
|
||||
+ case 1:
|
||||
+ /* SST25WF512 512 Kbit Serial Flash */
|
||||
+ case 0x48:
|
||||
+ /* SST25VF512 512 Kbit Serial Flash */
|
||||
+ cc->flash.sflash.numblocks = 16;
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ /* SST25WF010 1 Mbit Serial Flash */
|
||||
+ case 0x49:
|
||||
+ /* SST25VF010 1 Mbit Serial Flash */
|
||||
+ cc->flash.sflash.numblocks = 32;
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ /* SST25WF020 2 Mbit Serial Flash */
|
||||
+ case 0x43:
|
||||
+ /* SST25VF020 2 Mbit Serial Flash */
|
||||
+ cc->flash.sflash.numblocks = 64;
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ /* SST25WF040 4 Mbit Serial Flash */
|
||||
+ case 0x44:
|
||||
+ /* SST25VF040 4 Mbit Serial Flash */
|
||||
+ case 0x8d:
|
||||
+ /* SST25VF040B 4 Mbit Serial Flash */
|
||||
+ cc->flash.sflash.numblocks = 128;
|
||||
+ break;
|
||||
+ case 5:
|
||||
+ /* SST25WF080 8 Mbit Serial Flash */
|
||||
+ case 0x8e:
|
||||
+ /* SST25VF080B 8 Mbit Serial Flash */
|
||||
+ cc->flash.sflash.numblocks = 256;
|
||||
+ break;
|
||||
+ case 0x41:
|
||||
+ /* SST25VF016 16 Mbit Serial Flash */
|
||||
+ cc->flash.sflash.numblocks = 512;
|
||||
+ break;
|
||||
+ case 0x4a:
|
||||
+ /* SST25VF032 32 Mbit Serial Flash */
|
||||
+ cc->flash.sflash.numblocks = 1024;
|
||||
+ break;
|
||||
+ case 0x4b:
|
||||
+ /* SST25VF064 64 Mbit Serial Flash */
|
||||
+ cc->flash.sflash.numblocks = 2048;
|
||||
+ break;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case BCMA_CC_FLASHT_ATSER:
|
||||
+ /* Probe for Atmel chips */
|
||||
+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_STATUS);
|
||||
+ id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA) & 0x3c;
|
||||
+ switch (id) {
|
||||
+ case 0xc:
|
||||
+ /* Atmel AT45DB011 1Mbit Serial Flash */
|
||||
+ cc->flash.sflash.blocksize = 256;
|
||||
+ cc->flash.sflash.numblocks = 512;
|
||||
+ break;
|
||||
+ case 0x14:
|
||||
+ /* Atmel AT45DB021 2Mbit Serial Flash */
|
||||
+ cc->flash.sflash.blocksize = 256;
|
||||
+ cc->flash.sflash.numblocks = 1024;
|
||||
+ break;
|
||||
+ case 0x1c:
|
||||
+ /* Atmel AT45DB041 4Mbit Serial Flash */
|
||||
+ cc->flash.sflash.blocksize = 256;
|
||||
+ cc->flash.sflash.numblocks = 2048;
|
||||
+ break;
|
||||
+ case 0x24:
|
||||
+ /* Atmel AT45DB081 8Mbit Serial Flash */
|
||||
+ cc->flash.sflash.blocksize = 256;
|
||||
+ cc->flash.sflash.numblocks = 4096;
|
||||
+ break;
|
||||
+ case 0x2c:
|
||||
+ /* Atmel AT45DB161 16Mbit Serial Flash */
|
||||
+ cc->flash.sflash.blocksize = 512;
|
||||
+ cc->flash.sflash.numblocks = 4096;
|
||||
+ break;
|
||||
+ case 0x34:
|
||||
+ /* Atmel AT45DB321 32Mbit Serial Flash */
|
||||
+ cc->flash.sflash.blocksize = 512;
|
||||
+ cc->flash.sflash.numblocks = 8192;
|
||||
+ break;
|
||||
+ case 0x3c:
|
||||
+ /* Atmel AT45DB642 64Mbit Serial Flash */
|
||||
+ cc->flash.sflash.blocksize = 1024;
|
||||
+ cc->flash.sflash.numblocks = 8192;
|
||||
+ break;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ cc->flash.sflash.size = cc->flash.sflash.blocksize * cc->flash.sflash.numblocks;
|
||||
+
|
||||
+ return cc->flash.sflash.size ? 0 : -ENODEV;
|
||||
+}
|
||||
+
|
||||
+/* Read len bytes starting at offset into buf. Returns number of bytes read. */
|
||||
+int bcma_sflash_read(struct bcma_drv_cc *cc, u32 offset, u32 len,
|
||||
+ u8 *buf)
|
||||
+{
|
||||
+ u8 *from, *to;
|
||||
+ u32 cnt, i;
|
||||
+
|
||||
+ if (!len)
|
||||
+ return 0;
|
||||
+
|
||||
+ if ((offset + len) > cc->flash.sflash.size)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if ((len >= 4) && (offset & 3))
|
||||
+ cnt = 4 - (offset & 3);
|
||||
+ else if ((len >= 4) && ((u32)buf & 3))
|
||||
+ cnt = 4 - ((u32)buf & 3);
|
||||
+ else
|
||||
+ cnt = len;
|
||||
+
|
||||
+
|
||||
+ if (cc->core->id.rev == 12)
|
||||
+ from = (u8 *)KSEG1ADDR(BCMA_FLASH2 + offset);
|
||||
+ else
|
||||
+ from = (u8 *)KSEG0ADDR(BCMA_FLASH2 + offset);
|
||||
+
|
||||
+ to = (u8 *)buf;
|
||||
+
|
||||
+ if (cnt < 4) {
|
||||
+ for (i = 0; i < cnt; i++) {
|
||||
+ *to = readb(from);
|
||||
+ from++;
|
||||
+ to++;
|
||||
+ }
|
||||
+ return cnt;
|
||||
+ }
|
||||
+
|
||||
+ while (cnt >= 4) {
|
||||
+ *(u32 *)to = readl(from);
|
||||
+ from += 4;
|
||||
+ to += 4;
|
||||
+ cnt -= 4;
|
||||
+ }
|
||||
+
|
||||
+ return len - cnt;
|
||||
+}
|
||||
+
|
||||
+/* Poll for command completion. Returns zero when complete. */
|
||||
+int bcma_sflash_poll(struct bcma_drv_cc *cc, u32 offset)
|
||||
+{
|
||||
+ if (offset >= cc->flash.sflash.size)
|
||||
+ return -22;
|
||||
+
|
||||
+ switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
|
||||
+ case BCMA_CC_FLASHT_STSER:
|
||||
+ /* Check for ST Write In Progress bit */
|
||||
+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RDSR);
|
||||
+ return bcma_cc_read32(cc, BCMA_CC_FLASHDATA)
|
||||
+ & BCMA_CC_FLASHDATA_ST_WIP;
|
||||
+ case BCMA_CC_FLASHT_ATSER:
|
||||
+ /* Check for Atmel Ready bit */
|
||||
+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_STATUS);
|
||||
+ return !(bcma_cc_read32(cc, BCMA_CC_FLASHDATA)
|
||||
+ & BCMA_CC_FLASHDATA_AT_READY);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int sflash_st_write(struct bcma_drv_cc *cc, u32 offset, u32 len,
|
||||
+ const u8 *buf)
|
||||
+{
|
||||
+ struct bcma_bus *bus = cc->core->bus;
|
||||
+ int ret = 0;
|
||||
+ bool is4712b0 = (bus->chipinfo.id == 0x4712) && (bus->chipinfo.rev == 3);
|
||||
+ u32 mask;
|
||||
+
|
||||
+
|
||||
+ /* Enable writes */
|
||||
+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_WREN);
|
||||
+ if (is4712b0) {
|
||||
+ mask = 1 << 14;
|
||||
+ bcma_sflash_write_u8(cc, offset, *buf++);
|
||||
+ /* Set chip select */
|
||||
+ bcma_cc_set32(cc, BCMA_CC_GPIOOUT, mask);
|
||||
+ /* Issue a page program with the first byte */
|
||||
+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_PP);
|
||||
+ ret = 1;
|
||||
+ offset++;
|
||||
+ len--;
|
||||
+ while (len > 0) {
|
||||
+ if ((offset & 255) == 0) {
|
||||
+ /* Page boundary, drop cs and return */
|
||||
+ bcma_cc_mask32(cc, BCMA_CC_GPIOOUT, ~mask);
|
||||
+ udelay(1);
|
||||
+ if (!bcma_sflash_poll(cc, offset)) {
|
||||
+ /* Flash rejected command */
|
||||
+ return -EAGAIN;
|
||||
+ }
|
||||
+ return ret;
|
||||
+ } else {
|
||||
+ /* Write single byte */
|
||||
+ bcma_sflash_cmd(cc, *buf++);
|
||||
+ }
|
||||
+ ret++;
|
||||
+ offset++;
|
||||
+ len--;
|
||||
+ }
|
||||
+ /* All done, drop cs */
|
||||
+ bcma_cc_mask32(cc, BCMA_CC_GPIOOUT, ~mask);
|
||||
+ udelay(1);
|
||||
+ if (!bcma_sflash_poll(cc, offset)) {
|
||||
+ /* Flash rejected command */
|
||||
+ return -EAGAIN;
|
||||
+ }
|
||||
+ } else if (cc->core->id.rev >= 20) {
|
||||
+ bcma_sflash_write_u8(cc, offset, *buf++);
|
||||
+ /* Issue a page program with CSA bit set */
|
||||
+ bcma_sflash_cmd(cc,
|
||||
+ BCMA_CC_FLASHCTL_ST_CSA |
|
||||
+ BCMA_CC_FLASHCTL_ST_PP);
|
||||
+ ret = 1;
|
||||
+ offset++;
|
||||
+ len--;
|
||||
+ while (len > 0) {
|
||||
+ if ((offset & 255) == 0) {
|
||||
+ /* Page boundary, poll droping cs and return */
|
||||
+ bcma_cc_write32(cc, BCMA_CC_FLASHCTL, 0);
|
||||
+ udelay(1);
|
||||
+ if (!bcma_sflash_poll(cc, offset)) {
|
||||
+ /* Flash rejected command */
|
||||
+ return -EAGAIN;
|
||||
+ }
|
||||
+ return ret;
|
||||
+ } else {
|
||||
+ /* Write single byte */
|
||||
+ bcma_sflash_cmd(cc,
|
||||
+ BCMA_CC_FLASHCTL_ST_CSA |
|
||||
+ *buf++);
|
||||
+ }
|
||||
+ ret++;
|
||||
+ offset++;
|
||||
+ len--;
|
||||
+ }
|
||||
+ /* All done, drop cs & poll */
|
||||
+ bcma_cc_write32(cc, BCMA_CC_FLASHCTL, 0);
|
||||
+ udelay(1);
|
||||
+ if (!bcma_sflash_poll(cc, offset)) {
|
||||
+ /* Flash rejected command */
|
||||
+ return -EAGAIN;
|
||||
+ }
|
||||
+ } else {
|
||||
+ ret = 1;
|
||||
+ bcma_sflash_write_u8(cc, offset, *buf);
|
||||
+ /* Page program */
|
||||
+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_PP);
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int sflash_at_write(struct bcma_drv_cc *cc, u32 offset, u32 len,
|
||||
+ const u8 *buf)
|
||||
+{
|
||||
+ struct bcma_sflash *sfl = &cc->flash.sflash;
|
||||
+ u32 page, byte, mask;
|
||||
+ int ret = 0;
|
||||
+ mask = sfl->blocksize - 1;
|
||||
+ page = (offset & ~mask) << 1;
|
||||
+ byte = offset & mask;
|
||||
+ /* Read main memory page into buffer 1 */
|
||||
+ if (byte || (len < sfl->blocksize)) {
|
||||
+ int i = 100;
|
||||
+ bcma_cc_write32(cc, BCMA_CC_FLASHADDR, page);
|
||||
+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_BUF1_LOAD);
|
||||
+ /* 250 us for AT45DB321B */
|
||||
+ while (i > 0 && bcma_sflash_poll(cc, offset)) {
|
||||
+ udelay(10);
|
||||
+ i--;
|
||||
+ }
|
||||
+ BUG_ON(!bcma_sflash_poll(cc, offset));
|
||||
+ }
|
||||
+ /* Write into buffer 1 */
|
||||
+ for (ret = 0; (ret < (int)len) && (byte < sfl->blocksize); ret++) {
|
||||
+ bcma_sflash_write_u8(cc, byte++, *buf++);
|
||||
+ bcma_sflash_cmd(cc,
|
||||
+ BCMA_CC_FLASHCTL_AT_BUF1_WRITE);
|
||||
+ }
|
||||
+ /* Write buffer 1 into main memory page */
|
||||
+ bcma_cc_write32(cc, BCMA_CC_FLASHADDR, page);
|
||||
+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_BUF1_PROGRAM);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/* Write len bytes starting at offset into buf. Returns number of bytes
|
||||
+ * written. Caller should poll for completion.
|
||||
+ */
|
||||
+int bcma_sflash_write(struct bcma_drv_cc *cc, u32 offset, u32 len,
|
||||
+ const u8 *buf)
|
||||
+{
|
||||
+ struct bcma_sflash *sfl;
|
||||
+ int ret = 0, tries = NUM_RETRIES;
|
||||
+
|
||||
+ if (!len)
|
||||
+ return 0;
|
||||
+
|
||||
+ if ((offset + len) > cc->flash.sflash.size)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ sfl = &cc->flash.sflash;
|
||||
+ switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
|
||||
+ case BCMA_CC_FLASHT_STSER:
|
||||
+ do {
|
||||
+ ret = sflash_st_write(cc, offset, len, buf);
|
||||
+ tries--;
|
||||
+ } while (ret == -EAGAIN && tries > 0);
|
||||
+
|
||||
+ if (ret == -EAGAIN && tries == 0) {
|
||||
+ pr_info("ST Flash rejected write\n");
|
||||
+ ret = -EIO;
|
||||
+ }
|
||||
+ break;
|
||||
+ case BCMA_CC_FLASHT_ATSER:
|
||||
+ ret = sflash_at_write(cc, offset, len, buf);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/* Erase a region. Returns number of bytes scheduled for erasure.
|
||||
+ * Caller should poll for completion.
|
||||
+ */
|
||||
+int bcma_sflash_erase(struct bcma_drv_cc *cc, u32 offset)
|
||||
+{
|
||||
+ struct bcma_sflash *sfl;
|
||||
+
|
||||
+ if (offset >= cc->flash.sflash.size)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ sfl = &cc->flash.sflash;
|
||||
+ switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
|
||||
+ case BCMA_CC_FLASHT_STSER:
|
||||
+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_WREN);
|
||||
+ bcma_cc_write32(cc, BCMA_CC_FLASHADDR, offset);
|
||||
+ /* Newer flashes have "sub-sectors" which can be erased independently
|
||||
+ * with a new command: ST_SSE. The ST_SE command erases 64KB just as
|
||||
+ * before.
|
||||
+ */
|
||||
+ bcma_sflash_cmd(cc, (sfl->blocksize < (64 * 1024)) ? BCMA_CC_FLASHCTL_ST_SSE : BCMA_CC_FLASHCTL_ST_SE);
|
||||
+ return sfl->blocksize;
|
||||
+ case BCMA_CC_FLASHT_ATSER:
|
||||
+ bcma_cc_write32(cc, BCMA_CC_FLASHADDR, offset << 1);
|
||||
+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_PAGE_ERASE);
|
||||
+ return sfl->blocksize;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * writes the appropriate range of flash, a NULL buf simply erases
|
||||
+ * the region of flash
|
||||
+ */
|
||||
+int bcma_sflash_commit(struct bcma_drv_cc *cc, u32 offset, u32 len,
|
||||
+ const u8 *buf)
|
||||
+{
|
||||
+ struct bcma_sflash *sfl;
|
||||
+ u8 *block = NULL, *cur_ptr, *blk_ptr;
|
||||
+ u32 blocksize = 0, mask, cur_offset, cur_length, cur_retlen, remainder;
|
||||
+ u32 blk_offset, blk_len, copied;
|
||||
+ int bytes, ret = 0;
|
||||
+
|
||||
+ /* Check address range */
|
||||
+ if (len <= 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ sfl = &cc->flash.sflash;
|
||||
+ if ((offset + len) > sfl->size)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ blocksize = sfl->blocksize;
|
||||
+ mask = blocksize - 1;
|
||||
+
|
||||
+ /* Allocate a block of mem */
|
||||
+ block = kmalloc(blocksize, GFP_KERNEL);
|
||||
+ if (!block)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ while (len) {
|
||||
+ /* Align offset */
|
||||
+ cur_offset = offset & ~mask;
|
||||
+ cur_length = blocksize;
|
||||
+ cur_ptr = block;
|
||||
+
|
||||
+ remainder = blocksize - (offset & mask);
|
||||
+ if (len < remainder)
|
||||
+ cur_retlen = len;
|
||||
+ else
|
||||
+ cur_retlen = remainder;
|
||||
+
|
||||
+ /* buf == NULL means erase only */
|
||||
+ if (buf) {
|
||||
+ /* Copy existing data into holding block if necessary */
|
||||
+ if ((offset & mask) || (len < blocksize)) {
|
||||
+ blk_offset = cur_offset;
|
||||
+ blk_len = cur_length;
|
||||
+ blk_ptr = cur_ptr;
|
||||
+
|
||||
+ /* Copy entire block */
|
||||
+ while (blk_len) {
|
||||
+ copied = bcma_sflash_read(cc,
|
||||
+ blk_offset,
|
||||
+ blk_len, blk_ptr);
|
||||
+ blk_offset += copied;
|
||||
+ blk_len -= copied;
|
||||
+ blk_ptr += copied;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Copy input data into holding block */
|
||||
+ memcpy(cur_ptr + (offset & mask), buf, cur_retlen);
|
||||
+ }
|
||||
+
|
||||
+ /* Erase block */
|
||||
+ ret = bcma_sflash_erase(cc, cur_offset);
|
||||
+ if (ret < 0)
|
||||
+ goto done;
|
||||
+
|
||||
+ while (bcma_sflash_poll(cc, cur_offset));
|
||||
+
|
||||
+ /* buf == NULL means erase only */
|
||||
+ if (!buf) {
|
||||
+ offset += cur_retlen;
|
||||
+ len -= cur_retlen;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* Write holding block */
|
||||
+ while (cur_length > 0) {
|
||||
+ bytes = bcma_sflash_write(cc, cur_offset,
|
||||
+ cur_length, cur_ptr);
|
||||
+
|
||||
+ if (bytes < 0) {
|
||||
+ ret = bytes;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ while (bcma_sflash_poll(cc, cur_offset));
|
||||
+
|
||||
+ cur_offset += bytes;
|
||||
+ cur_length -= bytes;
|
||||
+ cur_ptr += bytes;
|
||||
+ }
|
||||
+
|
||||
+ offset += cur_retlen;
|
||||
+ len -= cur_retlen;
|
||||
+ buf += cur_retlen;
|
||||
+ }
|
||||
+
|
||||
+ ret = len;
|
||||
+done:
|
||||
+ kfree(block);
|
||||
+ return ret;
|
||||
+}
|
||||
--- a/drivers/bcma/driver_mips.c
|
||||
+++ b/drivers/bcma/driver_mips.c
|
||||
@@ -185,7 +185,13 @@ static void bcma_core_mips_flash_detect(
|
||||
switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
|
||||
case BCMA_CC_FLASHT_STSER:
|
||||
case BCMA_CC_FLASHT_ATSER:
|
||||
- pr_err("Serial flash not supported.\n");
|
||||
+#ifdef CONFIG_BCMA_SFLASH
|
||||
+ pr_info("found serial flash.\n");
|
||||
+ bus->drv_cc.flash_type = BCMA_SFLASH;
|
||||
+ bcma_sflash_init(&bus->drv_cc);
|
||||
+#else
|
||||
+ pr_info("serial flash not supported.\n");
|
||||
+#endif /* CONFIG_BCMA_SFLASH */
|
||||
break;
|
||||
case BCMA_CC_FLASHT_PARA:
|
||||
pr_info("found parallel flash.\n");
|
||||
--- a/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
@@ -358,6 +358,7 @@ struct bcma_chipcommon_pmu {
|
||||
#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
enum bcma_flash_type {
|
||||
BCMA_PFLASH,
|
||||
+ BCMA_SFLASH,
|
||||
};
|
||||
|
||||
struct bcma_pflash {
|
||||
@@ -366,8 +367,19 @@ struct bcma_pflash {
|
||||
u32 window_size;
|
||||
};
|
||||
|
||||
+#ifdef CONFIG_BCMA_SFLASH
|
||||
+struct bcma_sflash {
|
||||
+ u32 blocksize; /* Block size */
|
||||
+ u32 numblocks; /* Number of blocks */
|
||||
+ u32 size; /* Total size in bytes */
|
||||
+};
|
||||
+#endif /* CONFIG_BCMA_SFLASH */
|
||||
+
|
||||
union bcma_flash {
|
||||
struct bcma_pflash pflash;
|
||||
+#ifdef CONFIG_BCMA_SFLASH
|
||||
+ struct bcma_sflash sflash;
|
||||
+#endif /* CONFIG_BCMA_SFLASH */
|
||||
};
|
||||
|
||||
struct bcma_serial_port {
|
||||
@@ -433,4 +445,16 @@ u32 bcma_chipco_gpio_polarity(struct bcm
|
||||
/* PMU support */
|
||||
extern void bcma_pmu_init(struct bcma_drv_cc *cc);
|
||||
|
||||
+#ifdef CONFIG_BCMA_SFLASH
|
||||
+/* Chipcommon sflash support. */
|
||||
+int bcma_sflash_read(struct bcma_drv_cc *cc, u32 offset, u32 len,
|
||||
+ u8 *buf);
|
||||
+int bcma_sflash_poll(struct bcma_drv_cc *cc, u32 offset);
|
||||
+int bcma_sflash_write(struct bcma_drv_cc *cc, u32 offset, u32 len,
|
||||
+ const u8 *buf);
|
||||
+int bcma_sflash_erase(struct bcma_drv_cc *cc, u32 offset);
|
||||
+int bcma_sflash_commit(struct bcma_drv_cc *cc, u32 offset, u32 len,
|
||||
+ const u8 *buf);
|
||||
+#endif /* CONFIG_BCMA_SFLASH */
|
||||
+
|
||||
#endif /* LINUX_BCMA_DRIVER_CC_H_ */
|
|
@ -0,0 +1,579 @@
|
|||
From 4b449ce15d74e5973cde18381c2a3fa0616b2b3d Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sun, 17 Jul 2011 14:54:11 +0200
|
||||
Subject: [PATCH 14/18] mtd: bcm47xx: add bcm47xx part parser
|
||||
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/mtd/Kconfig | 7 +
|
||||
drivers/mtd/Makefile | 1 +
|
||||
drivers/mtd/bcm47xxpart.c | 536 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 544 insertions(+), 0 deletions(-)
|
||||
create mode 100644 drivers/mtd/bcm47xxpart.c
|
||||
|
||||
--- a/drivers/mtd/Kconfig
|
||||
+++ b/drivers/mtd/Kconfig
|
||||
@@ -173,6 +173,13 @@ config MTD_MYLOADER_PARTS
|
||||
You will still need the parsing functions to be called by the driver
|
||||
for your particular device. It won't happen automatically.
|
||||
|
||||
+config MTD_BCM47XX_PARTS
|
||||
+ tristate "BCM47XX partitioning support"
|
||||
+ default y
|
||||
+ depends on BCM47XX
|
||||
+ ---help---
|
||||
+ bcm47XX partitioning support
|
||||
+
|
||||
comment "User Modules And Translation Layers"
|
||||
|
||||
config MTD_CHAR
|
||||
--- a/drivers/mtd/Makefile
|
||||
+++ b/drivers/mtd/Makefile
|
||||
@@ -12,6 +12,7 @@ obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdli
|
||||
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
||||
obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o
|
||||
obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o
|
||||
+obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o
|
||||
|
||||
# 'Users' - code which presents functionality to userspace.
|
||||
obj-$(CONFIG_MTD_CHAR) += mtdchar.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/mtd/bcm47xxpart.c
|
||||
@@ -0,0 +1,536 @@
|
||||
+/*
|
||||
+ * 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
|
||||
+ */
|
||||
+
|
||||
+#define pr_fmt(fmt) "bcm47xx_part: " fmt
|
||||
+#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/partitions.h>
|
||||
+#include <linux/crc32.h>
|
||||
+#include <asm/io.h>
|
||||
+#include <asm/mach-bcm47xx/nvram.h>
|
||||
+#include <asm/mach-bcm47xx/bcm47xx.h>
|
||||
+#include <asm/fw/cfe/cfe_api.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 */
|
||||
+};
|
||||
+
|
||||
+/* for Edimax Print servers which use an additional header
|
||||
+ * then the firmware on flash looks like :
|
||||
+ * EDIMAX HEADER | TRX HEADER
|
||||
+ * As this header is 12 bytes long we have to handle it
|
||||
+ * and skip it to find the TRX header
|
||||
+ */
|
||||
+#define EDIMAX_PS_HEADER_MAGIC 0x36315350 /* "PS16" */
|
||||
+#define EDIMAX_PS_HEADER_LEN 0xc /* 12 bytes long for edimax header */
|
||||
+
|
||||
+#define NVRAM_SPACE 0x8000
|
||||
+
|
||||
+#define ROUTER_NETGEAR_WGR614L 1
|
||||
+#define ROUTER_NETGEAR_WNR834B 2
|
||||
+#define ROUTER_NETGEAR_WNDR3300 3
|
||||
+#define ROUTER_NETGEAR_WNR3500L 4
|
||||
+#define ROUTER_SIMPLETECH_SIMPLESHARE 5
|
||||
+
|
||||
+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, }, /* Used to create custom partitons with the function get_router() */
|
||||
+ { name: NULL, },
|
||||
+};
|
||||
+
|
||||
+static int
|
||||
+find_cfe_size(struct mtd_info *mtd)
|
||||
+{
|
||||
+ 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 < mtd->size; off += blocksize) {
|
||||
+ memset(buf, 0xe5, sizeof(buf));
|
||||
+
|
||||
+ /*
|
||||
+ * Read into buffer
|
||||
+ */
|
||||
+ if (mtd->read(mtd, off, sizeof(buf), &len, buf) ||
|
||||
+ len != sizeof(buf))
|
||||
+ continue;
|
||||
+
|
||||
+ if (le32_to_cpu(trx->magic) == EDIMAX_PS_HEADER_MAGIC) {
|
||||
+ if (mtd->read(mtd, off + EDIMAX_PS_HEADER_LEN,
|
||||
+ sizeof(buf), &len, buf) || len != sizeof(buf)) {
|
||||
+ continue;
|
||||
+ } else {
|
||||
+ pr_notice("Found edimax header\n");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* found a TRX header */
|
||||
+ if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
|
||||
+ goto found;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ pr_notice("%s: Couldn't find bootloader size\n", mtd->name);
|
||||
+ return -1;
|
||||
+
|
||||
+ found:
|
||||
+ pr_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);
|
||||
+ pr_warn("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, write data to flash.
|
||||
+ */
|
||||
+
|
||||
+ ret = mtd->write (mtd, pos, len, &retlen, buf);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ if (retlen != len)
|
||||
+ return -EIO;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int
|
||||
+find_dual_image_off (struct mtd_info *mtd)
|
||||
+{
|
||||
+ struct trx_header trx;
|
||||
+ int off, blocksize;
|
||||
+ size_t len;
|
||||
+
|
||||
+ blocksize = mtd->erasesize;
|
||||
+ if (blocksize < 0x10000)
|
||||
+ blocksize = 0x10000;
|
||||
+
|
||||
+ for (off = (128*1024); off < mtd->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){
|
||||
+ pr_notice("dual image TRX header found\n");
|
||||
+ return mtd->size / 2;
|
||||
+ } else {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int
|
||||
+find_root(struct mtd_info *mtd, struct mtd_partition *part)
|
||||
+{
|
||||
+ struct trx_header trx, *trx2;
|
||||
+ unsigned char buf[512], *block;
|
||||
+ int off, blocksize, trxoff = 0;
|
||||
+ u32 i, crc = ~0;
|
||||
+ size_t len;
|
||||
+ bool edimax = false;
|
||||
+
|
||||
+ blocksize = mtd->erasesize;
|
||||
+ if (blocksize < 0x10000)
|
||||
+ blocksize = 0x10000;
|
||||
+
|
||||
+ for (off = (128*1024); off < mtd->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 an edimax header */
|
||||
+ if (le32_to_cpu(trx.magic) == EDIMAX_PS_HEADER_MAGIC) {
|
||||
+ /* read the correct trx header */
|
||||
+ if (mtd->read(mtd, off + EDIMAX_PS_HEADER_LEN,
|
||||
+ sizeof(trx), &len, (char *) &trx) ||
|
||||
+ len != sizeof(trx)) {
|
||||
+ continue;
|
||||
+ } else {
|
||||
+ pr_notice("Found an edimax ps header\n");
|
||||
+ edimax = true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* 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;
|
||||
+ if (edimax) {
|
||||
+ off += EDIMAX_PS_HEADER_LEN;
|
||||
+ trxoff = EDIMAX_PS_HEADER_LEN;
|
||||
+ }
|
||||
+
|
||||
+ goto found;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ pr_warn("%s: Couldn't find root filesystem\n",
|
||||
+ mtd->name);
|
||||
+ return -1;
|
||||
+
|
||||
+ found:
|
||||
+ pr_notice("TRX offset : %x\n", trxoff);
|
||||
+ 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 - trxoff, mtd->erasesize, &len, block) || len != mtd->erasesize) {
|
||||
+ pr_err("Error accessing the first trx eraseblock\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ pr_notice("Updating TRX offsets and length:\n");
|
||||
+ pr_notice("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);
|
||||
+ pr_notice("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 + trxoff, &trx, sizeof(trx));
|
||||
+ if (mtd->unlock)
|
||||
+ mtd->unlock(mtd, off - trxoff, mtd->erasesize);
|
||||
+ erase_write(mtd, off - trxoff, mtd->erasesize, block);
|
||||
+ if (mtd->sync)
|
||||
+ mtd->sync(mtd);
|
||||
+ kfree(block);
|
||||
+ pr_notice("Done\n");
|
||||
+ }
|
||||
+
|
||||
+ return part->size;
|
||||
+}
|
||||
+
|
||||
+static int get_router(void)
|
||||
+{
|
||||
+ char buf[20];
|
||||
+ u32 boardnum = 0;
|
||||
+ u16 boardtype = 0;
|
||||
+ u16 boardrev = 0;
|
||||
+ u32 boardflags = 0;
|
||||
+ u16 sdram_init = 0;
|
||||
+ u16 cardbus = 0;
|
||||
+ u16 strev = 0;
|
||||
+
|
||||
+ if (nvram_getenv("boardnum", buf, sizeof(buf)) >= 0)
|
||||
+ boardnum = simple_strtoul(buf, NULL, 0);
|
||||
+ if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
|
||||
+ boardtype = simple_strtoul(buf, NULL, 0);
|
||||
+ if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
|
||||
+ boardrev = simple_strtoul(buf, NULL, 0);
|
||||
+ if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0)
|
||||
+ boardflags = simple_strtoul(buf, NULL, 0);
|
||||
+ if (nvram_getenv("sdram_init", buf, sizeof(buf)) >= 0)
|
||||
+ sdram_init = simple_strtoul(buf, NULL, 0);
|
||||
+ if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
|
||||
+ cardbus = simple_strtoul(buf, NULL, 0);
|
||||
+ if (nvram_getenv("st_rev", buf, sizeof(buf)) >= 0)
|
||||
+ strev = simple_strtoul(buf, NULL, 0);
|
||||
+
|
||||
+ if ((boardnum == 8 || boardnum == 01)
|
||||
+ && boardtype == 0x0472 && cardbus == 1) {
|
||||
+ /* Netgear WNR834B, Netgear WNR834Bv2 */
|
||||
+ return ROUTER_NETGEAR_WNR834B;
|
||||
+ }
|
||||
+
|
||||
+ if (boardnum == 01 && boardtype == 0x0472 && boardrev == 0x23) {
|
||||
+ /* Netgear WNDR-3300 */
|
||||
+ return ROUTER_NETGEAR_WNDR3300;
|
||||
+ }
|
||||
+
|
||||
+ if ((boardnum == 83258 || boardnum == 01)
|
||||
+ && boardtype == 0x048e
|
||||
+ && (boardrev == 0x11 || boardrev == 0x10)
|
||||
+ && boardflags == 0x750
|
||||
+ && sdram_init == 0x000A) {
|
||||
+ /* Netgear WGR614v8/L/WW 16MB ram, cfe v1.3 or v1.5 */
|
||||
+ return ROUTER_NETGEAR_WGR614L;
|
||||
+ }
|
||||
+
|
||||
+ if ((boardnum == 1 || boardnum == 3500)
|
||||
+ && boardtype == 0x04CF
|
||||
+ && (boardrev == 0x1213 || boardrev == 02)) {
|
||||
+ /* Netgear WNR3500v2/U/L */
|
||||
+ return ROUTER_NETGEAR_WNR3500L;
|
||||
+ }
|
||||
+
|
||||
+ if (boardtype == 0x042f
|
||||
+ && boardrev == 0x10
|
||||
+ && boardflags == 0
|
||||
+ && strev == 0x11) {
|
||||
+ /* Simpletech Simpleshare */
|
||||
+ return ROUTER_SIMPLETECH_SIMPLESHARE;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int parse_bcm47xx_partitions(struct mtd_info *mtd,
|
||||
+ struct mtd_partition **pparts,
|
||||
+// struct mtd_part_parser_data *data)
|
||||
+ unsigned long data)
|
||||
+{
|
||||
+ int cfe_size;
|
||||
+ int dual_image_offset = 0;
|
||||
+ /* e.g Netgear 0x003e0000-0x003f0000 : "board_data", we exclude this
|
||||
+ * part from our mapping to prevent overwriting len/checksum on e.g.
|
||||
+ * Netgear WGR614v8/L/WW
|
||||
+ */
|
||||
+ int custom_data_size = 0;
|
||||
+
|
||||
+ if ((cfe_size = find_cfe_size(mtd)) < 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* boot loader */
|
||||
+ bcm47xx_parts[0].offset = 0;
|
||||
+ bcm47xx_parts[0].size = cfe_size;
|
||||
+
|
||||
+ /* nvram */
|
||||
+ if (cfe_size != 384 * 1024) {
|
||||
+
|
||||
+ switch (get_router()) {
|
||||
+ case ROUTER_NETGEAR_WGR614L:
|
||||
+ case ROUTER_NETGEAR_WNR834B:
|
||||
+ case ROUTER_NETGEAR_WNDR3300:
|
||||
+ case ROUTER_NETGEAR_WNR3500L:
|
||||
+ /* Netgear: checksum is @ 0x003AFFF8 for 4M flash or checksum
|
||||
+ * is @ 0x007AFFF8 for 8M flash
|
||||
+ */
|
||||
+ custom_data_size = mtd->erasesize;
|
||||
+
|
||||
+ bcm47xx_parts[3].offset = mtd->size - roundup(NVRAM_SPACE, mtd->erasesize);
|
||||
+ bcm47xx_parts[3].size = roundup(NVRAM_SPACE, mtd->erasesize);
|
||||
+
|
||||
+ /* Place CFE board_data into a partition */
|
||||
+ bcm47xx_parts[4].name = "board_data";
|
||||
+ bcm47xx_parts[4].offset = bcm47xx_parts[3].offset - custom_data_size;
|
||||
+ bcm47xx_parts[4].size = custom_data_size;
|
||||
+ break;
|
||||
+
|
||||
+ case ROUTER_SIMPLETECH_SIMPLESHARE:
|
||||
+ /* Fixup Simpletech Simple share nvram */
|
||||
+
|
||||
+ pr_notice("Setting up simpletech nvram\n");
|
||||
+ custom_data_size = mtd->erasesize;
|
||||
+
|
||||
+ bcm47xx_parts[3].offset = mtd->size - roundup(NVRAM_SPACE, mtd->erasesize) * 2;
|
||||
+ bcm47xx_parts[3].size = roundup(NVRAM_SPACE, mtd->erasesize);
|
||||
+
|
||||
+ /* Place backup nvram into a partition */
|
||||
+ bcm47xx_parts[4].name = "nvram_copy";
|
||||
+ bcm47xx_parts[4].offset = mtd->size - roundup(NVRAM_SPACE, mtd->erasesize);
|
||||
+ bcm47xx_parts[4].size = roundup(NVRAM_SPACE, mtd->erasesize);
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ bcm47xx_parts[3].offset = mtd->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*/
|
||||
+ pr_notice("Looking for dual image\n");
|
||||
+ dual_image_offset=find_dual_image_off(mtd);
|
||||
+ /* linux (kernel and rootfs) */
|
||||
+ if (cfe_size != 384 * 1024) {
|
||||
+ if (get_router() == ROUTER_SIMPLETECH_SIMPLESHARE) {
|
||||
+ bcm47xx_parts[1].offset = bcm47xx_parts[0].size;
|
||||
+ bcm47xx_parts[1].size = bcm47xx_parts[4].offset - dual_image_offset -
|
||||
+ bcm47xx_parts[1].offset - custom_data_size;
|
||||
+ } else {
|
||||
+ bcm47xx_parts[1].offset = bcm47xx_parts[0].size;
|
||||
+ bcm47xx_parts[1].size = bcm47xx_parts[3].offset - dual_image_offset -
|
||||
+ bcm47xx_parts[1].offset - custom_data_size;
|
||||
+ }
|
||||
+ } 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 = mtd->size -
|
||||
+ bcm47xx_parts[0].size -
|
||||
+ (2*bcm47xx_parts[3].size) -
|
||||
+ mtd->erasesize - custom_data_size;
|
||||
+ }
|
||||
+
|
||||
+ /* find and size rootfs */
|
||||
+ find_root(mtd, &bcm47xx_parts[2]);
|
||||
+ bcm47xx_parts[2].size = mtd->size - dual_image_offset -
|
||||
+ bcm47xx_parts[2].offset -
|
||||
+ bcm47xx_parts[3].size - custom_data_size;
|
||||
+ *pparts = bcm47xx_parts;
|
||||
+ return bcm47xx_parts[4].name == NULL ? 4 : 5;
|
||||
+}
|
||||
+
|
||||
+static struct mtd_part_parser bcm47xx_parser = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .parse_fn = parse_bcm47xx_partitions,
|
||||
+ .name = "bcm47xx",
|
||||
+};
|
||||
+
|
||||
+static int __init bcm47xx_parser_init(void)
|
||||
+{
|
||||
+ return register_mtd_parser(&bcm47xx_parser);
|
||||
+}
|
||||
+
|
||||
+static void __exit bcm47xx_parser_exit(void)
|
||||
+{
|
||||
+ deregister_mtd_parser(&bcm47xx_parser);
|
||||
+}
|
||||
+
|
||||
+module_init(bcm47xx_parser_init);
|
||||
+module_exit(bcm47xx_parser_exit);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_DESCRIPTION("Parsing code for flash partitions on bcm47xx SoCs");
|
|
@ -0,0 +1,238 @@
|
|||
From 941c7a12af5d985c9dabc6813db3b75908bd619c Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sun, 17 Jul 2011 14:55:18 +0200
|
||||
Subject: [PATCH 15/22] mtd: bcm47xx: add parallel flash driver
|
||||
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/mtd/maps/Kconfig | 9 ++
|
||||
drivers/mtd/maps/Makefile | 1 +
|
||||
drivers/mtd/maps/bcm47xx-pflash.c | 196 +++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 206 insertions(+), 0 deletions(-)
|
||||
create mode 100644 drivers/mtd/maps/bcm47xx-pflash.c
|
||||
|
||||
--- a/drivers/mtd/maps/Kconfig
|
||||
+++ b/drivers/mtd/maps/Kconfig
|
||||
@@ -264,6 +264,15 @@ config MTD_LANTIQ
|
||||
help
|
||||
Support for NOR flash attached to the Lantiq SoC's External Bus Unit.
|
||||
|
||||
+config MTD_BCM47XX_PFLASH
|
||||
+ tristate "bcm47xx parallel flash support"
|
||||
+ default y
|
||||
+ depends on BCM47XX
|
||||
+ select MTD_PARTITIONS
|
||||
+ select MTD_BCM47XX_PARTS
|
||||
+ help
|
||||
+ Support for bcm47xx parallel flash
|
||||
+
|
||||
config MTD_DILNETPC
|
||||
tristate "CFI Flash device mapped on DIL/Net PC"
|
||||
depends on X86 && MTD_CFI_INTELEXT && BROKEN
|
||||
--- a/drivers/mtd/maps/Makefile
|
||||
+++ b/drivers/mtd/maps/Makefile
|
||||
@@ -60,3 +60,4 @@ obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr
|
||||
obj-$(CONFIG_MTD_BCM963XX) += bcm963xx-flash.o
|
||||
obj-$(CONFIG_MTD_LATCH_ADDR) += latch-addr-flash.o
|
||||
obj-$(CONFIG_MTD_LANTIQ) += lantiq-flash.o
|
||||
+obj-$(CONFIG_MTD_BCM47XX_PFLASH)+= bcm47xx-pflash.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/mtd/maps/bcm47xx-pflash.c
|
||||
@@ -0,0 +1,196 @@
|
||||
+/*
|
||||
+ * 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
|
||||
+ */
|
||||
+
|
||||
+#define pr_fmt(fmt) "bcm47xx_pflash: " fmt
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/sched.h>
|
||||
+#include <linux/mtd/mtd.h>
|
||||
+#include <linux/mtd/map.h>
|
||||
+#include <linux/mtd/partitions.h>
|
||||
+#include <asm/io.h>
|
||||
+#include <asm/mach-bcm47xx/bcm47xx.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#define WINDOW_ADDR 0x1fc00000
|
||||
+#define WINDOW_SIZE 0x400000
|
||||
+#define BUSWIDTH 2
|
||||
+
|
||||
+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,
|
||||
+};
|
||||
+
|
||||
+static const char *probes[] = { "bcm47xx", NULL };
|
||||
+
|
||||
+static int bcm47xx_mtd_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+#ifdef CONFIG_BCM47XX_SSB
|
||||
+ struct ssb_mipscore *mcore_ssb;
|
||||
+#endif
|
||||
+#ifdef CONFIG_BCM47XX_BCMA
|
||||
+ struct bcma_drv_cc *bcma_cc;
|
||||
+#endif
|
||||
+ int ret = 0;
|
||||
+ struct mtd_partition *partitions = NULL;
|
||||
+ int num_partitions = 0;
|
||||
+
|
||||
+ switch (bcm47xx_active_bus_type) {
|
||||
+#ifdef CONFIG_BCM47XX_SSB
|
||||
+ case BCM47XX_BUS_TYPE_SSB:
|
||||
+ mcore_ssb = &bcm47xx_bus.ssb.mipscore;
|
||||
+ bcm47xx_map.phys = mcore_ssb->flash_window;
|
||||
+ bcm47xx_map.size = mcore_ssb->flash_window_size;
|
||||
+ bcm47xx_map.bankwidth = mcore_ssb->flash_buswidth;
|
||||
+ break;
|
||||
+#endif
|
||||
+#ifdef CONFIG_BCM47XX_BCMA
|
||||
+ case BCM47XX_BUS_TYPE_BCMA:
|
||||
+ bcma_cc = &bcm47xx_bus.bcma.bus.drv_cc;
|
||||
+ if (bcma_cc->flash_type != BCMA_PFLASH)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ bcm47xx_map.phys = bcma_cc->flash.pflash.window;
|
||||
+ bcm47xx_map.size = bcma_cc->flash.pflash.window_size;
|
||||
+ bcm47xx_map.bankwidth = bcma_cc->flash.pflash.buswidth;
|
||||
+ break;
|
||||
+#endif
|
||||
+ }
|
||||
+
|
||||
+ pr_notice("flash init: 0x%08x 0x%08lx\n", bcm47xx_map.phys, bcm47xx_map.size);
|
||||
+ bcm47xx_map.virt = ioremap_nocache(bcm47xx_map.phys, bcm47xx_map.size);
|
||||
+
|
||||
+ if (!bcm47xx_map.virt) {
|
||||
+ pr_err("Failed to ioremap\n");
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ simple_map_init(&bcm47xx_map);
|
||||
+ /* override copy_from routine */
|
||||
+ bcm47xx_map.copy_from = bcm47xx_map_copy_from;
|
||||
+
|
||||
+ bcm47xx_mtd = do_map_probe("cfi_probe", &bcm47xx_map);
|
||||
+ if (!bcm47xx_mtd) {
|
||||
+ pr_err("Failed to do_map_probe\n");
|
||||
+ ret = -ENXIO;
|
||||
+ goto err_unmap;
|
||||
+ }
|
||||
+ bcm47xx_mtd->owner = THIS_MODULE;
|
||||
+
|
||||
+ pr_notice("Flash device: 0x%lx at 0x%x\n", bcm47xx_map.size, WINDOW_ADDR);
|
||||
+
|
||||
+ num_partitions = parse_mtd_partitions(bcm47xx_mtd, probes, &partitions, 0);
|
||||
+ if (num_partitions < 0) {
|
||||
+ ret = num_partitions;
|
||||
+ goto err_unmap;
|
||||
+ }
|
||||
+
|
||||
+ ret = mtd_device_register(bcm47xx_mtd, partitions, num_partitions);
|
||||
+
|
||||
+// ret = mtd_device_parse_register(bcm47xx_mtd, "bcm47xx", NULL, NULL, 0);
|
||||
+
|
||||
+ if (ret) {
|
||||
+ pr_err("Flash: mtd_device_register failed\n");
|
||||
+ goto err_destroy;
|
||||
+ }
|
||||
+ return 0;
|
||||
+
|
||||
+err_destroy:
|
||||
+ map_destroy(bcm47xx_mtd);
|
||||
+err_unmap:
|
||||
+ iounmap(bcm47xx_map.virt);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int __devexit bcm47xx_mtd_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ mtd_device_unregister(bcm47xx_mtd);
|
||||
+ map_destroy(bcm47xx_mtd);
|
||||
+ iounmap(bcm47xx_map.virt);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver bcm47xx_mtd_driver = {
|
||||
+ .remove = __devexit_p(bcm47xx_mtd_remove),
|
||||
+ .driver = {
|
||||
+ .name = "bcm47xx_pflash",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init init_bcm47xx_mtd(void)
|
||||
+{
|
||||
+ int ret = platform_driver_probe(&bcm47xx_mtd_driver, bcm47xx_mtd_probe);
|
||||
+
|
||||
+ if (ret)
|
||||
+ pr_err("error registering platform driver: %i\n", ret);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void __exit exit_bcm47xx_mtd(void)
|
||||
+{
|
||||
+ platform_driver_unregister(&bcm47xx_mtd_driver);
|
||||
+}
|
||||
+
|
||||
+module_init(init_bcm47xx_mtd);
|
||||
+module_exit(exit_bcm47xx_mtd);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_DESCRIPTION("BCM47XX parallel flash driver");
|
|
@ -0,0 +1,312 @@
|
|||
From 8a6398687998886c451c6df381c2320b6dddb3fe Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sun, 17 Jul 2011 14:55:45 +0200
|
||||
Subject: [PATCH 16/22] mtd: bcm47xx: add serial flash driver
|
||||
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/mtd/maps/Kconfig | 9 ++
|
||||
drivers/mtd/maps/Makefile | 1 +
|
||||
drivers/mtd/maps/bcm47xx-sflash.c | 270 +++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 280 insertions(+), 0 deletions(-)
|
||||
create mode 100644 drivers/mtd/maps/bcm47xx-sflash.c
|
||||
|
||||
--- a/drivers/mtd/maps/Kconfig
|
||||
+++ b/drivers/mtd/maps/Kconfig
|
||||
@@ -273,6 +273,15 @@ config MTD_BCM47XX_PFLASH
|
||||
help
|
||||
Support for bcm47xx parallel flash
|
||||
|
||||
+config MTD_BCM47XX_SFLASH
|
||||
+ tristate "bcm47xx serial flash support"
|
||||
+ default y
|
||||
+ depends on BCM47XX
|
||||
+ select MTD_PARTITIONS
|
||||
+ select MTD_BCM47XX_PARTS
|
||||
+ help
|
||||
+ Support for bcm47xx parallel flash
|
||||
+
|
||||
config MTD_DILNETPC
|
||||
tristate "CFI Flash device mapped on DIL/Net PC"
|
||||
depends on X86 && MTD_CFI_INTELEXT && BROKEN
|
||||
--- a/drivers/mtd/maps/Makefile
|
||||
+++ b/drivers/mtd/maps/Makefile
|
||||
@@ -61,3 +61,4 @@ obj-$(CONFIG_MTD_BCM963XX) += bcm963xx-f
|
||||
obj-$(CONFIG_MTD_LATCH_ADDR) += latch-addr-flash.o
|
||||
obj-$(CONFIG_MTD_LANTIQ) += lantiq-flash.o
|
||||
obj-$(CONFIG_MTD_BCM47XX_PFLASH)+= bcm47xx-pflash.o
|
||||
+obj-$(CONFIG_MTD_BCM47XX_SFLASH)+= bcm47xx-sflash.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/mtd/maps/bcm47xx-sflash.c
|
||||
@@ -0,0 +1,270 @@
|
||||
+/*
|
||||
+ * Broadcom SiliconBackplane chipcommon serial flash interface
|
||||
+ *
|
||||
+ * Copyright 2006, 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.
|
||||
+ *
|
||||
+ * $Id$
|
||||
+ */
|
||||
+
|
||||
+#define pr_fmt(fmt) "bcm47xx_sflash: " fmt
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/ioport.h>
|
||||
+#include <linux/sched.h>
|
||||
+#include <linux/mtd/mtd.h>
|
||||
+#include <linux/mtd/map.h>
|
||||
+#include <linux/mtd/partitions.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/delay.h>
|
||||
+
|
||||
+#include <bcm47xx.h>
|
||||
+
|
||||
+#include <linux/bcma/bcma.h>
|
||||
+#include <linux/bcma/bcma_driver_chipcommon.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+struct sflash_mtd {
|
||||
+ struct bcma_drv_cc *cc;
|
||||
+ struct mtd_info mtd;
|
||||
+ struct mtd_erase_region_info region;
|
||||
+};
|
||||
+
|
||||
+static struct sflash_mtd *sflash;
|
||||
+
|
||||
+static int
|
||||
+sflash_mtd_poll(struct sflash_mtd *sflash, unsigned int offset, int timeout)
|
||||
+{
|
||||
+ unsigned long now = jiffies;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ for (;;) {
|
||||
+ if (!bcma_sflash_poll(sflash->cc, offset)) {
|
||||
+ ret = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+ if (time_after(jiffies, now + timeout)) {
|
||||
+ pr_err("timeout while polling\n");
|
||||
+ ret = -ETIMEDOUT;
|
||||
+ break;
|
||||
+ }
|
||||
+ udelay(1);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+sflash_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
|
||||
+{
|
||||
+ struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv;
|
||||
+
|
||||
+ /* Check address range */
|
||||
+ if (!len)
|
||||
+ return 0;
|
||||
+
|
||||
+ if ((from + len) > mtd->size)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ *retlen = 0;
|
||||
+
|
||||
+ while (len) {
|
||||
+ int ret = bcma_sflash_read(sflash->cc, from, len, buf);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ from += (loff_t) ret;
|
||||
+ len -= ret;
|
||||
+ buf += ret;
|
||||
+ *retlen += ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+sflash_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
|
||||
+{
|
||||
+ struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv;
|
||||
+
|
||||
+ /* Check address range */
|
||||
+ if (!len)
|
||||
+ return 0;
|
||||
+
|
||||
+ if ((to + len) > mtd->size)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ *retlen = 0;
|
||||
+ while (len) {
|
||||
+ int bytes;
|
||||
+ int ret = bcma_sflash_write(sflash->cc, to, len, buf);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ bytes = ret;
|
||||
+
|
||||
+ ret = sflash_mtd_poll(sflash, (unsigned int) to, HZ / 10);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ to += (loff_t) bytes;
|
||||
+ len -= bytes;
|
||||
+ buf += bytes;
|
||||
+ *retlen += bytes;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+sflash_mtd_erase(struct mtd_info *mtd, struct erase_info *erase)
|
||||
+{
|
||||
+ struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv;
|
||||
+ int i, j, ret = 0;
|
||||
+ unsigned int addr, len;
|
||||
+
|
||||
+ /* Check address range */
|
||||
+ if (!erase->len)
|
||||
+ return 0;
|
||||
+ if ((erase->addr + erase->len) > mtd->size)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ addr = erase->addr;
|
||||
+ len = erase->len;
|
||||
+
|
||||
+ /* Ensure that requested regions are aligned */
|
||||
+ for (i = 0; i < mtd->numeraseregions; i++) {
|
||||
+ for (j = 0; j < mtd->eraseregions[i].numblocks; j++) {
|
||||
+ if (addr == mtd->eraseregions[i].offset +
|
||||
+ mtd->eraseregions[i].erasesize * j &&
|
||||
+ len >= mtd->eraseregions[i].erasesize) {
|
||||
+ if ((ret = bcma_sflash_erase(sflash->cc, addr)) < 0)
|
||||
+ break;
|
||||
+ if ((ret = sflash_mtd_poll(sflash, addr, 10 * HZ)))
|
||||
+ break;
|
||||
+ addr += mtd->eraseregions[i].erasesize;
|
||||
+ len -= mtd->eraseregions[i].erasesize;
|
||||
+ }
|
||||
+ }
|
||||
+ if (ret)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* Set erase status */
|
||||
+ if (ret)
|
||||
+ erase->state = MTD_ERASE_FAILED;
|
||||
+ else
|
||||
+ erase->state = MTD_ERASE_DONE;
|
||||
+
|
||||
+ /* Call erase callback */
|
||||
+ if (erase->callback)
|
||||
+ erase->callback(erase);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static const char *probes[] = { "bcm47xx", NULL };
|
||||
+
|
||||
+static int bcm47xx_sflash_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ struct mtd_partition *parts;
|
||||
+ int num_partitions = 0;
|
||||
+
|
||||
+ sflash = kzalloc(sizeof(struct sflash_mtd), GFP_KERNEL);
|
||||
+ if (!sflash)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ sflash->cc = &bcm47xx_bus.bcma.bus.drv_cc;
|
||||
+ if (sflash->cc->flash_type != BCMA_SFLASH)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ pr_info("found serial flash: blocksize=%dKB, numblocks=%d, size=%dKB\n",
|
||||
+ sflash->cc->flash.sflash.blocksize/1024,
|
||||
+ sflash->cc->flash.sflash.numblocks,
|
||||
+ sflash->cc->flash.sflash.size/1024);
|
||||
+
|
||||
+ /* Setup region info */
|
||||
+ sflash->region.offset = 0;
|
||||
+ sflash->region.erasesize = sflash->cc->flash.sflash.blocksize;
|
||||
+ sflash->region.numblocks = sflash->cc->flash.sflash.numblocks;
|
||||
+ if (sflash->region.erasesize > sflash->mtd.erasesize)
|
||||
+ sflash->mtd.erasesize = sflash->region.erasesize;
|
||||
+ sflash->mtd.size = sflash->cc->flash.sflash.size;
|
||||
+ sflash->mtd.numeraseregions = 1;
|
||||
+
|
||||
+ /* Register with MTD */
|
||||
+ sflash->mtd.name = "bcm47xx-sflash";
|
||||
+ sflash->mtd.type = MTD_NORFLASH;
|
||||
+ sflash->mtd.flags = MTD_CAP_NORFLASH;
|
||||
+ sflash->mtd.eraseregions = &sflash->region;
|
||||
+ sflash->mtd.erase = sflash_mtd_erase;
|
||||
+ sflash->mtd.read = sflash_mtd_read;
|
||||
+ sflash->mtd.write = sflash_mtd_write;
|
||||
+ sflash->mtd.writesize = 1;
|
||||
+ sflash->mtd.priv = sflash;
|
||||
+ sflash->mtd.owner = THIS_MODULE;
|
||||
+
|
||||
+ num_partitions = parse_mtd_partitions(&sflash->mtd, probes, &parts, 0);
|
||||
+ if (num_partitions < 0) {
|
||||
+ ret = num_partitions;
|
||||
+ goto err_destroy;
|
||||
+ }
|
||||
+
|
||||
+ ret = mtd_device_register(&sflash->mtd, parts, num_partitions);
|
||||
+
|
||||
+// ret = mtd_device_parse_register(bcm47xx_mtd, "bcm47xx", NULL, NULL, 0);
|
||||
+
|
||||
+ if (ret) {
|
||||
+ pr_err("mtd_device_register failed\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+ return 0;
|
||||
+
|
||||
+err_destroy:
|
||||
+ map_destroy(&sflash->mtd);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int __devexit bcm47xx_sflash_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ if (sflash) {
|
||||
+ mtd_device_unregister(&sflash->mtd);
|
||||
+ map_destroy(&sflash->mtd);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver bcm47xx_sflash_driver = {
|
||||
+ .remove = __devexit_p(bcm47xx_sflash_remove),
|
||||
+ .driver = {
|
||||
+ .name = "bcm47xx_sflash",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init init_bcm47xx_sflash(void)
|
||||
+{
|
||||
+ int ret = platform_driver_probe(&bcm47xx_sflash_driver, bcm47xx_sflash_probe);
|
||||
+
|
||||
+ if (ret)
|
||||
+ pr_err("error registering platform driver: %i\n", ret);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void __exit exit_bcm47xx_sflash(void)
|
||||
+{
|
||||
+ platform_driver_unregister(&bcm47xx_sflash_driver);
|
||||
+}
|
||||
+
|
||||
+module_init(init_bcm47xx_sflash);
|
||||
+module_exit(exit_bcm47xx_sflash);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_DESCRIPTION("BCM47XX parallel flash driver");
|
|
@ -0,0 +1,74 @@
|
|||
From 89b904335338c86ef2c40e7cc51e19673feb62c1 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sun, 17 Jul 2011 15:02:10 +0200
|
||||
Subject: [PATCH 17/22] bcm47xx: register flash drivers
|
||||
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
arch/mips/bcm47xx/setup.c | 50 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 files changed, 50 insertions(+), 0 deletions(-)
|
||||
|
||||
--- a/arch/mips/bcm47xx/setup.c
|
||||
+++ b/arch/mips/bcm47xx/setup.c
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <linux/ssb/ssb.h>
|
||||
#include <linux/ssb/ssb_embedded.h>
|
||||
#include <linux/bcma/bcma_soc.h>
|
||||
+#include <linux/platform_device.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/time.h>
|
||||
@@ -357,3 +358,52 @@ static int __init bcm47xx_register_bus_c
|
||||
return 0;
|
||||
}
|
||||
device_initcall(bcm47xx_register_bus_complete);
|
||||
+
|
||||
+static struct resource bcm47xx_pflash_resource = {
|
||||
+ .name = "para",
|
||||
+ .start = 0,
|
||||
+ .end = 0,
|
||||
+ .flags = 0,
|
||||
+};
|
||||
+
|
||||
+static struct platform_device bcm47xx_pflash = {
|
||||
+ .name = "bcm47xx_pflash",
|
||||
+ .resource = &bcm47xx_pflash_resource,
|
||||
+ .num_resources = 1,
|
||||
+};
|
||||
+
|
||||
+static struct resource bcm47xx_sflash_resource = {
|
||||
+ .name = "serial",
|
||||
+ .start = 0,
|
||||
+ .end = 0,
|
||||
+ .flags = 0,
|
||||
+};
|
||||
+
|
||||
+static struct platform_device bcm47xx_sflash = {
|
||||
+ .name = "bcm47xx_sflash",
|
||||
+ .resource = &bcm47xx_sflash_resource,
|
||||
+ .num_resources = 1,
|
||||
+};
|
||||
+
|
||||
+static int __init bcm47xx_register_flash(void)
|
||||
+{
|
||||
+ switch (bcm47xx_active_bus_type) {
|
||||
+#ifdef CONFIG_BCM47XX_SSB
|
||||
+ case BCM47XX_BUS_TYPE_SSB:
|
||||
+ return platform_device_register(&bcm47xx_pflash);
|
||||
+#endif
|
||||
+#ifdef CONFIG_BCM47XX_BCMA
|
||||
+ case BCM47XX_BUS_TYPE_BCMA:
|
||||
+ if (bcm47xx_bus.bcma.bus.drv_cc.flash_type == BCMA_PFLASH) {
|
||||
+ return platform_device_register(&bcm47xx_pflash);
|
||||
+ } else if (bcm47xx_bus.bcma.bus.drv_cc.flash_type == BCMA_SFLASH) {
|
||||
+ return platform_device_register(&bcm47xx_sflash);
|
||||
+ } else {
|
||||
+ printk(KERN_ERR "No flash device found\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+#endif
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+fs_initcall(bcm47xx_register_flash);
|
|
@ -0,0 +1,29 @@
|
|||
From 1b23f310d4a7d24efe5dffbbde6b2b84252e2d7b Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Fri, 22 Jul 2011 14:18:21 +0200
|
||||
Subject: [PATCH 19/22] bcma: to not route irqs on non pci devices
|
||||
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/driver_pci.c | 9 ++++++++-
|
||||
1 files changed, 8 insertions(+), 1 deletions(-)
|
||||
|
||||
--- a/drivers/bcma/driver_pci.c
|
||||
+++ b/drivers/bcma/driver_pci.c
|
||||
@@ -208,7 +208,14 @@ int bcma_core_pci_irq_ctl(struct bcma_dr
|
||||
{
|
||||
struct pci_dev *pdev = pc->core->bus->host_pci;
|
||||
u32 coremask, tmp;
|
||||
- int err;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) {
|
||||
+ /* This bcma device is not on a PCI host-bus. So the IRQs are
|
||||
+ * not routed through the PCI core.
|
||||
+ * So we must not enable routing through the PCI core. */
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
|
||||
if (err)
|
|
@ -0,0 +1,37 @@
|
|||
From f3007275d7706afb1381adb0003f3ba69d359c8f Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Fri, 22 Jul 2011 17:09:36 +0200
|
||||
Subject: [PATCH 20/22] bcma: small fixes needed to get b43 up with SoC
|
||||
|
||||
When using an SoC these small cahnges are neede to get it up
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/core.c | 2 ++
|
||||
drivers/bcma/main.c | 3 +++
|
||||
2 files changed, 5 insertions(+), 0 deletions(-)
|
||||
|
||||
--- a/drivers/bcma/core.c
|
||||
+++ b/drivers/bcma/core.c
|
||||
@@ -110,6 +110,8 @@ EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
|
||||
u32 bcma_core_dma_translation(struct bcma_device *core)
|
||||
{
|
||||
switch (core->bus->hosttype) {
|
||||
+ case BCMA_HOSTTYPE_SOC:
|
||||
+ return 0;
|
||||
case BCMA_HOSTTYPE_PCI:
|
||||
if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64)
|
||||
return BCMA_DMA_TRANSLATION_DMA64_CMT;
|
||||
--- a/drivers/bcma/main.c
|
||||
+++ b/drivers/bcma/main.c
|
||||
@@ -99,7 +99,10 @@ static int bcma_register_cores(struct bc
|
||||
core->irq = bus->host_pci->irq;
|
||||
break;
|
||||
case BCMA_HOSTTYPE_SDIO:
|
||||
+ break;
|
||||
case BCMA_HOSTTYPE_SOC:
|
||||
+ core->dev.dma_mask = &core->dev.coherent_dma_mask;
|
||||
+ core->dma_dev = &core->dev;
|
||||
break;
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
From 6dd27601bee9b3c26cdb67246b6da51dd696ac34 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Fri, 22 Jul 2011 17:11:51 +0200
|
||||
Subject: [PATCH 22/22] bcma: use randoom mac address as long as reading it out does not work
|
||||
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
drivers/bcma/sprom.c | 5 ++++-
|
||||
1 files changed, 4 insertions(+), 1 deletions(-)
|
||||
|
||||
--- a/drivers/bcma/sprom.c
|
||||
+++ b/drivers/bcma/sprom.c
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/slab.h>
|
||||
+#include <linux/etherdevice.h>
|
||||
|
||||
#define SPOFF(offset) ((offset) / sizeof(u16))
|
||||
|
||||
@@ -144,8 +145,10 @@ int bcma_sprom_get(struct bcma_bus *bus)
|
||||
if (!bus->drv_cc.core)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
- if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
|
||||
+ if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) {
|
||||
+ random_ether_addr(bus->sprom.il0mac);
|
||||
return -ENOENT;
|
||||
+ }
|
||||
|
||||
sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
|
||||
GFP_KERNEL);
|
|
@ -15,16 +15,16 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
|
||||
--- a/arch/mips/bcm47xx/setup.c
|
||||
+++ b/arch/mips/bcm47xx/setup.c
|
||||
@@ -30,6 +30,8 @@
|
||||
#include <linux/ssb/ssb.h>
|
||||
@@ -31,6 +31,8 @@
|
||||
#include <linux/ssb/ssb_embedded.h>
|
||||
#include <linux/bcma/bcma_soc.h>
|
||||
#include <linux/platform_device.h>
|
||||
+#include <linux/serial.h>
|
||||
+#include <linux/serial_8250.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/reboot.h>
|
||||
#include <asm/time.h>
|
||||
@@ -274,6 +276,31 @@ static int bcm47xx_get_invariants(struct
|
||||
@@ -275,6 +277,31 @@ static int bcm47xx_get_invariants(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
|||
static void __init bcm47xx_register_ssb(void)
|
||||
{
|
||||
int err;
|
||||
@@ -303,6 +330,10 @@ static void __init bcm47xx_register_ssb(
|
||||
@@ -304,6 +331,10 @@ static void __init bcm47xx_register_ssb(
|
||||
memcpy(&mcore->serial_ports[1], &port, sizeof(port));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
--- a/drivers/mtd/maps/Kconfig
|
||||
+++ b/drivers/mtd/maps/Kconfig
|
||||
@@ -332,6 +332,12 @@ config MTD_CFI_FLAGADM
|
||||
Mapping for the Flaga digital module. If you don't have one, ignore
|
||||
this setting.
|
||||
|
||||
+config MTD_BCM47XX
|
||||
+ tristate "BCM47xx flash device"
|
||||
+ depends on MIPS && MTD_CFI && BCM47XX
|
||||
+ help
|
||||
+ Support for the flash chips on the BCM947xx board.
|
||||
+
|
||||
config MTD_SOLUTIONENGINE
|
||||
tristate "CFI Flash device mapped on Hitachi SolutionEngine"
|
||||
depends on SUPERH && SOLUTION_ENGINE && MTD_CFI && MTD_REDBOOT_PARTS
|
||||
--- a/drivers/mtd/maps/Makefile
|
||||
+++ b/drivers/mtd/maps/Makefile
|
||||
@@ -28,6 +28,7 @@ obj-$(CONFIG_MTD_PMC_MSP_EVM) += pmcms
|
||||
obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o
|
||||
obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
|
||||
obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o
|
||||
+obj-$(CONFIG_MTD_BCM47XX) += bcm47xx-flash.o
|
||||
obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o
|
||||
obj-$(CONFIG_MTD_SBC_GXX) += sbc_gxx.o
|
||||
obj-$(CONFIG_MTD_SC520CDP) += sc520cdp.o
|
|
@ -1,68 +0,0 @@
|
|||
--- a/drivers/mtd/maps/bcm47xx-flash.c
|
||||
+++ b/drivers/mtd/maps/bcm47xx-flash.c
|
||||
@@ -44,9 +44,7 @@
|
||||
#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>
|
||||
@@ -120,7 +118,6 @@ static struct map_info bcm47xx_map = {
|
||||
phys: WINDOW_ADDR,
|
||||
};
|
||||
|
||||
-#ifdef CONFIG_MTD_PARTITIONS
|
||||
|
||||
static struct mtd_partition bcm47xx_parts[] = {
|
||||
{ name: "cfe", offset: 0, size: 0, mask_flags: MTD_WRITEABLE, },
|
||||
@@ -552,7 +549,6 @@ init_mtd_partitions(struct mtd_info *mtd
|
||||
|
||||
return bcm47xx_parts;
|
||||
}
|
||||
-#endif
|
||||
|
||||
int __init init_bcm47xx_map(void)
|
||||
{
|
||||
@@ -561,10 +557,8 @@ int __init init_bcm47xx_map(void)
|
||||
#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;
|
||||
@@ -602,15 +596,13 @@ int __init init_bcm47xx_map(void)
|
||||
|
||||
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);
|
||||
+ ret = mtd_device_register(bcm47xx_mtd, parts, i);
|
||||
if (ret) {
|
||||
- printk(KERN_ERR "Flash: add_mtd_partitions failed\n");
|
||||
+ printk(KERN_ERR "Flash: mtd_device_register failed\n");
|
||||
goto fail;
|
||||
}
|
||||
-#endif
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -624,9 +616,7 @@ int __init init_bcm47xx_map(void)
|
||||
|
||||
void __exit cleanup_bcm47xx_map(void)
|
||||
{
|
||||
-#ifdef CONFIG_MTD_PARTITIONS
|
||||
- del_mtd_partitions(bcm47xx_mtd);
|
||||
-#endif
|
||||
+ mtd_device_unregister(bcm47xx_mtd);
|
||||
map_destroy(bcm47xx_mtd);
|
||||
iounmap((void *)bcm47xx_map.virt);
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
--- a/drivers/mtd/maps/bcm47xx-flash.c
|
||||
+++ b/drivers/mtd/maps/bcm47xx-flash.c
|
||||
@@ -46,11 +46,9 @@
|
||||
#include <linux/mtd/map.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/crc32.h>
|
||||
-#ifdef CONFIG_SSB
|
||||
-#include <linux/ssb/ssb.h>
|
||||
-#endif
|
||||
#include <asm/io.h>
|
||||
#include <asm/mach-bcm47xx/nvram.h>
|
||||
+#include <asm/mach-bcm47xx/bcm47xx.h>
|
||||
#include <asm/fw/cfe/cfe_api.h>
|
||||
|
||||
|
||||
@@ -90,9 +88,6 @@ struct trx_header {
|
||||
#define ROUTER_NETGEAR_WNR3500L 4
|
||||
#define ROUTER_SIMPLETECH_SIMPLESHARE 5
|
||||
|
||||
-#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)
|
||||
@@ -552,27 +547,42 @@ init_mtd_partitions(struct mtd_info *mtd
|
||||
|
||||
int __init init_bcm47xx_map(void)
|
||||
{
|
||||
-#ifdef CONFIG_SSB
|
||||
- struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
|
||||
+#ifdef CONFIG_BCM47XX_SSB
|
||||
+ struct ssb_mipscore *mcore_ssb;
|
||||
+#endif
|
||||
+#ifdef CONFIG_BCM47XX_BCMA
|
||||
+ struct bcma_drv_mips *mcore_bcma;
|
||||
#endif
|
||||
size_t size;
|
||||
int ret = 0;
|
||||
+ u32 window = 0;
|
||||
+ u32 window_size = 0;
|
||||
struct mtd_partition *parts;
|
||||
int i;
|
||||
|
||||
-#ifdef CONFIG_SSB
|
||||
- u32 window = mcore->flash_window;
|
||||
- u32 window_size = mcore->flash_window_size;
|
||||
+ switch (bcm47xx_active_bus_type) {
|
||||
+#ifdef CONFIG_BCM47XX_SSB
|
||||
+ case BCM47XX_BUS_TYPE_SSB:
|
||||
+ mcore_ssb = &bcm47xx_bus.ssb.mipscore;
|
||||
+ window = mcore_ssb->flash_window;
|
||||
+ window_size = mcore_ssb->flash_window_size;
|
||||
+ bcm47xx_map.bankwidth = mcore_ssb->flash_buswidth;
|
||||
+ break;
|
||||
+#endif
|
||||
+#ifdef CONFIG_BCM47XX_BCMA
|
||||
+ case BCM47XX_BUS_TYPE_BCMA:
|
||||
+ mcore_bcma = &bcm47xx_bus.bcma.bus.drv_mips;
|
||||
+ window = mcore_bcma->flash_window;
|
||||
+ window_size = mcore_bcma->flash_window_size;
|
||||
+ bcm47xx_map.bankwidth = mcore_bcma->flash_buswidth;
|
||||
+ break;
|
||||
+#endif
|
||||
+ }
|
||||
|
||||
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");
|
|
@ -1,6 +1,6 @@
|
|||
--- a/arch/mips/bcm47xx/nvram.c
|
||||
+++ b/arch/mips/bcm47xx/nvram.c
|
||||
@@ -114,3 +114,30 @@ int nvram_getenv(char *name, char *val,
|
||||
@@ -117,3 +117,30 @@ int nvram_getenv(char *name, char *val,
|
||||
return NVRAM_ERR_ENVNOTFOUND;
|
||||
}
|
||||
EXPORT_SYMBOL(nvram_getenv);
|
||||
|
@ -33,10 +33,10 @@
|
|||
+EXPORT_SYMBOL(nvram_get);
|
||||
--- a/arch/mips/bcm47xx/setup.c
|
||||
+++ b/arch/mips/bcm47xx/setup.c
|
||||
@@ -388,3 +388,20 @@ static int __init bcm47xx_register_bus_c
|
||||
@@ -438,3 +438,20 @@ static int __init bcm47xx_register_flash
|
||||
return 0;
|
||||
}
|
||||
device_initcall(bcm47xx_register_bus_complete);
|
||||
fs_initcall(bcm47xx_register_flash);
|
||||
+
|
||||
+static int __init bcm47xx_register_gpiodev(void)
|
||||
+{
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
-obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o
|
||||
--- a/arch/mips/bcm47xx/wgt634u.c
|
||||
+++ /dev/null
|
||||
@@ -1,169 +0,0 @@
|
||||
@@ -1,170 +0,0 @@
|
||||
-/*
|
||||
- * This file is subject to the terms and conditions of the GNU General Public
|
||||
- * License. See the file "COPYING" in the main directory of this archive
|
||||
|
@ -142,11 +142,12 @@
|
|||
- * machine. Use the MAC address as an heuristic. Netgear Inc. has
|
||||
- * been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx.
|
||||
- */
|
||||
- u8 *et0mac;
|
||||
-
|
||||
- if (bcm47xx_active_bus_type != BCM47XX_BUS_TYPE_SSB)
|
||||
- return -ENODEV;
|
||||
-
|
||||
- u8 *et0mac = bcm47xx_bus.ssb.sprom.et0mac;
|
||||
- et0mac = bcm47xx_bus.ssb.sprom.et0mac;
|
||||
-
|
||||
- if (et0mac[0] == 0x00 &&
|
||||
- ((et0mac[1] == 0x09 && et0mac[2] == 0x5b) ||
|
||||
|
|
|
@ -254,7 +254,7 @@ out the configuration than the in kernel cfe config reader.
|
|||
|
||||
/* Probe for NVRAM header */
|
||||
static void early_nvram_init(void)
|
||||
@@ -55,6 +57,25 @@ static void early_nvram_init(void)
|
||||
@@ -58,6 +60,25 @@ static void early_nvram_init(void)
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ out the configuration than the in kernel cfe config reader.
|
|||
|
||||
off = FLASH_MIN;
|
||||
while (off <= lim) {
|
||||
@@ -96,6 +117,12 @@ int nvram_getenv(char *name, char *val,
|
||||
@@ -99,6 +120,12 @@ int nvram_getenv(char *name, char *val,
|
||||
if (!nvram_buf[0])
|
||||
early_nvram_init();
|
||||
|
||||
|
@ -293,7 +293,7 @@ out the configuration than the in kernel cfe config reader.
|
|||
/* Look for name=value and return value */
|
||||
var = &nvram_buf[sizeof(struct nvram_header)];
|
||||
end = nvram_buf + sizeof(nvram_buf) - 2;
|
||||
@@ -125,6 +152,9 @@ char *nvram_get(const char *name)
|
||||
@@ -128,6 +155,9 @@ char *nvram_get(const char *name)
|
||||
if (!nvram_buf[0])
|
||||
early_nvram_init();
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
ssb_printk(KERN_ERR PFX
|
||||
--- a/include/linux/ssb/ssb.h
|
||||
+++ b/include/linux/ssb/ssb.h
|
||||
@@ -155,9 +155,16 @@ struct ssb_bus_ops {
|
||||
@@ -157,9 +157,16 @@ struct ssb_bus_ops {
|
||||
#define SSB_DEV_MINI_MACPHY 0x823
|
||||
#define SSB_DEV_ARM_1176 0x824
|
||||
#define SSB_DEV_ARM_7TDMI 0x825
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/arch/mips/bcm47xx/setup.c
|
||||
+++ b/arch/mips/bcm47xx/setup.c
|
||||
@@ -273,6 +273,10 @@ static int bcm47xx_get_invariants(struct
|
||||
@@ -274,6 +274,10 @@ static int bcm47xx_get_invariants(struct
|
||||
if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
|
||||
iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
|
||||
|
||||
|
|
|
@ -185,7 +185,7 @@
|
|||
{
|
||||
struct ssb_bus *bus = pc->dev->bus;
|
||||
u16 chipid_top;
|
||||
@@ -403,28 +408,129 @@ static int pcicore_is_in_hostmode(struct
|
||||
@@ -403,25 +408,133 @@ static int pcicore_is_in_hostmode(struct
|
||||
}
|
||||
#endif /* CONFIG_SSB_PCICORE_HOSTMODE */
|
||||
|
||||
|
@ -298,8 +298,17 @@
|
|||
-static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
|
||||
+static void __devinit ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
|
||||
{
|
||||
+ ssb_pcicore_fix_sprom_core_index(pc);
|
||||
+
|
||||
/* Disable PCI interrupts. */
|
||||
ssb_write32(pc->dev, SSB_INTVEC, 0);
|
||||
+
|
||||
+ /* Additional PCIe always once-executed workarounds */
|
||||
+ if (pc->dev->id.coreid == SSB_DEV_PCIE) {
|
||||
+ ssb_pcicore_serdes_workaround(pc);
|
||||
+ /* TODO: ASPM */
|
||||
+ /* TODO: Clock Request Update */
|
||||
+ }
|
||||
}
|
||||
|
||||
-void ssb_pcicore_init(struct ssb_pcicore *pc)
|
||||
|
@ -314,25 +323,6 @@
|
|||
if (!ssb_device_is_enabled(dev))
|
||||
ssb_device_enable(dev, 0);
|
||||
|
||||
+ ssb_pcicore_fix_sprom_core_index(pc);
|
||||
+
|
||||
#ifdef CONFIG_SSB_PCICORE_HOSTMODE
|
||||
pc->hostmode = pcicore_is_in_hostmode(pc);
|
||||
if (pc->hostmode)
|
||||
@@ -432,6 +538,13 @@ void ssb_pcicore_init(struct ssb_pcicore
|
||||
#endif /* CONFIG_SSB_PCICORE_HOSTMODE */
|
||||
if (!pc->hostmode)
|
||||
ssb_pcicore_init_clientmode(pc);
|
||||
+
|
||||
+ /* Additional PCIe always once-executed workarounds */
|
||||
+ if (dev->id.coreid == SSB_DEV_PCIE) {
|
||||
+ ssb_pcicore_serdes_workaround(pc);
|
||||
+ /* TODO: ASPM */
|
||||
+ /* TODO: Clock Request Update */
|
||||
+ }
|
||||
}
|
||||
|
||||
static u32 ssb_pcie_read(struct ssb_pcicore *pc, u32 address)
|
||||
@@ -446,11 +559,35 @@ static void ssb_pcie_write(struct ssb_pc
|
||||
pcicore_write32(pc, 0x134, data);
|
||||
}
|
||||
|
@ -629,7 +619,19 @@
|
|||
}
|
||||
|
||||
int ssb_device_is_enabled(struct ssb_device *dev)
|
||||
@@ -1309,20 +1309,20 @@ EXPORT_SYMBOL(ssb_bus_may_powerdown);
|
||||
@@ -1266,7 +1266,10 @@ u32 ssb_dma_translation(struct ssb_devic
|
||||
case SSB_BUSTYPE_SSB:
|
||||
return 0;
|
||||
case SSB_BUSTYPE_PCI:
|
||||
- return SSB_PCI_DMA;
|
||||
+ if (ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64)
|
||||
+ return SSB_PCIE_DMA_H32;
|
||||
+ else
|
||||
+ return SSB_PCI_DMA;
|
||||
default:
|
||||
__ssb_dma_not_implemented(dev);
|
||||
}
|
||||
@@ -1309,20 +1312,20 @@ EXPORT_SYMBOL(ssb_bus_may_powerdown);
|
||||
|
||||
int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl)
|
||||
{
|
||||
|
@ -654,7 +656,7 @@
|
|||
return 0;
|
||||
error:
|
||||
ssb_printk(KERN_ERR PFX "Bus powerup failed\n");
|
||||
@@ -1330,6 +1330,37 @@ error:
|
||||
@@ -1330,6 +1333,37 @@ error:
|
||||
}
|
||||
EXPORT_SYMBOL(ssb_bus_powerup);
|
||||
|
||||
|
@ -724,6 +726,22 @@
|
|||
err = 0;
|
||||
goto out_free;
|
||||
}
|
||||
@@ -728,12 +734,9 @@ out_free:
|
||||
static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
|
||||
struct ssb_boardinfo *bi)
|
||||
{
|
||||
- pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
|
||||
- &bi->vendor);
|
||||
- pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
|
||||
- &bi->type);
|
||||
- pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
|
||||
- &bi->rev);
|
||||
+ bi->vendor = bus->host_pci->subsystem_vendor;
|
||||
+ bi->type = bus->host_pci->subsystem_device;
|
||||
+ bi->rev = bus->host_pci->revision;
|
||||
}
|
||||
|
||||
int ssb_pci_get_invariants(struct ssb_bus *bus,
|
||||
--- a/drivers/ssb/pcihost_wrapper.c
|
||||
+++ b/drivers/ssb/pcihost_wrapper.c
|
||||
@@ -53,8 +53,8 @@ static int ssb_pcihost_resume(struct pci
|
||||
|
@ -856,7 +874,25 @@
|
|||
/* core.c */
|
||||
--- a/include/linux/ssb/ssb.h
|
||||
+++ b/include/linux/ssb/ssb.h
|
||||
@@ -308,7 +308,7 @@ struct ssb_bus {
|
||||
@@ -27,6 +27,8 @@ struct ssb_sprom {
|
||||
u8 et1mdcport; /* MDIO for enet1 */
|
||||
u8 board_rev; /* Board revision number from SPROM. */
|
||||
u8 country_code; /* Country Code */
|
||||
+ u16 leddc_on_time; /* LED Powersave Duty Cycle On Count */
|
||||
+ u16 leddc_off_time; /* LED Powersave Duty Cycle Off Count */
|
||||
u8 ant_available_a; /* 2GHz antenna available bits (up to 4) */
|
||||
u8 ant_available_bg; /* 5GHz antenna available bits (up to 4) */
|
||||
u16 pa0b0;
|
||||
@@ -99,7 +101,7 @@ struct ssb_sprom {
|
||||
struct ssb_boardinfo {
|
||||
u16 vendor;
|
||||
u16 type;
|
||||
- u16 rev;
|
||||
+ u8 rev;
|
||||
};
|
||||
|
||||
|
||||
@@ -308,7 +310,7 @@ struct ssb_bus {
|
||||
|
||||
/* ID information about the Chip. */
|
||||
u16 chip_id;
|
||||
|
@ -865,7 +901,7 @@
|
|||
u16 sprom_offset;
|
||||
u16 sprom_size; /* number of words in sprom */
|
||||
u8 chip_package;
|
||||
@@ -404,7 +404,9 @@ extern bool ssb_is_sprom_available(struc
|
||||
@@ -404,7 +406,9 @@ extern bool ssb_is_sprom_available(struc
|
||||
|
||||
/* Set a fallback SPROM.
|
||||
* See kdoc at the function definition for complete documentation. */
|
||||
|
@ -876,7 +912,7 @@
|
|||
|
||||
/* Suspend a SSB bus.
|
||||
* Call this from the parent bus suspend routine. */
|
||||
@@ -518,6 +520,7 @@ extern int ssb_bus_may_powerdown(struct
|
||||
@@ -518,6 +522,7 @@ extern int ssb_bus_may_powerdown(struct
|
||||
* Otherwise static always-on powercontrol will be used. */
|
||||
extern int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl);
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
obj-$(CONFIG_STAGING) += staging/
|
||||
--- /dev/null
|
||||
+++ b/drivers/bcma/Kconfig
|
||||
@@ -0,0 +1,38 @@
|
||||
@@ -0,0 +1,44 @@
|
||||
+config BCMA_POSSIBLE
|
||||
+ bool
|
||||
+ depends on HAS_IOMEM && HAS_DMA
|
||||
|
@ -101,6 +101,12 @@
|
|||
+ bool "Support for BCMA on PCI-host bus"
|
||||
+ depends on BCMA_HOST_PCI_POSSIBLE
|
||||
+
|
||||
+config BCMA_DRIVER_PCI_HOSTMODE
|
||||
+ bool "Driver for PCI core working in hostmode"
|
||||
+ depends on BCMA && MIPS
|
||||
+ help
|
||||
+ PCI core hostmode operation (external PCI bus).
|
||||
+
|
||||
+config BCMA_DEBUG
|
||||
+ bool "BCMA debugging"
|
||||
+ depends on BCMA
|
||||
|
@ -112,10 +118,11 @@
|
|||
+endmenu
|
||||
--- /dev/null
|
||||
+++ b/drivers/bcma/Makefile
|
||||
@@ -0,0 +1,7 @@
|
||||
@@ -0,0 +1,8 @@
|
||||
+bcma-y += main.o scan.o core.o sprom.o
|
||||
+bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
|
||||
+bcma-y += driver_pci.o
|
||||
+bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
|
||||
+bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
|
||||
+obj-$(CONFIG_BCMA) += bcma.o
|
||||
+
|
||||
|
@ -150,7 +157,7 @@
|
|||
+- Create kernel Documentation (use info from README)
|
||||
--- /dev/null
|
||||
+++ b/drivers/bcma/bcma_private.h
|
||||
@@ -0,0 +1,31 @@
|
||||
@@ -0,0 +1,35 @@
|
||||
+#ifndef LINUX_BCMA_PRIVATE_H_
|
||||
+#define LINUX_BCMA_PRIVATE_H_
|
||||
+
|
||||
|
@ -181,10 +188,14 @@
|
|||
+extern void __exit bcma_host_pci_exit(void);
|
||||
+#endif /* CONFIG_BCMA_HOST_PCI */
|
||||
+
|
||||
+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
|
||||
+void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
|
||||
+#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
|
||||
+
|
||||
+#endif
|
||||
--- /dev/null
|
||||
+++ b/drivers/bcma/core.c
|
||||
@@ -0,0 +1,52 @@
|
||||
@@ -0,0 +1,124 @@
|
||||
+/*
|
||||
+ * Broadcom specific AMBA
|
||||
+ * Core ops
|
||||
|
@ -237,9 +248,81 @@
|
|||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(bcma_core_enable);
|
||||
+
|
||||
+void bcma_core_set_clockmode(struct bcma_device *core,
|
||||
+ enum bcma_clkmode clkmode)
|
||||
+{
|
||||
+ u16 i;
|
||||
+
|
||||
+ WARN_ON(core->id.id != BCMA_CORE_CHIPCOMMON &&
|
||||
+ core->id.id != BCMA_CORE_PCIE &&
|
||||
+ core->id.id != BCMA_CORE_80211);
|
||||
+
|
||||
+ switch (clkmode) {
|
||||
+ case BCMA_CLKMODE_FAST:
|
||||
+ bcma_set32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT);
|
||||
+ udelay(64);
|
||||
+ for (i = 0; i < 1500; i++) {
|
||||
+ if (bcma_read32(core, BCMA_CLKCTLST) &
|
||||
+ BCMA_CLKCTLST_HAVEHT) {
|
||||
+ i = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+ udelay(10);
|
||||
+ }
|
||||
+ if (i)
|
||||
+ pr_err("HT force timeout\n");
|
||||
+ break;
|
||||
+ case BCMA_CLKMODE_DYNAMIC:
|
||||
+ pr_warn("Dynamic clockmode not supported yet!\n");
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(bcma_core_set_clockmode);
|
||||
+
|
||||
+void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on)
|
||||
+{
|
||||
+ u16 i;
|
||||
+
|
||||
+ WARN_ON(req & ~BCMA_CLKCTLST_EXTRESREQ);
|
||||
+ WARN_ON(status & ~BCMA_CLKCTLST_EXTRESST);
|
||||
+
|
||||
+ if (on) {
|
||||
+ bcma_set32(core, BCMA_CLKCTLST, req);
|
||||
+ for (i = 0; i < 10000; i++) {
|
||||
+ if ((bcma_read32(core, BCMA_CLKCTLST) & status) ==
|
||||
+ status) {
|
||||
+ i = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+ udelay(10);
|
||||
+ }
|
||||
+ if (i)
|
||||
+ pr_err("PLL enable timeout\n");
|
||||
+ } else {
|
||||
+ pr_warn("Disabling PLL not supported yet!\n");
|
||||
+ }
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
|
||||
+
|
||||
+u32 bcma_core_dma_translation(struct bcma_device *core)
|
||||
+{
|
||||
+ switch (core->bus->hosttype) {
|
||||
+ case BCMA_HOSTTYPE_PCI:
|
||||
+ if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64)
|
||||
+ return BCMA_DMA_TRANSLATION_DMA64_CMT;
|
||||
+ else
|
||||
+ return BCMA_DMA_TRANSLATION_DMA32_CMT;
|
||||
+ default:
|
||||
+ pr_err("DMA translation unknown for host %d\n",
|
||||
+ core->bus->hosttype);
|
||||
+ }
|
||||
+ return BCMA_DMA_TRANSLATION_NONE;
|
||||
+}
|
||||
+EXPORT_SYMBOL(bcma_core_dma_translation);
|
||||
--- /dev/null
|
||||
+++ b/drivers/bcma/driver_chipcommon.c
|
||||
@@ -0,0 +1,89 @@
|
||||
@@ -0,0 +1,103 @@
|
||||
+/*
|
||||
+ * Broadcom specific AMBA
|
||||
+ * ChipCommon core driver
|
||||
|
@ -265,6 +348,9 @@
|
|||
+
|
||||
+void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
|
||||
+{
|
||||
+ u32 leddc_on = 10;
|
||||
+ u32 leddc_off = 90;
|
||||
+
|
||||
+ if (cc->core->id.rev >= 11)
|
||||
+ cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
|
||||
+ cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
|
||||
|
@ -280,6 +366,17 @@
|
|||
+ bcma_pmu_init(cc);
|
||||
+ if (cc->capabilities & BCMA_CC_CAP_PCTL)
|
||||
+ pr_err("Power control not implemented!\n");
|
||||
+
|
||||
+ if (cc->core->id.rev >= 16) {
|
||||
+ if (cc->core->bus->sprom.leddc_on_time &&
|
||||
+ cc->core->bus->sprom.leddc_off_time) {
|
||||
+ leddc_on = cc->core->bus->sprom.leddc_on_time;
|
||||
+ leddc_off = cc->core->bus->sprom.leddc_off_time;
|
||||
+ }
|
||||
+ bcma_cc_write32(cc, BCMA_CC_GPIOTIMER,
|
||||
+ ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
|
||||
+ (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
|
||||
|
@ -472,7 +569,7 @@
|
|||
+}
|
||||
--- /dev/null
|
||||
+++ b/drivers/bcma/driver_pci.c
|
||||
@@ -0,0 +1,187 @@
|
||||
@@ -0,0 +1,223 @@
|
||||
+/*
|
||||
+ * Broadcom specific AMBA
|
||||
+ * PCI Core
|
||||
|
@ -632,11 +729,47 @@
|
|||
+ * Init.
|
||||
+ **************************************************/
|
||||
+
|
||||
+void bcma_core_pci_init(struct bcma_drv_pci *pc)
|
||||
+static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
|
||||
+{
|
||||
+ bcma_pcicore_serdes_workaround(pc);
|
||||
+}
|
||||
+
|
||||
+static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
|
||||
+{
|
||||
+ struct bcma_bus *bus = pc->core->bus;
|
||||
+ u16 chipid_top;
|
||||
+
|
||||
+ chipid_top = (bus->chipinfo.id & 0xFF00);
|
||||
+ if (chipid_top != 0x4700 &&
|
||||
+ chipid_top != 0x5300)
|
||||
+ return false;
|
||||
+
|
||||
+ if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI)
|
||||
+ return false;
|
||||
+
|
||||
+#if 0
|
||||
+ /* TODO: on BCMA we use address from EROM instead of magic formula */
|
||||
+ u32 tmp;
|
||||
+ return !mips_busprobe32(tmp, (bus->mmio +
|
||||
+ (pc->core->core_index * BCMA_CORE_SIZE)));
|
||||
+#endif
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+void bcma_core_pci_init(struct bcma_drv_pci *pc)
|
||||
+{
|
||||
+ if (bcma_core_pci_is_in_hostmode(pc)) {
|
||||
+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
|
||||
+ bcma_core_pci_hostmode_init(pc);
|
||||
+#else
|
||||
+ pr_err("Driver compiled without support for hostmode PCI\n");
|
||||
+#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
|
||||
+ } else {
|
||||
+ bcma_core_pci_clientmode_init(pc);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
|
||||
+ bool enable)
|
||||
+{
|
||||
|
@ -916,7 +1049,7 @@
|
|||
+}
|
||||
--- /dev/null
|
||||
+++ b/drivers/bcma/main.c
|
||||
@@ -0,0 +1,255 @@
|
||||
@@ -0,0 +1,257 @@
|
||||
+/*
|
||||
+ * Broadcom specific AMBA
|
||||
+ * Bus subsystem
|
||||
|
@ -1068,7 +1201,9 @@
|
|||
+
|
||||
+ /* Try to get SPROM */
|
||||
+ err = bcma_sprom_get(bus);
|
||||
+ if (err) {
|
||||
+ if (err == -ENOENT) {
|
||||
+ pr_err("No SPROM available\n");
|
||||
+ } else if (err) {
|
||||
+ pr_err("Failed to get SPROM: %d\n", err);
|
||||
+ return -ENOENT;
|
||||
+ }
|
||||
|
@ -1596,7 +1731,7 @@
|
|||
+#endif /* BCMA_SCAN_H_ */
|
||||
--- /dev/null
|
||||
+++ b/include/linux/bcma/bcma.h
|
||||
@@ -0,0 +1,250 @@
|
||||
@@ -0,0 +1,271 @@
|
||||
+#ifndef LINUX_BCMA_H_
|
||||
+#define LINUX_BCMA_H_
|
||||
+
|
||||
|
@ -1624,6 +1759,11 @@
|
|||
+ u8 pkg;
|
||||
+};
|
||||
+
|
||||
+enum bcma_clkmode {
|
||||
+ BCMA_CLKMODE_FAST,
|
||||
+ BCMA_CLKMODE_DYNAMIC,
|
||||
+};
|
||||
+
|
||||
+struct bcma_host_ops {
|
||||
+ u8 (*read8)(struct bcma_device *core, u16 offset);
|
||||
+ u16 (*read16)(struct bcma_device *core, u16 offset);
|
||||
|
@ -1842,14 +1982,30 @@
|
|||
+ core->bus->ops->awrite32(core, offset, value);
|
||||
+}
|
||||
+
|
||||
+#define bcma_mask32(cc, offset, mask) \
|
||||
+ bcma_write32(cc, offset, bcma_read32(cc, offset) & (mask))
|
||||
+#define bcma_set32(cc, offset, set) \
|
||||
+ bcma_write32(cc, offset, bcma_read32(cc, offset) | (set))
|
||||
+#define bcma_maskset32(cc, offset, mask, set) \
|
||||
+ bcma_write32(cc, offset, (bcma_read32(cc, offset) & (mask)) | (set))
|
||||
+
|
||||
+extern bool bcma_core_is_enabled(struct bcma_device *core);
|
||||
+extern void bcma_core_disable(struct bcma_device *core, u32 flags);
|
||||
+extern int bcma_core_enable(struct bcma_device *core, u32 flags);
|
||||
+extern void bcma_core_set_clockmode(struct bcma_device *core,
|
||||
+ enum bcma_clkmode clkmode);
|
||||
+extern void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status,
|
||||
+ bool on);
|
||||
+#define BCMA_DMA_TRANSLATION_MASK 0xC0000000
|
||||
+#define BCMA_DMA_TRANSLATION_NONE 0x00000000
|
||||
+#define BCMA_DMA_TRANSLATION_DMA32_CMT 0x40000000 /* Client Mode Translation for 32-bit DMA */
|
||||
+#define BCMA_DMA_TRANSLATION_DMA64_CMT 0x80000000 /* Client Mode Translation for 64-bit DMA */
|
||||
+extern u32 bcma_core_dma_translation(struct bcma_device *core);
|
||||
+
|
||||
+#endif /* LINUX_BCMA_H_ */
|
||||
--- /dev/null
|
||||
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
@@ -0,0 +1,303 @@
|
||||
@@ -0,0 +1,296 @@
|
||||
+#ifndef LINUX_BCMA_DRIVER_CC_H_
|
||||
+#define LINUX_BCMA_DRIVER_CC_H_
|
||||
+
|
||||
|
@ -2031,15 +2187,7 @@
|
|||
+#define BCMA_CC_PROG_WAITCNT 0x0124
|
||||
+#define BCMA_CC_FLASH_CFG 0x0128
|
||||
+#define BCMA_CC_FLASH_WAITCNT 0x012C
|
||||
+#define BCMA_CC_CLKCTLST 0x01E0 /* Clock control and status (rev >= 20) */
|
||||
+#define BCMA_CC_CLKCTLST_FORCEALP 0x00000001 /* Force ALP request */
|
||||
+#define BCMA_CC_CLKCTLST_FORCEHT 0x00000002 /* Force HT request */
|
||||
+#define BCMA_CC_CLKCTLST_FORCEILP 0x00000004 /* Force ILP request */
|
||||
+#define BCMA_CC_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */
|
||||
+#define BCMA_CC_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */
|
||||
+#define BCMA_CC_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */
|
||||
+#define BCMA_CC_CLKCTLST_HAVEHT 0x00010000 /* HT available */
|
||||
+#define BCMA_CC_CLKCTLST_HAVEALP 0x00020000 /* APL available */
|
||||
+/* 0x1E0 is defined as shared BCMA_CLKCTLST */
|
||||
+#define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */
|
||||
+#define BCMA_CC_UART0_DATA 0x0300
|
||||
+#define BCMA_CC_UART0_IMR 0x0304
|
||||
|
@ -2096,7 +2244,8 @@
|
|||
+#define BCMA_CC_REGCTL_DATA 0x065C
|
||||
+#define BCMA_CC_PLLCTL_ADDR 0x0660
|
||||
+#define BCMA_CC_PLLCTL_DATA 0x0664
|
||||
+#define BCMA_CC_SPROM 0x0830 /* SPROM beginning */
|
||||
+#define BCMA_CC_SPROM 0x0800 /* SPROM beginning */
|
||||
+#define BCMA_CC_SPROM_PCIE6 0x0830 /* SPROM beginning on PCIe rev >= 6 */
|
||||
+
|
||||
+/* Data for the PMU, if available.
|
||||
+ * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
|
||||
|
@ -2249,17 +2398,42 @@
|
|||
+#endif /* LINUX_BCMA_DRIVER_PCI_H_ */
|
||||
--- /dev/null
|
||||
+++ b/include/linux/bcma/bcma_regs.h
|
||||
@@ -0,0 +1,34 @@
|
||||
@@ -0,0 +1,59 @@
|
||||
+#ifndef LINUX_BCMA_REGS_H_
|
||||
+#define LINUX_BCMA_REGS_H_
|
||||
+
|
||||
+/* Some single registers are shared between many cores */
|
||||
+/* BCMA_CLKCTLST: ChipCommon (rev >= 20), PCIe, 80211 */
|
||||
+#define BCMA_CLKCTLST 0x01E0 /* Clock control and status */
|
||||
+#define BCMA_CLKCTLST_FORCEALP 0x00000001 /* Force ALP request */
|
||||
+#define BCMA_CLKCTLST_FORCEHT 0x00000002 /* Force HT request */
|
||||
+#define BCMA_CLKCTLST_FORCEILP 0x00000004 /* Force ILP request */
|
||||
+#define BCMA_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */
|
||||
+#define BCMA_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */
|
||||
+#define BCMA_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */
|
||||
+#define BCMA_CLKCTLST_EXTRESREQ 0x00000700 /* Mask of external resource requests */
|
||||
+#define BCMA_CLKCTLST_HAVEALP 0x00010000 /* ALP available */
|
||||
+#define BCMA_CLKCTLST_HAVEHT 0x00020000 /* HT available */
|
||||
+#define BCMA_CLKCTLST_BP_ON_ALP 0x00040000 /* RO: running on ALP clock */
|
||||
+#define BCMA_CLKCTLST_BP_ON_HT 0x00080000 /* RO: running on HT clock */
|
||||
+#define BCMA_CLKCTLST_EXTRESST 0x07000000 /* Mask of external resource status */
|
||||
+/* Is there any BCM4328 on BCMA bus? */
|
||||
+#define BCMA_CLKCTLST_4328A0_HAVEHT 0x00010000 /* 4328a0 has reversed bits */
|
||||
+#define BCMA_CLKCTLST_4328A0_HAVEALP 0x00020000 /* 4328a0 has reversed bits */
|
||||
+
|
||||
+/* Agent registers (common for every core) */
|
||||
+#define BCMA_IOCTL 0x0408
|
||||
+#define BCMA_IOCTL 0x0408 /* IO control */
|
||||
+#define BCMA_IOCTL_CLK 0x0001
|
||||
+#define BCMA_IOCTL_FGC 0x0002
|
||||
+#define BCMA_IOCTL_CORE_BITS 0x3FFC
|
||||
+#define BCMA_IOCTL_PME_EN 0x4000
|
||||
+#define BCMA_IOCTL_BIST_EN 0x8000
|
||||
+#define BCMA_IOST 0x0500 /* IO status */
|
||||
+#define BCMA_IOST_CORE_BITS 0x0FFF
|
||||
+#define BCMA_IOST_DMA64 0x1000
|
||||
+#define BCMA_IOST_GATED_CLK 0x2000
|
||||
+#define BCMA_IOST_BIST_ERROR 0x4000
|
||||
+#define BCMA_IOST_BIST_DONE 0x8000
|
||||
+#define BCMA_RESET_CTL 0x0800
|
||||
+#define BCMA_RESET_CTL_RESET 0x0001
|
||||
+
|
||||
|
@ -2350,7 +2524,7 @@
|
|||
sizeof(struct virtio_device_id), "virtio",
|
||||
--- /dev/null
|
||||
+++ b/drivers/bcma/sprom.c
|
||||
@@ -0,0 +1,162 @@
|
||||
@@ -0,0 +1,171 @@
|
||||
+/*
|
||||
+ * Broadcom specific AMBA
|
||||
+ * SPROM reading
|
||||
|
@ -2373,12 +2547,12 @@
|
|||
+ * R/W ops.
|
||||
+ **************************************************/
|
||||
+
|
||||
+static void bcma_sprom_read(struct bcma_bus *bus, u16 *sprom)
|
||||
+static void bcma_sprom_read(struct bcma_bus *bus, u16 offset, u16 *sprom)
|
||||
+{
|
||||
+ int i;
|
||||
+ for (i = 0; i < SSB_SPROMSIZE_WORDS_R4; i++)
|
||||
+ sprom[i] = bcma_read16(bus->drv_cc.core,
|
||||
+ BCMA_CC_SPROM + (i * 2));
|
||||
+ offset + (i * 2));
|
||||
+}
|
||||
+
|
||||
+/**************************************************
|
||||
|
@ -2465,7 +2639,7 @@
|
|||
+ return err;
|
||||
+
|
||||
+ revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_REV;
|
||||
+ if (revision != 8) {
|
||||
+ if (revision != 8 && revision != 9) {
|
||||
+ pr_err("Unsupported SPROM revision: %d\n", revision);
|
||||
+ return -ENOENT;
|
||||
+ }
|
||||
|
@ -2490,18 +2664,27 @@
|
|||
+
|
||||
+int bcma_sprom_get(struct bcma_bus *bus)
|
||||
+{
|
||||
+ u16 offset;
|
||||
+ u16 *sprom;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ if (!bus->drv_cc.core)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
|
||||
+ return -ENOENT;
|
||||
+
|
||||
+ sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!sprom)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ bcma_sprom_read(bus, sprom);
|
||||
+ /* Most cards have SPROM moved by additional offset 0x30 (48 dwords).
|
||||
+ * According to brcm80211 this applies to cards with PCIe rev >= 6
|
||||
+ * TODO: understand this condition and use it */
|
||||
+ offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM :
|
||||
+ BCMA_CC_SPROM_PCIE6;
|
||||
+ bcma_sprom_read(bus, offset, sprom);
|
||||
+
|
||||
+ err = bcma_sprom_valid(sprom);
|
||||
+ if (err)
|
||||
|
@ -2513,3 +2696,20 @@
|
|||
+ kfree(sprom);
|
||||
+ return err;
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/drivers/bcma/driver_pci_host.c
|
||||
@@ -0,0 +1,14 @@
|
||||
+/*
|
||||
+ * Broadcom specific AMBA
|
||||
+ * PCI Core in hostmode
|
||||
+ *
|
||||
+ * Licensed under the GNU/GPL. See COPYING for details.
|
||||
+ */
|
||||
+
|
||||
+#include "bcma_private.h"
|
||||
+#include <linux/bcma/bcma.h>
|
||||
+
|
||||
+void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
|
||||
+{
|
||||
+ pr_err("No support for PCI core in hostmode yet\n");
|
||||
+}
|
||||
|
|
|
@ -17,3 +17,13 @@
|
|||
|
||||
config SSB_PCMCIAHOST_POSSIBLE
|
||||
bool
|
||||
--- a/drivers/bcma/Kconfig
|
||||
+++ b/drivers/bcma/Kconfig
|
||||
@@ -17,6 +17,7 @@ config BCMA
|
||||
config BCMA_BLOCKIO
|
||||
bool
|
||||
depends on BCMA
|
||||
+ default y
|
||||
|
||||
config BCMA_HOST_PCI_POSSIBLE
|
||||
bool
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
endif # BLOCK
|
||||
|
||||
@@ -177,6 +176,10 @@ source "fs/hfsplus/Kconfig"
|
||||
@@ -193,6 +192,10 @@ source "fs/hfsplus/Kconfig"
|
||||
source "fs/befs/Kconfig"
|
||||
source "fs/bfs/Kconfig"
|
||||
source "fs/efs/Kconfig"
|
||||
|
|
|
@ -179,6 +179,36 @@
|
|||
case SSB_PLLTYPE_1: /* 48Mhz base, 3 dividers */
|
||||
case SSB_PLLTYPE_3: /* 25Mhz, 2 dividers */
|
||||
case SSB_PLLTYPE_4: /* 48Mhz, 4 dividers */
|
||||
@@ -1265,7 +1266,10 @@ u32 ssb_dma_translation(struct ssb_devic
|
||||
case SSB_BUSTYPE_SSB:
|
||||
return 0;
|
||||
case SSB_BUSTYPE_PCI:
|
||||
- return SSB_PCI_DMA;
|
||||
+ if (ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64)
|
||||
+ return SSB_PCIE_DMA_H32;
|
||||
+ else
|
||||
+ return SSB_PCI_DMA;
|
||||
default:
|
||||
__ssb_dma_not_implemented(dev);
|
||||
}
|
||||
--- a/drivers/ssb/pci.c
|
||||
+++ b/drivers/ssb/pci.c
|
||||
@@ -734,12 +734,9 @@ out_free:
|
||||
static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
|
||||
struct ssb_boardinfo *bi)
|
||||
{
|
||||
- pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
|
||||
- &bi->vendor);
|
||||
- pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
|
||||
- &bi->type);
|
||||
- pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
|
||||
- &bi->rev);
|
||||
+ bi->vendor = bus->host_pci->subsystem_vendor;
|
||||
+ bi->type = bus->host_pci->subsystem_device;
|
||||
+ bi->rev = bus->host_pci->revision;
|
||||
}
|
||||
|
||||
int ssb_pci_get_invariants(struct ssb_bus *bus,
|
||||
--- a/drivers/ssb/pcihost_wrapper.c
|
||||
+++ b/drivers/ssb/pcihost_wrapper.c
|
||||
@@ -53,8 +53,8 @@ static int ssb_pcihost_resume(struct pci
|
||||
|
@ -213,3 +243,23 @@
|
|||
bus->chip_package = 0;
|
||||
} else {
|
||||
bus->chip_id = 0x4710;
|
||||
--- a/include/linux/ssb/ssb.h
|
||||
+++ b/include/linux/ssb/ssb.h
|
||||
@@ -27,6 +27,8 @@ struct ssb_sprom {
|
||||
u8 et1mdcport; /* MDIO for enet1 */
|
||||
u8 board_rev; /* Board revision number from SPROM. */
|
||||
u8 country_code; /* Country Code */
|
||||
+ u16 leddc_on_time; /* LED Powersave Duty Cycle On Count */
|
||||
+ u16 leddc_off_time; /* LED Powersave Duty Cycle Off Count */
|
||||
u8 ant_available_a; /* 2GHz antenna available bits (up to 4) */
|
||||
u8 ant_available_bg; /* 5GHz antenna available bits (up to 4) */
|
||||
u16 pa0b0;
|
||||
@@ -99,7 +101,7 @@ struct ssb_sprom {
|
||||
struct ssb_boardinfo {
|
||||
u16 vendor;
|
||||
u16 type;
|
||||
- u16 rev;
|
||||
+ u8 rev;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -12,17 +12,33 @@
|
|||
config BCMA_HOST_PCI_POSSIBLE
|
||||
bool
|
||||
depends on BCMA && PCI = y
|
||||
@@ -22,6 +27,12 @@ config BCMA_HOST_PCI
|
||||
bool "Support for BCMA on PCI-host bus"
|
||||
depends on BCMA_HOST_PCI_POSSIBLE
|
||||
|
||||
+config BCMA_DRIVER_PCI_HOSTMODE
|
||||
+ bool "Driver for PCI core working in hostmode"
|
||||
+ depends on BCMA && MIPS
|
||||
+ help
|
||||
+ PCI core hostmode operation (external PCI bus).
|
||||
+
|
||||
config BCMA_DEBUG
|
||||
bool "BCMA debugging"
|
||||
depends on BCMA
|
||||
--- a/drivers/bcma/Makefile
|
||||
+++ b/drivers/bcma/Makefile
|
||||
@@ -1,4 +1,4 @@
|
||||
@@ -1,6 +1,7 @@
|
||||
-bcma-y += main.o scan.o core.o
|
||||
+bcma-y += main.o scan.o core.o sprom.o
|
||||
bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
|
||||
bcma-y += driver_pci.o
|
||||
+bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
|
||||
bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
|
||||
obj-$(CONFIG_BCMA) += bcma.o
|
||||
|
||||
--- a/drivers/bcma/bcma_private.h
|
||||
+++ b/drivers/bcma/bcma_private.h
|
||||
@@ -13,12 +13,15 @@
|
||||
@@ -13,16 +13,23 @@
|
||||
struct bcma_bus;
|
||||
|
||||
/* main.c */
|
||||
|
@ -40,6 +56,14 @@
|
|||
#ifdef CONFIG_BCMA_HOST_PCI
|
||||
/* host_pci.c */
|
||||
extern int __init bcma_host_pci_init(void);
|
||||
extern void __exit bcma_host_pci_exit(void);
|
||||
#endif /* CONFIG_BCMA_HOST_PCI */
|
||||
|
||||
+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
|
||||
+void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
|
||||
+#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
|
||||
+
|
||||
#endif
|
||||
--- a/drivers/bcma/core.c
|
||||
+++ b/drivers/bcma/core.c
|
||||
@@ -19,7 +19,7 @@ bool bcma_core_is_enabled(struct bcma_de
|
||||
|
@ -59,6 +83,82 @@
|
|||
|
||||
int bcma_core_enable(struct bcma_device *core, u32 flags)
|
||||
{
|
||||
@@ -49,3 +50,75 @@ int bcma_core_enable(struct bcma_device
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_core_enable);
|
||||
+
|
||||
+void bcma_core_set_clockmode(struct bcma_device *core,
|
||||
+ enum bcma_clkmode clkmode)
|
||||
+{
|
||||
+ u16 i;
|
||||
+
|
||||
+ WARN_ON(core->id.id != BCMA_CORE_CHIPCOMMON &&
|
||||
+ core->id.id != BCMA_CORE_PCIE &&
|
||||
+ core->id.id != BCMA_CORE_80211);
|
||||
+
|
||||
+ switch (clkmode) {
|
||||
+ case BCMA_CLKMODE_FAST:
|
||||
+ bcma_set32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT);
|
||||
+ udelay(64);
|
||||
+ for (i = 0; i < 1500; i++) {
|
||||
+ if (bcma_read32(core, BCMA_CLKCTLST) &
|
||||
+ BCMA_CLKCTLST_HAVEHT) {
|
||||
+ i = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+ udelay(10);
|
||||
+ }
|
||||
+ if (i)
|
||||
+ pr_err("HT force timeout\n");
|
||||
+ break;
|
||||
+ case BCMA_CLKMODE_DYNAMIC:
|
||||
+ pr_warn("Dynamic clockmode not supported yet!\n");
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(bcma_core_set_clockmode);
|
||||
+
|
||||
+void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on)
|
||||
+{
|
||||
+ u16 i;
|
||||
+
|
||||
+ WARN_ON(req & ~BCMA_CLKCTLST_EXTRESREQ);
|
||||
+ WARN_ON(status & ~BCMA_CLKCTLST_EXTRESST);
|
||||
+
|
||||
+ if (on) {
|
||||
+ bcma_set32(core, BCMA_CLKCTLST, req);
|
||||
+ for (i = 0; i < 10000; i++) {
|
||||
+ if ((bcma_read32(core, BCMA_CLKCTLST) & status) ==
|
||||
+ status) {
|
||||
+ i = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+ udelay(10);
|
||||
+ }
|
||||
+ if (i)
|
||||
+ pr_err("PLL enable timeout\n");
|
||||
+ } else {
|
||||
+ pr_warn("Disabling PLL not supported yet!\n");
|
||||
+ }
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
|
||||
+
|
||||
+u32 bcma_core_dma_translation(struct bcma_device *core)
|
||||
+{
|
||||
+ switch (core->bus->hosttype) {
|
||||
+ case BCMA_HOSTTYPE_PCI:
|
||||
+ if (bcma_aread32(core, BCMA_IOST) & BCMA_IOST_DMA64)
|
||||
+ return BCMA_DMA_TRANSLATION_DMA64_CMT;
|
||||
+ else
|
||||
+ return BCMA_DMA_TRANSLATION_DMA32_CMT;
|
||||
+ default:
|
||||
+ pr_err("DMA translation unknown for host %d\n",
|
||||
+ core->bus->hosttype);
|
||||
+ }
|
||||
+ return BCMA_DMA_TRANSLATION_NONE;
|
||||
+}
|
||||
+EXPORT_SYMBOL(bcma_core_dma_translation);
|
||||
--- a/drivers/bcma/driver_chipcommon_pmu.c
|
||||
+++ b/drivers/bcma/driver_chipcommon_pmu.c
|
||||
@@ -53,6 +53,7 @@ static void bcma_pmu_resources_init(stru
|
||||
|
@ -94,11 +194,52 @@
|
|||
bus->chipinfo.id);
|
||||
--- a/drivers/bcma/driver_pci.c
|
||||
+++ b/drivers/bcma/driver_pci.c
|
||||
@@ -161,3 +161,27 @@ void bcma_core_pci_init(struct bcma_drv_
|
||||
@@ -157,7 +157,67 @@ static void bcma_pcicore_serdes_workarou
|
||||
* Init.
|
||||
**************************************************/
|
||||
|
||||
-void bcma_core_pci_init(struct bcma_drv_pci *pc)
|
||||
+static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
|
||||
{
|
||||
bcma_pcicore_serdes_workaround(pc);
|
||||
}
|
||||
+
|
||||
+static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
|
||||
+{
|
||||
+ struct bcma_bus *bus = pc->core->bus;
|
||||
+ u16 chipid_top;
|
||||
+
|
||||
+ chipid_top = (bus->chipinfo.id & 0xFF00);
|
||||
+ if (chipid_top != 0x4700 &&
|
||||
+ chipid_top != 0x5300)
|
||||
+ return false;
|
||||
+
|
||||
+ if (bus->sprom.boardflags_lo & SSB_PCICORE_BFL_NOPCI)
|
||||
+ return false;
|
||||
+
|
||||
+#if 0
|
||||
+ /* TODO: on BCMA we use address from EROM instead of magic formula */
|
||||
+ u32 tmp;
|
||||
+ return !mips_busprobe32(tmp, (bus->mmio +
|
||||
+ (pc->core->core_index * BCMA_CORE_SIZE)));
|
||||
+#endif
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+void bcma_core_pci_init(struct bcma_drv_pci *pc)
|
||||
+{
|
||||
+ if (bcma_core_pci_is_in_hostmode(pc)) {
|
||||
+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
|
||||
+ bcma_core_pci_hostmode_init(pc);
|
||||
+#else
|
||||
+ pr_err("Driver compiled without support for hostmode PCI\n");
|
||||
+#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
|
||||
+ } else {
|
||||
+ bcma_core_pci_clientmode_init(pc);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
|
||||
+ bool enable)
|
||||
+{
|
||||
|
@ -217,13 +358,15 @@
|
|||
break;
|
||||
case BCMA_HOSTTYPE_NONE:
|
||||
case BCMA_HOSTTYPE_SDIO:
|
||||
@@ -144,6 +147,13 @@ int bcma_bus_register(struct bcma_bus *b
|
||||
@@ -144,6 +147,15 @@ int bcma_bus_register(struct bcma_bus *b
|
||||
bcma_core_pci_init(&bus->drv_pci);
|
||||
}
|
||||
|
||||
+ /* Try to get SPROM */
|
||||
+ err = bcma_sprom_get(bus);
|
||||
+ if (err) {
|
||||
+ if (err == -ENOENT) {
|
||||
+ pr_err("No SPROM available\n");
|
||||
+ } else if (err) {
|
||||
+ pr_err("Failed to get SPROM: %d\n", err);
|
||||
+ return -ENOENT;
|
||||
+ }
|
||||
|
@ -231,7 +374,7 @@
|
|||
/* Register found cores */
|
||||
bcma_register_cores(bus);
|
||||
|
||||
@@ -151,13 +161,11 @@ int bcma_bus_register(struct bcma_bus *b
|
||||
@@ -151,13 +163,11 @@ int bcma_bus_register(struct bcma_bus *b
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -247,7 +390,7 @@
|
|||
{
|
||||
--- /dev/null
|
||||
+++ b/drivers/bcma/sprom.c
|
||||
@@ -0,0 +1,162 @@
|
||||
@@ -0,0 +1,171 @@
|
||||
+/*
|
||||
+ * Broadcom specific AMBA
|
||||
+ * SPROM reading
|
||||
|
@ -270,12 +413,12 @@
|
|||
+ * R/W ops.
|
||||
+ **************************************************/
|
||||
+
|
||||
+static void bcma_sprom_read(struct bcma_bus *bus, u16 *sprom)
|
||||
+static void bcma_sprom_read(struct bcma_bus *bus, u16 offset, u16 *sprom)
|
||||
+{
|
||||
+ int i;
|
||||
+ for (i = 0; i < SSB_SPROMSIZE_WORDS_R4; i++)
|
||||
+ sprom[i] = bcma_read16(bus->drv_cc.core,
|
||||
+ BCMA_CC_SPROM + (i * 2));
|
||||
+ offset + (i * 2));
|
||||
+}
|
||||
+
|
||||
+/**************************************************
|
||||
|
@ -362,7 +505,7 @@
|
|||
+ return err;
|
||||
+
|
||||
+ revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_REV;
|
||||
+ if (revision != 8) {
|
||||
+ if (revision != 8 && revision != 9) {
|
||||
+ pr_err("Unsupported SPROM revision: %d\n", revision);
|
||||
+ return -ENOENT;
|
||||
+ }
|
||||
|
@ -387,18 +530,27 @@
|
|||
+
|
||||
+int bcma_sprom_get(struct bcma_bus *bus)
|
||||
+{
|
||||
+ u16 offset;
|
||||
+ u16 *sprom;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ if (!bus->drv_cc.core)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
+ if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
|
||||
+ return -ENOENT;
|
||||
+
|
||||
+ sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!sprom)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ bcma_sprom_read(bus, sprom);
|
||||
+ /* Most cards have SPROM moved by additional offset 0x30 (48 dwords).
|
||||
+ * According to brcm80211 this applies to cards with PCIe rev >= 6
|
||||
+ * TODO: understand this condition and use it */
|
||||
+ offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM :
|
||||
+ BCMA_CC_SPROM_PCIE6;
|
||||
+ bcma_sprom_read(bus, offset, sprom);
|
||||
+
|
||||
+ err = bcma_sprom_valid(sprom);
|
||||
+ if (err)
|
||||
|
@ -420,7 +572,19 @@
|
|||
|
||||
#include "bcma_regs.h"
|
||||
|
||||
@@ -31,6 +32,12 @@ struct bcma_host_ops {
|
||||
@@ -24,6 +25,11 @@ struct bcma_chipinfo {
|
||||
u8 pkg;
|
||||
};
|
||||
|
||||
+enum bcma_clkmode {
|
||||
+ BCMA_CLKMODE_FAST,
|
||||
+ BCMA_CLKMODE_DYNAMIC,
|
||||
+};
|
||||
+
|
||||
struct bcma_host_ops {
|
||||
u8 (*read8)(struct bcma_device *core, u16 offset);
|
||||
u16 (*read16)(struct bcma_device *core, u16 offset);
|
||||
@@ -31,6 +37,12 @@ struct bcma_host_ops {
|
||||
void (*write8)(struct bcma_device *core, u16 offset, u8 value);
|
||||
void (*write16)(struct bcma_device *core, u16 offset, u16 value);
|
||||
void (*write32)(struct bcma_device *core, u16 offset, u32 value);
|
||||
|
@ -433,7 +597,7 @@
|
|||
/* Agent ops */
|
||||
u32 (*aread32)(struct bcma_device *core, u16 offset);
|
||||
void (*awrite32)(struct bcma_device *core, u16 offset, u32 value);
|
||||
@@ -117,6 +124,8 @@ struct bcma_device {
|
||||
@@ -117,6 +129,8 @@ struct bcma_device {
|
||||
struct bcma_device_id id;
|
||||
|
||||
struct device dev;
|
||||
|
@ -442,7 +606,7 @@
|
|||
bool dev_registered;
|
||||
|
||||
u8 core_index;
|
||||
@@ -179,6 +188,10 @@ struct bcma_bus {
|
||||
@@ -179,6 +193,10 @@ struct bcma_bus {
|
||||
|
||||
struct bcma_drv_cc drv_cc;
|
||||
struct bcma_drv_pci drv_pci;
|
||||
|
@ -453,7 +617,7 @@
|
|||
};
|
||||
|
||||
extern inline u32 bcma_read8(struct bcma_device *core, u16 offset)
|
||||
@@ -208,6 +221,18 @@ void bcma_write32(struct bcma_device *co
|
||||
@@ -208,6 +226,18 @@ void bcma_write32(struct bcma_device *co
|
||||
{
|
||||
core->bus->ops->write32(core, offset, value);
|
||||
}
|
||||
|
@ -472,21 +636,56 @@
|
|||
extern inline u32 bcma_aread32(struct bcma_device *core, u16 offset)
|
||||
{
|
||||
return core->bus->ops->aread32(core, offset);
|
||||
@@ -219,6 +244,7 @@ void bcma_awrite32(struct bcma_device *c
|
||||
@@ -218,7 +248,24 @@ void bcma_awrite32(struct bcma_device *c
|
||||
core->bus->ops->awrite32(core, offset, value);
|
||||
}
|
||||
|
||||
+#define bcma_mask32(cc, offset, mask) \
|
||||
+ bcma_write32(cc, offset, bcma_read32(cc, offset) & (mask))
|
||||
+#define bcma_set32(cc, offset, set) \
|
||||
+ bcma_write32(cc, offset, bcma_read32(cc, offset) | (set))
|
||||
+#define bcma_maskset32(cc, offset, mask, set) \
|
||||
+ bcma_write32(cc, offset, (bcma_read32(cc, offset) & (mask)) | (set))
|
||||
+
|
||||
extern bool bcma_core_is_enabled(struct bcma_device *core);
|
||||
+extern void bcma_core_disable(struct bcma_device *core, u32 flags);
|
||||
extern int bcma_core_enable(struct bcma_device *core, u32 flags);
|
||||
+extern void bcma_core_set_clockmode(struct bcma_device *core,
|
||||
+ enum bcma_clkmode clkmode);
|
||||
+extern void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status,
|
||||
+ bool on);
|
||||
+#define BCMA_DMA_TRANSLATION_MASK 0xC0000000
|
||||
+#define BCMA_DMA_TRANSLATION_NONE 0x00000000
|
||||
+#define BCMA_DMA_TRANSLATION_DMA32_CMT 0x40000000 /* Client Mode Translation for 32-bit DMA */
|
||||
+#define BCMA_DMA_TRANSLATION_DMA64_CMT 0x80000000 /* Client Mode Translation for 64-bit DMA */
|
||||
+extern u32 bcma_core_dma_translation(struct bcma_device *core);
|
||||
|
||||
#endif /* LINUX_BCMA_H_ */
|
||||
--- a/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
|
||||
@@ -244,6 +244,7 @@
|
||||
@@ -179,15 +179,7 @@
|
||||
#define BCMA_CC_PROG_WAITCNT 0x0124
|
||||
#define BCMA_CC_FLASH_CFG 0x0128
|
||||
#define BCMA_CC_FLASH_WAITCNT 0x012C
|
||||
-#define BCMA_CC_CLKCTLST 0x01E0 /* Clock control and status (rev >= 20) */
|
||||
-#define BCMA_CC_CLKCTLST_FORCEALP 0x00000001 /* Force ALP request */
|
||||
-#define BCMA_CC_CLKCTLST_FORCEHT 0x00000002 /* Force HT request */
|
||||
-#define BCMA_CC_CLKCTLST_FORCEILP 0x00000004 /* Force ILP request */
|
||||
-#define BCMA_CC_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */
|
||||
-#define BCMA_CC_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */
|
||||
-#define BCMA_CC_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */
|
||||
-#define BCMA_CC_CLKCTLST_HAVEHT 0x00010000 /* HT available */
|
||||
-#define BCMA_CC_CLKCTLST_HAVEALP 0x00020000 /* APL available */
|
||||
+/* 0x1E0 is defined as shared BCMA_CLKCTLST */
|
||||
#define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */
|
||||
#define BCMA_CC_UART0_DATA 0x0300
|
||||
#define BCMA_CC_UART0_IMR 0x0304
|
||||
@@ -244,6 +236,8 @@
|
||||
#define BCMA_CC_REGCTL_DATA 0x065C
|
||||
#define BCMA_CC_PLLCTL_ADDR 0x0660
|
||||
#define BCMA_CC_PLLCTL_DATA 0x0664
|
||||
+#define BCMA_CC_SPROM 0x0830 /* SPROM beginning */
|
||||
+#define BCMA_CC_SPROM 0x0800 /* SPROM beginning */
|
||||
+#define BCMA_CC_SPROM_PCIE6 0x0830 /* SPROM beginning on PCIe rev >= 6 */
|
||||
|
||||
/* Data for the PMU, if available.
|
||||
* Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
|
||||
|
@ -500,3 +699,92 @@
|
|||
+ struct bcma_device *core, bool enable);
|
||||
|
||||
#endif /* LINUX_BCMA_DRIVER_PCI_H_ */
|
||||
--- a/drivers/bcma/driver_chipcommon.c
|
||||
+++ b/drivers/bcma/driver_chipcommon.c
|
||||
@@ -23,6 +23,9 @@ static inline u32 bcma_cc_write32_masked
|
||||
|
||||
void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
+ u32 leddc_on = 10;
|
||||
+ u32 leddc_off = 90;
|
||||
+
|
||||
if (cc->core->id.rev >= 11)
|
||||
cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
|
||||
cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
|
||||
@@ -38,6 +41,17 @@ void bcma_core_chipcommon_init(struct bc
|
||||
bcma_pmu_init(cc);
|
||||
if (cc->capabilities & BCMA_CC_CAP_PCTL)
|
||||
pr_err("Power control not implemented!\n");
|
||||
+
|
||||
+ if (cc->core->id.rev >= 16) {
|
||||
+ if (cc->core->bus->sprom.leddc_on_time &&
|
||||
+ cc->core->bus->sprom.leddc_off_time) {
|
||||
+ leddc_on = cc->core->bus->sprom.leddc_on_time;
|
||||
+ leddc_off = cc->core->bus->sprom.leddc_off_time;
|
||||
+ }
|
||||
+ bcma_cc_write32(cc, BCMA_CC_GPIOTIMER,
|
||||
+ ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
|
||||
+ (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
|
||||
--- /dev/null
|
||||
+++ b/drivers/bcma/driver_pci_host.c
|
||||
@@ -0,0 +1,14 @@
|
||||
+/*
|
||||
+ * Broadcom specific AMBA
|
||||
+ * PCI Core in hostmode
|
||||
+ *
|
||||
+ * Licensed under the GNU/GPL. See COPYING for details.
|
||||
+ */
|
||||
+
|
||||
+#include "bcma_private.h"
|
||||
+#include <linux/bcma/bcma.h>
|
||||
+
|
||||
+void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
|
||||
+{
|
||||
+ pr_err("No support for PCI core in hostmode yet\n");
|
||||
+}
|
||||
--- a/include/linux/bcma/bcma_regs.h
|
||||
+++ b/include/linux/bcma/bcma_regs.h
|
||||
@@ -1,13 +1,38 @@
|
||||
#ifndef LINUX_BCMA_REGS_H_
|
||||
#define LINUX_BCMA_REGS_H_
|
||||
|
||||
+/* Some single registers are shared between many cores */
|
||||
+/* BCMA_CLKCTLST: ChipCommon (rev >= 20), PCIe, 80211 */
|
||||
+#define BCMA_CLKCTLST 0x01E0 /* Clock control and status */
|
||||
+#define BCMA_CLKCTLST_FORCEALP 0x00000001 /* Force ALP request */
|
||||
+#define BCMA_CLKCTLST_FORCEHT 0x00000002 /* Force HT request */
|
||||
+#define BCMA_CLKCTLST_FORCEILP 0x00000004 /* Force ILP request */
|
||||
+#define BCMA_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */
|
||||
+#define BCMA_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */
|
||||
+#define BCMA_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */
|
||||
+#define BCMA_CLKCTLST_EXTRESREQ 0x00000700 /* Mask of external resource requests */
|
||||
+#define BCMA_CLKCTLST_HAVEALP 0x00010000 /* ALP available */
|
||||
+#define BCMA_CLKCTLST_HAVEHT 0x00020000 /* HT available */
|
||||
+#define BCMA_CLKCTLST_BP_ON_ALP 0x00040000 /* RO: running on ALP clock */
|
||||
+#define BCMA_CLKCTLST_BP_ON_HT 0x00080000 /* RO: running on HT clock */
|
||||
+#define BCMA_CLKCTLST_EXTRESST 0x07000000 /* Mask of external resource status */
|
||||
+/* Is there any BCM4328 on BCMA bus? */
|
||||
+#define BCMA_CLKCTLST_4328A0_HAVEHT 0x00010000 /* 4328a0 has reversed bits */
|
||||
+#define BCMA_CLKCTLST_4328A0_HAVEALP 0x00020000 /* 4328a0 has reversed bits */
|
||||
+
|
||||
/* Agent registers (common for every core) */
|
||||
-#define BCMA_IOCTL 0x0408
|
||||
+#define BCMA_IOCTL 0x0408 /* IO control */
|
||||
#define BCMA_IOCTL_CLK 0x0001
|
||||
#define BCMA_IOCTL_FGC 0x0002
|
||||
#define BCMA_IOCTL_CORE_BITS 0x3FFC
|
||||
#define BCMA_IOCTL_PME_EN 0x4000
|
||||
#define BCMA_IOCTL_BIST_EN 0x8000
|
||||
+#define BCMA_IOST 0x0500 /* IO status */
|
||||
+#define BCMA_IOST_CORE_BITS 0x0FFF
|
||||
+#define BCMA_IOST_DMA64 0x1000
|
||||
+#define BCMA_IOST_GATED_CLK 0x2000
|
||||
+#define BCMA_IOST_BIST_ERROR 0x4000
|
||||
+#define BCMA_IOST_BIST_DONE 0x8000
|
||||
#define BCMA_RESET_CTL 0x0800
|
||||
#define BCMA_RESET_CTL_RESET 0x0001
|
||||
|
||||
|
|
|
@ -17,3 +17,13 @@
|
|||
|
||||
config SSB_PCMCIAHOST_POSSIBLE
|
||||
bool
|
||||
--- a/drivers/bcma/Kconfig
|
||||
+++ b/drivers/bcma/Kconfig
|
||||
@@ -17,6 +17,7 @@ config BCMA
|
||||
config BCMA_BLOCKIO
|
||||
bool
|
||||
depends on BCMA
|
||||
+ default y
|
||||
|
||||
config BCMA_HOST_PCI_POSSIBLE
|
||||
bool
|
||||
|
|
Loading…
Reference in New Issue