Signed-off-by: Rafał Miłecki <zajec5@gmail.com> SVN-Revision: 47483master
parent
d42669bf33
commit
b2dab45aa7
@ -0,0 +1,485 @@ |
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Thu, 15 Oct 2015 07:23:25 +0200
|
||||
Subject: [PATCH] ssb: pick PCMCIA host code support from b43 driver
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
ssb bus can be found on various "host" devices like PCI/PCMCIA/SDIO.
|
||||
Every ssb bus contains cores AKA devices.
|
||||
The main idea is to have ssb driver scan/initialize bus and register
|
||||
ready-to-use cores. This way ssb drivers can operate on a single core
|
||||
mostly ignoring underlaying details.
|
||||
|
||||
For some reason PCMCIA support was split between ssb and b43. We got
|
||||
PCMCIA host device probing in b43, then bus scanning in ssb and then
|
||||
wireless core probing back in b43. The truth is it's very unlikely we
|
||||
will ever see PCMCIA ssb device with no 802.11 core but I still don't
|
||||
see any advantage of the current architecture.
|
||||
|
||||
With proposed change we get the same functionality with a simpler
|
||||
architecture, less Kconfig symbols, one killed EXPORT and hopefully
|
||||
cleaner b43. Since b43 supports both: ssb & bcma I prefer to keep ssb
|
||||
specific code in ssb driver.
|
||||
|
||||
This mostly moves code from b43's pcmcia.c to bridge_pcmcia_80211.c. We
|
||||
already use similar solution with b43_pci_bridge.c. I didn't use "b43"
|
||||
in name of this new file as in theory any driver can operate on wireless
|
||||
core.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
---
|
||||
delete mode 100644 drivers/net/wireless/b43/pcmcia.c
|
||||
delete mode 100644 drivers/net/wireless/b43/pcmcia.h
|
||||
create mode 100644 drivers/ssb/bridge_pcmcia_80211.c
|
||||
|
||||
--- a/drivers/net/wireless/b43/Kconfig
|
||||
+++ b/drivers/net/wireless/b43/Kconfig
|
||||
@@ -72,26 +72,6 @@ config B43_PCICORE_AUTOSELECT
|
||||
select SSB_DRIVER_PCICORE
|
||||
default y
|
||||
|
||||
-config B43_PCMCIA
|
||||
- bool "Broadcom 43xx PCMCIA device support"
|
||||
- depends on B43 && B43_SSB && SSB_PCMCIAHOST_POSSIBLE
|
||||
- select SSB_PCMCIAHOST
|
||||
- ---help---
|
||||
- Broadcom 43xx PCMCIA device support.
|
||||
-
|
||||
- Support for 16bit PCMCIA devices.
|
||||
- Please note that most PC-CARD devices are _NOT_ 16bit PCMCIA
|
||||
- devices, but 32bit CardBUS devices. CardBUS devices are supported
|
||||
- out of the box by b43.
|
||||
-
|
||||
- With this config option you can drive b43 cards in
|
||||
- CompactFlash formfactor in a PCMCIA adaptor.
|
||||
- CF b43 cards can sometimes be found in handheld PCs.
|
||||
-
|
||||
- It's safe to select Y here, even if you don't have a B43 PCMCIA device.
|
||||
-
|
||||
- If unsure, say N.
|
||||
-
|
||||
config B43_SDIO
|
||||
bool "Broadcom 43xx SDIO device support"
|
||||
depends on B43 && B43_SSB && SSB_SDIOHOST_POSSIBLE
|
||||
--- a/drivers/net/wireless/b43/Makefile
|
||||
+++ b/drivers/net/wireless/b43/Makefile
|
||||
@@ -21,7 +21,6 @@ b43-y += pio.o
|
||||
b43-y += rfkill.o
|
||||
b43-y += ppr.o
|
||||
b43-$(CPTCFG_B43_LEDS) += leds.o
|
||||
-b43-$(CPTCFG_B43_PCMCIA) += pcmcia.o
|
||||
b43-$(CPTCFG_B43_SDIO) += sdio.o
|
||||
b43-$(CPTCFG_B43_DEBUG) += debugfs.o
|
||||
|
||||
--- a/drivers/net/wireless/b43/main.c
|
||||
+++ b/drivers/net/wireless/b43/main.c
|
||||
@@ -56,7 +56,6 @@
|
||||
#include "sysfs.h"
|
||||
#include "xmit.h"
|
||||
#include "lo.h"
|
||||
-#include "pcmcia.h"
|
||||
#include "sdio.h"
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
|
||||
@@ -5850,12 +5849,9 @@ static int __init b43_init(void)
|
||||
int err;
|
||||
|
||||
b43_debugfs_init();
|
||||
- err = b43_pcmcia_init();
|
||||
- if (err)
|
||||
- goto err_dfs_exit;
|
||||
err = b43_sdio_init();
|
||||
if (err)
|
||||
- goto err_pcmcia_exit;
|
||||
+ goto err_dfs_exit;
|
||||
#ifdef CPTCFG_B43_BCMA
|
||||
err = bcma_driver_register(&b43_bcma_driver);
|
||||
if (err)
|
||||
@@ -5878,8 +5874,6 @@ err_bcma_driver_exit:
|
||||
err_sdio_exit:
|
||||
#endif
|
||||
b43_sdio_exit();
|
||||
-err_pcmcia_exit:
|
||||
- b43_pcmcia_exit();
|
||||
err_dfs_exit:
|
||||
b43_debugfs_exit();
|
||||
return err;
|
||||
@@ -5894,7 +5888,6 @@ static void __exit b43_exit(void)
|
||||
bcma_driver_unregister(&b43_bcma_driver);
|
||||
#endif
|
||||
b43_sdio_exit();
|
||||
- b43_pcmcia_exit();
|
||||
b43_debugfs_exit();
|
||||
}
|
||||
|
||||
--- a/drivers/net/wireless/b43/pcmcia.h
|
||||
+++ /dev/null
|
||||
@@ -1,20 +0,0 @@
|
||||
-#ifndef B43_PCMCIA_H_
|
||||
-#define B43_PCMCIA_H_
|
||||
-
|
||||
-#ifdef CPTCFG_B43_PCMCIA
|
||||
-
|
||||
-int b43_pcmcia_init(void);
|
||||
-void b43_pcmcia_exit(void);
|
||||
-
|
||||
-#else /* CPTCFG_B43_PCMCIA */
|
||||
-
|
||||
-static inline int b43_pcmcia_init(void)
|
||||
-{
|
||||
- return 0;
|
||||
-}
|
||||
-static inline void b43_pcmcia_exit(void)
|
||||
-{
|
||||
-}
|
||||
-
|
||||
-#endif /* CPTCFG_B43_PCMCIA */
|
||||
-#endif /* B43_PCMCIA_H_ */
|
||||
--- a/drivers/ssb/Makefile
|
||||
+++ b/drivers/ssb/Makefile
|
||||
@@ -5,7 +5,7 @@ ssb-$(CPTCFG_SSB_SPROM) += sprom.o
|
||||
|
||||
# host support
|
||||
ssb-$(CPTCFG_SSB_PCIHOST) += pci.o pcihost_wrapper.o
|
||||
-ssb-$(CPTCFG_SSB_PCMCIAHOST) += pcmcia.o
|
||||
+ssb-$(CPTCFG_SSB_PCMCIAHOST) += pcmcia.o bridge_pcmcia_80211.o
|
||||
ssb-$(CPTCFG_SSB_SDIOHOST) += sdio.o
|
||||
|
||||
# built-in drivers
|
||||
--- /dev/null
|
||||
+++ b/drivers/ssb/bridge_pcmcia_80211.c
|
||||
@@ -0,0 +1,128 @@
|
||||
+/*
|
||||
+ * Broadcom 43xx PCMCIA-SSB bridge module
|
||||
+ *
|
||||
+ * Copyright (c) 2007 Michael Buesch <m@bues.ch>
|
||||
+ *
|
||||
+ * Licensed under the GNU/GPL. See COPYING for details.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/ssb/ssb.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/module.h>
|
||||
+
|
||||
+#include <pcmcia/cistpl.h>
|
||||
+#include <pcmcia/ciscode.h>
|
||||
+#include <pcmcia/ds.h>
|
||||
+#include <pcmcia/cisreg.h>
|
||||
+
|
||||
+#include "ssb_private.h"
|
||||
+
|
||||
+static const struct pcmcia_device_id ssb_host_pcmcia_tbl[] = {
|
||||
+ PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
|
||||
+ PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476),
|
||||
+ PCMCIA_DEVICE_NULL,
|
||||
+};
|
||||
+
|
||||
+MODULE_DEVICE_TABLE(pcmcia, ssb_host_pcmcia_tbl);
|
||||
+
|
||||
+static int ssb_host_pcmcia_probe(struct pcmcia_device *dev)
|
||||
+{
|
||||
+ struct ssb_bus *ssb;
|
||||
+ int err = -ENOMEM;
|
||||
+ int res = 0;
|
||||
+
|
||||
+ ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
|
||||
+ if (!ssb)
|
||||
+ goto out_error;
|
||||
+
|
||||
+ err = -ENODEV;
|
||||
+
|
||||
+ dev->config_flags |= CONF_ENABLE_IRQ;
|
||||
+
|
||||
+ dev->resource[2]->flags |= WIN_ENABLE | WIN_DATA_WIDTH_16 |
|
||||
+ WIN_USE_WAIT;
|
||||
+ dev->resource[2]->start = 0;
|
||||
+ dev->resource[2]->end = SSB_CORE_SIZE;
|
||||
+ res = pcmcia_request_window(dev, dev->resource[2], 250);
|
||||
+ if (res != 0)
|
||||
+ goto err_kfree_ssb;
|
||||
+
|
||||
+ res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
|
||||
+ if (res != 0)
|
||||
+ goto err_disable;
|
||||
+
|
||||
+ if (!dev->irq)
|
||||
+ goto err_disable;
|
||||
+
|
||||
+ res = pcmcia_enable_device(dev);
|
||||
+ if (res != 0)
|
||||
+ goto err_disable;
|
||||
+
|
||||
+ err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
|
||||
+ if (err)
|
||||
+ goto err_disable;
|
||||
+ dev->priv = ssb;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_disable:
|
||||
+ pcmcia_disable_device(dev);
|
||||
+err_kfree_ssb:
|
||||
+ kfree(ssb);
|
||||
+out_error:
|
||||
+ ssb_err("Initialization failed (%d, %d)\n", res, err);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static void ssb_host_pcmcia_remove(struct pcmcia_device *dev)
|
||||
+{
|
||||
+ struct ssb_bus *ssb = dev->priv;
|
||||
+
|
||||
+ ssb_bus_unregister(ssb);
|
||||
+ pcmcia_disable_device(dev);
|
||||
+ kfree(ssb);
|
||||
+ dev->priv = NULL;
|
||||
+}
|
||||
+
|
||||
+#ifdef CPTCFG_PM
|
||||
+static int ssb_host_pcmcia_suspend(struct pcmcia_device *dev)
|
||||
+{
|
||||
+ struct ssb_bus *ssb = dev->priv;
|
||||
+
|
||||
+ return ssb_bus_suspend(ssb);
|
||||
+}
|
||||
+
|
||||
+static int ssb_host_pcmcia_resume(struct pcmcia_device *dev)
|
||||
+{
|
||||
+ struct ssb_bus *ssb = dev->priv;
|
||||
+
|
||||
+ return ssb_bus_resume(ssb);
|
||||
+}
|
||||
+#else /* CPTCFG_PM */
|
||||
+# define ssb_host_pcmcia_suspend NULL
|
||||
+# define ssb_host_pcmcia_resume NULL
|
||||
+#endif /* CPTCFG_PM */
|
||||
+
|
||||
+static struct pcmcia_driver ssb_host_pcmcia_driver = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .name = "ssb-pcmcia",
|
||||
+ .id_table = ssb_host_pcmcia_tbl,
|
||||
+ .probe = ssb_host_pcmcia_probe,
|
||||
+ .remove = ssb_host_pcmcia_remove,
|
||||
+ .suspend = ssb_host_pcmcia_suspend,
|
||||
+ .resume = ssb_host_pcmcia_resume,
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * These are not module init/exit functions!
|
||||
+ * The module_pcmcia_driver() helper cannot be used here.
|
||||
+ */
|
||||
+int ssb_host_pcmcia_init(void)
|
||||
+{
|
||||
+ return pcmcia_register_driver(&ssb_host_pcmcia_driver);
|
||||
+}
|
||||
+
|
||||
+void ssb_host_pcmcia_exit(void)
|
||||
+{
|
||||
+ pcmcia_unregister_driver(&ssb_host_pcmcia_driver);
|
||||
+}
|
||||
--- a/drivers/ssb/main.c
|
||||
+++ b/drivers/ssb/main.c
|
||||
@@ -906,7 +906,6 @@ int ssb_bus_pcmciabus_register(struct ss
|
||||
|
||||
return err;
|
||||
}
|
||||
-EXPORT_SYMBOL(ssb_bus_pcmciabus_register);
|
||||
#endif /* CPTCFG_SSB_PCMCIAHOST */
|
||||
|
||||
#ifdef CPTCFG_SSB_SDIOHOST
|
||||
@@ -1474,6 +1473,12 @@ static int __init ssb_modinit(void)
|
||||
/* don't fail SSB init because of this */
|
||||
err = 0;
|
||||
}
|
||||
+ err = ssb_host_pcmcia_init();
|
||||
+ if (err) {
|
||||
+ ssb_err("PCMCIA host initialization failed\n");
|
||||
+ /* don't fail SSB init because of this */
|
||||
+ err = 0;
|
||||
+ }
|
||||
err = ssb_gige_init();
|
||||
if (err) {
|
||||
ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n");
|
||||
@@ -1491,6 +1496,7 @@ fs_initcall(ssb_modinit);
|
||||
static void __exit ssb_modexit(void)
|
||||
{
|
||||
ssb_gige_exit();
|
||||
+ ssb_host_pcmcia_exit();
|
||||
b43_pci_ssb_bridge_exit();
|
||||
bus_unregister(&ssb_bustype);
|
||||
}
|
||||
--- a/drivers/ssb/ssb_private.h
|
||||
+++ b/drivers/ssb/ssb_private.h
|
||||
@@ -94,6 +94,8 @@ extern int ssb_pcmcia_get_invariants(str
|
||||
extern int ssb_pcmcia_hardware_setup(struct ssb_bus *bus);
|
||||
extern void ssb_pcmcia_exit(struct ssb_bus *bus);
|
||||
extern int ssb_pcmcia_init(struct ssb_bus *bus);
|
||||
+extern int ssb_host_pcmcia_init(void);
|
||||
+extern void ssb_host_pcmcia_exit(void);
|
||||
extern const struct ssb_bus_ops ssb_pcmcia_ops;
|
||||
#else /* CPTCFG_SSB_PCMCIAHOST */
|
||||
static inline int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
|
||||
@@ -117,6 +119,13 @@ static inline int ssb_pcmcia_init(struct
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
+static inline int ssb_host_pcmcia_init(void)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+static inline void ssb_host_pcmcia_exit(void)
|
||||
+{
|
||||
+}
|
||||
#endif /* CPTCFG_SSB_PCMCIAHOST */
|
||||
|
||||
/* sdio.c */
|
||||
--- a/drivers/net/wireless/b43/pcmcia.c
|
||||
+++ /dev/null
|
||||
@@ -1,145 +0,0 @@
|
||||
-/*
|
||||
-
|
||||
- Broadcom B43 wireless driver
|
||||
-
|
||||
- Copyright (c) 2007 Michael Buesch <m@bues.ch>
|
||||
-
|
||||
- This program is free software; you can redistribute it and/or modify
|
||||
- it under the terms of the GNU General Public License as published by
|
||||
- the Free Software Foundation; either version 2 of the License, or
|
||||
- (at your option) any later version.
|
||||
-
|
||||
- This program is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU General Public License
|
||||
- along with this program; see the file COPYING. If not, write to
|
||||
- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
|
||||
- Boston, MA 02110-1301, USA.
|
||||
-
|
||||
-*/
|
||||
-
|
||||
-#include "pcmcia.h"
|
||||
-
|
||||
-#include <linux/ssb/ssb.h>
|
||||
-#include <linux/slab.h>
|
||||
-#include <linux/module.h>
|
||||
-
|
||||
-#include <pcmcia/cistpl.h>
|
||||
-#include <pcmcia/ciscode.h>
|
||||
-#include <pcmcia/ds.h>
|
||||
-#include <pcmcia/cisreg.h>
|
||||
-
|
||||
-
|
||||
-static const struct pcmcia_device_id b43_pcmcia_tbl[] = {
|
||||
- PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
|
||||
- PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476),
|
||||
- PCMCIA_DEVICE_NULL,
|
||||
-};
|
||||
-
|
||||
-MODULE_DEVICE_TABLE(pcmcia, b43_pcmcia_tbl);
|
||||
-
|
||||
-#ifdef CONFIG_PM
|
||||
-static int b43_pcmcia_suspend(struct pcmcia_device *dev)
|
||||
-{
|
||||
- struct ssb_bus *ssb = dev->priv;
|
||||
-
|
||||
- return ssb_bus_suspend(ssb);
|
||||
-}
|
||||
-
|
||||
-static int b43_pcmcia_resume(struct pcmcia_device *dev)
|
||||
-{
|
||||
- struct ssb_bus *ssb = dev->priv;
|
||||
-
|
||||
- return ssb_bus_resume(ssb);
|
||||
-}
|
||||
-#else /* CONFIG_PM */
|
||||
-# define b43_pcmcia_suspend NULL
|
||||
-# define b43_pcmcia_resume NULL
|
||||
-#endif /* CONFIG_PM */
|
||||
-
|
||||
-static int b43_pcmcia_probe(struct pcmcia_device *dev)
|
||||
-{
|
||||
- struct ssb_bus *ssb;
|
||||
- int err = -ENOMEM;
|
||||
- int res = 0;
|
||||
-
|
||||
- ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
|
||||
- if (!ssb)
|
||||
- goto out_error;
|
||||
-
|
||||
- err = -ENODEV;
|
||||
-
|
||||
- dev->config_flags |= CONF_ENABLE_IRQ;
|
||||
-
|
||||
- dev->resource[2]->flags |= WIN_ENABLE | WIN_DATA_WIDTH_16 |
|
||||
- WIN_USE_WAIT;
|
||||
- dev->resource[2]->start = 0;
|
||||
- dev->resource[2]->end = SSB_CORE_SIZE;
|
||||
- res = pcmcia_request_window(dev, dev->resource[2], 250);
|
||||
- if (res != 0)
|
||||
- goto err_kfree_ssb;
|
||||
-
|
||||
- res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
|
||||
- if (res != 0)
|
||||
- goto err_disable;
|
||||
-
|
||||
- if (!dev->irq)
|
||||
- goto err_disable;
|
||||
-
|
||||
- res = pcmcia_enable_device(dev);
|
||||
- if (res != 0)
|
||||
- goto err_disable;
|
||||
-
|
||||
- err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
|
||||
- if (err)
|
||||
- goto err_disable;
|
||||
- dev->priv = ssb;
|
||||
-
|
||||
- return 0;
|
||||
-
|
||||
-err_disable:
|
||||
- pcmcia_disable_device(dev);
|
||||
-err_kfree_ssb:
|
||||
- kfree(ssb);
|
||||
-out_error:
|
||||
- printk(KERN_ERR "b43-pcmcia: Initialization failed (%d, %d)\n",
|
||||
- res, err);
|
||||
- return err;
|
||||
-}
|
||||
-
|
||||
-static void b43_pcmcia_remove(struct pcmcia_device *dev)
|
||||
-{
|
||||
- struct ssb_bus *ssb = dev->priv;
|
||||
-
|
||||
- ssb_bus_unregister(ssb);
|
||||
- pcmcia_disable_device(dev);
|
||||
- kfree(ssb);
|
||||
- dev->priv = NULL;
|
||||
-}
|
||||
-
|
||||
-static struct pcmcia_driver b43_pcmcia_driver = {
|
||||
- .owner = THIS_MODULE,
|
||||
- .name = "b43-pcmcia",
|
||||
- .id_table = b43_pcmcia_tbl,
|
||||
- .probe = b43_pcmcia_probe,
|
||||
- .remove = b43_pcmcia_remove,
|
||||
- .suspend = b43_pcmcia_suspend,
|
||||
- .resume = b43_pcmcia_resume,
|
||||
-};
|
||||
-
|
||||
-/*
|
||||
- * These are not module init/exit functions!
|
||||
- * The module_pcmcia_driver() helper cannot be used here.
|
||||
- */
|
||||
-int b43_pcmcia_init(void)
|
||||
-{
|
||||
- return pcmcia_register_driver(&b43_pcmcia_driver);
|
||||
-}
|
||||
-
|
||||
-void b43_pcmcia_exit(void)
|
||||
-{
|
||||
- pcmcia_unregister_driver(&b43_pcmcia_driver);
|
||||
-}
|
@ -0,0 +1,686 @@ |
||||
--- a/arch/mips/bcm47xx/Kconfig
|
||||
+++ b/arch/mips/bcm47xx/Kconfig
|
||||
@@ -4,6 +4,7 @@ config BCM47XX_SSB
|
||||
bool "SSB Support for Broadcom BCM47XX"
|
||||
select SYS_HAS_CPU_BMIPS32_3300
|
||||
select SSB
|
||||
+ select SSB_HOST_SOC
|
||||
select SSB_DRIVER_MIPS
|
||||
select SSB_DRIVER_EXTIF
|
||||
select SSB_EMBEDDED
|
||||
--- a/drivers/ssb/Kconfig
|
||||
+++ b/drivers/ssb/Kconfig
|
||||
@@ -80,6 +80,15 @@ config SSB_SDIOHOST
|
||||
|
||||
If unsure, say N
|
||||
|
||||
+config SSB_HOST_SOC
|
||||
+ bool "Support for SSB bus on SoC"
|
||||
+ depends on SSB
|
||||
+ help
|
||||
+ Host interface for a SSB directly mapped into memory. This is
|
||||
+ for some Broadcom SoCs from the BCM47xx and BCM53xx lines.
|
||||
+
|
||||
+ If unsure, say N
|
||||
+
|
||||
config SSB_SILENT
|
||||
bool "No SSB kernel messages"
|
||||
depends on SSB && EXPERT
|
||||
--- a/drivers/ssb/Makefile
|
||||
+++ b/drivers/ssb/Makefile
|
||||
@@ -5,8 +5,9 @@ ssb-$(CONFIG_SSB_SPROM) += sprom.o
|
||||
|
||||
# host support
|
||||
ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o
|
||||
-ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o
|
||||
+ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o bridge_pcmcia_80211.o
|
||||
ssb-$(CONFIG_SSB_SDIOHOST) += sdio.o
|
||||
+ssb-$(CONFIG_SSB_HOST_SOC) += host_soc.o
|
||||
|
||||
# built-in drivers
|
||||
ssb-y += driver_chipcommon.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/ssb/bridge_pcmcia_80211.c
|
||||
@@ -0,0 +1,128 @@
|
||||
+/*
|
||||
+ * Broadcom 43xx PCMCIA-SSB bridge module
|
||||
+ *
|
||||
+ * Copyright (c) 2007 Michael Buesch <m@bues.ch>
|
||||
+ *
|
||||
+ * Licensed under the GNU/GPL. See COPYING for details.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/ssb/ssb.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/module.h>
|
||||
+
|
||||
+#include <pcmcia/cistpl.h>
|
||||
+#include <pcmcia/ciscode.h>
|
||||
+#include <pcmcia/ds.h>
|
||||
+#include <pcmcia/cisreg.h>
|
||||
+
|
||||
+#include "ssb_private.h"
|
||||
+
|
||||
+static const struct pcmcia_device_id ssb_host_pcmcia_tbl[] = {
|
||||
+ PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
|
||||
+ PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476),
|
||||
+ PCMCIA_DEVICE_NULL,
|
||||
+};
|
||||
+
|
||||
+MODULE_DEVICE_TABLE(pcmcia, ssb_host_pcmcia_tbl);
|
||||
+
|
||||
+static int ssb_host_pcmcia_probe(struct pcmcia_device *dev)
|
||||
+{
|
||||
+ struct ssb_bus *ssb;
|
||||
+ int err = -ENOMEM;
|
||||
+ int res = 0;
|
||||
+
|
||||
+ ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
|
||||
+ if (!ssb)
|
||||
+ goto out_error;
|
||||
+
|
||||
+ err = -ENODEV;
|
||||
+
|
||||
+ dev->config_flags |= CONF_ENABLE_IRQ;
|
||||
+
|
||||
+ dev->resource[2]->flags |= WIN_ENABLE | WIN_DATA_WIDTH_16 |
|
||||
+ WIN_USE_WAIT;
|
||||
+ dev->resource[2]->start = 0;
|
||||
+ dev->resource[2]->end = SSB_CORE_SIZE;
|
||||
+ res = pcmcia_request_window(dev, dev->resource[2], 250);
|
||||
+ if (res != 0)
|
||||
+ goto err_kfree_ssb;
|
||||
+
|
||||
+ res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
|
||||
+ if (res != 0)
|
||||
+ goto err_disable;
|
||||
+
|
||||
+ if (!dev->irq)
|
||||
+ goto err_disable;
|
||||
+
|
||||
+ res = pcmcia_enable_device(dev);
|
||||
+ if (res != 0)
|
||||
+ goto err_disable;
|
||||
+
|
||||
+ err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
|
||||
+ if (err)
|
||||
+ goto err_disable;
|
||||
+ dev->priv = ssb;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_disable:
|
||||
+ pcmcia_disable_device(dev);
|
||||
+err_kfree_ssb:
|
||||
+ kfree(ssb);
|
||||
+out_error:
|
||||
+ ssb_err("Initialization failed (%d, %d)\n", res, err);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static void ssb_host_pcmcia_remove(struct pcmcia_device *dev)
|
||||
+{
|
||||
+ struct ssb_bus *ssb = dev->priv;
|
||||
+
|
||||
+ ssb_bus_unregister(ssb);
|
||||
+ pcmcia_disable_device(dev);
|
||||
+ kfree(ssb);
|
||||
+ dev->priv = NULL;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_PM
|
||||
+static int ssb_host_pcmcia_suspend(struct pcmcia_device *dev)
|
||||
+{
|
||||
+ struct ssb_bus *ssb = dev->priv;
|
||||
+
|
||||
+ return ssb_bus_suspend(ssb);
|
||||
+}
|
||||
+
|
||||
+static int ssb_host_pcmcia_resume(struct pcmcia_device *dev)
|
||||
+{
|
||||
+ struct ssb_bus *ssb = dev->priv;
|
||||
+
|
||||
+ return ssb_bus_resume(ssb);
|
||||
+}
|
||||
+#else /* CONFIG_PM */
|
||||
+# define ssb_host_pcmcia_suspend NULL
|
||||
+# define ssb_host_pcmcia_resume NULL
|
||||
+#endif /* CONFIG_PM */
|
||||
+
|
||||
+static struct pcmcia_driver ssb_host_pcmcia_driver = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .name = "ssb-pcmcia",
|
||||
+ .id_table = ssb_host_pcmcia_tbl,
|
||||
+ .probe = ssb_host_pcmcia_probe,
|
||||
+ .remove = ssb_host_pcmcia_remove,
|
||||
+ .suspend = ssb_host_pcmcia_suspend,
|
||||
+ .resume = ssb_host_pcmcia_resume,
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * These are not module init/exit functions!
|
||||
+ * The module_pcmcia_driver() helper cannot be used here.
|
||||
+ */
|
||||
+int ssb_host_pcmcia_init(void)
|
||||
+{
|
||||
+ return pcmcia_register_driver(&ssb_host_pcmcia_driver);
|
||||
+}
|
||||
+
|
||||
+void ssb_host_pcmcia_exit(void)
|
||||
+{
|
||||
+ pcmcia_unregister_driver(&ssb_host_pcmcia_driver);
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/drivers/ssb/host_soc.c
|
||||
@@ -0,0 +1,173 @@
|
||||
+/*
|
||||
+ * Sonics Silicon Backplane SoC host related functions.
|
||||
+ * Subsystem core
|
||||
+ *
|
||||
+ * Copyright 2005, Broadcom Corporation
|
||||
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
|
||||
+ *
|
||||
+ * Licensed under the GNU/GPL. See COPYING for details.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/ssb/ssb.h>
|
||||
+
|
||||
+#include "ssb_private.h"
|
||||
+
|
||||
+static u8 ssb_host_soc_read8(struct ssb_device *dev, u16 offset)
|
||||
+{
|
||||
+ struct ssb_bus *bus = dev->bus;
|
||||
+
|
||||
+ offset += dev->core_index * SSB_CORE_SIZE;
|
||||
+ return readb(bus->mmio + offset);
|
||||
+}
|
||||
+
|
||||
+static u16 ssb_host_soc_read16(struct ssb_device *dev, u16 offset)
|
||||
+{
|
||||
+ struct ssb_bus *bus = dev->bus;
|
||||
+
|
||||
+ offset += dev->core_index * SSB_CORE_SIZE;
|
||||
+ return readw(bus->mmio + offset);
|
||||
+}
|
||||
+
|
||||
+static u32 ssb_host_soc_read32(struct ssb_device *dev, u16 offset)
|
||||
+{
|
||||
+ struct ssb_bus *bus = dev->bus;
|
||||
+
|
||||
+ offset += dev->core_index * SSB_CORE_SIZE;
|
||||
+ return readl(bus->mmio + offset);
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_SSB_BLOCKIO
|
||||
+static void ssb_host_soc_block_read(struct ssb_device *dev, void *buffer,
|
||||
+ size_t count, u16 offset, u8 reg_width)
|
||||
+{
|
||||
+ struct ssb_bus *bus = dev->bus;
|
||||
+ void __iomem *addr;
|
||||
+
|
||||
+ offset += dev->core_index * SSB_CORE_SIZE;
|
||||
+ addr = bus->mmio + offset;
|
||||
+
|
||||
+ switch (reg_width) {
|
||||
+ case sizeof(u8): {
|
||||
+ u8 *buf = buffer;
|
||||
+
|
||||
+ while (count) {
|
||||
+ *buf = __raw_readb(addr);
|
||||
+ buf++;
|
||||
+ count--;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ case sizeof(u16): {
|
||||
+ __le16 *buf = buffer;
|
||||
+
|
||||
+ SSB_WARN_ON(count & 1);
|
||||
+ while (count) {
|
||||
+ *buf = (__force __le16)__raw_readw(addr);
|
||||
+ buf++;
|
||||
+ count -= 2;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ case sizeof(u32): {
|
||||
+ __le32 *buf = buffer;
|
||||
+
|
||||
+ SSB_WARN_ON(count & 3);
|
||||
+ while (count) {
|
||||
+ *buf = (__force __le32)__raw_readl(addr);
|
||||
+ buf++;
|
||||
+ count -= 4;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ default:
|
||||
+ SSB_WARN_ON(1);
|
||||
+ }
|
||||
+}
|
||||
+#endif /* CONFIG_SSB_BLOCKIO */
|
||||
+
|
||||
+static void ssb_host_soc_write8(struct ssb_device *dev, u16 offset, u8 value)
|
||||
+{
|
||||
+ struct ssb_bus *bus = dev->bus;
|
||||
+
|
||||
+ offset += dev->core_index * SSB_CORE_SIZE;
|
||||
+ writeb(value, bus->mmio + offset);
|
||||
+}
|
||||
+
|
||||
+static void ssb_host_soc_write16(struct ssb_device *dev, u16 offset, u16 value)
|
||||
+{
|
||||
+ struct ssb_bus *bus = dev->bus;
|
||||
+
|
||||
+ offset += dev->core_index * SSB_CORE_SIZE;
|
||||
+ writew(value, bus->mmio + offset);
|
||||
+}
|
||||
+
|
||||
+static void ssb_host_soc_write32(struct ssb_device *dev, u16 offset, u32 value)
|
||||
+{
|
||||
+ struct ssb_bus *bus = dev->bus;
|
||||
+
|
||||
+ offset += dev->core_index * SSB_CORE_SIZE;
|
||||
+ writel(value, bus->mmio + offset);
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_SSB_BLOCKIO
|
||||
+static void ssb_host_soc_block_write(struct ssb_device *dev, const void *buffer,
|
||||
+ size_t count, u16 offset, u8 reg_width)
|
||||
+{
|
||||
+ struct ssb_bus *bus = dev->bus;
|
||||
+ void __iomem *addr;
|
||||
+
|
||||
+ offset += dev->core_index * SSB_CORE_SIZE;
|
||||
+ addr = bus->mmio + offset;
|
||||
+
|
||||
+ switch (reg_width) {
|
||||
+ case sizeof(u8): {
|
||||
+ const u8 *buf = buffer;
|
||||
+
|
||||
+ while (count) {
|
||||
+ __raw_writeb(*buf, addr);
|
||||
+ buf++;
|
||||
+ count--;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ case sizeof(u16): {
|
||||
+ const __le16 *buf = buffer;
|
||||
+
|
||||
+ SSB_WARN_ON(count & 1);
|
||||
+ while (count) {
|
||||
+ __raw_writew((__force u16)(*buf), addr);
|
||||
+ buf++;
|
||||
+ count -= 2;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ case sizeof(u32): {
|
||||
+ const __le32 *buf = buffer;
|
||||
+
|
||||
+ SSB_WARN_ON(count & 3);
|
||||
+ while (count) {
|
||||
+ __raw_writel((__force u32)(*buf), addr);
|
||||
+ buf++;
|
||||
+ count -= 4;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ default:
|
||||
+ SSB_WARN_ON(1);
|
||||
+ }
|
||||
+}
|
||||
+#endif /* CONFIG_SSB_BLOCKIO */
|
||||
+
|
||||
+/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
|
||||
+const struct ssb_bus_ops ssb_host_soc_ops = {
|
||||
+ .read8 = ssb_host_soc_read8,
|
||||
+ .read16 = ssb_host_soc_read16,
|
||||
+ .read32 = ssb_host_soc_read32,
|
||||
+ .write8 = ssb_host_soc_write8,
|
||||
+ .write16 = ssb_host_soc_write16,
|
||||
+ .write32 = ssb_host_soc_write32,
|
||||
+#ifdef CONFIG_SSB_BLOCKIO
|
||||
+ .block_read = ssb_host_soc_block_read,
|
||||
+ .block_write = ssb_host_soc_block_write,
|
||||
+#endif
|
||||
+};
|
||||
--- a/drivers/ssb/main.c
|
||||
+++ b/drivers/ssb/main.c
|
||||
@@ -596,166 +596,6 @@ error:
|
||||
return err;
|
||||
}
|
||||
|
||||
-static u8 ssb_ssb_read8(struct ssb_device *dev, u16 offset)
|
||||
-{
|
||||
- struct ssb_bus *bus = dev->bus;
|
||||
-
|
||||
- offset += dev->core_index * SSB_CORE_SIZE;
|
||||
- return readb(bus->mmio + offset);
|
||||
-}
|
||||
-
|
||||
-static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset)
|
||||
-{
|
||||
- struct ssb_bus *bus = dev->bus;
|
||||
-
|
||||
- offset += dev->core_index * SSB_CORE_SIZE;
|
||||
- return readw(bus->mmio + offset);
|
||||
-}
|
||||
-
|
||||
-static u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset)
|
||||
-{
|
||||
- struct ssb_bus *bus = dev->bus;
|
||||
-
|
||||
- offset += dev->core_index * SSB_CORE_SIZE;
|
||||
- return readl(bus->mmio + offset);
|
||||
-}
|
||||
-
|
||||
-#ifdef CONFIG_SSB_BLOCKIO
|
||||
-static void ssb_ssb_block_read(struct ssb_device *dev, void *buffer,
|
||||
- size_t count, u16 offset, u8 reg_width)
|
||||
-{
|
||||
- struct ssb_bus *bus = dev->bus;
|
||||
- void __iomem *addr;
|
||||
-
|
||||
- offset += dev->core_index * SSB_CORE_SIZE;
|
||||
- addr = bus->mmio + offset;
|
||||
-
|
||||
- switch (reg_width) {
|
||||
- case sizeof(u8): {
|
||||
- u8 *buf = buffer;
|
||||
-
|
||||
- while (count) {
|
||||
- *buf = __raw_readb(addr);
|
||||
- buf++;
|
||||
- count--;
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- case sizeof(u16): {
|
||||
- __le16 *buf = buffer;
|
||||
-
|
||||
- SSB_WARN_ON(count & 1);
|
||||
- while (count) {
|
||||
- *buf = (__force __le16)__raw_readw(addr);
|
||||
- buf++;
|
||||
- count -= 2;
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- case sizeof(u32): {
|
||||
- __le32 *buf = buffer;
|
||||
-
|
||||
- SSB_WARN_ON(count & 3);
|
||||
- while (count) {
|
||||
- *buf = (__force __le32)__raw_readl(addr);
|
||||
- buf++;
|
||||
- count -= 4;
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- default:
|
||||
- SSB_WARN_ON(1);
|
||||
- }
|
||||
-}
|
||||
-#endif /* CONFIG_SSB_BLOCKIO */
|
||||
-
|
||||
-static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
|
||||
-{
|
||||
- struct ssb_bus *bus = dev->bus;
|
||||
-
|
||||
- offset += dev->core_index * SSB_CORE_SIZE;
|
||||
- writeb(value, bus->mmio + offset);
|
||||
-}
|
||||
-
|
||||
-static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value)
|
||||
-{
|
||||
- struct ssb_bus *bus = dev->bus;
|
||||
-
|
||||
- offset += dev->core_index * SSB_CORE_SIZE;
|
||||
- writew(value, bus->mmio + offset);
|
||||
-}
|
||||
-
|
||||
-static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value)
|
||||
-{
|
||||
- struct ssb_bus *bus = dev->bus;
|
||||
-
|
||||
- offset += dev->core_index * SSB_CORE_SIZE;
|
||||
- writel(value, bus->mmio + offset);
|
||||
-}
|
||||
-
|
||||
-#ifdef CONFIG_SSB_BLOCKIO
|
||||
-static void ssb_ssb_block_write(struct ssb_device *dev, const void *buffer,
|
||||
- size_t count, u16 offset, u8 reg_width)
|
||||
-{
|
||||
- struct ssb_bus *bus = dev->bus;
|
||||
- void __iomem *addr;
|
||||
-
|
||||
- offset += dev->core_index * SSB_CORE_SIZE;
|
||||
- addr = bus->mmio + offset;
|
||||
-
|
||||
- switch (reg_width) {
|
||||
- case sizeof(u8): {
|
||||
- const u8 *buf = buffer;
|
||||
-
|
||||
- while (count) {
|
||||
- __raw_writeb(*buf, addr);
|
||||
- buf++;
|
||||
- count--;
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- case sizeof(u16): {
|
||||
- const __le16 *buf = buffer;
|
||||
-
|
||||
- SSB_WARN_ON(count & 1);
|
||||
- while (count) {
|
||||
- __raw_writew((__force u16)(*buf), addr);
|
||||
- buf++;
|
||||
- count -= 2;
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- case sizeof(u32): {
|
||||
- const __le32 *buf = buffer;
|
||||
-
|
||||
- SSB_WARN_ON(count & 3);
|
||||
- while (count) {
|
||||
- __raw_writel((__force u32)(*buf), addr);
|
||||
- buf++;
|
||||
- count -= 4;
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- default:
|
||||
- SSB_WARN_ON(1);
|
||||
- }
|
||||
-}
|
||||
-#endif /* CONFIG_SSB_BLOCKIO */
|
||||
-
|
||||
-/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
|
||||
-static const struct ssb_bus_ops ssb_ssb_ops = {
|
||||
- .read8 = ssb_ssb_read8,
|
||||
- .read16 = ssb_ssb_read16,
|
||||
- .read32 = ssb_ssb_read32,
|
||||
- .write8 = ssb_ssb_write8,
|
||||
- .write16 = ssb_ssb_write16,
|
||||
- .write32 = ssb_ssb_write32,
|
||||
-#ifdef CONFIG_SSB_BLOCKIO
|
||||
- .block_read = ssb_ssb_block_read,
|
||||
- .block_write = ssb_ssb_block_write,
|
||||
-#endif
|
||||
-};
|
||||
-
|
||||
static int ssb_fetch_invariants(struct ssb_bus *bus,
|
||||
ssb_invariants_func_t get_invariants)
|
||||
{
|
||||
@@ -876,7 +716,6 @@ int ssb_bus_pcibus_register(struct ssb_b
|
||||
|
||||
return err;
|
||||
}
|
||||
-EXPORT_SYMBOL(ssb_bus_pcibus_register);
|
||||
#endif /* CONFIG_SSB_PCIHOST */
|
||||
|
||||
#ifdef CONFIG_SSB_PCMCIAHOST
|
||||
@@ -898,7 +737,6 @@ int ssb_bus_pcmciabus_register(struct ss
|
||||
|
||||
return err;
|
||||
}
|
||||
-EXPORT_SYMBOL(ssb_bus_pcmciabus_register);
|
||||
#endif /* CONFIG_SSB_PCMCIAHOST */
|
||||
|
||||
#ifdef CONFIG_SSB_SDIOHOST
|
||||
@@ -923,13 +761,14 @@ int ssb_bus_sdiobus_register(struct ssb_
|
||||
EXPORT_SYMBOL(ssb_bus_sdiobus_register);
|
||||
#endif /* CONFIG_SSB_PCMCIAHOST */
|
||||
|
||||
+#ifdef CONFIG_SSB_HOST_SOC
|
||||
int ssb_bus_ssbbus_register(struct ssb_bus *bus, unsigned long baseaddr,
|
||||
ssb_invariants_func_t get_invariants)
|
||||
{
|
||||
int err;
|
||||
|
||||
bus->bustype = SSB_BUSTYPE_SSB;
|
||||
- bus->ops = &ssb_ssb_ops;
|
||||
+ bus->ops = &ssb_host_soc_ops;
|
||||
|
||||
err = ssb_bus_register(bus, get_invariants, baseaddr);
|
||||
if (!err) {
|
||||
@@ -939,6 +778,7 @@ int ssb_bus_ssbbus_register(struct ssb_b
|
||||
|
||||
return err;
|
||||
}
|
||||
+#endif
|
||||
|
||||
int __ssb_driver_register(struct ssb_driver *drv, struct module *owner)
|
||||
{
|
||||
@@ -1465,6 +1305,12 @@ static int __init ssb_modinit(void)
|
||||
/* don't fail SSB init because of this */
|
||||
err = 0;
|
||||
}
|
||||
+ err = ssb_host_pcmcia_init();
|
||||
+ if (err) {
|
||||
+ ssb_err("PCMCIA host initialization failed\n");
|
||||
+ /* don't fail SSB init because of this */
|
||||
+ err = 0;
|
||||
+ }
|
||||
err = ssb_gige_init();
|
||||
if (err) {
|
||||
ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n");
|
||||
@@ -1482,6 +1328,7 @@ fs_initcall(ssb_modinit);
|
||||
static void __exit ssb_modexit(void)
|
||||
{
|
||||
ssb_gige_exit();
|
||||
+ ssb_host_pcmcia_exit();
|
||||
b43_pci_ssb_bridge_exit();
|
||||
bus_unregister(&ssb_bustype);
|
||||
}
|
||||
--- a/drivers/ssb/pcmcia.c
|
||||
+++ b/drivers/ssb/pcmcia.c
|
||||
@@ -147,8 +147,7 @@ error:
|
||||
return err;
|
||||
}
|
||||
|
||||
-int ssb_pcmcia_switch_core(struct ssb_bus *bus,
|
||||
- struct ssb_device *dev)
|
||||
+static int ssb_pcmcia_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
--- a/drivers/ssb/sdio.c
|
||||
+++ b/drivers/ssb/sdio.c
|
||||
@@ -200,7 +200,7 @@ out:
|
||||
}
|
||||
|
||||
/* host must be already claimed */
|
||||
-int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
|
||||
+static int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
|
||||
{
|
||||
u8 coreidx = dev->core_index;
|
||||
u32 sbaddr;
|
||||
--- a/drivers/ssb/ssb_private.h
|
||||
+++ b/drivers/ssb/ssb_private.h
|
||||
@@ -85,8 +85,6 @@ static inline int ssb_pci_init(struct ss
|
||||
|
||||
/* pcmcia.c */
|
||||
#ifdef CONFIG_SSB_PCMCIAHOST
|
||||
-extern int ssb_pcmcia_switch_core(struct ssb_bus *bus,
|
||||
- struct ssb_device *dev);
|
||||
extern int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
|
||||
u8 coreidx);
|
||||
extern int ssb_pcmcia_switch_segment(struct ssb_bus *bus,
|
||||
@@ -96,13 +94,10 @@ extern int ssb_pcmcia_get_invariants(str
|
||||
extern int ssb_pcmcia_hardware_setup(struct ssb_bus *bus);
|
||||
extern void ssb_pcmcia_exit(struct ssb_bus *bus);
|
||||
extern int ssb_pcmcia_init(struct ssb_bus *bus);
|
||||
+extern int ssb_host_pcmcia_init(void);
|
||||
+extern void ssb_host_pcmcia_exit(void);
|
||||
extern const struct ssb_bus_ops ssb_pcmcia_ops;
|
||||
#else /* CONFIG_SSB_PCMCIAHOST */
|
||||
-static inline int ssb_pcmcia_switch_core(struct ssb_bus *bus,
|
||||
- struct ssb_device *dev)
|
||||
-{
|
||||
- return 0;
|
||||
-}
|
||||
static inline int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
|
||||
u8 coreidx)
|
||||
{
|
||||
@@ -124,6 +119,13 @@ static inline int ssb_pcmcia_init(struct
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
+static inline int ssb_host_pcmcia_init(void)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+static inline void ssb_host_pcmcia_exit(void)
|
||||
+{
|
||||
+}
|
||||
#endif /* CONFIG_SSB_PCMCIAHOST */
|
||||
|
||||
/* sdio.c */
|
||||
@@ -132,9 +134,7 @@ extern int ssb_sdio_get_invariants(struc
|
||||
struct ssb_init_invariants *iv);
|
||||
|
||||
extern u32 ssb_sdio_scan_read32(struct ssb_bus *bus, u16 offset);
|
||||
-extern int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev);
|
||||
extern int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx);
|
||||
-extern int ssb_sdio_hardware_setup(struct ssb_bus *bus);
|
||||
extern void ssb_sdio_exit(struct ssb_bus *bus);
|
||||
extern int ssb_sdio_init(struct ssb_bus *bus);
|
||||
|
||||
@@ -144,19 +144,10 @@ static inline u32 ssb_sdio_scan_read32(s
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
-static inline int ssb_sdio_switch_core(struct ssb_bus *bus,
|
||||
- struct ssb_device *dev)
|
||||
-{
|
||||
- return 0;
|
||||
-}
|
||||
static inline int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
-static inline int ssb_sdio_hardware_setup(struct ssb_bus *bus)
|
||||
-{
|
||||
- return 0;
|
||||
-}
|
||||
static inline void ssb_sdio_exit(struct ssb_bus *bus)
|
||||
{
|
||||
}
|
||||
@@ -166,6 +157,13 @@ static inline int ssb_sdio_init(struct s
|
||||
}
|
||||
#endif /* CONFIG_SSB_SDIOHOST */
|
||||
|
||||
+/**************************************************
|
||||
+ * host_soc.c
|
||||
+ **************************************************/
|
||||
+
|
||||
+#ifdef CONFIG_SSB_HOST_SOC
|
||||
+extern const struct ssb_bus_ops ssb_host_soc_ops;
|
||||
+#endif
|
||||
|
||||
/* scan.c */
|
||||
extern const char *ssb_core_name(u16 coreid);
|
@ -0,0 +1,686 @@ |
||||
--- a/arch/mips/bcm47xx/Kconfig
|
||||
+++ b/arch/mips/bcm47xx/Kconfig
|
||||
@@ -4,6 +4,7 @@ config BCM47XX_SSB
|
||||
bool "SSB Support for Broadcom BCM47XX"
|
||||
select SYS_HAS_CPU_BMIPS32_3300
|
||||
select SSB
|
||||
+ select SSB_HOST_SOC
|
||||
select SSB_DRIVER_MIPS
|
||||
select SSB_DRIVER_EXTIF
|
||||
select SSB_EMBEDDED
|
||||
--- a/drivers/ssb/Kconfig
|
||||
+++ b/drivers/ssb/Kconfig
|
||||
@@ -80,6 +80,15 @@ config SSB_SDIOHOST
|
||||
|
||||
If unsure, say N
|
||||
|
||||
+config SSB_HOST_SOC
|
||||
+ bool "Support for SSB bus on SoC"
|
||||
+ depends on SSB
|
||||
+ help
|
||||
+ Host interface for a SSB directly mapped into memory. This is
|
||||
+ for some Broadcom SoCs from the BCM47xx and BCM53xx lines.
|
||||
+
|
||||
+ If unsure, say N
|
||||
+
|
||||
config SSB_SILENT
|
||||
bool "No SSB kernel messages"
|
||||
depends on SSB && EXPERT
|
||||
--- a/drivers/ssb/Makefile
|
||||
+++ b/drivers/ssb/Makefile
|
||||
@@ -5,8 +5,9 @@ ssb-$(CONFIG_SSB_SPROM) += sprom.o
|
||||
|
||||
# host support
|
||||
ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o
|
||||
-ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o
|
||||
+ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o bridge_pcmcia_80211.o
|
||||
ssb-$(CONFIG_SSB_SDIOHOST) += sdio.o
|
||||
+ssb-$(CONFIG_SSB_HOST_SOC) += host_soc.o
|
||||
|
||||
# built-in drivers
|
||||
ssb-y += driver_chipcommon.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/ssb/bridge_pcmcia_80211.c
|
||||
@@ -0,0 +1,128 @@
|
||||
+/*
|
||||
+ * Broadcom 43xx PCMCIA-SSB bridge module
|
||||
+ *
|
||||
+ * Copyright (c) 2007 Michael Buesch <m@bues.ch>
|
||||
+ *
|
||||
+ * Licensed under the GNU/GPL. See COPYING for details.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/ssb/ssb.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/module.h>
|
||||
+
|
||||
+#include <pcmcia/cistpl.h>
|
||||
+#include <pcmcia/ciscode.h>
|
||||
+#include <pcmcia/ds.h>
|
||||
+#include <pcmcia/cisreg.h>
|
||||
+
|
||||
+#include "ssb_private.h"
|
||||
+
|
||||
+static const struct pcmcia_device_id ssb_host_pcmcia_tbl[] = {
|
||||
+ PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
|
||||
+ PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476),
|
||||
+ PCMCIA_DEVICE_NULL,
|
||||
+};
|
||||
+
|
||||
+MODULE_DEVICE_TABLE(pcmcia, ssb_host_pcmcia_tbl);
|
||||
+
|
||||
+static int ssb_host_pcmcia_probe(struct pcmcia_device *dev)
|
||||
+{
|
||||
+ struct ssb_bus *ssb;
|
||||
+ int err = -ENOMEM;
|
||||
+ int res = 0;
|
||||
+
|
||||
+ ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
|
||||
+ if (!ssb)
|
||||
+ goto out_error;
|
||||
+
|
||||
+ err = -ENODEV;
|
||||
+
|
||||
+ dev->config_flags |= CONF_ENABLE_IRQ;
|
||||
+
|
||||
+ dev->resource[2]->flags |= WIN_ENABLE | WIN_DATA_WIDTH_16 |
|
||||
+ WIN_USE_WAIT;
|
||||
+ dev->resource[2]->start = 0;
|
||||
+ dev->resource[2]->end = SSB_CORE_SIZE;
|
||||
+ res = pcmcia_request_window(dev, dev->resource[2], 250);
|
||||
+ if (res != 0)
|
||||
+ goto err_kfree_ssb;
|
||||
+
|
||||
+ res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
|
||||
+ if (res != 0)
|
||||
+ goto err_disable;
|
||||
+
|
||||
+ if (!dev->irq)
|
||||
+ goto err_disable;
|
||||
+
|
||||
+ res = pcmcia_enable_device(dev);
|
||||
+ if (res != 0)
|
||||
+ goto err_disable;
|
||||
+
|
||||
+ err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
|
||||
+ if (err)
|
||||
+ goto err_disable;
|
||||
+ dev->priv = ssb;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_disable:
|
||||
+ pcmcia_disable_device(dev);
|
||||
+err_kfree_ssb:
|
||||
+ kfree(ssb);
|
||||
+out_error:
|
||||
+ ssb_err("Initialization failed (%d, %d)\n", res, err);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static void ssb_host_pcmcia_remove(struct pcmcia_device *dev)
|
||||
+{
|
||||
+ struct ssb_bus *ssb = dev->priv;
|
||||
+
|
||||
+ ssb_bus_unregister(ssb);
|
||||
+ pcmcia_disable_device(dev);
|
||||
+ kfree(ssb);
|
||||
+ dev->priv = NULL;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_PM
|
||||
+static int ssb_host_pcmcia_suspend(struct pcmcia_device *dev)
|
||||
+{
|
||||
+ struct ssb_bus *ssb = dev->priv;
|
||||
+
|
||||
+ return ssb_bus_suspend(ssb);
|
||||
+}
|
||||
+
|
||||
+static int ssb_host_pcmcia_resume(struct pcmcia_device *dev)
|
||||
+{
|
||||
+ struct ssb_bus *ssb = dev->priv;
|
||||
+
|
||||
+ return ssb_bus_resume(ssb);
|
||||
+}
|
||||
+#else /* CONFIG_PM */
|
||||
+# define ssb_host_pcmcia_suspend NULL
|
||||
+# define ssb_host_pcmcia_resume NULL
|
||||
+#endif /* CONFIG_PM */
|
||||
+
|
||||
+static struct pcmcia_driver ssb_host_pcmcia_driver = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .name = "ssb-pcmcia",
|
||||
+ .id_table = ssb_host_pcmcia_tbl,
|
||||
+ .probe = ssb_host_pcmcia_probe,
|
||||
+ .remove = ssb_host_pcmcia_remove,
|
||||
+ .suspend = ssb_host_pcmcia_suspend,
|
||||
+ .resume = ssb_host_pcmcia_resume,
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * These are not module init/exit functions!
|
||||
+ * The module_pcmcia_driver() helper cannot be used here.
|
||||
+ */
|
||||
+int ssb_host_pcmcia_init(void)
|
||||
+{
|
||||
+ return pcmcia_register_driver(&ssb_host_pcmcia_driver);
|
||||
+}
|
||||
+
|
||||
+void ssb_host_pcmcia_exit(void)
|
||||
+{
|
||||
+ pcmcia_unregister_driver(&ssb_host_pcmcia_driver);
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/drivers/ssb/host_soc.c
|
||||
@@ -0,0 +1,173 @@
|
||||
+/*
|
||||
+ * Sonics Silicon Backplane SoC host related functions.
|
||||
+ * Subsystem core
|
||||
+ *
|
||||
+ * Copyright 2005, Broadcom Corporation
|
||||
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
|
||||
+ *
|
||||
+ * Licensed under the GNU/GPL. See COPYING for details.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/ssb/ssb.h>
|
||||
+
|
||||
+#include "ssb_private.h"
|
||||
+
|
||||
+static u8 ssb_host_soc_read8(struct ssb_device *dev, u16 offset)
|
||||
+{
|
||||
+ struct ssb_bus *bus = dev->bus;
|
||||
+
|
||||
+ offset += dev->core_index * SSB_CORE_SIZE;
|
||||
+ return readb(bus->mmio + offset);
|
||||
+}
|
||||
+
|
||||
+static u16 ssb_host_soc_read16(struct ssb_device *dev, u16 offset)
|
||||
+{
|
||||
+ struct ssb_bus *bus = dev->bus;
|
||||
+
|
||||
+ offset += dev->core_index * SSB_CORE_SIZE;
|
||||
+ return readw(bus->mmio + offset);
|
||||
+}
|
||||
+
|
||||
+static u32 ssb_host_soc_read32(struct ssb_device *dev, u16 offset)
|
||||
+{
|
||||
+ struct ssb_bus *bus = dev->bus;
|
||||
+
|
||||
+ offset += dev->core_index * SSB_CORE_SIZE;
|
||||
+ return readl(bus->mmio + offset);
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_SSB_BLOCKIO
|
||||
+static void ssb_host_soc_block_read(struct ssb_device *dev, void *buffer,
|
||||
+ size_t count, u16 offset, u8 reg_width)
|
||||
+{
|
||||
+ struct ssb_bus *bus = dev->bus;
|
||||
+ void __iomem *addr;
|
||||
+
|
||||
+ offset += dev->core_index * SSB_CORE_SIZE;
|
||||
+ addr = bus->mmio + offset;
|
||||
+
|
||||
+ switch (reg_width) {
|
||||
+ case sizeof(u8): {
|
||||
+ u8 *buf = buffer;
|
||||
+
|
||||
+ while (count) {
|
||||
+ *buf = __raw_readb(addr);
|
||||
+ buf++;
|
||||
+ count--;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ case sizeof(u16): {
|
||||
+ __le16 *buf = buffer;
|
||||
+
|
||||
+ SSB_WARN_ON(count & 1);
|
||||
+ while (count) {
|
||||
+ *buf = (__force __le16)__raw_readw(addr);
|
||||
+ buf++;
|
||||
+ count -= 2;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ case sizeof(u32): {
|
||||
+ __le32 *buf = buffer;
|
||||
+
|
||||
+ SSB_WARN_ON(count & 3);
|
||||
+ while (count) {
|
||||
+ *buf = (__force __le32)__raw_readl(addr);
|
||||
+ buf++;
|
||||
+ count -= 4;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ default:
|
||||
+ SSB_WARN_ON(1);
|
||||
+ }
|
||||
+}
|
||||
+#endif /* CONFIG_SSB_BLOCKIO */
|
||||
+
|
||||
+static void ssb_host_soc_write8(struct ssb_device *dev, u16 offset, u8 value)
|
||||
+{
|
||||
+ struct ssb_bus *bus = dev->bus;
|
||||
+
|
||||
+ offset += dev->core_index * SSB_CORE_SIZE;
|
||||
+ writeb(value, bus->mmio + offset);
|
||||
+}
|
||||
+
|
||||
+static void ssb_host_soc_write16(struct ssb_device *dev, u16 offset, u16 value)
|
||||
+{
|
||||
+ struct ssb_bus *bus = dev->bus;
|
||||
+
|
||||
+ offset += dev->core_index * SSB_CORE_SIZE;
|
||||
+ writew(value, bus->mmio + offset);
|
||||
+}
|
||||
+
|
||||
+static void ssb_host_soc_write32(struct ssb_device *dev, u16 offset, u32 value)
|
||||
+{
|
||||
+ struct ssb_bus *bus = dev->bus;
|
||||
+
|
||||
+ offset += dev->core_index * SSB_CORE_SIZE;
|
||||
+ writel(value, bus->mmio + offset);
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_SSB_BLOCKIO
|
||||
+static void ssb_host_soc_block_write(struct ssb_device *dev, const void *buffer,
|
||||
+ size_t count, u16 offset, u8 reg_width)
|
||||
+{
|
||||
+ struct ssb_bus *bus = dev->bus;
|
||||
+ void __iomem *addr;
|
||||
+
|
||||
+ offset += dev->core_index * SSB_CORE_SIZE;
|
||||
+ addr = bus->mmio + offset;
|
||||
+
|
||||
+ switch (reg_width) {
|
||||
+ case sizeof(u8): {
|
||||
+ const u8 *buf = buffer;
|
||||
+
|
||||
+ while (count) {
|
||||
+ __raw_writeb(*buf, addr);
|
||||
+ buf++;
|
||||
+ count--;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ case sizeof(u16): {
|
||||
+ const __le16 *buf = buffer;
|
||||
+
|
||||
+ SSB_WARN_ON(count & 1);
|
||||
+ while (count) {
|
||||
+ __raw_writew((__force u16)(*buf), addr);
|
||||
+ buf++;
|
||||
+ count -= 2;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ case sizeof(u32): {
|
||||
+ const __le32 *buf = buffer;
|
||||
+
|
||||
+ SSB_WARN_ON(count & 3);
|
||||
+ while (count) {
|
||||
+ __raw_writel((__force u32)(*buf), addr);
|
||||
+ buf++;
|
||||
+ count -= 4;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ default:
|
||||
+ SSB_WARN_ON(1);
|
||||
+ }
|
||||
+}
|
||||
+#endif /* CONFIG_SSB_BLOCKIO */
|
||||
+
|
||||
+/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
|
||||
+const struct ssb_bus_ops ssb_host_soc_ops = {
|
||||
+ .read8 = ssb_host_soc_read8,
|
||||
+ .read16 = ssb_host_soc_read16,
|
||||
+ .read32 = ssb_host_soc_read32,
|
||||
+ .write8 = ssb_host_soc_write8,
|
||||
+ .write16 = ssb_host_soc_write16,
|
||||
+ .write32 = ssb_host_soc_write32,
|
||||
+#ifdef CONFIG_SSB_BLOCKIO
|
||||
+ .block_read = ssb_host_soc_block_read,
|
||||
+ .block_write = ssb_host_soc_block_write,
|
||||
+#endif
|
||||
+};
|
||||
--- a/drivers/ssb/main.c
|
||||
+++ b/drivers/ssb/main.c
|
||||
@@ -596,166 +596,6 @@ error:
|
||||
return err;
|
||||
}
|
||||
|
||||
-static u8 ssb_ssb_read8(struct ssb_device *dev, u16 offset)
|
||||
-{
|
||||
- struct ssb_bus *bus = dev->bus;
|
||||
-
|
||||
- offset += dev->core_index * SSB_CORE_SIZE;
|
||||
- return readb(bus->mmio + offset);
|
||||
-}
|
||||
-
|
||||
-static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset)
|
||||
-{
|
||||
- struct ssb_bus *bus = dev->bus;
|
||||
-
|
||||
- offset += dev->core_index * SSB_CORE_SIZE;
|
||||
- return readw(bus->mmio + offset);
|
||||
-}
|
||||
-
|
||||
-static u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset)
|
||||
-{
|
||||
- struct ssb_bus *bus = dev->bus;
|
||||
-
|
||||
- offset += dev->core_index * SSB_CORE_SIZE;
|
||||
- return readl(bus->mmio + offset);
|
||||
-}
|
||||
-
|
||||
-#ifdef CONFIG_SSB_BLOCKIO
|
||||
-static void ssb_ssb_block_read(struct ssb_device *dev, void *buffer,
|
||||
- size_t count, u16 offset, u8 reg_width)
|
||||
-{
|
||||
- struct ssb_bus *bus = dev->bus;
|
||||
- void __iomem *addr;
|
||||
-
|
||||
- offset += dev->core_index * SSB_CORE_SIZE;
|
||||
- addr = bus->mmio + offset;
|
||||
-
|
||||
- switch (reg_width) {
|
||||
- case sizeof(u8): {
|
||||
- u8 *buf = buffer;
|
||||
-
|
||||
- while (count) {
|
||||
- *buf = __raw_readb(addr);
|
||||
- buf++;
|
||||
- count--;
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- case sizeof(u16): {
|
||||
- __le16 *buf = buffer;
|
||||
-
|
||||
- SSB_WARN_ON(count & 1);
|
||||
- while (count) {
|
||||
- *buf = (__force __le16)__raw_readw(addr);
|
||||
- buf++;
|
||||
- count -= 2;
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- case sizeof(u32): {
|
||||
- __le32 *buf = buffer;
|
||||
-
|
||||
- SSB_WARN_ON(count & 3);
|
||||
- while (count) {
|
||||
- *buf = (__force __le32)__raw_readl(addr);
|
||||
- buf++;
|
||||
- count -= 4;
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- default:
|
||||
- SSB_WARN_ON(1);
|
||||
- }
|
||||
-}
|
||||
-#endif /* CONFIG_SSB_BLOCKIO */
|
||||
-
|
||||
-static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
|
||||
-{
|
||||
- struct ssb_bus *bus = dev->bus;
|
||||
-
|
||||
- offset += dev->core_index * SSB_CORE_SIZE;
|
||||
- writeb(value, bus->mmio + offset);
|
||||
-}
|
||||
-
|
||||
-static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value)
|
||||
-{
|
||||
- struct ssb_bus *bus = dev->bus;
|
||||
-
|
||||
- offset += dev->core_index * SSB_CORE_SIZE;
|
||||
- writew(value, bus->mmio + offset);
|
||||
-}
|
||||
-
|
||||
-static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value)
|
||||
-{
|
||||
- struct ssb_bus *bus = dev->bus;
|
||||
-
|
||||
- offset += dev->core_index * SSB_CORE_SIZE;
|
||||
- writel(value, bus->mmio + offset);
|
||||
-}
|
||||
-
|
||||
-#ifdef CONFIG_SSB_BLOCKIO
|
||||
-static void ssb_ssb_block_write(struct ssb_device *dev, const void *buffer,
|
||||
- size_t count, u16 offset, u8 reg_width)
|
||||
-{
|
||||
- struct ssb_bus *bus = dev->bus;
|
||||
- void __iomem *addr;
|
||||
-
|
||||
- offset += dev->core_index * SSB_CORE_SIZE;
|
||||
- addr = bus->mmio + offset;
|
||||
-
|
||||
- switch (reg_width) {
|
||||
- case sizeof(u8): {
|
||||
- const u8 *buf = buffer;
|
||||
-
|
||||
- while (count) {
|
||||
- __raw_writeb(*buf, addr);
|
||||
- buf++;
|
||||
- count--;
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- case sizeof(u16): {
|
||||
- const __le16 *buf = buffer;
|
||||
-
|
||||
- SSB_WARN_ON(count & 1);
|
||||
- while (count) {
|
||||
- __raw_writew((__force u16)(*buf), addr);
|
||||
- buf++;
|
||||
- count -= 2;
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- case sizeof(u32): {
|
||||
- const __le32 *buf = buffer;
|
||||
-
|
||||
- SSB_WARN_ON(count & 3);
|
||||
- while (count) {
|
||||
- __raw_writel((__force u32)(*buf), addr);
|
||||
- buf++;
|
||||
- count -= 4;
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- default:
|
||||
- SSB_WARN_ON(1);
|
||||
- }
|
||||
-}
|
||||
-#endif /* CONFIG_SSB_BLOCKIO */
|
||||
-
|
||||
-/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
|
||||
-static const struct ssb_bus_ops ssb_ssb_ops = {
|
||||
- .read8 = ssb_ssb_read8,
|
||||
- .read16 = ssb_ssb_read16,
|
||||
- .read32 = ssb_ssb_read32,
|
||||
- .write8 = ssb_ssb_write8,
|
||||
- .write16 = ssb_ssb_write16,
|
||||
- .write32 = ssb_ssb_write32,
|
||||
-#ifdef CONFIG_SSB_BLOCKIO
|
||||
- .block_read = ssb_ssb_block_read,
|
||||
- .block_write = ssb_ssb_block_write,
|
||||
-#endif
|
||||
-};
|
||||
-
|
||||
static int ssb_fetch_invariants(struct ssb_bus *bus,
|
||||
ssb_invariants_func_t get_invariants)
|
||||
{
|
||||
@@ -876,7 +716,6 @@ int ssb_bus_pcibus_register(struct ssb_b
|
||||
|
||||
return err;
|
||||
}
|
||||
-EXPORT_SYMBOL(ssb_bus_pcibus_register);
|
||||
#endif /* CONFIG_SSB_PCIHOST */
|
||||
|
||||
#ifdef CONFIG_SSB_PCMCIAHOST
|
||||
@@ -898,7 +737,6 @@ int ssb_bus_pcmciabus_register(struct ss
|
||||
|
||||
return err;
|
||||
}
|
||||
-EXPORT_SYMBOL(ssb_bus_pcmciabus_register);
|
||||
#endif /* CONFIG_SSB_PCMCIAHOST */
|
||||
|
||||
#ifdef CONFIG_SSB_SDIOHOST
|
||||
@@ -923,13 +761,14 @@ int ssb_bus_sdiobus_register(struct ssb_
|
||||
EXPORT_SYMBOL(ssb_bus_sdiobus_register);
|
||||
#endif /* CONFIG_SSB_PCMCIAHOST */
|
||||
|
||||
+#ifdef CONFIG_SSB_HOST_SOC
|
||||
int ssb_bus_ssbbus_register(struct ssb_bus *bus, unsigned long baseaddr,
|
||||
ssb_invariants_func_t get_invariants)
|
||||
{
|
||||
int err;
|
||||
|
||||
bus->bustype = SSB_BUSTYPE_SSB;
|
||||
- bus->ops = &ssb_ssb_ops;
|
||||
+ bus->ops = &ssb_host_soc_ops;
|
||||
|
||||
err = ssb_bus_register(bus, get_invariants, baseaddr);
|
||||
if (!err) {
|
||||
@@ -939,6 +778,7 @@ int ssb_bus_ssbbus_register(struct ssb_b
|
||||
|
||||
return err;
|
||||
}
|
||||
+#endif
|
||||
|
||||
int __ssb_driver_register(struct ssb_driver *drv, struct module *owner)
|
||||
{
|
||||
@@ -1465,6 +1305,12 @@ static int __init ssb_modinit(void)
|
||||
/* don't fail SSB init because of this */
|
||||
err = 0;
|
||||
}
|
||||
+ err = ssb_host_pcmcia_init();
|
||||
+ if (err) {
|
||||
+ ssb_err("PCMCIA host initialization failed\n");
|
||||
+ /* don't fail SSB init because of this */
|
||||
+ err = 0;
|
||||
+ }
|
||||
err = ssb_gige_init();
|
||||
if (err) {
|
||||
ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n");
|
||||
@@ -1482,6 +1328,7 @@ fs_initcall(ssb_modinit);
|
||||
static void __exit ssb_modexit(void)
|
||||
{
|
||||
ssb_gige_exit();
|
||||
+ ssb_host_pcmcia_exit();
|
||||
b43_pci_ssb_bridge_exit();
|
||||
bus_unregister(&ssb_bustype);
|
||||
}
|
||||
--- a/drivers/ssb/pcmcia.c
|
||||
+++ b/drivers/ssb/pcmcia.c
|
||||
@@ -147,8 +147,7 @@ error:
|
||||
return err;
|
||||
}
|
||||
|
||||
-int ssb_pcmcia_switch_core(struct ssb_bus *bus,
|
||||
- struct ssb_device *dev)
|
||||
+static int ssb_pcmcia_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
--- a/drivers/ssb/sdio.c
|
||||
+++ b/drivers/ssb/sdio.c
|
||||
@@ -200,7 +200,7 @@ out:
|
||||
}
|
||||
|
||||
/* host must be already claimed */
|
||||
-int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
|
||||
+static int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
|
||||
{
|
||||
u8 coreidx = dev->core_index;
|
||||
u32 sbaddr;
|
||||
--- a/drivers/ssb/ssb_private.h
|
||||
+++ b/drivers/ssb/ssb_private.h
|
||||
@@ -85,8 +85,6 @@ static inline int ssb_pci_init(struct ss
|
||||
|
||||
/* pcmcia.c */
|
||||
#ifdef CONFIG_SSB_PCMCIAHOST
|
||||
-extern int ssb_pcmcia_switch_core(struct ssb_bus *bus,
|
||||
- struct ssb_device *dev);
|
||||
extern int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
|
||||
u8 coreidx);
|
||||
extern int ssb_pcmcia_switch_segment(struct ssb_bus *bus,
|
||||
@@ -96,13 +94,10 @@ extern int ssb_pcmcia_get_invariants(str
|
||||
extern int ssb_pcmcia_hardware_setup(struct ssb_bus *bus);
|
||||
extern void ssb_pcmcia_exit(struct ssb_bus *bus);
|
||||
extern int ssb_pcmcia_init(struct ssb_bus *bus);
|
||||
+extern int ssb_host_pcmcia_init(void);
|
||||
+extern void ssb_host_pcmcia_exit(void);
|
||||
extern const struct ssb_bus_ops ssb_pcmcia_ops;
|
||||
#else /* CONFIG_SSB_PCMCIAHOST */
|
||||
-static inline int ssb_pcmcia_switch_core(struct ssb_bus *bus,
|
||||
- struct ssb_device *dev)
|
||||
-{
|
||||
- return 0;
|
||||
-}
|
||||
static inline int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
|
||||
u8 coreidx)
|
||||
{
|
||||
@@ -124,6 +119,13 @@ static inline int ssb_pcmcia_init(struct
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
+static inline int ssb_host_pcmcia_init(void)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+static inline void ssb_host_pcmcia_exit(void)
|
||||
+{
|
||||
+}
|
||||
#endif /* CONFIG_SSB_PCMCIAHOST */
|
||||
|
||||
/* sdio.c */
|
||||
@@ -132,9 +134,7 @@ extern int ssb_sdio_get_invariants(struc
|
||||
struct ssb_init_invariants *iv);
|
||||
|
||||
extern u32 ssb_sdio_scan_read32(struct ssb_bus *bus, u16 offset);
|
||||
-extern int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev);
|
||||
extern int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx);
|
||||
-extern int ssb_sdio_hardware_setup(struct ssb_bus *bus);
|
||||
extern void ssb_sdio_exit(struct ssb_bus *bus);
|
||||
extern int ssb_sdio_init(struct ssb_bus *bus);
|
||||
|
||||
@@ -144,19 +144,10 @@ static inline u32 ssb_sdio_scan_read32(s
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
-static inline int ssb_sdio_switch_core(struct ssb_bus *bus,
|
||||
- struct ssb_device *dev)
|
||||
-{
|
||||
- return 0;
|
||||
-}
|
||||
static inline int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
-static inline int ssb_sdio_hardware_setup(struct ssb_bus *bus)
|
||||
-{
|
||||
- return 0;
|
||||
-}
|
||||
static inline void ssb_sdio_exit(struct ssb_bus *bus)
|
||||
{
|
||||
}
|
||||
@@ -166,6 +157,13 @@ static inline int ssb_sdio_init(struct s
|
||||
}
|
||||
#endif /* CONFIG_SSB_SDIOHOST */
|
||||
|
||||
+/**************************************************
|
||||
+ * host_soc.c
|
||||
+ **************************************************/
|
||||
+
|
||||
+#ifdef CONFIG_SSB_HOST_SOC
|
||||
+extern const struct ssb_bus_ops ssb_host_soc_ops;
|
||||
+#endif
|
||||
|
||||
/* scan.c */
|
||||
extern const char *ssb_core_name(u16 coreid);
|
Loading…
Reference in new issue