kernel: backport ssb changes from 4.4-rc1

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>

SVN-Revision: 47483
This commit is contained in:
Rafał Miłecki 2015-11-16 06:55:38 +00:00
parent d42669bf33
commit b2dab45aa7
8 changed files with 1871 additions and 14 deletions

View file

@ -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);
-}

View file

@ -10,7 +10,7 @@
struct b43_phy phy;
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -76,6 +76,11 @@ MODULE_FIRMWARE("b43/ucode16_mimo.fw");
@@ -75,6 +75,11 @@ MODULE_FIRMWARE("b43/ucode16_mimo.fw");
MODULE_FIRMWARE("b43/ucode5.fw");
MODULE_FIRMWARE("b43/ucode9.fw");
@ -22,7 +22,7 @@
static int modparam_bad_frames_preempt;
module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
MODULE_PARM_DESC(bad_frames_preempt,
@@ -2883,10 +2888,10 @@ static int b43_gpio_init(struct b43_wlde
@@ -2882,10 +2887,10 @@ static int b43_gpio_init(struct b43_wlde
u32 mask, set;
b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0);

View file

@ -11,7 +11,7 @@
b43-$(CPTCFG_B43_LEDS) += leds.o
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -2009,10 +2009,12 @@ static void b43_do_interrupt_thread(stru
@@ -2008,10 +2008,12 @@ static void b43_do_interrupt_thread(stru
dma_reason[0], dma_reason[1],
dma_reason[2], dma_reason[3],
dma_reason[4], dma_reason[5]);
@ -75,7 +75,7 @@
#endif /* B43_PIO_H_ */
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -118,7 +118,7 @@ config B43_BCMA_PIO
@@ -98,7 +98,7 @@ config B43_BCMA_PIO
default y
config B43_PIO

View file

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -1649,7 +1649,7 @@ static void b43_write_beacon_template(st
@@ -1648,7 +1648,7 @@ static void b43_write_beacon_template(st
len, ram_offset, shm_size_offset, rate);
/* Write the PHY TX control parameters. */
@ -9,7 +9,7 @@
antenna = b43_antenna_to_phyctl(antenna);
ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
/* We can't send beacons with short preamble. Would get PHY errors. */
@@ -3301,8 +3301,8 @@ static int b43_chip_init(struct b43_wlde
@@ -3300,8 +3300,8 @@ static int b43_chip_init(struct b43_wlde
/* Select the antennae */
if (phy->ops->set_rx_antenna)
@ -20,7 +20,7 @@
if (phy->type == B43_PHYTYPE_B) {
value16 = b43_read16(dev, 0x005E);
@@ -4002,7 +4002,6 @@ static int b43_op_config(struct ieee8021
@@ -4001,7 +4001,6 @@ static int b43_op_config(struct ieee8021
struct b43_wldev *dev = wl->current_dev;
struct b43_phy *phy = &dev->phy;
struct ieee80211_conf *conf = &hw->conf;
@ -28,7 +28,7 @@
int err = 0;
mutex_lock(&wl->mutex);
@@ -4045,11 +4044,9 @@ static int b43_op_config(struct ieee8021
@@ -4044,11 +4043,9 @@ static int b43_op_config(struct ieee8021
}
/* Antennas for RX and management frame TX. */
@ -42,7 +42,7 @@
if (wl->radio_enabled != phy->radio_on) {
if (wl->radio_enabled) {
@@ -5210,6 +5207,47 @@ static int b43_op_get_survey(struct ieee
@@ -5209,6 +5206,47 @@ static int b43_op_get_survey(struct ieee
return 0;
}
@ -90,7 +90,7 @@
static const struct ieee80211_ops b43_hw_ops = {
.tx = b43_op_tx,
.conf_tx = b43_op_conf_tx,
@@ -5231,6 +5269,8 @@ static const struct ieee80211_ops b43_hw
@@ -5230,6 +5268,8 @@ static const struct ieee80211_ops b43_hw
.sw_scan_complete = b43_op_sw_scan_complete_notifier,
.get_survey = b43_op_get_survey,
.rfkill_poll = b43_rfkill_poll,
@ -99,7 +99,7 @@
};
/* Hard-reset the chip. Do not call this directly.
@@ -5539,6 +5579,8 @@ static int b43_one_core_attach(struct b4
@@ -5538,6 +5578,8 @@ static int b43_one_core_attach(struct b4
if (!wldev)
goto out;
@ -108,7 +108,7 @@
wldev->use_pio = b43_modparam_pio;
wldev->dev = dev;
wldev->wl = wl;
@@ -5629,6 +5671,9 @@ static struct b43_wl *b43_wireless_init(
@@ -5628,6 +5670,9 @@ static struct b43_wl *b43_wireless_init(
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;

View file

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -2900,6 +2900,14 @@ static int b43_gpio_init(struct b43_wlde
@@ -2899,6 +2899,14 @@ static int b43_gpio_init(struct b43_wlde
} else if (dev->dev->chip_id == 0x5354) {
/* Don't allow overtaking buttons GPIOs */
set &= 0x2; /* 0x2 is LED GPIO on BCM5354 */

View file

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -118,7 +118,7 @@ static int b43_modparam_pio = 0;
@@ -117,7 +117,7 @@ static int b43_modparam_pio = 0;
module_param_named(pio, b43_modparam_pio, int, 0644);
MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");

View file

@ -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);

View file

@ -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);