From 5f2d6171e1e70584b9819771443485750453fd16 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 31 Jan 2012 00:03:31 +0100 Subject: bcma: add the core unit number Some SoCs have two pcie or gmac cores and we need to know the number of the specific core on the bus. This is the case for the BCM4706. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- include/linux/bcma/bcma.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux/bcma/bcma.h') diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 83c209f39493..024a6e2a9083 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -136,6 +136,7 @@ struct bcma_device { bool dev_registered; u8 core_index; + u8 core_unit; u32 addr; u32 wrap; -- cgit v1.3-14-g43fede From 8f9ada4fa1926e540b1562cb9bacb3e51a698c35 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 31 Jan 2012 00:03:36 +0100 Subject: bcma: add bus num counter If we have two bcma buses on one computer the second will not work without this patch. Now each bus gets an own number. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/bcma/main.c | 12 +++++++++++- include/linux/bcma/bcma.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'include/linux/bcma/bcma.h') diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 3363036f23dc..bcd1c01cde9e 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -13,6 +13,12 @@ MODULE_DESCRIPTION("Broadcom's specific AMBA driver"); MODULE_LICENSE("GPL"); +/* contains the number the next bus should get. */ +static unsigned int bcma_bus_next_num = 0; + +/* bcma_buses_mutex locks the bcma_bus_next_num */ +static DEFINE_MUTEX(bcma_buses_mutex); + static int bcma_bus_match(struct device *dev, struct device_driver *drv); static int bcma_device_probe(struct device *dev); static int bcma_device_remove(struct device *dev); @@ -93,7 +99,7 @@ static int bcma_register_cores(struct bcma_bus *bus) core->dev.release = bcma_release_core_dev; core->dev.bus = &bcma_bus_type; - dev_set_name(&core->dev, "bcma%d:%d", 0/*bus->num*/, dev_id); + dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id); switch (bus->hosttype) { case BCMA_HOSTTYPE_PCI: @@ -137,6 +143,10 @@ int __devinit bcma_bus_register(struct bcma_bus *bus) int err; struct bcma_device *core; + mutex_lock(&bcma_buses_mutex); + bus->num = bcma_bus_next_num++; + mutex_unlock(&bcma_buses_mutex); + /* Scan for devices (cores) */ err = bcma_bus_scan(bus); if (err) { diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 024a6e2a9083..b9f65fbee42f 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -196,6 +196,7 @@ struct bcma_bus { struct list_head cores; u8 nr_cores; u8 init_done:1; + u8 num; struct bcma_drv_cc drv_cc; struct bcma_drv_pci drv_pci; -- cgit v1.3-14-g43fede From 1c9351cf2180924c91bb85e5ba607f24a3d875b1 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 28 Feb 2012 00:56:09 +0100 Subject: bcma: export bcma_find_core This function is needed by the bcm47xx arch code to get the number of the ieee80211 core. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/bcma/main.c | 3 ++- include/linux/bcma/bcma.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'include/linux/bcma/bcma.h') diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index b8379b90d045..7e138ec21357 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -61,7 +61,7 @@ static struct bus_type bcma_bus_type = { .dev_attrs = bcma_device_attrs, }; -static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid) +struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid) { struct bcma_device *core; @@ -71,6 +71,7 @@ static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid) } return NULL; } +EXPORT_SYMBOL_GPL(bcma_find_core); static void bcma_release_core_dev(struct device *dev) { diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index b9f65fbee42f..46bbd088c4ad 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -284,6 +284,7 @@ static inline void bcma_maskset16(struct bcma_device *cc, bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set); } +extern struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid); 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); -- cgit v1.3-14-g43fede From a027237a56f7d519eee5749cfb720e568d0bb0b6 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 28 Feb 2012 00:56:10 +0100 Subject: bcma: add support for sprom not found on the device On SoCs the sprom is stored in the nvram in a special partition on the flash chip. The nvram contains the sprom for the main bus, but sometimes also for a pci devices using bcma. This patch makes it possible for the arch code to register a function to fetch the needed sprom from the nvram and provide it to the bcma code. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/bcma/sprom.c | 77 ++++++++++++++++++++++++++++++++++++++++++----- include/linux/bcma/bcma.h | 6 ++++ 2 files changed, 75 insertions(+), 8 deletions(-) (limited to 'include/linux/bcma/bcma.h') diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index ca7752510d5b..916ae255ff64 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -2,6 +2,8 @@ * Broadcom specific AMBA * SPROM reading * + * Copyright 2011, 2012, Hauke Mehrtens + * * Licensed under the GNU/GPL. See COPYING for details. */ @@ -14,6 +16,45 @@ #include #include +static int(*get_fallback_sprom)(struct bcma_bus *dev, struct ssb_sprom *out); + +/** + * bcma_arch_register_fallback_sprom - Registers a method providing a + * fallback SPROM if no SPROM is found. + * + * @sprom_callback: The callback function. + * + * With this function the architecture implementation may register a + * callback handler which fills the SPROM data structure. The fallback is + * used for PCI based BCMA devices, where no valid SPROM can be found + * in the shadow registers and to provide the SPROM for SoCs where BCMA is + * to controll the system bus. + * + * This function is useful for weird architectures that have a half-assed + * BCMA device hardwired to their PCI bus. + * + * This function is available for architecture code, only. So it is not + * exported. + */ +int bcma_arch_register_fallback_sprom(int (*sprom_callback)(struct bcma_bus *bus, + struct ssb_sprom *out)) +{ + if (get_fallback_sprom) + return -EEXIST; + get_fallback_sprom = sprom_callback; + + return 0; +} + +static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus, + struct ssb_sprom *out) +{ + if (!get_fallback_sprom) + return -ENOENT; + + return get_fallback_sprom(bus, out); +} + /************************************************** * R/W ops. **************************************************/ @@ -246,23 +287,43 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) SSB_SROM8_FEM_ANTSWLUT_SHIFT); } +static bool bcma_is_sprom_available(struct bcma_bus *bus) +{ + u32 sromctrl; + + if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) + return false; + + if (bus->drv_cc.core->id.rev >= 32) { + sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL); + return sromctrl & BCMA_CC_SROM_CONTROL_PRESENT; + } + return true; +} + int bcma_sprom_get(struct bcma_bus *bus) { u16 offset; u16 *sprom; - u32 sromctrl; int err = 0; if (!bus->drv_cc.core) return -EOPNOTSUPP; - if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) - return -ENOENT; - - if (bus->drv_cc.core->id.rev >= 32) { - sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL); - if (!(sromctrl & BCMA_CC_SROM_CONTROL_PRESENT)) - return -ENOENT; + if (!bcma_is_sprom_available(bus)) { + /* + * Maybe there is no SPROM on the device? + * Now we ask the arch code if there is some sprom + * available for this device in some other storage. + */ + err = bcma_fill_sprom_with_fallback(bus, &bus->sprom); + if (err) { + pr_warn("Using fallback SPROM failed (err %d)\n", err); + } else { + pr_debug("Using SPROM revision %d provided by" + " platform.\n", bus->sprom.revision); + return 0; + } } sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 46bbd088c4ad..5af9a075498f 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -176,6 +176,12 @@ int __bcma_driver_register(struct bcma_driver *drv, struct module *owner); extern void bcma_driver_unregister(struct bcma_driver *drv); +/* Set a fallback SPROM. + * See kdoc at the function definition for complete documentation. */ +extern int bcma_arch_register_fallback_sprom( + int (*sprom_callback)(struct bcma_bus *bus, + struct ssb_sprom *out)); + struct bcma_bus { /* The MMIO area. */ void __iomem *mmio; -- cgit v1.3-14-g43fede