Skip to contentSkip to conversation

bcma: add support for embedded devices like bcm4716

RFC PATCH Superseded Hauke Mehrtens 8 participants 47 messages Jun 5, 2011 – Jun 11, 2011

Subsystems (4)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore

Hauke Mehrtens

author maintainer
#0 lore raw

cover bcma: add support for embedded devices like bcm4716

This patch series adds support for embedded devices like bcm47xx to bcma. Bcma is used on bcm4716 and bcm4718 SoCs. With these patches my bcm4716 device boots up till it tries to access the flash, because the serial flash chip is unsupported for now, this will be my next task. This adds support for MIPS cores, interrupt configuration and the serial console.

These patches are based on ssb code, some patches by George Kashperko and Bernhard Loos and parts of the source code release by ASUS and Netgear for their devices.

This was tested on a Netgear WNDR3400, but did not work fully because of serial flash.

This is bases on linux-next next-20110603, to which subsystem maintainer should I send these patches later, as it is based on the most recent version of bcma and bcm47xx?
I do not have any normal PCIe based wireless device using this bus, so I have not tested it with such a device, it will be nice to hear if it is still working on them.
The parallel flash should work so it could be that it will boot on an Asus rt-n16, I have not tested that.

An Ethernet driver is not included because the Braodcom source code available is not licensed under a GPL compatible license and building a new driver on that based is not possible.

Hauke Mehrtens (10):
bcma: Use array to store cores.
bcma: Make it possible to run bcma_register_cores() later
bcma: add embedded bus
bcma: add mips driver
bcma: add serial support
bcma: get CPU clock
bcma: add pci(e) host mode
bcm47xx: prepare to support different buses
bcm47xx: add support for bcma bus
bcm47xx: fix irq assignment for new SoCs.

 arch/mips/Kconfig                            |    4 +
 arch/mips/bcm47xx/gpio.c                     |   63 +++++---
 arch/mips/bcm47xx/irq.c                      |    8 +
 arch/mips/bcm47xx/nvram.c                    |   21 ++-
 arch/mips/bcm47xx/serial.c                   |   37 ++++-
 arch/mips/bcm47xx/setup.c                    |   55 +++++-
 arch/mips/bcm47xx/time.c                     |   12 +-
 arch/mips/bcm47xx/wgt634u.c                  |   13 +-
 arch/mips/include/asm/mach-bcm47xx/bcm47xx.h |   17 ++-
 arch/mips/include/asm/mach-bcm47xx/gpio.h    |   71 ++++++--
 drivers/bcma/Kconfig                         |   20 ++
 drivers/bcma/Makefile                        |    3 +
 drivers/bcma/bcma_private.h                  |   16 ++
 drivers/bcma/driver_chipcommon.c             |   62 +++++++
 drivers/bcma/driver_chipcommon_pmu.c         |   86 +++++++++
 drivers/bcma/driver_mips.c                   |  248 ++++++++++++++++++++++++++
 drivers/bcma/driver_pci.c                    |   12 ++-
 drivers/bcma/driver_pci_host.c               |   44 +++++
 drivers/bcma/host_embedded.c                 |   93 ++++++++++
 drivers/bcma/main.c                          |  160 +++++++++++++----
 drivers/bcma/scan.c                          |   87 +++++----
 drivers/watchdog/bcm47xx_wdt.c               |   18 ++-
 include/linux/bcma/bcma.h                    |   24 ++-
 include/linux/bcma/bcma_driver_chipcommon.h  |   35 ++++
 include/linux/bcma/bcma_driver_mips.h        |   52 ++++++
 include/linux/bcma/bcma_driver_pci.h         |    1 +
 include/linux/bcma/bcma_embedded.h           |    8 +
 27 files changed, 1132 insertions(+), 138 deletions(-)
 create mode 100644 drivers/bcma/driver_mips.c
 create mode 100644 drivers/bcma/driver_pci_host.c
 create mode 100644 drivers/bcma/host_embedded.c
 create mode 100644 include/linux/bcma/bcma_driver_mips.h
 create mode 100644 include/linux/bcma/bcma_embedded.h
Signature · 1 line
1.7.4.1
author maintainer
#1 lore raw

RFC PATCH 1/10 bcma: Use array to store cores.

When using bcma on a embedded device it is initialized very early at boot. We have to do so as the cpu and interrupt management and all other devices are attached to this bus and it has to be initialized so early. In that stage we can not allocate memory or sleep, just use the memory on the stack and in the text segment as the kernel is not initialized far enough. This patch removed the kzallocs from the scan code. Some earlier version of the bcma implementation and the normal ssb implementation are doing it like this.
The __bcma_dev_wrapper struct is used as the container for the device struct as bcma_device will be too big if it includes struct device.

---
 drivers/bcma/main.c       |   86 ++++++++++++++++++++++++++++----------------
 drivers/bcma/scan.c       |   58 +++++++++++-------------------
 include/linux/bcma/bcma.h |   16 ++++++--
 3 files changed, 89 insertions(+), 71 deletions(-)
drivers/bcma/main.c +55 -31
index a2f6b18..b0e7f5e 100644
@@ -17,23 +17,27 @@ static int bcma_device_remove(struct device *dev);
 
 static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
-	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
-	return sprintf(buf, "0x%03X\n", core->id.manuf);
+	struct __bcma_dev_wrapper *wrapper = container_of(dev,
+						struct __bcma_dev_wrapper, dev);
+	return sprintf(buf, "0x%03X\n", wrapper->core->id.manuf);
 }
 static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
-	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
-	return sprintf(buf, "0x%03X\n", core->id.id);
+	struct __bcma_dev_wrapper *wrapper = container_of(dev,
+						struct __bcma_dev_wrapper, dev);
+	return sprintf(buf, "0x%03X\n", wrapper->core->id.id);
 }
 static ssize_t rev_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
-	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
-	return sprintf(buf, "0x%02X\n", core->id.rev);
+	struct __bcma_dev_wrapper *wrapper = container_of(dev,
+						struct __bcma_dev_wrapper, dev);
+	return sprintf(buf, "0x%02X\n", wrapper->core->id.rev);
 }
 static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
-	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
-	return sprintf(buf, "0x%X\n", core->id.class);
+	struct __bcma_dev_wrapper *wrapper = container_of(dev,
+						struct __bcma_dev_wrapper, dev);
+	return sprintf(buf, "0x%X\n", wrapper->core->id.class);
 }
 static struct device_attribute bcma_device_attrs[] = {
 	__ATTR_RO(manuf),
@@ -53,27 +57,30 @@ static struct bus_type bcma_bus_type = {
 
 static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
 {
-	struct bcma_device *core;
-
-	list_for_each_entry(core, &bus->cores, list) {
-		if (core->id.id == coreid)
-			return core;
+	u8 i;
+	for (i = 0; i < bus->nr_cores; i++) {
+		if (bus->cores[i].id.id == coreid)
+			return &bus->cores[i];
 	}
 	return NULL;
 }
 
 static void bcma_release_core_dev(struct device *dev)
 {
-	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
-	kfree(core);
+	struct __bcma_dev_wrapper *wrapper = container_of(dev,
+						struct __bcma_dev_wrapper, dev);
+	kfree(wrapper);
 }
 
 static int bcma_register_cores(struct bcma_bus *bus)
 {
 	struct bcma_device *core;
-	int err, dev_id = 0;
+	struct __bcma_dev_wrapper *wrapper;
+	int i, err, dev_id = 0;
+
+	for (i = 0; i < bus->nr_cores; i++) {
+		core = &(bus->cores[i]);
 
-	list_for_each_entry(core, &bus->cores, list) {
 		/* We support that cores ourself */
 		switch (core->id.id) {
 		case BCMA_CORE_CHIPCOMMON:
@@ -82,28 +89,37 @@ static int bcma_register_cores(struct bcma_bus *bus)
 			continue;
 		}
 
-		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);
+		wrapper = kzalloc(sizeof(*wrapper), GFP_KERNEL);
+		if (!wrapper) {
+			pr_err("Could not allocate wrapper for core 0x%03X\n",
+			       core->id.id);
+			continue;
+		}
+
+		wrapper->core = core;
+		wrapper->dev.release = bcma_release_core_dev;
+		wrapper->dev.bus = &bcma_bus_type;
+		dev_set_name(&wrapper->dev, "bcma%d:%d", 0/*bus->num*/, dev_id);
 
 		switch (bus->hosttype) {
 		case BCMA_HOSTTYPE_PCI:
-			core->dev.parent = &bus->host_pci->dev;
-			core->dma_dev = &bus->host_pci->dev;
-			core->irq = bus->host_pci->irq;
+			wrapper->dev.parent = &bus->host_pci->dev;
+			wrapper->core->dma_dev = &bus->host_pci->dev;
+			wrapper->core->irq = bus->host_pci->irq;
 			break;
 		case BCMA_HOSTTYPE_NONE:
 		case BCMA_HOSTTYPE_SDIO:
 			break;
 		}
 
-		err = device_register(&core->dev);
+		err = device_register(&wrapper->dev);
 		if (err) {
 			pr_err("Could not register dev for core 0x%03X\n",
 			       core->id.id);
+			kfree(wrapper);
 			continue;
 		}
-		core->dev_registered = true;
+		core->dev = &wrapper->dev;
 		dev_id++;
 	}
 
@@ -113,10 +129,12 @@ static int bcma_register_cores(struct bcma_bus *bus)
 static void bcma_unregister_cores(struct bcma_bus *bus)
 {
 	struct bcma_device *core;
+	int i;
 
-	list_for_each_entry(core, &bus->cores, list) {
-		if (core->dev_registered)
-			device_unregister(&core->dev);
+	for (i = 0; i < bus->nr_cores; i++) {
+		core = &(bus->cores[i]);
+		if (core->dev)
+			device_unregister(core->dev);
 	}
 }
 
@@ -179,7 +197,9 @@ EXPORT_SYMBOL_GPL(bcma_driver_unregister);
 
 static int bcma_bus_match(struct device *dev, struct device_driver *drv)
 {
-	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
+	struct __bcma_dev_wrapper *wrapper = container_of(dev,
+						struct __bcma_dev_wrapper, dev);
+	struct bcma_device *core = wrapper->core;
 	struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
 	const struct bcma_device_id *cid = &core->id;
 	const struct bcma_device_id *did;
@@ -196,7 +216,9 @@ static int bcma_bus_match(struct device *dev, struct device_driver *drv)
 
 static int bcma_device_probe(struct device *dev)
 {
-	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
+	struct __bcma_dev_wrapper *wrapper = container_of(dev,
+						struct __bcma_dev_wrapper, dev);
+	struct bcma_device *core = wrapper->core;
 	struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
 					       drv);
 	int err = 0;
@@ -209,7 +231,9 @@ static int bcma_device_probe(struct device *dev)
 
 static int bcma_device_remove(struct device *dev)
 {
-	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
+	struct __bcma_dev_wrapper *wrapper = container_of(dev,
+						struct __bcma_dev_wrapper, dev);
+	struct bcma_device *core = wrapper->core;
 	struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
 					       drv);
 
drivers/bcma/scan.c +22 -36

115 lines not on this page · raw message

include/linux/bcma/bcma.h +12 -4
index 27a27a7..3dc5302 100644
@@ -118,14 +118,23 @@ struct bcma_host_ops {
 
 #define BCMA_MAX_NR_CORES		16
 
+/* 1) It is not allowed to put struct device statically in bcma_device
+ * 2) We can not just use pointer to struct device because we use container_of
+ * 3) We do not have pointer to struct bcma_device in struct device
+ * Solution: use such a dummy wrapper
+ */
+struct __bcma_dev_wrapper {
+	struct device dev;
+	struct bcma_device *core;
+};
+
 struct bcma_device {
 	struct bcma_bus *bus;
 	struct bcma_device_id id;
 
-	struct device dev;
+	struct device *dev;
 	struct device *dma_dev;
 	unsigned int irq;
-	bool dev_registered;
 
 	u8 core_index;
 
@@ -133,7 +142,6 @@ struct bcma_device {
 	u32 wrap;
 
 	void *drvdata;
-	struct list_head list;
 };
 
 static inline void *bcma_get_drvdata(struct bcma_device *core)
@@ -182,7 +190,7 @@ struct bcma_bus {
 	struct bcma_chipinfo chipinfo;
 
 	struct bcma_device *mapped_core;
-	struct list_head cores;
+	struct bcma_device cores[BCMA_MAX_NR_CORES];
 	u8 nr_cores;
 
 	struct bcma_drv_cc drv_cc;
Signature · 1 line
1.7.4.1
#2 lore raw

Re: [RFC][PATCH 01/10] bcma: Use array to store cores.

Quoted 10 lines · Hauke Mehrtens

When using bcma on a embedded device it is initialized very early at boot. We have to do so as the cpu and interrupt management and all other devices are attached to this bus and it has to be initialized so early. In that stage we can not allocate memory or sleep, just use the memory on the stack and in the text segment as the kernel is not initialized far enough. This patch removed the kzallocs from the scan code. Some earlier version of the bcma implementation and the normal ssb implementation are doing it like this.
The __bcma_dev_wrapper struct is used as the container for the device struct as bcma_device will be too big if it includes struct device.

Does this prevent using list_for_each() and friends to be used on the device list? If so, could you consider a different approach. There were good reasons to get rid of the bcma_dev_wrapper struct if I recall discussions on the mailing list correctly. I also see tendency to use ssb solutions without considering alternatives. For this particular example, please consider adding a bcma_zalloc(), which does kzalloc for non-embedded platforms and returns array pointers for embedded platform. You could also consider this behavior for the embedded bus only.

Gr. AvS

Signature · 2 lines
Almost nobody dances sober, unless they happen to be insane.
-- H.P. Lovecraft --
maintainer
#3 lore raw

RFC PATCH 1/10 bcma: Use array to store cores.

In reply to Hauke Mehrtens

Greg, Arnd: could you take a look at this patch, please?

With proposed patch we are going back to this ugly array and wrappers hacks.

I was really happy with our final solution, but it seems it's not doable for embedded systems...? Is there something better we can do about this?

2011/6/6 Hauke Mehrtens <[email protected]>:

Quoted 368 lines

When using bcma on a embedded device it is initialized very early at boot. We have to do so as the cpu and interrupt management and all other devices are attached to this bus and it has to be initialized so early. In that stage we can not allocate memory or sleep, just use the memory on the stack and in the text segment as the kernel is not initialized far enough. This patch removed the kzallocs from the scan code. Some earlier version of the bcma implementation and the normal ssb implementation are doing it like this.
The __bcma_dev_wrapper struct is used as the container for the device struct as bcma_device will be too big if it includes struct device.

---

?drivers/bcma/main.c ? ? ? | ? 86 ++++++++++++++++++++++++++++----------------
?drivers/bcma/scan.c ? ? ? | ? 58 +++++++++++-------------------
?include/linux/bcma/bcma.h | ? 16 ++++++--

?3 files changed, 89 insertions(+), 71 deletions(-)

drivers/bcma/main.c +24 -17
index a2f6b18..b0e7f5e 100644
@@ -17,23 +17,27 @@ static int bcma_device_remove(struct device *dev);
 
 ?static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf)
 ?{
- ? ? ? struct bcma_device *core = container_of(dev, struct bcma_device, dev);
- ? ? ? return sprintf(buf, "0x%03X\n", core->id.manuf);
+ ? ? ? struct __bcma_dev_wrapper *wrapper = container_of(dev,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct __bcma_dev_wrapper, dev);
+ ? ? ? return sprintf(buf, "0x%03X\n", wrapper->core->id.manuf);
 ?}
 ?static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf)
 ?{
- ? ? ? struct bcma_device *core = container_of(dev, struct bcma_device, dev);
- ? ? ? return sprintf(buf, "0x%03X\n", core->id.id);
+ ? ? ? struct __bcma_dev_wrapper *wrapper = container_of(dev,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct __bcma_dev_wrapper, dev);
+ ? ? ? return sprintf(buf, "0x%03X\n", wrapper->core->id.id);
 ?}
 ?static ssize_t rev_show(struct device *dev, struct device_attribute *attr, char *buf)
 ?{
- ? ? ? struct bcma_device *core = container_of(dev, struct bcma_device, dev);
- ? ? ? return sprintf(buf, "0x%02X\n", core->id.rev);
+ ? ? ? struct __bcma_dev_wrapper *wrapper = container_of(dev,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct __bcma_dev_wrapper, dev);
+ ? ? ? return sprintf(buf, "0x%02X\n", wrapper->core->id.rev);
 ?}
 ?static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf)
 ?{
- ? ? ? struct bcma_device *core = container_of(dev, struct bcma_device, dev);
- ? ? ? return sprintf(buf, "0x%X\n", core->id.class);
+ ? ? ? struct __bcma_dev_wrapper *wrapper = container_of(dev,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct __bcma_dev_wrapper, dev);
+ ? ? ? return sprintf(buf, "0x%X\n", wrapper->core->id.class);
 ?}
 ?static struct device_attribute bcma_device_attrs[] = {
 ? ? ? ?__ATTR_RO(manuf),
@@ -53,27 +57,30 @@ static struct bus_type bcma_bus_type = {
 
 ?static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
 ?{
- ? ? ? struct bcma_device *core;
-
- ? ? ? list_for_each_entry(core, &bus->cores, list) {
- ? ? ? ? ? ? ? if (core->id.id == coreid)
- ? ? ? ? ? ? ? ? ? ? ? return core;
+ ? ? ? u8 i;
+ ? ? ? for (i = 0; i < bus->nr_cores; i++) {
+ ? ? ? ? ? ? ? if (bus->cores[i].id.id == coreid)
+ ? ? ? ? ? ? ? ? ? ? ? return &bus->cores[i];
 ? ? ? ?}
 ? ? ? ?return NULL;
 ?}
 
 ?static void bcma_release_core_dev(struct device *dev)
 ?{
- ? ? ? struct bcma_device *core = container_of(dev, struct bcma_device, dev);
- ? ? ? kfree(core);
+ ? ? ? struct __bcma_dev_wrapper *wrapper = container_of(dev,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct __bcma_dev_wrapper, dev);
+ ? ? ? kfree(wrapper);
 ?}
 
 ?static int bcma_register_cores(struct bcma_bus *bus)
 ?{
 ? ? ? ?struct bcma_device *core;
- ? ? ? int err, dev_id = 0;
+ ? ? ? struct __bcma_dev_wrapper *wrapper;
+ ? ? ? int i, err, dev_id = 0;
+
+ ? ? ? for (i = 0; i < bus->nr_cores; i++) {
+ ? ? ? ? ? ? ? core = &(bus->cores[i]);
 
- ? ? ? list_for_each_entry(core, &bus->cores, list) {

? ? ? ? ? ? ? ?/* We support that cores ourself */ ? ? ? ? ? ? ? ?switch (core->id.id) {
? ? ? ? ? ? ? ?case BCMA_CORE_CHIPCOMMON:

drivers/bcma/main.c +11 -3
@@ -82,28 +89,37 @@ static int bcma_register_cores(struct bcma_bus *bus)
 ? ? ? ? ? ? ? ? ? ? ? ?continue;
 ? ? ? ? ? ? ? ?}
 
- ? ? ? ? ? ? ? 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);
+ ? ? ? ? ? ? ? wrapper = kzalloc(sizeof(*wrapper), GFP_KERNEL);
+ ? ? ? ? ? ? ? if (!wrapper) {
+ ? ? ? ? ? ? ? ? ? ? ? pr_err("Could not allocate wrapper for core 0x%03X\n",
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?core->id.id);
+ ? ? ? ? ? ? ? ? ? ? ? continue;
+ ? ? ? ? ? ? ? }
+
+ ? ? ? ? ? ? ? wrapper->core = core;
+ ? ? ? ? ? ? ? wrapper->dev.release = bcma_release_core_dev;
+ ? ? ? ? ? ? ? wrapper->dev.bus = &bcma_bus_type;
+ ? ? ? ? ? ? ? dev_set_name(&wrapper->dev, "bcma%d:%d", 0/*bus->num*/, dev_id);
 
 ? ? ? ? ? ? ? ?switch (bus->hosttype) {

? ? ? ? ? ? ? ?case BCMA_HOSTTYPE_PCI:
- ? ? ? ? ? ? ? ? ? ? ? core->dev.parent = &bus->host_pci->dev;
- ? ? ? ? ? ? ? ? ? ? ? core->dma_dev = &bus->host_pci->dev;
- ? ? ? ? ? ? ? ? ? ? ? core->irq = bus->host_pci->irq;
+ ? ? ? ? ? ? ? ? ? ? ? wrapper->dev.parent = &bus->host_pci->dev;
+ ? ? ? ? ? ? ? ? ? ? ? wrapper->core->dma_dev = &bus->host_pci->dev;
+ ? ? ? ? ? ? ? ? ? ? ? wrapper->core->irq = bus->host_pci->irq; ? ? ? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ? ? ?case BCMA_HOSTTYPE_NONE:
? ? ? ? ? ? ? ?case BCMA_HOSTTYPE_SDIO:
? ? ? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ? ? ?}

- ? ? ? ? ? ? ? err = device_register(&core->dev);
+ ? ? ? ? ? ? ? err = device_register(&wrapper->dev);
? ? ? ? ? ? ? ?if (err) {
? ? ? ? ? ? ? ? ? ? ? ?pr_err("Could not register dev for core 0x%03X\n", ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? core->id.id);
+ ? ? ? ? ? ? ? ? ? ? ? kfree(wrapper);
? ? ? ? ? ? ? ? ? ? ? ?continue;
? ? ? ? ? ? ? ?}
- ? ? ? ? ? ? ? core->dev_registered = true;
+ ? ? ? ? ? ? ? core->dev = &wrapper->dev;
? ? ? ? ? ? ? ?dev_id++;
? ? ? ?}

drivers/bcma/main.c +14 -6
@@ -113,10 +129,12 @@ static int bcma_register_cores(struct bcma_bus *bus)
 ?static void bcma_unregister_cores(struct bcma_bus *bus)
 ?{
 ? ? ? ?struct bcma_device *core;
+ ? ? ? int i;
 
- ? ? ? list_for_each_entry(core, &bus->cores, list) {
- ? ? ? ? ? ? ? if (core->dev_registered)
- ? ? ? ? ? ? ? ? ? ? ? device_unregister(&core->dev);
+ ? ? ? for (i = 0; i < bus->nr_cores; i++) {
+ ? ? ? ? ? ? ? core = &(bus->cores[i]);
+ ? ? ? ? ? ? ? if (core->dev)
+ ? ? ? ? ? ? ? ? ? ? ? device_unregister(core->dev);
 ? ? ? ?}
 ?}
 
@@ -179,7 +197,9 @@ EXPORT_SYMBOL_GPL(bcma_driver_unregister);
 
 ?static int bcma_bus_match(struct device *dev, struct device_driver *drv)
 ?{
- ? ? ? struct bcma_device *core = container_of(dev, struct bcma_device, dev);
+ ? ? ? struct __bcma_dev_wrapper *wrapper = container_of(dev,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct __bcma_dev_wrapper, dev);
+ ? ? ? struct bcma_device *core = wrapper->core;
 ? ? ? ?struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
 ? ? ? ?const struct bcma_device_id *cid = &core->id;
 ? ? ? ?const struct bcma_device_id *did;
@@ -196,7 +216,9 @@ static int bcma_bus_match(struct device *dev, struct device_driver *drv)
 
 ?static int bcma_device_probe(struct device *dev)
 ?{
- ? ? ? struct bcma_device *core = container_of(dev, struct bcma_device, dev);
+ ? ? ? struct __bcma_dev_wrapper *wrapper = container_of(dev,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct __bcma_dev_wrapper, dev);
+ ? ? ? struct bcma_device *core = wrapper->core;
 ? ? ? ?struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? drv);
 ? ? ? ?int err = 0;
@@ -209,7 +231,9 @@ static int bcma_device_probe(struct device *dev)
 
 ?static int bcma_device_remove(struct device *dev)
 ?{
- ? ? ? struct bcma_device *core = container_of(dev, struct bcma_device, dev);
+ ? ? ? struct __bcma_dev_wrapper *wrapper = container_of(dev,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct __bcma_dev_wrapper, dev);
+ ? ? ? struct bcma_device *core = wrapper->core;
 ? ? ? ?struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? drv);
 
drivers/bcma/scan.c +2 -8
index 40d7dcc..70b39f7 100644
@@ -211,9 +211,6 @@ int bcma_bus_scan(struct bcma_bus *bus)
 ? ? ? ?s32 tmp;
 ? ? ? ?u8 i, j;
 
- ? ? ? int err;
-
- ? ? ? INIT_LIST_HEAD(&bus->cores);
 ? ? ? ?bus->nr_cores = 0;
 
 ? ? ? ?bcma_scan_switch_core(bus, BCMA_ADDR_BASE);
@@ -230,11 +227,8 @@ int bcma_bus_scan(struct bcma_bus *bus)
 ? ? ? ?bcma_scan_switch_core(bus, erombase);
 
 ? ? ? ?while (eromptr < eromend) {
- ? ? ? ? ? ? ? struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL);
- ? ? ? ? ? ? ? if (!core)
- ? ? ? ? ? ? ? ? ? ? ? return -ENOMEM;
- ? ? ? ? ? ? ? INIT_LIST_HEAD(&core->list);
- ? ? ? ? ? ? ? core->bus = bus;
+ ? ? ? ? ? ? ? struct bcma_device core = { };
+ ? ? ? ? ? ? ? core.bus = bus;
 

? ? ? ? ? ? ? ?/* get CIs */
? ? ? ? ? ? ? ?cia = bcma_erom_get_ci(bus, &eromptr);

drivers/bcma/scan.c +3 -6
@@ -242,27 +236,24 @@ int bcma_bus_scan(struct bcma_bus *bus)
 ? ? ? ? ? ? ? ? ? ? ? ?bcma_erom_push_ent(&eromptr);
 ? ? ? ? ? ? ? ? ? ? ? ?if (bcma_erom_is_end(bus, &eromptr))
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break;
- ? ? ? ? ? ? ? ? ? ? ? err= -EILSEQ;
- ? ? ? ? ? ? ? ? ? ? ? goto out;
+ ? ? ? ? ? ? ? ? ? ? ? return -EILSEQ;
 ? ? ? ? ? ? ? ?}
 ? ? ? ? ? ? ? ?cib = bcma_erom_get_ci(bus, &eromptr);
- ? ? ? ? ? ? ? if (cib < 0) {
- ? ? ? ? ? ? ? ? ? ? ? err= -EILSEQ;
- ? ? ? ? ? ? ? ? ? ? ? goto out;
- ? ? ? ? ? ? ? }
+ ? ? ? ? ? ? ? if (cib < 0)
+ ? ? ? ? ? ? ? ? ? ? ? return -EILSEQ;
 

? ? ? ? ? ? ? ?/* parse CIs */
- ? ? ? ? ? ? ? core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
- ? ? ? ? ? ? ? core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
- ? ? ? ? ? ? ? core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT;
+ ? ? ? ? ? ? ? core.id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
+ ? ? ? ? ? ? ? core.id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
+ ? ? ? ? ? ? ? core.id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT; ? ? ? ? ? ? ? ?ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT; ? ? ? ? ? ? ? ?ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT; ? ? ? ? ? ? ? ?wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT; ? ? ? ? ? ? ? ?wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT;
- ? ? ? ? ? ? ? core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;
+ ? ? ? ? ? ? ? core.id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;

- ? ? ? ? ? ? ? if (((core->id.manuf == BCMA_MANUF_ARM) &&
- ? ? ? ? ? ? ? ? ? ?(core->id.id == 0xFFF)) ||
+ ? ? ? ? ? ? ? if (((core.id.manuf == BCMA_MANUF_ARM) &&
+ ? ? ? ? ? ? ? ? ? ?(core.id.id == 0xFFF)) ||
? ? ? ? ? ? ? ? ? ?(ports[1] == 0)) {
? ? ? ? ? ? ? ? ? ? ? ?bcma_erom_skip_component(bus, &eromptr); ? ? ? ? ? ? ? ? ? ? ? ?continue;

drivers/bcma/scan.c +0 -0
@@ -285,10 +276,8 @@ int bcma_bus_scan(struct bcma_bus *bus)

? ? ? ? ? ? ? ?/* get & parse master ports */
? ? ? ? ? ? ? ?for (i = 0; i < ports[0]; i++) {
? ? ? ? ? ? ? ? ? ? ? ?u32 mst_port_d = bcma_erom_get_mst_port(bus, &eromptr);
- ? ? ? ? ? ? ? ? ? ? ? if (mst_port_d < 0) {
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? err= -EILSEQ;
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? goto out;
- ? ? ? ? ? ? ? ? ? ? ? }
+ ? ? ? ? ? ? ? ? ? ? ? if (mst_port_d < 0)
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return -EILSEQ;
? ? ? ? ? ? ? ?}

? ? ? ? ? ? ? ?/* get & parse slave ports */

drivers/bcma/scan.c +3 -3
@@ -303,7 +292,7 @@ int bcma_bus_scan(struct bcma_bus *bus)
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break;
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?} else {
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (i == 0 && j == 0)
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? core->addr = tmp;
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? core.addr = tmp;
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
 ? ? ? ? ? ? ? ? ? ? ? ?}
 ? ? ? ? ? ? ? ?}
@@ -320,7 +309,7 @@ int bcma_bus_scan(struct bcma_bus *bus)
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break;
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?} else {
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (i == 0 && j == 0)
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? core->wrap = tmp;
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? core.wrap = tmp;
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
 ? ? ? ? ? ? ? ? ? ? ? ?}
 ? ? ? ? ? ? ? ?}
@@ -338,22 +327,19 @@ int bcma_bus_scan(struct bcma_bus *bus)
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break;
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?} else {
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (wrappers[0] == 0 && !i && !j)
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? core->wrap = tmp;
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? core.wrap = tmp;
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
 ? ? ? ? ? ? ? ? ? ? ? ?}
 ? ? ? ? ? ? ? ?}
 

? ? ? ? ? ? ? ?pr_info("Core %d found: %s "
? ? ? ? ? ? ? ? ? ? ? ?"(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
- ? ? ? ? ? ? ? ? ? ? ? bus->nr_cores, bcma_device_name(&core->id),
- ? ? ? ? ? ? ? ? ? ? ? core->id.manuf, core->id.id, core->id.rev,
- ? ? ? ? ? ? ? ? ? ? ? core->id.class);

drivers/bcma/scan.c +6 -6
-
- ? ? ? ? ? ? ? core->core_index = bus->nr_cores++;
- ? ? ? ? ? ? ? list_add(&core->list, &bus->cores);
- ? ? ? ? ? ? ? continue;
-out:
- ? ? ? ? ? ? ? return err;
+ ? ? ? ? ? ? ? ? ? ? ? bus->nr_cores, bcma_device_name(&core.id),
+ ? ? ? ? ? ? ? ? ? ? ? core.id.manuf, core.id.id, core.id.rev,
+ ? ? ? ? ? ? ? ? ? ? ? core.id.class);
+
+ ? ? ? ? ? ? ? core.core_index = bus->nr_cores;
+ ? ? ? ? ? ? ? bus->cores[bus->nr_cores++] = core;

? ? ? ?}

? ? ? ?return 0;

include/linux/bcma/bcma.h +0 -0
index 27a27a7..3dc5302 100644
@@ -118,14 +118,23 @@ struct bcma_host_ops {
 

?#define BCMA_MAX_NR_CORES ? ? ? ? ? ? ?16

include/linux/bcma/bcma.h +10 -0
+/* 1) It is not allowed to put struct device statically in bcma_device
+ * 2) We can not just use pointer to struct device because we use container_of
+ * 3) We do not have pointer to struct bcma_device in struct device
+ * Solution: use such a dummy wrapper
+ */
+struct __bcma_dev_wrapper {
+ ? ? ? struct device dev;
+ ? ? ? struct bcma_device *core;
+};
+

?struct bcma_device {
? ? ? ?struct bcma_bus *bus;
? ? ? ?struct bcma_device_id id;

- ? ? ? struct device dev;
+ ? ? ? struct device *dev;
? ? ? ?struct device *dma_dev;
? ? ? ?unsigned int irq;
- ? ? ? bool dev_registered;

? ? ? ?u8 core_index;

include/linux/bcma/bcma.h +1 -3
@@ -133,7 +142,6 @@ struct bcma_device {
 ? ? ? ?u32 wrap;
 
 ? ? ? ?void *drvdata;
- ? ? ? struct list_head list;
 ?};
 
 ?static inline void *bcma_get_drvdata(struct bcma_device *core)
@@ -182,7 +190,7 @@ struct bcma_bus {
 ? ? ? ?struct bcma_chipinfo chipinfo;
 
 ? ? ? ?struct bcma_device *mapped_core;
- ? ? ? struct list_head cores;
+ ? ? ? struct bcma_device cores[BCMA_MAX_NR_CORES];
 ? ? ? ?u8 nr_cores;
 
 ? ? ? ?struct bcma_drv_cc drv_cc;
--

1.7.4.1

#4 lore raw

Re: [RFC][PATCH 01/10] bcma: Use array to store cores.

Quoted 7 lines · Rafał Miłecki

Greg, Arnd: could you take a look at this patch, please?

With proposed patch we are going back to this ugly array and wrappers hacks.

I was really happy with our final solution, but it seems it's not doable for embedded systems...? Is there something better we can do about this?

I do agree with Rafał that we should look for another alternative. I posted a suggestion earlier regarding this patch. Can anyone tell me whether that could prevent need for the array/wrapper hack.

Gr. AvS

Signature · 2 lines
Almost nobody dances sober, unless they happen to be insane.
-- H.P. Lovecraft --
#5 lore raw

Re: [RFC][PATCH 01/10] bcma: Use array to store cores.

In reply to Rafał Miłecki
Quoted 21 lines · Rafał Miłecki

Greg, Arnd: could you take a look at this patch, please?

With proposed patch we are going back to this ugly array and wrappers hacks.

I was really happy with our final solution, but it seems it's not doable for embedded systems...? Is there something better we can do about this?

2011/6/6 Hauke Mehrtens <[email protected]>:

Quoted 12 lines

When using bcma on a embedded device it is initialized very early at boot. We have to do so as the cpu and interrupt management and all other devices are attached to this bus and it has to be initialized so early. In that stage we can not allocate memory or sleep, just use the memory on the stack and in the text segment as the kernel is not initialized far enough. This patch removed the kzallocs from the scan code. Some earlier version of the bcma implementation and the normal ssb implementation are doing it like this.
The __bcma_dev_wrapper struct is used as the container for the device struct as bcma_device will be too big if it includes struct device.

If you rely on device scan to find your CPUs and interrupt controllers, you are screwed already, this won't work.

In that case, it's better to have a few "early" drivers, as few as possible, that don't go through the bus scan at all but have their own ways of bootstrapping themselves. I don't know what you mean by "CPU management", but I can only assume that it's not doing that much, and you can just put the register values into the device tree.

For an interrupt controller, it should be ok to have it initialized late, as long as it's only responsible for the devices on the same bus and not for instance for IPI interrupts. Just make sure that you do the bus scan and the initialization of the IRQ driver before you initialize any drivers that rely in on the interrupts to be working.

Arnd

#6 lore raw

Re: [RFC][PATCH 01/10] bcma: Use array to store cores.

Hi,

Quoted 23 lines · Rafał Miłecki
Quoted 21 lines

Greg, Arnd: could you take a look at this patch, please?

With proposed patch we are going back to this ugly array and wrappers hacks.

I was really happy with our final solution, but it seems it's not doable for embedded systems...? Is there something better we can do about this?

2011/6/6 Hauke Mehrtens <[email protected]>:

Quoted 12 lines

When using bcma on a embedded device it is initialized very early at boot. We have to do so as the cpu and interrupt management and all other devices are attached to this bus and it has to be initialized so early. In that stage we can not allocate memory or sleep, just use the memory on the stack and in the text segment as the kernel is not initialized far enough. This patch removed the kzallocs from the scan code. Some earlier version of the bcma implementation and the normal ssb implementation are doing it like this.
The __bcma_dev_wrapper struct is used as the container for the device struct as bcma_device will be too big if it includes struct device.

Quoted 8 lines

If you rely on device scan to find your CPUs and interrupt controllers, you are screwed already, this won't work.

In that case, it's better to have a few "early" drivers, as few as possible, that don't go through the bus scan at all but have their own ways of bootstrapping themselves. I don't know what you mean by "CPU management", but I can only assume that it's not doing that much, and you can just put the register values into the device tree.

GPIOs, flash and UART could get initialized early without erom scanning as Chipcommon seems always to be the #0 core on the amba interconnect.

Quoted 6 lines

For an interrupt controller, it should be ok to have it initialized late, as long as it's only responsible for the devices on the same bus and not for instance for IPI interrupts. Just make sure that you do the bus scan and the initialization of the IRQ driver before you initialize any drivers that rely in on the interrupts to be working.

Without proper timer init (which requires both the chipcommon and mips cores knowledge) kernel will get hung somewhere inside calibrate_delay. It could get addressed if get bus scan called in arch_init_irq or plat_time_init - both are executed before calibrate_delay and with slab available.

Have nice day,
George

#7 lore raw

Re: [RFC][PATCH 01/10] bcma: Use array to store cores.

Quoted 11 lines · George Kashperko
Quoted 5 lines

For an interrupt controller, it should be ok to have it initialized late, as long as it's only responsible for the devices on the same bus and not for instance for IPI interrupts. Just make sure that you do the bus scan and the initialization of the IRQ driver before you initialize any drivers that rely in on the interrupts to be working.

Without proper timer init (which requires both the chipcommon and mips cores knowledge) kernel will get hung somewhere inside calibrate_delay. It could get addressed if get bus scan called in arch_init_irq or plat_time_init - both are executed before calibrate_delay and with slab available.

Ok, so you need the interrupt controller to be working for the timer tick, right? I think another option (if that's not what you mean already) would be to have a simpler way to find a device on the bus that can be called before doing a full scan.

Early drivers would then have to know what is there and call a function like "bcma_find_device(BCMA_DEV_ID_IRQ)", while drivers that are not required to be up just register a regular device driver with a probe function that gets called after the bus scan creates device structures.

Arnd

author maintainer
#8 lore raw

RFC PATCH 1/10 bcma: Use array to store cores.

Quoted 18 lines · Arnd Bergmann
Quoted 11 lines · George Kashperko
Quoted 5 lines

For an interrupt controller, it should be ok to have it initialized late, as long as it's only responsible for the devices on the same bus and not for instance for IPI interrupts. Just make sure that you do the bus scan and the initialization of the IRQ driver before you initialize any drivers that rely in on the interrupts to be working.

Without proper timer init (which requires both the chipcommon and mips cores knowledge) kernel will get hung somewhere inside calibrate_delay. It could get addressed if get bus scan called in arch_init_irq or plat_time_init - both are executed before calibrate_delay and with slab available.

Ok, so you need the interrupt controller to be working for the timer tick, right? I think another option (if that's not what you mean already) would be to have a simpler way to find a device on the bus that can be called before doing a full scan.

Quoted 6 lines

Early drivers would then have to know what is there and call a function like "bcma_find_device(BCMA_DEV_ID_IRQ)", while drivers that are not required to be up just register a regular device driver with a probe function that gets called after the bus scan creates device structures.

Arnd

Accessing chip common should be possible without scanning the hole bus as it is at the first position and initializing most things just needs chip common. For initializing the interrupts scanning is needed as we do not know where the mips core is located.

As we can not use kalloc on early boot we could use a function which uses kalloc under normal conditions and when on early boot the architecture code which starts the bcma code should also provide a function which returns a pointer to some memory in its text segment to use. We need space for 16 cores in the architecture code.

In addition bcma_bus_register(struct bcma_bus *bus) has to be divided into two parts. The first part will scan the bus and initialize chip common and mips core. The second part will initialize pci core and register the devices in the system. When using this under normal conditions they will be called directly after each other.

Hauke

#9 lore raw

Re: [RFC][PATCH 01/10] bcma: Use array to store cores.

Quoted 11 lines · On Monday 06 June 2011 23:38:50 Hauke Mehrtens wrote:

Accessing chip common should be possible without scanning the hole bus as it is at the first position and initializing most things just needs chip common. For initializing the interrupts scanning is needed as we do not know where the mips core is located.

As we can not use kalloc on early boot we could use a function which uses kalloc under normal conditions and when on early boot the architecture code which starts the bcma code should also provide a function which returns a pointer to some memory in its text segment to use. We need space for 16 cores in the architecture code.

Quoted 5 lines

In addition bcma_bus_register(struct bcma_bus *bus) has to be divided into two parts. The first part will scan the bus and initialize chip common and mips core. The second part will initialize pci core and register the devices in the system. When using this under normal conditions they will be called directly after each other.

Just split out the minimal low-level function from the bcma_bus_scan then, to locate a single device based on some identifier. The bcma_bus_scan() function can then repeatedly allocate one device and pass it to the low-level function when doing the proper scan, while the arch code calls the low-level function directly with static data.

Arnd

#10 lore raw

Re: [RFC][PATCH 01/10] bcma: Use array to store cores.

Quoted 17 lines · Arnd Bergmann
Quoted 11 lines · On Monday 06 June 2011 23:38:50 Hauke Mehrtens wrote:

Accessing chip common should be possible without scanning the hole bus as it is at the first position and initializing most things just needs chip common. For initializing the interrupts scanning is needed as we do not know where the mips core is located.

As we can not use kalloc on early boot we could use a function which uses kalloc under normal conditions and when on early boot the architecture code which starts the bcma code should also provide a function which returns a pointer to some memory in its text segment to use. We need space for 16 cores in the architecture code.

Quoted 5 lines

In addition bcma_bus_register(struct bcma_bus *bus) has to be divided into two parts. The first part will scan the bus and initialize chip common and mips core. The second part will initialize pci core and register the devices in the system. When using this under normal conditions they will be called directly after each other.

Quoted 6 lines

Just split out the minimal low-level function from the bcma_bus_scan then, to locate a single device based on some identifier. The bcma_bus_scan() function can then repeatedly allocate one device and pass it to the low-level function when doing the proper scan, while the arch code calls the low-level function directly with static data.

If going for this we should pass struct bcma_device_id as match parameter as that identifies the core appropriately although you probably only want to match manufacturer and core identifiers.

Gr. AvS

Signature · 2 lines
Almost nobody dances sober, unless they happen to be insane.
-- H.P. Lovecraft --
author maintainer
#11 lore raw

RFC PATCH 1/10 bcma: Use array to store cores.

Quoted 25 lines · Arend van Spriel
Quoted 17 lines · Arnd Bergmann
Quoted 11 lines · On Monday 06 June 2011 23:38:50 Hauke Mehrtens wrote:

Accessing chip common should be possible without scanning the hole bus as it is at the first position and initializing most things just needs chip common. For initializing the interrupts scanning is needed as we do not know where the mips core is located.

As we can not use kalloc on early boot we could use a function which uses kalloc under normal conditions and when on early boot the architecture code which starts the bcma code should also provide a function which returns a pointer to some memory in its text segment to use. We need space for 16 cores in the architecture code.

Quoted 5 lines

In addition bcma_bus_register(struct bcma_bus *bus) has to be divided into two parts. The first part will scan the bus and initialize chip common and mips core. The second part will initialize pci core and register the devices in the system. When using this under normal conditions they will be called directly after each other.

Quoted 6 lines

Just split out the minimal low-level function from the bcma_bus_scan then, to locate a single device based on some identifier. The bcma_bus_scan() function can then repeatedly allocate one device and pass it to the low-level function when doing the proper scan, while the arch code calls the low-level function directly with static data.

Quoted 6 lines

If going for this we should pass struct bcma_device_id as match parameter as that identifies the core appropriately although you probably only want to match manufacturer and core identifiers.

Gr. AvS

What is the problem with scanning the full bus? Scanning in general works for embedded devices, just allocating memory with kalloc does not work at that time, but the architecture code (something in arch/mips/bcm47xx/) could provide some memory to store the struct bcma_core, like it does for struct bcma_bus. We could just provide memory for chipcommon and mips core or memory for all possible 16 cores, the maximum number, as most embedded devices have ~9 cores providing memory for 16 cores is not a big vast of memory and then we could use the normal scan function.

A special scan function would just skip the wrong cores so I do not see any advantage in that.

We could build a scan function which searches for one core and uses a struct bcma_core stored on the stack and returns the struct bcma_core if it found the wanted one. Then we could search for chipcommon and mips and store then in arch code in arch/mips/bcm47xx and use them. When boot is ready and we are searching the complete bus there is probably something differences in the init process from normal init as we already initialized chipcommon sometime earlier. I Would prefer to scan the bus completely and initialize chipcommon and mips in early boot.

Hauke

maintainer
#12 lore raw

RFC PATCH 1/10 bcma: Use array to store cores.

2011/6/7 Hauke Mehrtens <[email protected]>:

Quoted 26 lines · Arend van Spriel
Quoted 25 lines · Arnd Bergmann
Quoted 23 lines · On Monday 06 June 2011 23:38:50 Hauke Mehrtens wrote:
Quoted 11 lines

Accessing chip common should be possible without scanning the hole bus as it is at the first position and initializing most things just needs chip common. For initializing the interrupts scanning is needed as we do not know where the mips core is located.

As we can not use kalloc on early boot we could use a function which uses kalloc under normal conditions and when on early boot the architecture code which starts the bcma code should also provide a function which returns a pointer to some memory in its text segment to use. We need space for 16 cores in the architecture code.

Quoted 5 lines

In addition bcma_bus_register(struct bcma_bus *bus) has to be divided into two parts. The first part will scan the bus and initialize chip common and mips core. The second part will initialize pci core and register the devices in the system. When using this under normal conditions they will be called directly after each other.

Just split out the minimal low-level function from the bcma_bus_scan then, to locate a single device based on some identifier. The bcma_bus_scan() function can then repeatedly allocate one device and pass it to the low-level function when doing the proper scan, while the arch code calls the low-level function directly with static data.

Quoted 8 lines
Quoted 6 lines

If going for this we should pass struct bcma_device_id as match parameter as that identifies the core appropriately although you probably only want to match manufacturer and core identifiers.

Gr. AvS

What is the problem with scanning the full bus?

Because full scanning needs one of the following:
1) Working alloc - not possible for SoCs
2) Hacks with wrappers, static cores info, lack of optimization (list)

Quoted 6 lines

A special scan function would just skip the wrong cores so I do not see any advantage in that.

We could build a scan function which searches for one core and uses a struct bcma_core stored on the stack and returns the struct bcma_core if it found the wanted one.

Yeah, this should be quite easy.

struct bcma_device core = bcma_early_find_core(bus, CC); bcma_cc_init(core);

Quoted 2 lines

Then we could search for chipcommon and mips
and store then in arch code in arch/mips/bcm47xx and use them.

Not sure about this one. You have drivers for chipcommon and mips as part of bcma. Do you need to involve arch/mips/bcm47xx to this?

Quoted 4 lines

When boot
is ready and we are searching the complete bus there is probably something differences in the init process from normal init as we already initialized chipcommon sometime earlier.

Nothing hard to handle.

Quoted 2 lines

I Would prefer to scan the bus
completely and initialize chipcommon and mips in early boot.

Really, I've nothing against scanning and splitting init into "early" and "late". It's going back to static fields and wrappers that I don't like :(

Signature · 1 line
Rafa?
#13 lore raw

RFC PATCH 1/10 bcma: Use array to store cores.

Quoted 2 lines · On Wed, 8 Jun 2011 02:06:11 +0200 Rafa? Mi?ecki <[email protected]> wrote:

Because full scanning needs one of the following:
1) Working alloc - not possible for SoCs

Isn't there a bootmem allocator available on MIPS?

author maintainer
#14 lore raw

RFC PATCH 1/10 bcma: Use array to store cores.

Quoted 7 lines · Michael B?sch
Quoted 2 lines · On Wed, 8 Jun 2011 02:06:11 +0200 Rafa? Mi?ecki <[email protected]> wrote:

Because full scanning needs one of the following:
1) Working alloc - not possible for SoCs

Isn't there a bootmem allocator available on MIPS?

The bootmem allocator is working on mips, but it is initialized after plat_mem_setup() was called. To use it we have to move the start of bcma to some other place in the bcm47xx code.

We need access to the common and mips core for different functions in the bcm47xx code and these functions are getting called by the mips code, so we can not store these struct bcma_devices on the stack.

I would use this struct on the embedded device and use it in the text segment of the bcm47xx code.

In include/linux/bcma/bcma.h:

struct bcma_soc {
	struct bcma_bus bus;
	struct bcma_device core_cc;
	struct bcma_device core_mips;
};

In arch/mips/bcm47xx/setup.c
struct bcma_soc bus;

The chipcommon and mips core can be initilized early without the need use of any alloc. The bcm47xx code will call bcma_bus_early_register(struct bcma_soc *soc) and this code will find these two cores, add then to the list of cores in bcma_bus and run the init code for them. After that we have all we need to boot up the device. After the kernel page allocator is fully set up we would search for all the other cores and add them to the list of cores and do the initialization for them. The two cores in struct bcma_soc will never be accessed directly but only through struct bcma_bus so that there is no difference from early boot and normal mode.

Hauke

author maintainer
#15 lore raw

RFC PATCH 2/10 bcma: Make it possible to run bcma_register_cores() later

In reply to Hauke Mehrtens

On embedded device we can not allocate memory with kalloc or sleep for some time, when bcma is initialized, because this is done early in the boot process. This patch makes it possible to do the bcma_register_cores() sometime later and not directly after searching for the cores. The initialization of the PCI(e) core is also done later as it uses udelay(), which will not work so early. The buses are placed into a list and bcma_register_cores() will be run when the bcma module is initialized. When using bcma on a PCI-Bus in a normal PC bcma_register_cores() is triggered directly after bcma_bus_register(). This patch is based on ssb code.

---
 drivers/bcma/main.c       |   65 ++++++++++++++++++++++++++++++++++++++++++---
 include/linux/bcma/bcma.h |    3 ++
 2 files changed, 64 insertions(+), 4 deletions(-)
drivers/bcma/main.c +61 -4
index b0e7f5e..1afa107 100644
@@ -15,6 +15,16 @@ 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);
 
+/* Temporary list of yet-to-be-attached buses */
+static LIST_HEAD(attach_queue);
+/* There are differences in the codeflow, if the bus is
+ * initialized from early boot, as various needed services
+ * are not available early. This is a mechanism to delay
+ * these initializations to after early boot has finished.
+ * It's also used to avoid mutex locking, as that's not
+ * available and needed early. */
+static bool bcma_is_early_boot = 1;
+
 static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct __bcma_dev_wrapper *wrapper = container_of(dev,
@@ -126,6 +136,36 @@ static int bcma_register_cores(struct bcma_bus *bus)
 	return 0;
 }
 
+static int bcma_attach_queued_buses(void)
+{
+	struct bcma_bus *bus, *n;
+	int err = 0;
+	int drop_them_all = 0;
+
+	list_for_each_entry_safe(bus, n, &attach_queue, attach_list) {
+		if (drop_them_all) {
+			list_del(&bus->attach_list);
+			continue;
+		}
+		/* Can't init the PCIcore in bcma_bus_register(), as that
+		 * is too early in boot for embedded systems
+		 * (no udelay() available). So do it here in attach stage.
+		 */
+		if (bus->drv_pci.core)
+			bcma_core_pci_init(&bus->drv_pci);
+
+		err = bcma_register_cores(bus);
+		if (err) {
+			drop_them_all = 1;
+			list_del(&bus->attach_list);
+			continue;
+		}
+		list_del(&bus->attach_list);
+	}
+
+	return err;
+}
+
 static void bcma_unregister_cores(struct bcma_bus *bus)
 {
 	struct bcma_device *core;
@@ -157,15 +197,20 @@ int bcma_bus_register(struct bcma_bus *bus)
 		bcma_core_chipcommon_init(&bus->drv_cc);
 	}
 
-	/* Init PCIE core */
+	/* Find PCIE core */
 	core = bcma_find_core(bus, BCMA_CORE_PCIE);
 	if (core) {
+		/* will be initilized in bcma_attach_queued_buses() */
 		bus->drv_pci.core = core;
-		bcma_core_pci_init(&bus->drv_pci);
 	}
 
-	/* Register found cores */
-	bcma_register_cores(bus);
+	/* Queue it for attach.
+	 * See the comment at the bcma_is_early_boot definition. */
+	list_add_tail(&bus->attach_list, &attach_queue);
+	if (!bcma_is_early_boot) {
+		/* This is not early boot, so we must attach the bus now */
+		bcma_attach_queued_buses();
+	}
 
 	pr_info("Bus registered\n");
 
@@ -247,10 +292,22 @@ static int __init bcma_modinit(void)
 {
 	int err;
 
+	/* See the comment at the bcma_is_early_boot definition */
+	bcma_is_early_boot = 0;
+
 	err = bus_register(&bcma_bus_type);
 	if (err)
 		return err;
 
+	/* Maybe we already registered some buses at early boot.
+	 * Check for this and attach them.
+	 */
+	err = bcma_attach_queued_buses();
+	if (err) {
+		pr_err("Attaching core registered in early boot failed\n");
+		err = 0;
+	}
+
 #ifdef CONFIG_BCMA_HOST_PCI
 	err = bcma_host_pci_init();
 	if (err) {
include/linux/bcma/bcma.h +3 -0
index 3dc5302..8b6feca 100644
@@ -195,6 +195,9 @@ struct bcma_bus {
 
 	struct bcma_drv_cc drv_cc;
 	struct bcma_drv_pci drv_pci;
+
+	/* Internal-only stuff follows. Do not touch. */
+	struct list_head attach_list;
 };
 
 extern inline u32 bcma_read8(struct bcma_device *core, u16 offset)
Signature · 1 line
1.7.4.1
author maintainer
#16 lore raw

RFC PATCH 3/10 bcma: add embedded bus

In reply to Hauke Mehrtens

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.

---
 drivers/bcma/Kconfig               |    5 ++
 drivers/bcma/Makefile              |    1 +
 drivers/bcma/host_embedded.c       |   93 ++++++++++++++++++++++++++++++++++++
 drivers/bcma/main.c                |    1 +
 drivers/bcma/scan.c                |   29 ++++++++++-
 include/linux/bcma/bcma.h          |    3 +
 include/linux/bcma/bcma_embedded.h |    8 +++
 7 files changed, 138 insertions(+), 2 deletions(-)
 create mode 100644 drivers/bcma/host_embedded.c
 create mode 100644 include/linux/bcma/bcma_embedded.h
drivers/bcma/Kconfig +5 -0
index 83e9adf..0390e32 100644
@@ -27,6 +27,11 @@ config BCMA_HOST_PCI
 	bool "Support for BCMA on PCI-host bus"
 	depends on BCMA_HOST_PCI_POSSIBLE
 
+config BCMA_HOST_EMBEDDED
+	bool
+	depends on BCMA && MIPS
+	default n
+
 config BCMA_DEBUG
 	bool "BCMA debugging"
 	depends on BCMA
drivers/bcma/Makefile +1 -0
index 0d56245..e509b1b 100644
@@ -2,6 +2,7 @@ bcma-y					+= main.o scan.o core.o
 bcma-y					+= driver_chipcommon.o driver_chipcommon_pmu.o
 bcma-y					+= driver_pci.o
 bcma-$(CONFIG_BCMA_HOST_PCI)		+= host_pci.o
+bcma-$(CONFIG_BCMA_HOST_EMBEDDED)	+= host_embedded.o
 obj-$(CONFIG_BCMA)			+= bcma.o
 
 ccflags-$(CONFIG_BCMA_DEBUG)		:= -DDEBUG
drivers/bcma/host_embedded.c new file +93 -0

93 lines not on this page · raw message

drivers/bcma/main.c +1 -0
index 1afa107..c5bcb5f 100644
@@ -119,6 +119,7 @@ static int bcma_register_cores(struct bcma_bus *bus)
 			break;
 		case BCMA_HOSTTYPE_NONE:
 		case BCMA_HOSTTYPE_SDIO:
+		case BCMA_HOSTTYPE_EMBEDDED:
 			break;
 		}
 
drivers/bcma/scan.c +27 -2
index 70b39f7..9229615 100644
@@ -203,7 +203,7 @@ static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr,
 int bcma_bus_scan(struct bcma_bus *bus)
 {
 	u32 erombase;
-	u32 __iomem *eromptr, *eromend;
+	u32 __iomem *eromptr, *eromend, *mmio;
 
 	s32 cia, cib;
 	u8 ports[2], wrappers[2];
@@ -219,9 +219,34 @@ int bcma_bus_scan(struct bcma_bus *bus)
 	bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
 	bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
 	bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
+	bus->nr_cores = (tmp & BCMA_CC_ID_NRCORES) >> BCMA_CC_ID_NRCORES_SHIFT;
+
+	/* If we are an embedded device we now know the number of avaliable
+	 * core and ioremap the correct space.
+	 */
+	if (bus->hosttype == BCMA_HOSTTYPE_EMBEDDED) {
+		iounmap(bus->mmio);
+		mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * bus->nr_cores);
+		if (!mmio)
+			return -ENOMEM;
+		bus->mmio = mmio;
+
+		mmio = ioremap(BCMA_WRAP_BASE, BCMA_CORE_SIZE * bus->nr_cores);
+		if (!mmio)
+			return -ENOMEM;
+		bus->host_embedded = mmio;
+	}
+	/* reset it to 0 as we use it for counting */
+	bus->nr_cores = 0;
 
 	erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
-	eromptr = bus->mmio;
+	if (bus->hosttype == BCMA_HOSTTYPE_EMBEDDED) {
+		eromptr = ioremap(erombase, BCMA_CORE_SIZE);
+		if (!eromptr)
+			return -ENOMEM;
+	} else
+		eromptr = bus->mmio;
+
 	eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
 
 	bcma_scan_switch_core(bus, erombase);
include/linux/bcma/bcma.h +3 -0
index 8b6feca..192c4ae 100644
@@ -16,6 +16,7 @@ enum bcma_hosttype {
 	BCMA_HOSTTYPE_NONE,
 	BCMA_HOSTTYPE_PCI,
 	BCMA_HOSTTYPE_SDIO,
+	BCMA_HOSTTYPE_EMBEDDED,
 };
 
 struct bcma_chipinfo {
@@ -185,6 +186,8 @@ struct bcma_bus {
 		struct pci_dev *host_pci;
 		/* Pointer to the SDIO device (only for BCMA_HOSTTYPE_SDIO) */
 		struct sdio_func *host_sdio;
+		/* Pointer to the embedded iomem (only for BCMA_HOSTTYPE_EMBEDDED) */
+		void __iomem *host_embedded;
 	};
 
 	struct bcma_chipinfo chipinfo;
include/linux/bcma/bcma_embedded.h new file +8 -0
new file mode 100644
index 0000000..0faf46d
@@ -0,0 +1,8 @@
+#ifndef LINUX_BCMA_EMBEDDED_H_
+#define LINUX_BCMA_EMBEDDED_H_
+
+#include <linux/bcma/bcma.h>
+
+extern int bcma_host_bcma_register(struct bcma_bus *bus);
+
+#endif /* LINUX_BCMA_EMBEDDED_H_ */
Signature · 1 line
1.7.4.1
#17 lore raw

Re: [RFC][PATCH 03/10] bcma: add embedded bus

Hauke,

Minor nit:

Quoted 23 lines · Hauke Mehrtens

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.

---

drivers/bcma/scan.c +9 -0
index 70b39f7..9229615 100644
@@ -219,9 +219,34 @@ int bcma_bus_scan(struct bcma_bus *bus)
        bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
        bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
        bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
+       bus->nr_cores = (tmp & BCMA_CC_ID_NRCORES) >> BCMA_CC_ID_NRCORES_SHIFT;
+
+       /* If we are an embedded device we now know the number of avaliable
+        * core and ioremap the correct space.
+        */
+       if (bus->hosttype == BCMA_HOSTTYPE_EMBEDDED) {
+               iounmap(bus->mmio);
+               mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * bus->nr_cores);
+               if (!mmio)

drivers/bcma/scan.c int bcma_bus_scan(struct bcma_bus *bus) · line 240

Quoted 10 lines
drivers/bcma/scan.c +10 -0
+                       return -ENOMEM;
+               bus->mmio = mmio;
+
+               mmio = ioremap(BCMA_WRAP_BASE, BCMA_CORE_SIZE * bus->nr_cores);
+               if (!mmio)
+                       return -ENOMEM;
+               bus->host_embedded = mmio;
+       }
+       /* reset it to 0 as we use it for counting */
+       bus->nr_cores = 0;

Would it make sense to use a local variable for nr_cores, and only use it within the BCMA_HOSTTYPE_EMBEDDED if statement, rather than re-using bus->nr_cores and having to reset it?

Thanks,

Signature · 5 lines
Julian Calaby

Email: [email protected]
Profile: http://www.google.com/profiles/julian.calaby/
.Plan: http://sites.google.com/site/juliancalaby/
author maintainer
#18 lore raw

RFC PATCH 3/10 bcma: add embedded bus

Quoted 34 lines · Julian Calaby

Hauke,

Minor nit:

Quoted 29 lines · Hauke Mehrtens

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.

---

drivers/bcma/scan.c +15 -0
index 70b39f7..9229615 100644
@@ -219,9 +219,34 @@ int bcma_bus_scan(struct bcma_bus *bus)
       bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
       bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
       bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
+       bus->nr_cores = (tmp & BCMA_CC_ID_NRCORES) >> BCMA_CC_ID_NRCORES_SHIFT;
+
+       /* If we are an embedded device we now know the number of avaliable
+        * core and ioremap the correct space.
+        */
+       if (bus->hosttype == BCMA_HOSTTYPE_EMBEDDED) {
+               iounmap(bus->mmio);
+               mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * bus->nr_cores);
+               if (!mmio)
+                       return -ENOMEM;
+               bus->mmio = mmio;
+
+               mmio = ioremap(BCMA_WRAP_BASE, BCMA_CORE_SIZE * bus->nr_cores);
+               if (!mmio)
+                       return -ENOMEM;
Quoted 8 lines

drivers/bcma/scan.c int bcma_bus_scan(struct bcma_bus *bus) · line 240

Quoted 4 lines
drivers/bcma/scan.c +4 -0
+               bus->host_embedded = mmio;
+       }
+       /* reset it to 0 as we use it for counting */
+       bus->nr_cores = 0;

Would it make sense to use a local variable for nr_cores, and only use it within the BCMA_HOSTTYPE_EMBEDDED if statement, rather than re-using bus->nr_cores and having to reset it?

Yes that looks better.

Hauke

maintainer
#19 lore raw

RFC PATCH 3/10 bcma: add embedded bus

In reply to Hauke Mehrtens

Hauke,

My idea for naming schema was to use:
bcma_host_TYPE_*

Like:
bcma_host_pci_*
bcma_host_sdio_*

You are using:
bcma_host_bcma_*

What do you think about changing this to:
bcma_host_embedded_*
or just some:
bcma_host_emb_*
?

Does it make more sense to you? I was trying to keep names in bcma really clear, so every first-time-reader can see differences between hosts, host and driver, etc.

2011/6/6 Hauke Mehrtens <[email protected]>:

drivers/bcma/host_embedded.c line 3

Quoted 6 lines
drivers/bcma/host_embedded.c new file +3 -0
@@ -0,0 +1,93 @@
+/*
+ * Broadcom specific AMBA
+ * PCI Host

s/PCI/Embedded/

drivers/bcma/host_embedded.c line 13

Quoted 10 lines
drivers/bcma/host_embedded.c new file +10 -0
+int bcma_host_bcma_register(struct bcma_bus *bus)
+{
+ ? ? ? u32 __iomem *mmio;
+ ? ? ? /* iomap only first core. We have to read some register on this core
+ ? ? ? ?* to get the number of cores. This is sone in bcma_scan()
+ ? ? ? ?*/
+ ? ? ? mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
+ ? ? ? if (!mmio)
+ ? ? ? ? ? ? ? return -ENOMEM;
+ ? ? ? bus->mmio = mmio;

Maybe just:
bus->mmio = ioremap(...);
? :)

Quoted 33 lines
drivers/bcma/host_embedded.c new file +7 -0
+ ? ? ? /* Host specific */
+ ? ? ? bus->hosttype = BCMA_HOSTTYPE_EMBEDDED;
+ ? ? ? bus->ops = &bcma_host_bcma_ops;
+
+ ? ? ? /* Register */
+ ? ? ? return bcma_bus_register(bus);
+}
drivers/bcma/main.c +0 -0
index 1afa107..c5bcb5f 100644
@@ -119,6 +119,7 @@ static int bcma_register_cores(struct bcma_bus *bus)
 ? ? ? ? ? ? ? ? ? ? ? ?break;

? ? ? ? ? ? ? ?case BCMA_HOSTTYPE_NONE:
? ? ? ? ? ? ? ?case BCMA_HOSTTYPE_SDIO:
+ ? ? ? ? ? ? ? case BCMA_HOSTTYPE_EMBEDDED:
? ? ? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ? ? ?}

drivers/bcma/scan.c +1 -1
index 70b39f7..9229615 100644
@@ -203,7 +203,7 @@ static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr,
 ?int bcma_bus_scan(struct bcma_bus *bus)
 ?{
 ? ? ? ?u32 erombase;
- ? ? ? u32 __iomem *eromptr, *eromend;
+ ? ? ? u32 __iomem *eromptr, *eromend, *mmio;
 
 ? ? ? ?s32 cia, cib;
 ? ? ? ?u8 ports[2], wrappers[2];

drivers/bcma/scan.c int bcma_bus_scan(struct bcma_bus *bus) · line 222

Quoted 4 lines
drivers/bcma/scan.c +1 -0
@@ -219,9 +219,34 @@ int bcma_bus_scan(struct bcma_bus *bus)
 ? ? ? ?bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
 ? ? ? ?bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
 ? ? ? ?bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
+ ? ? ? bus->nr_cores = (tmp & BCMA_CC_ID_NRCORES) >> BCMA_CC_ID_NRCORES_SHIFT;

I'd use different variable as Julian suggested.

drivers/bcma/scan.c int bcma_bus_scan(struct bcma_bus *bus) · line 226

Quoted 4 lines
drivers/bcma/scan.c +4 -0
+
+ ? ? ? /* If we are an embedded device we now know the number of avaliable
+ ? ? ? ?* core and ioremap the correct space.
+ ? ? ? ?*/

Typo: avaliable

drivers/bcma/scan.c int bcma_bus_scan(struct bcma_bus *bus) · line 237

Quoted 11 lines
drivers/bcma/scan.c +11 -0
+ ? ? ? if (bus->hosttype == BCMA_HOSTTYPE_EMBEDDED) {
+ ? ? ? ? ? ? ? iounmap(bus->mmio);
+ ? ? ? ? ? ? ? mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * bus->nr_cores);
+ ? ? ? ? ? ? ? if (!mmio)
+ ? ? ? ? ? ? ? ? ? ? ? return -ENOMEM;
+ ? ? ? ? ? ? ? bus->mmio = mmio;
+
+ ? ? ? ? ? ? ? mmio = ioremap(BCMA_WRAP_BASE, BCMA_CORE_SIZE * bus->nr_cores);
+ ? ? ? ? ? ? ? if (!mmio)
+ ? ? ? ? ? ? ? ? ? ? ? return -ENOMEM;
+ ? ? ? ? ? ? ? bus->host_embedded = mmio;

Do we really need both? mmio and host_embedded? What about keeping mmio only and using it in calculation for read/write[8,16,32]?

drivers/bcma/scan.c int bcma_bus_scan(struct bcma_bus *bus) · line 248

Quoted 12 lines
drivers/bcma/scan.c +9 -1
+ ? ? ? }
+ ? ? ? /* reset it to 0 as we use it for counting */
+ ? ? ? bus->nr_cores = 0;
 
 ? ? ? ?erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
- ? ? ? eromptr = bus->mmio;
+ ? ? ? if (bus->hosttype == BCMA_HOSTTYPE_EMBEDDED) {
+ ? ? ? ? ? ? ? eromptr = ioremap(erombase, BCMA_CORE_SIZE);
+ ? ? ? ? ? ? ? if (!eromptr)
+ ? ? ? ? ? ? ? ? ? ? ? return -ENOMEM;
+ ? ? ? } else
+ ? ? ? ? ? ? ? eromptr = bus->mmio;

I though eromptr = bus->mmio; will do the trick for embedded as well. I think I need some time to read about IO mapping and understand that.

Signature · 1 line
Rafa?
#20 lore raw

Re: [RFC][PATCH 03/10] bcma: add embedded bus

Hi,

Quoted 18 lines

Hauke,

My idea for naming schema was to use:
bcma_host_TYPE_*

Like:
bcma_host_pci_*
bcma_host_sdio_*

You are using:
bcma_host_bcma_*

What do you think about changing this to:
bcma_host_embedded_*
or just some:
bcma_host_emb_*
?

Quoted 3 lines

Does it make more sense to you? I was trying to keep names in bcma really clear, so every first-time-reader can see differences between hosts, host and driver, etc.

how about bcma_host_soc ?

Quoted 59 lines

2011/6/6 Hauke Mehrtens <[email protected]>:

drivers/bcma/host_embedded.c line 3

Quoted 6 lines
drivers/bcma/host_embedded.c new file +3 -0
@@ -0,0 +1,93 @@
+/*
+ * Broadcom specific AMBA
+ * PCI Host

s/PCI/Embedded/

drivers/bcma/host_embedded.c line 85

Quoted 10 lines
drivers/bcma/host_embedded.c new file +10 -0
+int bcma_host_bcma_register(struct bcma_bus *bus)
+{
+       u32 __iomem *mmio;
+       /* iomap only first core. We have to read some register on this core
+        * to get the number of cores. This is sone in bcma_scan()
+        */
+       mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
+       if (!mmio)
+               return -ENOMEM;
+       bus->mmio = mmio;

Maybe just:
bus->mmio = ioremap(...);
? :)

Quoted 30 lines
drivers/bcma/host_embedded.c new file +7 -0
+       /* Host specific */
+       bus->hosttype = BCMA_HOSTTYPE_EMBEDDED;
+       bus->ops = &bcma_host_bcma_ops;
+
+       /* Register */
+       return bcma_bus_register(bus);
+}
drivers/bcma/main.c +1 -0
index 1afa107..c5bcb5f 100644
@@ -119,6 +119,7 @@ static int bcma_register_cores(struct bcma_bus *bus)
                       break;
               case BCMA_HOSTTYPE_NONE:
               case BCMA_HOSTTYPE_SDIO:
+               case BCMA_HOSTTYPE_EMBEDDED:
                       break;
               }
 
drivers/bcma/scan.c +1 -1
index 70b39f7..9229615 100644
@@ -203,7 +203,7 @@ static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr,
 int bcma_bus_scan(struct bcma_bus *bus)
 {
       u32 erombase;
-       u32 __iomem *eromptr, *eromend;
+       u32 __iomem *eromptr, *eromend, *mmio;
 
Quoted 8 lines

drivers/bcma/scan.c int bcma_bus_scan(struct bcma_bus *bus) · line 222

Quoted 7 lines
drivers/bcma/scan.c +1 -0
       s32 cia, cib;
       u8 ports[2], wrappers[2];
@@ -219,9 +219,34 @@ int bcma_bus_scan(struct bcma_bus *bus)
       bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
       bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
       bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
+       bus->nr_cores = (tmp & BCMA_CC_ID_NRCORES) >> BCMA_CC_ID_NRCORES_SHIFT;

To avoid using wrapper struct and at the same time to save on embedded reservations you could let the bus get scanned twice on SoC - first time discovering just system devices (chipcommon and mips core) required for early setup (you will never register those to the linux device subsystem so you can have them marked as __initdata and have no ->release callback therefore), second time full scan with registering the whole bus when done.

Have nice day,
George

maintainer
#21 lore raw

RFC PATCH 3/10 bcma: add embedded bus

W dniu 6 czerwca 2011 12:32 u?ytkownik George Kashperko <[email protected]> napisa?:

Quoted 20 lines

Hi,

Quoted 18 lines

Hauke,

My idea for naming schema was to use:
bcma_host_TYPE_*

Like:
bcma_host_pci_*
bcma_host_sdio_*

You are using:
bcma_host_bcma_*

What do you think about changing this to:
bcma_host_embedded_*
or just some:
bcma_host_emb_*
?

Quoted 5 lines
Quoted 3 lines

Does it make more sense to you? I was trying to keep names in bcma really clear, so every first-time-reader can see differences between hosts, host and driver, etc.

how about bcma_host_soc ?

We get then inconsistency with "BCMA_HOSTTYPE_EMBEDDED". I'd like to
1) See something like bcma_host_emb...
xor
2) Use bcma_host_soc_* and BCMA_HOSTTYPE_SOC

Signature · 1 line
Rafa?
#22 lore raw

Re: [RFC][PATCH 03/10] bcma: add embedded bus

Quoted 22 lines · Rafał Miłecki

W dniu 6 czerwca 2011 12:32 użytkownik George Kashperko

Quoted 20 lines · <[email protected]> napisał:

Hi,

Quoted 18 lines

Hauke,

My idea for naming schema was to use:
bcma_host_TYPE_*

Like:
bcma_host_pci_*
bcma_host_sdio_*

You are using:
bcma_host_bcma_*

What do you think about changing this to:
bcma_host_embedded_*
or just some:
bcma_host_emb_*
?

Quoted 9 lines
Quoted 4 lines
Quoted 3 lines

Does it make more sense to you? I was trying to keep names in bcma really clear, so every first-time-reader can see differences between hosts, host and driver, etc.

how about bcma_host_soc ?

We get then inconsistency with "BCMA_HOSTTYPE_EMBEDDED". I'd like to
1) See something like bcma_host_emb...
xor
2) Use bcma_host_soc_* and BCMA_HOSTTYPE_SOC

I would go for option 2). It more clearly says what it is. Embedded is a broader term. As an example, a handset is an embedded device, but it may use BCMA_HOSTTYPE_SDIO.

Gr. AvS

Signature · 2 lines
Almost nobody dances sober, unless they happen to be insane.
-- H.P. Lovecraft --
maintainer
#23 lore raw

RFC PATCH 3/10 bcma: add embedded bus

W dniu 6 czerwca 2011 12:55 u?ytkownik Arend van Spriel <[email protected]> napisa?:

Quoted 37 lines · Rafa? Mi?ecki
Quoted 28 lines

W dniu 6 czerwca 2011 12:32 u?ytkownik George Kashperko <[email protected]> ?napisa?:

Quoted 25 lines

Hi,

Quoted 21 lines

Hauke,

My idea for naming schema was to use:
bcma_host_TYPE_*

Like:
bcma_host_pci_*
bcma_host_sdio_*

You are using:
bcma_host_bcma_*

What do you think about changing this to:
bcma_host_embedded_*
or just some:
bcma_host_emb_*
?

Does it make more sense to you? I was trying to keep names in bcma really clear, so every first-time-reader can see differences between hosts, host and driver, etc.

Quoted 7 lines
Quoted 1 line

how about bcma_host_soc ?

We get then inconsistency with "BCMA_HOSTTYPE_EMBEDDED". I'd like to
1) See something like bcma_host_emb...
xor
2) Use bcma_host_soc_* and BCMA_HOSTTYPE_SOC

Quoted 3 lines

I would go for option 2). It more clearly says what it is. Embedded is a broader term. As an example, a handset is an embedded device, but it may use BCMA_HOSTTYPE_SDIO.

Good point, agree.

Signature · 1 line
Rafa?
author maintainer
#24 lore raw

RFC PATCH 3/10 bcma: add embedded bus

In reply to Rafał Miłecki
Quoted 18 lines · Rafa? Mi?ecki

Hauke,

My idea for naming schema was to use:
bcma_host_TYPE_*

Like:
bcma_host_pci_*
bcma_host_sdio_*

You are using:
bcma_host_bcma_*

What do you think about changing this to:
bcma_host_embedded_*
or just some:
bcma_host_emb_*
?

Quoted 4 lines

Does it make more sense to you? I was trying to keep names in bcma really clear, so every first-time-reader can see differences between hosts, host and driver, etc.

At first I named it bcma_host_bcma_ but then renamed the file name, but forgot the function names. I will rename it all to bcma_host_soc_* host_sco.c and so on.

Quoted 11 lines

2011/6/6 Hauke Mehrtens <[email protected]>:

drivers/bcma/host_embedded.c line 3

Quoted 6 lines
drivers/bcma/host_embedded.c new file +3 -0
@@ -0,0 +1,93 @@
+/*
+ * Broadcom specific AMBA
+ * PCI Host

s/PCI/Embedded/

Quoted 14 lines

drivers/bcma/host_embedded.c line 85

Quoted 10 lines
drivers/bcma/host_embedded.c new file +10 -0
+int bcma_host_bcma_register(struct bcma_bus *bus)
+{
+       u32 __iomem *mmio;
+       /* iomap only first core. We have to read some register on this core
+        * to get the number of cores. This is sone in bcma_scan()
+        */
+       mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
+       if (!mmio)
+               return -ENOMEM;
+       bus->mmio = mmio;

Maybe just:
bus->mmio = ioremap(...);
? :)

yes makes sens.

Quoted 31 lines
Quoted 31 lines
drivers/bcma/host_embedded.c new file +7 -0
+       /* Host specific */
+       bus->hosttype = BCMA_HOSTTYPE_EMBEDDED;
+       bus->ops = &bcma_host_bcma_ops;
+
+       /* Register */
+       return bcma_bus_register(bus);
+}
drivers/bcma/main.c +1 -0
index 1afa107..c5bcb5f 100644
@@ -119,6 +119,7 @@ static int bcma_register_cores(struct bcma_bus *bus)
                       break;
               case BCMA_HOSTTYPE_NONE:
               case BCMA_HOSTTYPE_SDIO:
+               case BCMA_HOSTTYPE_EMBEDDED:
                       break;
               }
 
drivers/bcma/scan.c +1 -1
index 70b39f7..9229615 100644
@@ -203,7 +203,7 @@ static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr,
 int bcma_bus_scan(struct bcma_bus *bus)
 {
       u32 erombase;
-       u32 __iomem *eromptr, *eromend;
+       u32 __iomem *eromptr, *eromend, *mmio;
 
Quoted 9 lines

drivers/bcma/scan.c int bcma_bus_scan(struct bcma_bus *bus) · line 222

Quoted 7 lines
drivers/bcma/scan.c +1 -0
       s32 cia, cib;
       u8 ports[2], wrappers[2];
@@ -219,9 +219,34 @@ int bcma_bus_scan(struct bcma_bus *bus)
       bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
       bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
       bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
+       bus->nr_cores = (tmp & BCMA_CC_ID_NRCORES) >> BCMA_CC_ID_NRCORES_SHIFT;

I'd use different variable as Julian suggested.

yes

Quoted 8 lines

drivers/bcma/scan.c int bcma_bus_scan(struct bcma_bus *bus) · line 226

Quoted 6 lines
drivers/bcma/scan.c +4 -0
+
+       /* If we are an embedded device we now know the number of avaliable
+        * core and ioremap the correct space.
+        */

Typo: avaliable

my favorite typo ;-)

Quoted 14 lines

drivers/bcma/scan.c int bcma_bus_scan(struct bcma_bus *bus) · line 237

Quoted 13 lines
drivers/bcma/scan.c +11 -0
+       if (bus->hosttype == BCMA_HOSTTYPE_EMBEDDED) {
+               iounmap(bus->mmio);
+               mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * bus->nr_cores);
+               if (!mmio)
+                       return -ENOMEM;
+               bus->mmio = mmio;
+
+               mmio = ioremap(BCMA_WRAP_BASE, BCMA_CORE_SIZE * bus->nr_cores);
+               if (!mmio)
+                       return -ENOMEM;
+               bus->host_embedded = mmio;
Quoted 2 lines

Do we really need both? mmio and host_embedded? What about keeping mmio only and using it in calculation for read/write[8,16,32]?

These are two different memory regions, it should be possible to calculate the other address, but I do not like that. As host_embedded is in a union this does not waste any memory.

Quoted 14 lines

drivers/bcma/scan.c int bcma_bus_scan(struct bcma_bus *bus) · line 248

Quoted 13 lines
drivers/bcma/scan.c +9 -1
+       }
+       /* reset it to 0 as we use it for counting */
+       bus->nr_cores = 0;
 
       erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
-       eromptr = bus->mmio;
+       if (bus->hosttype == BCMA_HOSTTYPE_EMBEDDED) {
+               eromptr = ioremap(erombase, BCMA_CORE_SIZE);
+               if (!eromptr)
+                       return -ENOMEM;
+       } else
+               eromptr = bus->mmio;
Quoted 3 lines

I though eromptr = bus->mmio; will do the trick for embedded as well. I think I need some time to read about IO mapping and understand that.

No they are different eromptr is 0x1810e000 and bus->mmio is 0xb8000000 for example on my device. I tried using eromptr = bus->mmio; on embedded and it did not work.

Hauke

maintainer
#25 lore raw

RFC PATCH 3/10 bcma: add embedded bus

W dniu 7 czerwca 2011 00:00 u?ytkownik Hauke Mehrtens <[email protected]> napisa?:

Quoted 13 lines · Rafa? Mi?ecki
Quoted 12 lines
Quoted 11 lines

+ ? ? ? if (bus->hosttype == BCMA_HOSTTYPE_EMBEDDED) {
+ ? ? ? ? ? ? ? iounmap(bus->mmio);
+ ? ? ? ? ? ? ? mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * bus->nr_cores);
+ ? ? ? ? ? ? ? if (!mmio)
+ ? ? ? ? ? ? ? ? ? ? ? return -ENOMEM;
+ ? ? ? ? ? ? ? bus->mmio = mmio;
+
+ ? ? ? ? ? ? ? mmio = ioremap(BCMA_WRAP_BASE, BCMA_CORE_SIZE * bus->nr_cores);
+ ? ? ? ? ? ? ? if (!mmio)
+ ? ? ? ? ? ? ? ? ? ? ? return -ENOMEM;
+ ? ? ? ? ? ? ? bus->host_embedded = mmio;

Quoted 6 lines
Quoted 2 lines

Do we really need both? mmio and host_embedded? What about keeping mmio only and using it in calculation for read/write[8,16,32]?

These are two different memory regions, it should be possible to calculate the other address, but I do not like that. As host_embedded is in a union this does not waste any memory.

Ah, OK, I can see what does happen here. You are using:
1) bus->mmio for first core
2) bus->host_embedded for first agent/wrapper

I'm not sure if this is a correct approach. Doing "core_index * BCMA_CORE_SIZE" comes from ssb, where it was the way to calculate offset. In case of BCMA we are reading all the info from (E)EPROM, which also includes addresses of the cores.

IMO you should use core->addr and core->wrap for read/write ops. I believe this is approach Broadcom decided to use for BCMA, when designing (E)EPROM.

You should not need bus->host_embedded then, maybe you could even do not set bus->mmio?

Signature · 1 line
Rafa?
#26 lore raw

Re: [RFC][PATCH 03/10] bcma: add embedded bus

Quoted 23 lines · Rafał Miłecki

W dniu 7 czerwca 2011 00:00 użytkownik Hauke Mehrtens

Quoted 12 lines · <[email protected]> napisał:
Quoted 11 lines · Rafał Miłecki
Quoted 11 lines
drivers/bcma/scan.c +11 -0
+       if (bus->hosttype == BCMA_HOSTTYPE_EMBEDDED) {
+               iounmap(bus->mmio);
+               mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * bus->nr_cores);
+               if (!mmio)
+                       return -ENOMEM;
+               bus->mmio = mmio;
+
+               mmio = ioremap(BCMA_WRAP_BASE, BCMA_CORE_SIZE * bus->nr_cores);
+               if (!mmio)
+                       return -ENOMEM;
+               bus->host_embedded = mmio;
Quoted 5 lines
Quoted 2 lines

Do we really need both? mmio and host_embedded? What about keeping mmio only and using it in calculation for read/write[8,16,32]?

These are two different memory regions, it should be possible to calculate the other address, but I do not like that. As host_embedded is in a union this does not waste any memory.

Ah, OK, I can see what does happen here. You are using:
1) bus->mmio for first core
2) bus->host_embedded for first agent/wrapper

Quoted 8 lines

I'm not sure if this is a correct approach. Doing "core_index * BCMA_CORE_SIZE" comes from ssb, where it was the way to calculate offset. In case of BCMA we are reading all the info from (E)EPROM, which also includes addresses of the cores.

IMO you should use core->addr and core->wrap for read/write ops. I believe this is approach Broadcom decided to use for BCMA, when designing (E)EPROM.

Agree. There is no guarantee for the core index to relate to the physical address. Chip designer may be systematic in this and the index*size method may work, but not by design.

Gr. AvS

Signature · 2 lines
Almost nobody dances sober, unless they happen to be insane.
-- H.P. Lovecraft --
author maintainer
#27 lore raw

RFC PATCH 3/10 bcma: add embedded bus

Quoted 35 lines · Arend van Spriel
Quoted 25 lines · Rafa? Mi?ecki

W dniu 7 czerwca 2011 00:00 u?ytkownik Hauke Mehrtens <[email protected]> napisa?:

Quoted 14 lines · Rafa? Mi?ecki
Quoted 13 lines
Quoted 13 lines
drivers/bcma/scan.c +3 -0
+       if (bus->hosttype == BCMA_HOSTTYPE_EMBEDDED) {
+               iounmap(bus->mmio);
+               mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE *

bus->nr_cores);

drivers/bcma/host_embedded.c new file +5 -0
+               if (!mmio)
+                       return -ENOMEM;
+               bus->mmio = mmio;
+
+               mmio = ioremap(BCMA_WRAP_BASE, BCMA_CORE_SIZE *

bus->nr_cores);

drivers/bcma/scan.c +3 -0
+               if (!mmio)
+                       return -ENOMEM;
+               bus->host_embedded = mmio;
Quoted 5 lines
Quoted 2 lines

Do we really need both? mmio and host_embedded? What about keeping mmio only and using it in calculation for read/write[8,16,32]?

These are two different memory regions, it should be possible to calculate the other address, but I do not like that. As host_embedded is in a union this does not waste any memory.

Ah, OK, I can see what does happen here. You are using:
1) bus->mmio for first core
2) bus->host_embedded for first agent/wrapper

Quoted 8 lines

I'm not sure if this is a correct approach. Doing "core_index * BCMA_CORE_SIZE" comes from ssb, where it was the way to calculate offset. In case of BCMA we are reading all the info from (E)EPROM, which also includes addresses of the cores.

IMO you should use core->addr and core->wrap for read/write ops. I believe this is approach Broadcom decided to use for BCMA, when designing (E)EPROM.

Quoted 6 lines

Agree. There is no guarantee for the core index to relate to the physical address. Chip designer may be systematic in this and the index*size method may work, but not by design.

Gr. AvS

Ok I will use these addresses.

Hauke

author maintainer
#28 lore raw

RFC PATCH 4/10 bcma: add mips driver

In reply to Hauke Mehrtens

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 system.

---
 drivers/bcma/Kconfig                  |   11 ++-
 drivers/bcma/Makefile                 |    1 +
 drivers/bcma/bcma_private.h           |    3 +
 drivers/bcma/driver_mips.c            |  227 +++++++++++++++++++++++++++++++++
 drivers/bcma/main.c                   |    8 +
 include/linux/bcma/bcma.h             |    2 +
 include/linux/bcma/bcma_driver_mips.h |   40 ++++++
 7 files changed, 291 insertions(+), 1 deletions(-)
 create mode 100644 drivers/bcma/driver_mips.c
 create mode 100644 include/linux/bcma/bcma_driver_mips.h
drivers/bcma/Kconfig +10 -1
index 0390e32..568d30b 100644
@@ -29,9 +29,18 @@ config BCMA_HOST_PCI
 
 config BCMA_HOST_EMBEDDED
 	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
+	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
drivers/bcma/Makefile +1 -0
index e509b1b..50ddab8 100644
@@ -1,6 +1,7 @@
 bcma-y					+= main.o scan.o core.o
 bcma-y					+= driver_chipcommon.o driver_chipcommon_pmu.o
 bcma-y					+= driver_pci.o
+bcma-$(CONFIG_BCMA_DRIVER_MIPS)		+= driver_mips.o
 bcma-$(CONFIG_BCMA_HOST_PCI)		+= host_pci.o
 bcma-$(CONFIG_BCMA_HOST_EMBEDDED)	+= host_embedded.o
 obj-$(CONFIG_BCMA)			+= bcma.o
drivers/bcma/bcma_private.h +3 -0
index 2f72e9c..842ee17 100644
@@ -19,6 +19,9 @@ extern void bcma_bus_unregister(struct bcma_bus *bus);
 /* scan.c */
 int bcma_bus_scan(struct bcma_bus *bus);
 
+/* driver_mips.c */
+extern unsigned int bcma_core_mips_irq(struct bcma_device *dev);
+
 #ifdef CONFIG_BCMA_HOST_PCI
 /* host_pci.c */
 extern int __init bcma_host_pci_init(void);
drivers/bcma/driver_mips.c new file +227 -0

227 lines not on this page · raw message

drivers/bcma/main.c +8 -0
index c5bcb5f..0b4e26d 100644
@@ -96,6 +96,7 @@ static int bcma_register_cores(struct bcma_bus *bus)
 		case BCMA_CORE_CHIPCOMMON:
 		case BCMA_CORE_PCI:
 		case BCMA_CORE_PCIE:
+		case BCMA_CORE_MIPS_74K:
 			continue;
 		}
 
@@ -198,6 +199,13 @@ int bcma_bus_register(struct bcma_bus *bus)
 		bcma_core_chipcommon_init(&bus->drv_cc);
 	}
 
+	/* 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);
+	}
+
 	/* Find PCIE core */
 	core = bcma_find_core(bus, BCMA_CORE_PCIE);
 	if (core) {
include/linux/bcma/bcma.h +2 -0
index 192c4ae..c5d7d4d 100644
@@ -6,6 +6,7 @@
 
 #include <linux/bcma/bcma_driver_chipcommon.h>
 #include <linux/bcma/bcma_driver_pci.h>
+#include <linux/bcma/bcma_driver_mips.h>
 
 #include "bcma_regs.h"
 
@@ -198,6 +199,7 @@ struct bcma_bus {
 
 	struct bcma_drv_cc drv_cc;
 	struct bcma_drv_pci drv_pci;
+	struct bcma_drv_mips drv_mips;
 
 	/* Internal-only stuff follows. Do not touch. */
 	struct list_head attach_list;
include/linux/bcma/bcma_driver_mips.h new file +40 -0
new file mode 100644
index 0000000..5faf30c
@@ -0,0 +1,40 @@
+#ifndef LINUX_BCMA_DRIVER_MIPS_H_
+#define LINUX_BCMA_DRIVER_MIPS_H_
+
+#define BCMA_MIPS_IPSFLAG		0x0F08
+#define	 BCMA_MIPS_IPSFLAG_IRQ1		0x0000003F /* which sbflags get routed to mips interrupt 1 */
+#define	 BCMA_MIPS_IPSFLAG_IRQ1_SHIFT	0
+#define	 BCMA_MIPS_IPSFLAG_IRQ2		0x00003F00 /* which sbflags get routed to mips interrupt 2 */
+#define	 BCMA_MIPS_IPSFLAG_IRQ2_SHIFT	8
+#define	 BCMA_MIPS_IPSFLAG_IRQ3		0x003F0000 /* which sbflags get routed to mips interrupt 3 */
+#define	 BCMA_MIPS_IPSFLAG_IRQ3_SHIFT	16
+#define	 BCMA_MIPS_IPSFLAG_IRQ4		0x3F000000 /* which sbflags get routed to mips interrupt 4 */
+#define	 BCMA_MIPS_IPSFLAG_IRQ4_SHIFT	24
+
+/* MIPS 74K core registers */
+#define BCMA_MIPS_MIPS74K_CORECTL	0x0000
+#define BCMA_MIPS_MIPS74K_EXCEPTBASE	0x0004
+#define BCMA_MIPS_MIPS74K_BIST		0x000C
+#define BCMA_MIPS_MIPS74K_INTMASK_INT0	0x0014
+#define BCMA_MIPS_MIPS74K_INTMASK(int) ((int) * 4 + BCMA_MIPS_MIPS74K_INTMASK_INT0)
+#define BCMA_MIPS_MIPS74K_NMIMASK	0x002C
+#define BCMA_MIPS_MIPS74K_GPIOSEL	0x0040
+#define BCMA_MIPS_MIPS74K_GPIOOUT	0x0044
+#define BCMA_MIPS_MIPS74K_GPIOEN	0x0048
+#define BCMA_MIPS_MIPS74K_CLKCTLST	0x01E0
+
+#define BCMA_MIPS_OOBSELOUTA30		0x100
+
+struct bcma_device;
+
+struct bcma_drv_mips {
+	struct bcma_device *core;
+
+	u8 flash_buswidth;
+	u32 flash_window;
+	u32 flash_window_size;
+};
+
+extern void bcma_core_mips_init(struct bcma_drv_mips *mcore);
+
+#endif /* LINUX_BCMA_DRIVER_MIPS_H_ */
Signature · 1 line
1.7.4.1
maintainer
#29 lore raw

RFC PATCH 4/10 bcma: add mips driver

2011/6/6 Hauke Mehrtens <[email protected]>:

drivers/bcma/bcma_private.h extern void bcma_bus_unregister(struct bcma_bus *bus); · line 23

Quoted 2 lines
drivers/bcma/bcma_private.h +2 -0
+/* driver_mips.c */
+extern unsigned int bcma_core_mips_irq(struct bcma_device *dev);

Does it compile without CONFIG_BCMA_DRIVER_MIPS?

Quoted 5 lines

+/* Get the MIPS IRQ assignment for a specified device.
+ * If unassigned, 0 is returned.
+ * If disabled, 5 is returned.
+ * If not supported, 6 is returned.
+ */

Does it ever return 6?

Review

Quoted 11 lines
(quoted diff) +11 -0
+unsigned int bcma_core_mips_irq(struct bcma_device *dev)
+{
+ ? ? ? struct bcma_device *mdev = dev->bus->drv_mips.core;
+ ? ? ? u32 irqflag;
+ ? ? ? unsigned int irq;
+
+ ? ? ? irqflag = bcma_core_mips_irqflag(dev);
+
+ ? ? ? for (irq = 1; irq <= 4; irq++)
+ ? ? ? ? ? ? ? if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) & (1 << irqflag))
+ ? ? ? ? ? ? ? ? ? ? ? break;

Use scripts/checkpatch*. Braces around "for" and split line to match 80 chars width.

Why don't you just use "return irq;" instead of break?

Review

Quoted 5 lines
(quoted diff) +5 -0
+
+ ? ? ? if (irq == 5)
+ ? ? ? ? ? ? ? irq = 0;
+
+ ? ? ? return irq;

You can just make it "return 0;" after changing break to return.

Quoted 5 lines

+ ? ? ? ? ? ? ? ? ? ? ? for (i = 0; i < bus->nr_cores; i++)
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if ((1 << bcma_core_mips_irqflag(&bus->cores[i])) == oldirqflag) {
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? bcma_core_mips_set_irq(&bus->cores[i], 0);
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

Braces for "for".

Quoted 1 line

+ ? ? ? pr_info("after irq reconfiguration\n");

Make first letter uppercase. I'm not English expert, but doesn't something like "IRQ reconfiguration done" sound better?

Signature · 1 line
Rafa?
author maintainer
#30 lore raw

RFC PATCH 4/10 bcma: add mips driver

Quoted 5 lines · Rafa? Mi?ecki

2011/6/6 Hauke Mehrtens <[email protected]>:

drivers/bcma/bcma_private.h extern void bcma_bus_unregister(struct bcma_bus *bus); · line 23

Quoted 2 lines
drivers/bcma/bcma_private.h +2 -0
+/* driver_mips.c */
+extern unsigned int bcma_core_mips_irq(struct bcma_device *dev);

Does it compile without CONFIG_BCMA_DRIVER_MIPS?

No ;-) Thought about it after sending these patches, some other patches will have the same problem.

Quoted 9 lines
Quoted 7 lines

+/* Get the MIPS IRQ assignment for a specified device.
+ * If unassigned, 0 is returned.
+ * If disabled, 5 is returned.
+ * If not supported, 6 is returned.
+ */

Does it ever return 6?

Some old comment, will fix this.

Quoted 15 lines

drivers/bcma/driver_mips.c line 84

Quoted 12 lines
drivers/bcma/driver_mips.c new file +11 -0
+unsigned int bcma_core_mips_irq(struct bcma_device *dev)
+{
+       struct bcma_device *mdev = dev->bus->drv_mips.core;
+       u32 irqflag;
+       unsigned int irq;
+
+       irqflag = bcma_core_mips_irqflag(dev);
+
+       for (irq = 1; irq <= 4; irq++)
+               if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) & (1 << irqflag))
+                       break;

Use scripts/checkpatch*. Braces around "for" and split line to match 80 chars width.

Will check all patches with scripts/checkpatch.sh

Quoted 2 lines

Why don't you just use "return irq;" instead of break?

yes this will be better.

Quoted 9 lines

drivers/bcma/driver_mips.c line 89

Quoted 7 lines
drivers/bcma/driver_mips.c new file +5 -0
+
+       if (irq == 5)
+               irq = 0;
+
+       return irq;

You can just make it "return 0;" after changing break to return.

agree

Quoted 9 lines

drivers/bcma/driver_mips.c line 129

Quoted 7 lines
drivers/bcma/driver_mips.c new file +5 -0
+                       for (i = 0; i < bus->nr_cores; i++)
+                               if ((1 << bcma_core_mips_irqflag(&bus->cores[i])) == oldirqflag) {
+                                       bcma_core_mips_set_irq(&bus->cores[i], 0);
+                                       break;
+                               }

Braces for "for".

Is this needed after the coding guildlines? Shouldn't they be removed if they are not needed?

Quoted 6 lines
Quoted 2 lines

+ pr_info("after irq reconfiguration\n");

Make first letter uppercase. I'm not English expert, but doesn't something like "IRQ reconfiguration done" sound better?

Sounds better.

maintainer
#31 lore raw

RFC PATCH 4/10 bcma: add mips driver

W dniu 7 czerwca 2011 00:06 u?ytkownik Hauke Mehrtens <[email protected]> napisa?:

Quoted 10 lines · Rafa? Mi?ecki
Quoted 7 lines
Quoted 5 lines

+ ? ? ? ? ? ? ? ? ? ? ? for (i = 0; i < bus->nr_cores; i++)
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if ((1 << bcma_core_mips_irqflag(&bus->cores[i])) == oldirqflag) {
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? bcma_core_mips_set_irq(&bus->cores[i], 0);
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

Braces for "for".

Is this needed after the coding guildlines? Shouldn't they be removed if they are not needed?

Whoops, after re-checking coding style it seems I was wrong.

Signature · 1 line
Rafa?
author maintainer
#32 lore raw

RFC PATCH 5/10 bcma: add serial console support

In reply to Hauke Mehrtens

This adds support for serial console to bcma, when operating on an embedded device.

---
 drivers/bcma/bcma_private.h           |    4 ++
 drivers/bcma/driver_chipcommon.c      |   62 +++++++++++++++++++++++++++++++++
 drivers/bcma/driver_mips.c            |    9 +++++
 include/linux/bcma/bcma_driver_mips.h |   11 ++++++
 4 files changed, 86 insertions(+), 0 deletions(-)
drivers/bcma/bcma_private.h +4 -0
index 842ee17..c65a6e2 100644
@@ -22,6 +22,10 @@ int bcma_bus_scan(struct bcma_bus *bus);
 /* driver_mips.c */
 extern unsigned int bcma_core_mips_irq(struct bcma_device *dev);
 
+/* driver_chipcommon.c */
+extern int bcma_chipco_serial_init(struct bcma_drv_cc *cc,
+				   struct bcma_drv_mips_serial_port *ports);
+
 #ifdef CONFIG_BCMA_HOST_PCI
 /* host_pci.c */
 extern int __init bcma_host_pci_init(void);
drivers/bcma/driver_chipcommon.c +62 -0

65 lines not on this page · raw message

drivers/bcma/driver_mips.c +9 -0
index 0a6c217..40e4a6d 100644
@@ -155,6 +155,14 @@ static void bcma_core_mips_dump_irq(struct bcma_bus *bus)
 	}
 }
 
+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;
@@ -223,5 +231,6 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore)
 	pr_info("after irq reconfiguration\n");
 	bcma_core_mips_dump_irq(bus);
 
+	bcma_core_mips_serial_init(mcore);
 	bcma_core_mips_flash_detect(mcore);
 }
include/linux/bcma/bcma_driver_mips.h +11 -0
index 5faf30c..6584e7d 100644
@@ -27,9 +27,20 @@
 
 struct bcma_device;
 
+struct bcma_drv_mips_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;
 
+	int nr_serial_ports;
+	struct bcma_drv_mips_serial_port serial_ports[4];
+
 	u8 flash_buswidth;
 	u32 flash_window;
 	u32 flash_window_size;
Signature · 1 line
1.7.4.1
maintainer
#33 lore raw

RFC PATCH 5/10 bcma: add serial console support

2011/6/6 Hauke Mehrtens <[email protected]>:

Quoted 5 lines

+ ? ? ? if ((ccrev >= 11) && (ccrev != 15) && (ccrev != 20)) {
+ ? ? ? ....
+ ? ? ? } else
+ ? ? ? ? ? ? ? pr_err("serial not supported on this device ccrev: 0x%x\n",
+ ? ? ? ? ? ? ? ? ? ? ?ccrev);

Please use scripts/checkpatch* for your patches. I believe it will alert you about lacking brackets for "else" (kernel coding style).

Signature · 1 line
Rafa?
author maintainer
#34 lore raw

RFC PATCH 6/10 bcma: get CPU clock

In reply to Hauke Mehrtens

Add method to return the clock of the CPU. This is needed by the arch code to calculate the mips_hpt_frequency.

---
 drivers/bcma/bcma_private.h                 |    3 +
 drivers/bcma/driver_chipcommon_pmu.c        |   86 +++++++++++++++++++++++++++
 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, 137 insertions(+), 0 deletions(-)
drivers/bcma/bcma_private.h +3 -0
index c65a6e2..fbabe19 100644
@@ -22,6 +22,9 @@ int bcma_bus_scan(struct bcma_bus *bus);
 /* driver_mips.c */
 extern unsigned int bcma_core_mips_irq(struct bcma_device *dev);
 
+/* driver_chipcommon_pmu.c */
+extern u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
+
 /* driver_chipcommon.c */
 extern int bcma_chipco_serial_init(struct bcma_drv_cc *cc,
 				   struct bcma_drv_mips_serial_port *ports);
drivers/bcma/driver_chipcommon_pmu.c +86 -0

95 lines not on this page · raw message

drivers/bcma/driver_mips.c +12 -0
index 40e4a6d..faaa232 100644
@@ -155,6 +155,18 @@ static void bcma_core_mips_dump_irq(struct bcma_bus *bus)
 	}
 }
 
+u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
+{
+	struct bcma_bus *bus = mcore->core->bus;
+
+	if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
+		return bcma_pmu_get_clockcpu(&bus->drv_cc);
+
+	pr_err("No PMU available, need this to get the cpu clock\n");
+	return 0;
+}
+EXPORT_SYMBOL(bcma_cpu_clock);
+
 static void bcma_core_mips_serial_init(struct bcma_drv_mips *mcore)
 {
 	struct bcma_bus *bus = mcore->core->bus;
include/linux/bcma/bcma_driver_chipcommon.h +35 -0
index 083c3b6..77dc08c 100644
@@ -245,6 +245,41 @@
 #define BCMA_CC_PLLCTL_ADDR		0x0660
 #define BCMA_CC_PLLCTL_DATA		0x0664
 
+/* Divider allocation in 4716/47162/5356 */
+#define BCMA_CC_PMU5_MAINPLL_CPU	1
+#define BCMA_CC_PMU5_MAINPLL_MEM	2
+#define BCMA_CC_PMU5_MAINPLL_SSB	3
+
+/* 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
+/* HT clock for systems with PMU-enabled chipcommon */
+#define BCMA_CC_PMU_HT_CLOCK		80000000
+
+/* PMU rev 5 (& 6) */
+#define	BCMA_CC_PPL_P1P2_OFF		0
+#define	BCMA_CC_PPL_P1_MASK		0x0f000000
+#define	BCMA_CC_PPL_P1_SHIFT		24
+#define	BCMA_CC_PPL_P2_MASK		0x00f00000
+#define	BCMA_CC_PPL_P2_SHIFT		20
+#define	BCMA_CC_PPL_M14_OFF		1
+#define	BCMA_CC_PPL_MDIV_MASK		0x000000ff
+#define	BCMA_CC_PPL_MDIV_WIDTH		8
+#define	BCMA_CC_PPL_NM5_OFF		2
+#define	BCMA_CC_PPL_NDIV_MASK		0xfff00000
+#define	BCMA_CC_PPL_NDIV_SHIFT		20
+#define	BCMA_CC_PPL_FMAB_OFF		3
+#define	BCMA_CC_PPL_MRAT_MASK		0xf0000000
+#define	BCMA_CC_PPL_MRAT_SHIFT		28
+#define	BCMA_CC_PPL_ABRAT_MASK		0x08000000
+#define	BCMA_CC_PPL_ABRAT_SHIFT		27
+#define	BCMA_CC_PPL_FDIV_MASK		0x07ffffff
+#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)
  */
include/linux/bcma/bcma_driver_mips.h +1 -0
index 6584e7d..8346fde 100644
@@ -47,5 +47,6 @@ struct bcma_drv_mips {
 };
 
 extern void bcma_core_mips_init(struct bcma_drv_mips *mcore);
+extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore);
 
 #endif /* LINUX_BCMA_DRIVER_MIPS_H_ */
Signature · 1 line
1.7.4.1
maintainer
#35 lore raw

RFC PATCH 6/10 bcma: get CPU clock

2011/6/6 Hauke Mehrtens <[email protected]>:

drivers/bcma/driver_mips.c static void bcma_core_mips_dump_irq(struct bcma_bus *bus) · line 168

Quoted 11 lines
drivers/bcma/driver_mips.c +11 -0
+u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
+{
+ ? ? ? struct bcma_bus *bus = mcore->core->bus;
+
+ ? ? ? if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
+ ? ? ? ? ? ? ? return bcma_pmu_get_clockcpu(&bus->drv_cc);
+
+ ? ? ? pr_err("No PMU available, need this to get the cpu clock\n");
+ ? ? ? return 0;
+}
+EXPORT_SYMBOL(bcma_cpu_clock);

Are you really going to use this in some separated driver? If you're, I heard that exporting symbol should go in pair with patch enabling usage of such a symbol.

Signature · 1 line
Rafa?
maintainer
#36 lore raw

RFC PATCH 6/10 bcma: get CPU clock

W dniu 6 czerwca 2011 12:34 u?ytkownik Rafa? Mi?ecki <[email protected]> napisa?:

Quoted 16 lines

2011/6/6 Hauke Mehrtens <[email protected]>:

drivers/bcma/driver_mips.c static void bcma_core_mips_dump_irq(struct bcma_bus *bus) · line 168

Quoted 11 lines
drivers/bcma/driver_mips.c +11 -0
+u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
+{
+ ? ? ? struct bcma_bus *bus = mcore->core->bus;
+
+ ? ? ? if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
+ ? ? ? ? ? ? ? return bcma_pmu_get_clockcpu(&bus->drv_cc);
+
+ ? ? ? pr_err("No PMU available, need this to get the cpu clock\n");
+ ? ? ? return 0;
+}
+EXPORT_SYMBOL(bcma_cpu_clock);

Are you really going to use this in some separated driver? If you're, I heard that exporting symbol should go in pair with patch enabling usage of such a symbol.

I've just read patch 09/10, sorry for the noise :)

Signature · 1 line
Rafa?
author maintainer
#37 lore raw

RFC PATCH 7/10 bcma: add pci(e) host mode

In reply to Hauke Mehrtens

This adds some stub for a pci(e) host controller. This controller is found on some embedded devices to attach other chips.

---
 drivers/bcma/Kconfig                 |    6 ++++
 drivers/bcma/Makefile                |    1 +
 drivers/bcma/bcma_private.h          |    6 ++++
 drivers/bcma/driver_pci.c            |   12 ++++++++-
 drivers/bcma/driver_pci_host.c       |   44 ++++++++++++++++++++++++++++++++++
 include/linux/bcma/bcma_driver_pci.h |    1 +
 6 files changed, 69 insertions(+), 1 deletions(-)
 create mode 100644 drivers/bcma/driver_pci_host.c
drivers/bcma/Kconfig +6 -0
index 568d30b..c863a87 100644
@@ -27,6 +27,12 @@ config BCMA_HOST_PCI
 	bool "Support for BCMA on PCI-host bus"
 	depends on BCMA_HOST_PCI_POSSIBLE
 
+config BCMA_PCICORE_HOSTMODE
+	bool "Hostmode support for BCMA PCI core"
+	depends on BCMA_DRIVER_MIPS
+	help
+	  PCIcore hostmode operation (external PCI bus).
+
 config BCMA_HOST_EMBEDDED
 	bool
 	depends on BCMA_DRIVER_MIPS
drivers/bcma/Makefile +1 -0
index 50ddab8..f99abfe 100644
@@ -1,6 +1,7 @@
 bcma-y					+= main.o scan.o core.o
 bcma-y					+= driver_chipcommon.o driver_chipcommon_pmu.o
 bcma-y					+= driver_pci.o
+bcma-$(CONFIG_BCMA_PCICORE_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_EMBEDDED)	+= host_embedded.o
drivers/bcma/bcma_private.h +6 -0
index fbabe19..13cf25a 100644
@@ -29,6 +29,12 @@ extern u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
 extern int bcma_chipco_serial_init(struct bcma_drv_cc *cc,
 				   struct bcma_drv_mips_serial_port *ports);
 
+#ifdef CONFIG_BCMA_PCICORE_HOSTMODE
+/* driver_pci_host.c */
+extern int bcma_pcicore_is_in_hostmode(struct bcma_drv_pci *pc);
+extern void bcma_pcicore_init_hostmode(struct bcma_drv_pci *pc);
+#endif /* CONFIG_BCMA_PCICORE_HOSTMODE */
+
 #ifdef CONFIG_BCMA_HOST_PCI
 /* host_pci.c */
 extern int __init bcma_host_pci_init(void);
drivers/bcma/driver_pci.c +11 -1
index 789d68b..cf8cbe0 100644
@@ -159,7 +159,17 @@ static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc)
 
 void bcma_core_pci_init(struct bcma_drv_pci *pc)
 {
-	bcma_pcicore_serdes_workaround(pc);
+	struct bcma_device *core = pc->core;
+
+	if (!bcma_core_is_enabled(core))
+		bcma_core_enable(core, 0);
+#ifdef CONFIG_BCMA_PCICORE_HOSTMODE
+	pc->hostmode = bcma_pcicore_is_in_hostmode(pc);
+	if (pc->hostmode)
+		bcma_pcicore_init_hostmode(pc);
+#endif /* CONFIG_BCMA_PCICORE_HOSTMODE */
+	if (!pc->hostmode)
+		bcma_pcicore_serdes_workaround(pc);
 }
 
 int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
drivers/bcma/driver_pci_host.c new file +44 -0

44 lines not on this page · raw message

include/linux/bcma/bcma_driver_pci.h +1 -0
index b7e191c..5bbc58f 100644
@@ -78,6 +78,7 @@ struct pci_dev;
 struct bcma_drv_pci {
 	struct bcma_device *core;
 	u8 setup_done:1;
+	u8 hostmode:1;
 };
 
 /* Register access */
Signature · 1 line
1.7.4.1
maintainer
#38 lore raw

RFC PATCH 7/10 bcma: add pci(e) host mode

2011/6/6 Hauke Mehrtens <[email protected]>:

Quoted 5 lines

+config BCMA_PCICORE_HOSTMODE
+ ? ? ? bool "Hostmode support for BCMA PCI core"
+ ? ? ? depends on BCMA_DRIVER_MIPS
+ ? ? ? help
+ ? ? ? ? PCIcore hostmode operation (external PCI bus).

I think you started to use BCMA_DRIVER_corename. Could you stick to it (one schema), please? Maybe just
BCMA_DRIVER_PCI_HOSTMODE
?

Review

Quoted 7 lines
(quoted diff) +7 -0
+#ifdef CONFIG_BCMA_PCICORE_HOSTMODE
+ ? ? ? pc->hostmode = bcma_pcicore_is_in_hostmode(pc);
+ ? ? ? if (pc->hostmode)
+ ? ? ? ? ? ? ? bcma_pcicore_init_hostmode(pc);
+#endif /* CONFIG_BCMA_PCICORE_HOSTMODE */
+ ? ? ? if (!pc->hostmode)
+ ? ? ? ? ? ? ? bcma_pcicore_serdes_workaround(pc);

Does it make sense to init hostmode PCI like clientmode if we just disable CONFIG_BCMA_PCICORE_HOSTMODE?

I think we should always check if core is host or client mode and use correct initialization only. We should not init it as clientmode just because we do not have driver for host mode.

drivers/bcma/driver_pci_host.c line 3

Quoted 9 lines
drivers/bcma/driver_pci_host.c new file +3 -0
new file mode 100644
index 0000000..b52c6c9
@@ -0,0 +1,44 @@
+/*
+ * Broadcom specific AMBA
+ * PCI Core

Please rename "PCI Core", add something about hostmode.

Signature · 1 line
Rafa?
author maintainer
#39 lore raw

RFC PATCH 7/10 bcma: add pci(e) host mode

Quoted 7 lines · Rafa? Mi?ecki

2011/6/6 Hauke Mehrtens <[email protected]>:

drivers/bcma/Kconfig config BCMA_HOST_PCI · line 34

Quoted 5 lines
drivers/bcma/Kconfig +5 -0
+config BCMA_PCICORE_HOSTMODE
+       bool "Hostmode support for BCMA PCI core"
+       depends on BCMA_DRIVER_MIPS
+       help
+         PCIcore hostmode operation (external PCI bus).
Quoted 5 lines

I think you started to use BCMA_DRIVER_corename. Could you stick to it (one schema), please? Maybe just
BCMA_DRIVER_PCI_HOSTMODE
?

Yes sounds better.

Quoted 12 lines

drivers/bcma/driver_pci.c static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc) · line 172

Quoted 8 lines
drivers/bcma/driver_pci.c +7 -0
+#ifdef CONFIG_BCMA_PCICORE_HOSTMODE
+       pc->hostmode = bcma_pcicore_is_in_hostmode(pc);
+       if (pc->hostmode)
+               bcma_pcicore_init_hostmode(pc);
+#endif /* CONFIG_BCMA_PCICORE_HOSTMODE */
+       if (!pc->hostmode)
+               bcma_pcicore_serdes_workaround(pc);

Does it make sense to init hostmode PCI like clientmode if we just disable CONFIG_BCMA_PCICORE_HOSTMODE?

Quoted 3 lines

I think we should always check if core is host or client mode and use correct initialization only. We should not init it as clientmode just because we do not have driver for host mode.

Yes we should not initialize a host mode pci core with client init code as it will break my device. ;-) I will place bcma_pcicore_is_in_hostmode() into the normal PCI driver code so it is available all the time.

Quoted 14 lines

drivers/bcma/driver_pci_host.c line 3

Quoted 11 lines
drivers/bcma/driver_pci_host.c new file +3 -0
new file mode 100644
index 0000000..b52c6c9
@@ -0,0 +1,44 @@
+/*
+ * Broadcom specific AMBA
+ * PCI Core

Please rename "PCI Core", add something about hostmode.

Missed that while copy and past.

Hauke

maintainer
#40 lore raw

RFC PATCH 7/10 bcma: add pci(e) host mode

In reply to Hauke Mehrtens

2011/6/6 Hauke Mehrtens <[email protected]>:

drivers/bcma/bcma_private.h extern u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc); · line 36

Quoted 5 lines
drivers/bcma/bcma_private.h +5 -0
+#ifdef CONFIG_BCMA_PCICORE_HOSTMODE
+/* driver_pci_host.c */
+extern int bcma_pcicore_is_in_hostmode(struct bcma_drv_pci *pc);
+extern void bcma_pcicore_init_hostmode(struct bcma_drv_pci *pc);
+#endif /* CONFIG_BCMA_PCICORE_HOSTMODE */

I don't know if I'm overreacting, but I really don't like naming mess in the ssb.

Why don't you use bcma_core_pci_* to be consistent?

Signature · 1 line
Rafa?
author maintainer
#41 lore raw

RFC PATCH 8/10 bcm47xx: prepare to support different buses

In reply to Hauke Mehrtens

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.

---
 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/time.c                     |    9 +++-
 arch/mips/bcm47xx/wgt634u.c                  |   13 ++++--
 arch/mips/include/asm/mach-bcm47xx/bcm47xx.h |   14 ++++++-
 arch/mips/include/asm/mach-bcm47xx/gpio.h    |   53 +++++++++++++++++-------
 drivers/watchdog/bcm47xx_wdt.c               |   12 +++++-
 9 files changed, 156 insertions(+), 61 deletions(-)
arch/mips/bcm47xx/gpio.c +34 -22
index e4a5ee9..2f6d2df 100644
@@ -20,42 +20,54 @@ static DECLARE_BITMAP(gpio_in_use, BCM47XX_EXTIF_GPIO_LINES);
 
 int gpio_request(unsigned gpio, const char *tag)
 {
-	if (ssb_chipco_available(&ssb_bcm47xx.chipco) &&
-	    ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
-		return -EINVAL;
+	switch (bcm47xx_active_bus_type) {
+	case BCM47XX_BUS_TYPE_SSB:
+		if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
+		    ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
+			return -EINVAL;
 
-	if (ssb_extif_available(&ssb_bcm47xx.extif) &&
-	    ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
-		return -EINVAL;
+		if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
+		    ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
+			return -EINVAL;
 
-	if (test_and_set_bit(gpio, gpio_in_use))
-		return -EBUSY;
+		if (test_and_set_bit(gpio, gpio_in_use))
+			return -EBUSY;
 
-	return 0;
+		return 0;
+	}
+	return -EINVAL;
 }
 EXPORT_SYMBOL(gpio_request);
 
 void gpio_free(unsigned gpio)
 {
-	if (ssb_chipco_available(&ssb_bcm47xx.chipco) &&
-	    ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
-		return;
+	switch (bcm47xx_active_bus_type) {
+	case BCM47XX_BUS_TYPE_SSB:
+		if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
+		    ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
+			return;
 
-	if (ssb_extif_available(&ssb_bcm47xx.extif) &&
-	    ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
-		return;
+		if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
+		    ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
+			return;
 
-	clear_bit(gpio, gpio_in_use);
+		clear_bit(gpio, gpio_in_use);
+		return;
+	}
 }
 EXPORT_SYMBOL(gpio_free);
 
 int gpio_to_irq(unsigned gpio)
 {
-	if (ssb_chipco_available(&ssb_bcm47xx.chipco))
-		return ssb_mips_irq(ssb_bcm47xx.chipco.dev) + 2;
-	else if (ssb_extif_available(&ssb_bcm47xx.extif))
-		return ssb_mips_irq(ssb_bcm47xx.extif.dev) + 2;
-	else
-		return -EINVAL;
+	switch (bcm47xx_active_bus_type) {
+	case BCM47XX_BUS_TYPE_SSB:
+		if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco))
+			return ssb_mips_irq(bcm47xx_bus.ssb.chipco.dev) + 2;
+		else if (ssb_extif_available(&bcm47xx_bus.ssb.extif))
+			return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2;
+		else
+			return -EINVAL;
+	}
+	return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(gpio_to_irq);
arch/mips/bcm47xx/nvram.c +11 -4
index 54db815..d2304d0 100644
@@ -26,14 +26,21 @@ static char nvram_buf[NVRAM_SPACE];
 /* Probe for NVRAM header */
 static void early_nvram_init(void)
 {
-	struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
+	struct ssb_mipscore *mcore_ssb;
 	struct nvram_header *header;
 	int i;
-	u32 base, lim, off;
+	u32 base = 0;
+	u32 lim = 0;
+	u32 off;
 	u32 *src, *dst;
 
-	base = mcore->flash_window;
-	lim = mcore->flash_window_size;
+	switch (bcm47xx_active_bus_type) {
+	case BCM47XX_BUS_TYPE_SSB:
+		mcore_ssb = &bcm47xx_bus.ssb.mipscore;
+		base = mcore_ssb->flash_window;
+		lim = mcore_ssb->flash_window_size;
+		break;
+	}
 
 	off = FLASH_MIN;
 	while (off <= lim) {
arch/mips/bcm47xx/serial.c +11 -2
index 59c11af..87c2c5e 100644
@@ -23,10 +23,10 @@ static struct platform_device uart8250_device = {
 	},
 };
 
-static int __init uart8250_init(void)
+static int __init uart8250_init_ssb(void)
 {
 	int i;
-	struct ssb_mipscore *mcore = &(ssb_bcm47xx.mipscore);
+	struct ssb_mipscore *mcore = &(bcm47xx_bus.ssb.mipscore);
 
 	memset(&uart8250_data, 0,  sizeof(uart8250_data));
 
@@ -45,6 +45,15 @@ static int __init uart8250_init(void)
 	return platform_device_register(&uart8250_device);
 }
 
+static int __init uart8250_init(void)
+{
+	switch (bcm47xx_active_bus_type) {
+	case BCM47XX_BUS_TYPE_SSB:
+		return uart8250_init_ssb();
+	}
+	return -EINVAL;
+}
+
 module_init(uart8250_init);
 
 MODULE_AUTHOR("Aurelien Jarno <[email protected]>");
arch/mips/bcm47xx/setup.c +25 -7
index 73b529b..c64b76d 100644
@@ -35,15 +35,21 @@
 #include <bcm47xx.h>
 #include <asm/mach-bcm47xx/nvram.h>
 
-struct ssb_bus ssb_bcm47xx;
-EXPORT_SYMBOL(ssb_bcm47xx);
+union bcm47xx_bus bcm47xx_bus;
+EXPORT_SYMBOL(bcm47xx_bus);
+
+enum bcm47xx_bus_type bcm47xx_active_bus_type;
 
 static void bcm47xx_machine_restart(char *command)
 {
 	printk(KERN_ALERT "Please stand by while rebooting the system...\n");
 	local_irq_disable();
 	/* Set the watchdog timer to reset immediately */
-	ssb_watchdog_timer_set(&ssb_bcm47xx, 1);
+	switch (bcm47xx_active_bus_type) {
+	case BCM47XX_BUS_TYPE_SSB:
+		ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1);
+		break;
+	}
 	while (1)
 		cpu_relax();
 }
@@ -52,7 +58,11 @@ static void bcm47xx_machine_halt(void)
 {
 	/* Disable interrupts and watchdog and spin forever */
 	local_irq_disable();
-	ssb_watchdog_timer_set(&ssb_bcm47xx, 0);
+	switch (bcm47xx_active_bus_type) {
+	case BCM47XX_BUS_TYPE_SSB:
+		ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
+		break;
+	}
 	while (1)
 		cpu_relax();
 }
@@ -247,7 +257,7 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
 	return 0;
 }
 
-void __init plat_mem_setup(void)
+static void __init bcm47xx_register_ssb(void)
 {
 	int err;
 	char buf[100];
@@ -258,12 +268,12 @@ void __init plat_mem_setup(void)
 		printk(KERN_WARNING "bcm47xx: someone else already registered"
 			" a ssb SPROM callback handler (err %d)\n", err);
 
-	err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
+	err = ssb_bus_ssbbus_register(&(bcm47xx_bus.ssb), SSB_ENUM_BASE,
 				      bcm47xx_get_invariants);
 	if (err)
 		panic("Failed to initialize SSB bus (err %d)\n", err);
 
-	mcore = &ssb_bcm47xx.mipscore;
+	mcore = &bcm47xx_bus.ssb.mipscore;
 	if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
 		if (strstr(buf, "console=ttyS1")) {
 			struct ssb_serial_port port;
@@ -276,6 +286,14 @@ void __init plat_mem_setup(void)
 			memcpy(&mcore->serial_ports[1], &port, sizeof(port));
 		}
 	}
+}
+
+void __init plat_mem_setup(void)
+{
+	struct cpuinfo_mips *c = &current_cpu_data;
+
+	bcm47xx_active_bus_type = BCM47XX_BUS_TYPE_SSB;
+	bcm47xx_register_ssb();
 
 	_machine_restart = bcm47xx_machine_restart;
 	_machine_halt = bcm47xx_machine_halt;
arch/mips/bcm47xx/time.c +7 -2
index 0c6f47b..a7be993 100644
@@ -30,7 +30,7 @@
 
 void __init plat_time_init(void)
 {
-	unsigned long hz;
+	unsigned long hz = 0;
 
 	/*
 	 * Use deterministic values for initial counter interrupt
@@ -39,7 +39,12 @@ void __init plat_time_init(void)
 	write_c0_count(0);
 	write_c0_compare(0xffff);
 
-	hz = ssb_cpu_clock(&ssb_bcm47xx.mipscore) / 2;
+	switch (bcm47xx_active_bus_type) {
+	case BCM47XX_BUS_TYPE_SSB:
+		hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2;
+		break;
+	}
+
 	if (!hz)
 		hz = 100000000;
 
arch/mips/bcm47xx/wgt634u.c +8 -5
index 74d0696..79ecd0a 100644
@@ -108,7 +108,7 @@ static irqreturn_t gpio_interrupt(int irq, void *ignored)
 
 	/* Interrupts are shared, check if the current one is
 	   a GPIO interrupt. */
-	if (!ssb_chipco_irq_status(&ssb_bcm47xx.chipco,
+	if (!ssb_chipco_irq_status(&bcm47xx_bus.ssb.chipco,
 				   SSB_CHIPCO_IRQ_GPIO))
 		return IRQ_NONE;
 
@@ -133,21 +133,24 @@ static int __init wgt634u_init(void)
 	 * been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx.
 	 */
 
-	u8 *et0mac = ssb_bcm47xx.sprom.et0mac;
+	if (bcm47xx_active_bus_type != BCM47XX_BUS_TYPE_SSB)
+		return -ENODEV;
+
+	u8 *et0mac = bcm47xx_bus.ssb.sprom.et0mac;
 
 	if (et0mac[0] == 0x00 &&
 	    ((et0mac[1] == 0x09 && et0mac[2] == 0x5b) ||
 	     (et0mac[1] == 0x0f && et0mac[2] == 0xb5))) {
-		struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
+		struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore;
 
 		printk(KERN_INFO "WGT634U machine detected.\n");
 
 		if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET),
 				 gpio_interrupt, IRQF_SHARED,
-				 "WGT634U GPIO", &ssb_bcm47xx.chipco)) {
+				 "WGT634U GPIO", &bcm47xx_bus.ssb.chipco)) {
 			gpio_direction_input(WGT634U_GPIO_RESET);
 			gpio_intmask(WGT634U_GPIO_RESET, 1);
-			ssb_chipco_irq_mask(&ssb_bcm47xx.chipco,
+			ssb_chipco_irq_mask(&bcm47xx_bus.ssb.chipco,
 					    SSB_CHIPCO_IRQ_GPIO,
 					    SSB_CHIPCO_IRQ_GPIO);
 		}
arch/mips/include/asm/mach-bcm47xx/bcm47xx.h +12 -2
index d008f47..4be8b95 100644
@@ -19,7 +19,17 @@
 #ifndef __ASM_BCM47XX_H
 #define __ASM_BCM47XX_H
 
-/* SSB bus */
-extern struct ssb_bus ssb_bcm47xx;
+#include <linux/ssb/ssb.h>
+
+enum bcm47xx_bus_type {
+	BCM47XX_BUS_TYPE_SSB,
+};
+
+union bcm47xx_bus {
+	struct ssb_bus ssb;
+};
+
+extern union bcm47xx_bus bcm47xx_bus;
+extern enum bcm47xx_bus_type bcm47xx_active_bus_type;
 
 #endif /* __ASM_BCM47XX_H */
arch/mips/include/asm/mach-bcm47xx/gpio.h +38 -15

79 lines not on this page · raw message

drivers/watchdog/bcm47xx_wdt.c +10 -2
index bd44417..7e4e063 100644
@@ -54,12 +54,20 @@ static atomic_t ticks;
 static inline void bcm47xx_wdt_hw_start(void)
 {
 	/* this is 2,5s on 100Mhz clock  and 2s on 133 Mhz */
-	ssb_watchdog_timer_set(&ssb_bcm47xx, 0xfffffff);
+	switch (bcm47xx_active_bus_type) {
+	case BCM47XX_BUS_TYPE_SSB:
+		ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff);
+		break;
+	}
 }
 
 static inline int bcm47xx_wdt_hw_stop(void)
 {
-	return ssb_watchdog_timer_set(&ssb_bcm47xx, 0);
+	switch (bcm47xx_active_bus_type) {
+	case BCM47XX_BUS_TYPE_SSB:
+		return ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
+	}
+	return -EINVAL;
 }
 
 static void bcm47xx_timer_tick(unsigned long unused)
Signature · 1 line
1.7.4.1
author maintainer
#42 lore raw

RFC PATCH 9/10 bcm47xx: add support for bcma bus

In reply to Hauke Mehrtens

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 74K CPUs.

---
 arch/mips/Kconfig                            |    4 +++
 arch/mips/bcm47xx/gpio.c                     |    9 ++++++++
 arch/mips/bcm47xx/nvram.c                    |    6 +++++
 arch/mips/bcm47xx/serial.c                   |   24 +++++++++++++++++++++++
 arch/mips/bcm47xx/setup.c                    |   27 ++++++++++++++++++++++++-
 arch/mips/bcm47xx/time.c                     |    3 ++
 arch/mips/include/asm/mach-bcm47xx/bcm47xx.h |    3 ++
 arch/mips/include/asm/mach-bcm47xx/gpio.h    |   18 +++++++++++++++++
 drivers/watchdog/bcm47xx_wdt.c               |    6 +++++
 9 files changed, 98 insertions(+), 2 deletions(-)
arch/mips/Kconfig +4 -0
index 653da62..bdb0341 100644
@@ -100,6 +100,10 @@ config BCM47XX
 	select SSB_EMBEDDED
 	select SSB_B43_PCI_BRIDGE if PCI
 	select SSB_PCICORE_HOSTMODE if PCI
+	select BCMA
+	select BCMA_HOST_EMBEDDED
+	select BCMA_DRIVER_MIPS
+	select BCMA_PCICORE_HOSTMODE
 	select GENERIC_GPIO
 	select SYS_HAS_EARLY_PRINTK
 	select CFE
arch/mips/bcm47xx/gpio.c +9 -0
index 2f6d2df..42af3f8 100644
@@ -34,6 +34,9 @@ int gpio_request(unsigned gpio, const char *tag)
 			return -EBUSY;
 
 		return 0;
+	case BCM47XX_BUS_TYPE_BCMA:
+		/* Not implemenmted yet */
+		return -EINVAL;
 	}
 	return -EINVAL;
 }
@@ -53,6 +56,9 @@ void gpio_free(unsigned gpio)
 
 		clear_bit(gpio, gpio_in_use);
 		return;
+	case BCM47XX_BUS_TYPE_BCMA:
+		/* Not implemenmted yet */
+		return;
 	}
 }
 EXPORT_SYMBOL(gpio_free);
@@ -67,6 +73,9 @@ int gpio_to_irq(unsigned gpio)
 			return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2;
 		else
 			return -EINVAL;
+	case BCM47XX_BUS_TYPE_BCMA:
+		/* Not implemenmted yet */
+		return -EINVAL;
 	}
 	return -EINVAL;
 }
arch/mips/bcm47xx/nvram.c +6 -0
index d2304d0..75c36c4 100644
@@ -27,6 +27,7 @@ static char nvram_buf[NVRAM_SPACE];
 static void early_nvram_init(void)
 {
 	struct ssb_mipscore *mcore_ssb;
+	struct bcma_drv_mips *mcore_bcma;
 	struct nvram_header *header;
 	int i;
 	u32 base = 0;
@@ -40,6 +41,11 @@ static void early_nvram_init(void)
 		base = mcore_ssb->flash_window;
 		lim = mcore_ssb->flash_window_size;
 		break;
+	case BCM47XX_BUS_TYPE_BCMA:
+		mcore_bcma = &bcm47xx_bus.bcma.drv_mips;
+		base = mcore_bcma->flash_window;
+		lim = mcore_bcma->flash_window_size;
+		break;
 	}
 
 	off = FLASH_MIN;
arch/mips/bcm47xx/serial.c +24 -0
index 87c2c5e..ed74d975 100644
@@ -45,11 +45,35 @@ static int __init uart8250_init_ssb(void)
 	return platform_device_register(&uart8250_device);
 }
 
+static int __init uart8250_init_bcma(void)
+{
+	int i;
+	struct bcma_drv_mips *mcore = &(bcm47xx_bus.bcma.drv_mips);
+
+	memset(&uart8250_data, 0,  sizeof(uart8250_data));
+
+	for (i = 0; i < mcore->nr_serial_ports; i++) {
+		struct plat_serial8250_port *p = &(uart8250_data[i]);
+		struct bcma_drv_mips_serial_port *bcma_port = &(mcore->serial_ports[i]);
+
+		p->mapbase = (unsigned int) bcma_port->regs;
+		p->membase = (void *) bcma_port->regs;
+		p->irq = bcma_port->irq + 2;
+		p->uartclk = bcma_port->baud_base;
+		p->regshift = bcma_port->reg_shift;
+		p->iotype = UPIO_MEM;
+		p->flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+	}
+	return platform_device_register(&uart8250_device);
+}
+
 static int __init uart8250_init(void)
 {
 	switch (bcm47xx_active_bus_type) {
 	case BCM47XX_BUS_TYPE_SSB:
 		return uart8250_init_ssb();
+	case BCM47XX_BUS_TYPE_BCMA:
+		return uart8250_init_bcma();
 	}
 	return -EINVAL;
 }
arch/mips/bcm47xx/setup.c +25 -2
index c64b76d..8dd82f3 100644
@@ -29,6 +29,7 @@
 #include <linux/types.h>
 #include <linux/ssb/ssb.h>
 #include <linux/ssb/ssb_embedded.h>
+#include <linux/bcma/bcma_embedded.h>
 #include <asm/bootinfo.h>
 #include <asm/reboot.h>
 #include <asm/time.h>
@@ -49,6 +50,9 @@ static void bcm47xx_machine_restart(char *command)
 	case BCM47XX_BUS_TYPE_SSB:
 		ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1);
 		break;
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.drv_cc, 1);
+		break;
 	}
 	while (1)
 		cpu_relax();
@@ -62,6 +66,9 @@ static void bcm47xx_machine_halt(void)
 	case BCM47XX_BUS_TYPE_SSB:
 		ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
 		break;
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.drv_cc, 0);
+		break;
 	}
 	while (1)
 		cpu_relax();
@@ -288,12 +295,28 @@ static void __init bcm47xx_register_ssb(void)
 	}
 }
 
+static void __init bcm47xx_register_bcma(void)
+{
+	int err;
+
+	err = bcma_host_bcma_register(&bcm47xx_bus.bcma);
+	if (err)
+		panic("Failed to initialize BCMA bus (err %d)\n", err);
+}
+
 void __init plat_mem_setup(void)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
 
-	bcm47xx_active_bus_type = BCM47XX_BUS_TYPE_SSB;
-	bcm47xx_register_ssb();
+	if (c->cputype == CPU_74K) {
+		printk(KERN_INFO "bcm47xx: using bcma bus\n");
+		bcm47xx_active_bus_type = BCM47XX_BUS_TYPE_BCMA;
+		bcm47xx_register_bcma();
+	} else {
+		printk(KERN_INFO "bcm47xx: using ssb bus\n");
+		bcm47xx_active_bus_type = BCM47XX_BUS_TYPE_SSB;
+		bcm47xx_register_ssb();
+	}
 
 	_machine_restart = bcm47xx_machine_restart;
 	_machine_halt = bcm47xx_machine_halt;
arch/mips/bcm47xx/time.c +3 -0
index a7be993..ace3ba2 100644
@@ -43,6 +43,9 @@ void __init plat_time_init(void)
 	case BCM47XX_BUS_TYPE_SSB:
 		hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2;
 		break;
+	case BCM47XX_BUS_TYPE_BCMA:
+		hz = bcma_cpu_clock(&bcm47xx_bus.bcma.drv_mips) / 2;
+		break;
 	}
 
 	if (!hz)
arch/mips/include/asm/mach-bcm47xx/bcm47xx.h +3 -0
index 4be8b95..3e6ccb9 100644
@@ -20,13 +20,16 @@
 #define __ASM_BCM47XX_H
 
 #include <linux/ssb/ssb.h>
+#include <linux/bcma/bcma.h>
 
 enum bcm47xx_bus_type {
 	BCM47XX_BUS_TYPE_SSB,
+	BCM47XX_BUS_TYPE_BCMA,
 };
 
 union bcm47xx_bus {
 	struct ssb_bus ssb;
+	struct bcma_bus bcma;
 };
 
 extern union bcm47xx_bus bcm47xx_bus;
arch/mips/include/asm/mach-bcm47xx/gpio.h +18 -0
index 16d6c19..e8629a8 100644
@@ -24,6 +24,9 @@ static inline int gpio_get_value(unsigned gpio)
 	switch (bcm47xx_active_bus_type) {
 	case BCM47XX_BUS_TYPE_SSB:
 		return ssb_gpio_in(&bcm47xx_bus.ssb, 1 << gpio);
+	case BCM47XX_BUS_TYPE_BCMA:
+		/* Not implemenmted yet */
+		return -EINVAL;
 	}
 	return -EINVAL;
 }
@@ -33,6 +36,9 @@ static inline void gpio_set_value(unsigned gpio, int value)
 	switch (bcm47xx_active_bus_type) {
 	case BCM47XX_BUS_TYPE_SSB:
 		ssb_gpio_out(&bcm47xx_bus.ssb, 1 << gpio, value ? 1 << gpio : 0);
+	case BCM47XX_BUS_TYPE_BCMA:
+		/* Not implemenmted yet */
+		return;
 	}
 }
 
@@ -42,6 +48,9 @@ static inline int gpio_direction_input(unsigned gpio)
 	case BCM47XX_BUS_TYPE_SSB:
 		ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 0);
 		return 0;
+	case BCM47XX_BUS_TYPE_BCMA:
+		/* Not implemenmted yet */
+		return -EINVAL;
 	}
 	return -EINVAL;
 }
@@ -55,6 +64,9 @@ static inline int gpio_direction_output(unsigned gpio, int value)
 		/* then set the gpio mode */
 		ssb_gpio_outen(&bcm47xx_bus.ssb, 1 << gpio, 1 << gpio);
 		return 0;
+	case BCM47XX_BUS_TYPE_BCMA:
+		/* Not implemenmted yet */
+		return -EINVAL;
 	}
 	return -EINVAL;
 }
@@ -66,6 +78,9 @@ static inline int gpio_intmask(unsigned gpio, int value)
 		ssb_gpio_intmask(&bcm47xx_bus.ssb, 1 << gpio,
 				 value ? 1 << gpio : 0);
 		return 0;
+	case BCM47XX_BUS_TYPE_BCMA:
+		/* Not implemenmted yet */
+		return -EINVAL;
 	}
 	return -EINVAL;
 }
@@ -77,6 +92,9 @@ static inline int gpio_polarity(unsigned gpio, int value)
 		ssb_gpio_polarity(&bcm47xx_bus.ssb, 1 << gpio,
 				  value ? 1 << gpio : 0);
 		return 0;
+	case BCM47XX_BUS_TYPE_BCMA:
+		/* Not implemenmted yet */
+		return -EINVAL;
 	}
 	return -EINVAL;
 }
drivers/watchdog/bcm47xx_wdt.c +6 -0
index 7e4e063..8a31494 100644
@@ -58,6 +58,9 @@ static inline void bcm47xx_wdt_hw_start(void)
 	case BCM47XX_BUS_TYPE_SSB:
 		ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff);
 		break;
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.drv_cc, 0xfffffff);
+		break;
 	}
 }
 
@@ -66,6 +69,9 @@ static inline int bcm47xx_wdt_hw_stop(void)
 	switch (bcm47xx_active_bus_type) {
 	case BCM47XX_BUS_TYPE_SSB:
 		return ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
+	case BCM47XX_BUS_TYPE_BCMA:
+		bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.drv_cc, 0);
+		return 0;
 	}
 	return -EINVAL;
 }
Signature · 1 line
1.7.4.1
maintainer
#43 lore raw

RFC PATCH 9/10 bcm47xx: add support for bcma bus

2011/6/6 Hauke Mehrtens <[email protected]>:

Quoted 22 lines

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 74K CPUs.

---

?arch/mips/Kconfig ? ? ? ? ? ? ? ? ? ? ? ? ? ?| ? ?4 +++
?arch/mips/bcm47xx/gpio.c ? ? ? ? ? ? ? ? ? ? | ? ?9 ++++++++
?arch/mips/bcm47xx/nvram.c ? ? ? ? ? ? ? ? ? ?| ? ?6 +++++
?arch/mips/bcm47xx/serial.c ? ? ? ? ? ? ? ? ? | ? 24 +++++++++++++++++++++++
?arch/mips/bcm47xx/setup.c ? ? ? ? ? ? ? ? ? ?| ? 27 ++++++++++++++++++++++++-
?arch/mips/bcm47xx/time.c ? ? ? ? ? ? ? ? ? ? | ? ?3 ++
?arch/mips/include/asm/mach-bcm47xx/bcm47xx.h | ? ?3 ++
?arch/mips/include/asm/mach-bcm47xx/gpio.h ? ?| ? 18 +++++++++++++++++
?drivers/watchdog/bcm47xx_wdt.c ? ? ? ? ? ? ? | ? ?6 +++++

?9 files changed, 98 insertions(+), 2 deletions(-)

arch/mips/Kconfig +0 -0
index 653da62..bdb0341 100644
@@ -100,6 +100,10 @@ config BCM47XX
Quoted 7 lines

? ? ? ?select SSB_EMBEDDED
? ? ? ?select SSB_B43_PCI_BRIDGE if PCI
? ? ? ?select SSB_PCICORE_HOSTMODE if PCI
+ ? ? ? select BCMA
+ ? ? ? select BCMA_HOST_EMBEDDED
+ ? ? ? select BCMA_DRIVER_MIPS
+ ? ? ? select BCMA_PCICORE_HOSTMODE

I'm not involved in development for embedded devices but I believe that space is quite important for them.

You force compiling both: ssb and bcma for every device using bcm47xx. I think ppl may want to compile only one bus driver.

Signature · 1 line
Rafa?
author maintainer
#44 lore raw

RFC PATCH 9/10 bcm47xx: add support for bcma bus

Quoted 34 lines · Rafa? Mi?ecki

2011/6/6 Hauke Mehrtens <[email protected]>:

Quoted 22 lines

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 74K CPUs.

---
 arch/mips/Kconfig                            |    4 +++
 arch/mips/bcm47xx/gpio.c                     |    9 ++++++++
 arch/mips/bcm47xx/nvram.c                    |    6 +++++
 arch/mips/bcm47xx/serial.c                   |   24 +++++++++++++++++++++++
 arch/mips/bcm47xx/setup.c                    |   27 ++++++++++++++++++++++++-
 arch/mips/bcm47xx/time.c                     |    3 ++
 arch/mips/include/asm/mach-bcm47xx/bcm47xx.h |    3 ++
 arch/mips/include/asm/mach-bcm47xx/gpio.h    |   18 +++++++++++++++++
 drivers/watchdog/bcm47xx_wdt.c               |    6 +++++
 9 files changed, 98 insertions(+), 2 deletions(-)
arch/mips/Kconfig +0 -0
index 653da62..bdb0341 100644

arch/mips/Kconfig config BCM47XX · line 106

Quoted 7 lines
arch/mips/Kconfig +4 -0
@@ -100,6 +100,10 @@ config BCM47XX
       select SSB_EMBEDDED
       select SSB_B43_PCI_BRIDGE if PCI
       select SSB_PCICORE_HOSTMODE if PCI
+       select BCMA
+       select BCMA_HOST_EMBEDDED
+       select BCMA_DRIVER_MIPS
+       select BCMA_PCICORE_HOSTMODE

I'm not involved in development for embedded devices but I believe that space is quite important for them.

Quoted 3 lines

You force compiling both: ssb and bcma for every device using bcm47xx. I think ppl may want to compile only one bus driver.

Yes that has to be improved as there should also be an option to use the compiler optimazions for the new MIPS 74K CPU core.

Hauke

author maintainer
#45 lore raw

RFC PATCH 10/10 bcm47xx: fix irq assignment for new SoCs.

In reply to Hauke Mehrtens
---
 arch/mips/bcm47xx/irq.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)
arch/mips/bcm47xx/irq.c +8 -0
index 325757a..3642cee 100644
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <asm/irq_cpu.h>
+#include <bcm47xx.h>
 
 void plat_irq_dispatch(void)
 {
@@ -51,5 +52,12 @@ void plat_irq_dispatch(void)
 
 void __init arch_init_irq(void)
 {
+	if (bcm47xx_active_bus_type == BCM47XX_BUS_TYPE_BCMA) {
+		bcma_write32(bcm47xx_bus.bcma.drv_mips.core,
+			     BCMA_MIPS_MIPS74K_INTMASK(5), 1 << 31);
+		/* the kernel reads the timer irq from some register and thinks
+		 * it's #5, but we offset it by 2 and route to #7 */
+		cp0_compare_irq = 7;
+	}
 	mips_cpu_irq_init();
 }
Signature · 1 line
1.7.4.1
#46 lore raw

Re: [RFC][PATCH 10/10] bcm47xx: fix irq assignment for new SoCs.

Hello.

Quoted 9 lines · Hauke Mehrtens
---
  arch/mips/bcm47xx/irq.c |    8 ++++++++
  1 files changed, 8 insertions(+), 0 deletions(-)
arch/mips/bcm47xx/irq.c +0 -0
index 325757a..3642cee 100644

[...]

arch/mips/bcm47xx/irq.c void plat_irq_dispatch(void) · line 59

Quoted 9 lines
arch/mips/bcm47xx/irq.c +5 -0
@@ -51,5 +52,12 @@ void plat_irq_dispatch(void)
 
  void __init arch_init_irq(void)
  {
+	if (bcm47xx_active_bus_type == BCM47XX_BUS_TYPE_BCMA) {
+		bcma_write32(bcm47xx_bus.bcma.drv_mips.core,
+			     BCMA_MIPS_MIPS74K_INTMASK(5), 1<<  31);
+		/* the kernel reads the timer irq from some register and thinks
+		 * it's #5, but we offset it by 2 and route to #7 */

The preferred style for the multi-line comments is this:

/*
* bla
* bla
*/

WBR, Sergei