aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ssb
diff options
context:
space:
mode:
authorRafał Miłecki <zajec5@gmail.com>2015-10-15 01:23:25 -0400
committerKalle Valo <kvalo@codeaurora.org>2015-10-28 15:04:04 -0400
commit399500da18f7fe79699c0e4f603f8874cecb3898 (patch)
tree0c42ef4110c225788c1a5e9b4bbb670f736eca09 /drivers/ssb
parent0117e78aec73f1c0869e50d11a255b28aa4db8f0 (diff)
ssb: pick PCMCIA host code support from b43 driver
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>
Diffstat (limited to 'drivers/ssb')
-rw-r--r--drivers/ssb/Makefile2
-rw-r--r--drivers/ssb/bridge_pcmcia_80211.c128
-rw-r--r--drivers/ssb/main.c8
-rw-r--r--drivers/ssb/ssb_private.h9
4 files changed, 145 insertions, 2 deletions
diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile
index b1ddc116d387..7daa03e34b37 100644
--- a/drivers/ssb/Makefile
+++ b/drivers/ssb/Makefile
@@ -5,7 +5,7 @@ ssb-$(CONFIG_SSB_SPROM) += sprom.o
5 5
6# host support 6# host support
7ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o 7ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o
8ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o 8ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o bridge_pcmcia_80211.o
9ssb-$(CONFIG_SSB_SDIOHOST) += sdio.o 9ssb-$(CONFIG_SSB_SDIOHOST) += sdio.o
10 10
11# built-in drivers 11# built-in drivers
diff --git a/drivers/ssb/bridge_pcmcia_80211.c b/drivers/ssb/bridge_pcmcia_80211.c
new file mode 100644
index 000000000000..d70568ea02d5
--- /dev/null
+++ b/drivers/ssb/bridge_pcmcia_80211.c
@@ -0,0 +1,128 @@
1/*
2 * Broadcom 43xx PCMCIA-SSB bridge module
3 *
4 * Copyright (c) 2007 Michael Buesch <m@bues.ch>
5 *
6 * Licensed under the GNU/GPL. See COPYING for details.
7 */
8
9#include <linux/ssb/ssb.h>
10#include <linux/slab.h>
11#include <linux/module.h>
12
13#include <pcmcia/cistpl.h>
14#include <pcmcia/ciscode.h>
15#include <pcmcia/ds.h>
16#include <pcmcia/cisreg.h>
17
18#include "ssb_private.h"
19
20static const struct pcmcia_device_id ssb_host_pcmcia_tbl[] = {
21 PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
22 PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476),
23 PCMCIA_DEVICE_NULL,
24};
25
26MODULE_DEVICE_TABLE(pcmcia, ssb_host_pcmcia_tbl);
27
28static int ssb_host_pcmcia_probe(struct pcmcia_device *dev)
29{
30 struct ssb_bus *ssb;
31 int err = -ENOMEM;
32 int res = 0;
33
34 ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
35 if (!ssb)
36 goto out_error;
37
38 err = -ENODEV;
39
40 dev->config_flags |= CONF_ENABLE_IRQ;
41
42 dev->resource[2]->flags |= WIN_ENABLE | WIN_DATA_WIDTH_16 |
43 WIN_USE_WAIT;
44 dev->resource[2]->start = 0;
45 dev->resource[2]->end = SSB_CORE_SIZE;
46 res = pcmcia_request_window(dev, dev->resource[2], 250);
47 if (res != 0)
48 goto err_kfree_ssb;
49
50 res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
51 if (res != 0)
52 goto err_disable;
53
54 if (!dev->irq)
55 goto err_disable;
56
57 res = pcmcia_enable_device(dev);
58 if (res != 0)
59 goto err_disable;
60
61 err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
62 if (err)
63 goto err_disable;
64 dev->priv = ssb;
65
66 return 0;
67
68err_disable:
69 pcmcia_disable_device(dev);
70err_kfree_ssb:
71 kfree(ssb);
72out_error:
73 ssb_err("Initialization failed (%d, %d)\n", res, err);
74 return err;
75}
76
77static void ssb_host_pcmcia_remove(struct pcmcia_device *dev)
78{
79 struct ssb_bus *ssb = dev->priv;
80
81 ssb_bus_unregister(ssb);
82 pcmcia_disable_device(dev);
83 kfree(ssb);
84 dev->priv = NULL;
85}
86
87#ifdef CONFIG_PM
88static int ssb_host_pcmcia_suspend(struct pcmcia_device *dev)
89{
90 struct ssb_bus *ssb = dev->priv;
91
92 return ssb_bus_suspend(ssb);
93}
94
95static int ssb_host_pcmcia_resume(struct pcmcia_device *dev)
96{
97 struct ssb_bus *ssb = dev->priv;
98
99 return ssb_bus_resume(ssb);
100}
101#else /* CONFIG_PM */
102# define ssb_host_pcmcia_suspend NULL
103# define ssb_host_pcmcia_resume NULL
104#endif /* CONFIG_PM */
105
106static struct pcmcia_driver ssb_host_pcmcia_driver = {
107 .owner = THIS_MODULE,
108 .name = "ssb-pcmcia",
109 .id_table = ssb_host_pcmcia_tbl,
110 .probe = ssb_host_pcmcia_probe,
111 .remove = ssb_host_pcmcia_remove,
112 .suspend = ssb_host_pcmcia_suspend,
113 .resume = ssb_host_pcmcia_resume,
114};
115
116/*
117 * These are not module init/exit functions!
118 * The module_pcmcia_driver() helper cannot be used here.
119 */
120int ssb_host_pcmcia_init(void)
121{
122 return pcmcia_register_driver(&ssb_host_pcmcia_driver);
123}
124
125void ssb_host_pcmcia_exit(void)
126{
127 pcmcia_unregister_driver(&ssb_host_pcmcia_driver);
128}
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index 8cf23a2468ba..90ec6a048b4c 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -897,7 +897,6 @@ int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
897 897
898 return err; 898 return err;
899} 899}
900EXPORT_SYMBOL(ssb_bus_pcmciabus_register);
901#endif /* CONFIG_SSB_PCMCIAHOST */ 900#endif /* CONFIG_SSB_PCMCIAHOST */
902 901
903#ifdef CONFIG_SSB_SDIOHOST 902#ifdef CONFIG_SSB_SDIOHOST
@@ -1464,6 +1463,12 @@ static int __init ssb_modinit(void)
1464 /* don't fail SSB init because of this */ 1463 /* don't fail SSB init because of this */
1465 err = 0; 1464 err = 0;
1466 } 1465 }
1466 err = ssb_host_pcmcia_init();
1467 if (err) {
1468 ssb_err("PCMCIA host initialization failed\n");
1469 /* don't fail SSB init because of this */
1470 err = 0;
1471 }
1467 err = ssb_gige_init(); 1472 err = ssb_gige_init();
1468 if (err) { 1473 if (err) {
1469 ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n"); 1474 ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n");
@@ -1481,6 +1486,7 @@ fs_initcall(ssb_modinit);
1481static void __exit ssb_modexit(void) 1486static void __exit ssb_modexit(void)
1482{ 1487{
1483 ssb_gige_exit(); 1488 ssb_gige_exit();
1489 ssb_host_pcmcia_exit();
1484 b43_pci_ssb_bridge_exit(); 1490 b43_pci_ssb_bridge_exit();
1485 bus_unregister(&ssb_bustype); 1491 bus_unregister(&ssb_bustype);
1486} 1492}
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h
index 8a2ebc88c66f..93bb8f0195a9 100644
--- a/drivers/ssb/ssb_private.h
+++ b/drivers/ssb/ssb_private.h
@@ -94,6 +94,8 @@ extern int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
94extern int ssb_pcmcia_hardware_setup(struct ssb_bus *bus); 94extern int ssb_pcmcia_hardware_setup(struct ssb_bus *bus);
95extern void ssb_pcmcia_exit(struct ssb_bus *bus); 95extern void ssb_pcmcia_exit(struct ssb_bus *bus);
96extern int ssb_pcmcia_init(struct ssb_bus *bus); 96extern int ssb_pcmcia_init(struct ssb_bus *bus);
97extern int ssb_host_pcmcia_init(void);
98extern void ssb_host_pcmcia_exit(void);
97extern const struct ssb_bus_ops ssb_pcmcia_ops; 99extern const struct ssb_bus_ops ssb_pcmcia_ops;
98#else /* CONFIG_SSB_PCMCIAHOST */ 100#else /* CONFIG_SSB_PCMCIAHOST */
99static inline int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus, 101static inline int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
@@ -117,6 +119,13 @@ static inline int ssb_pcmcia_init(struct ssb_bus *bus)
117{ 119{
118 return 0; 120 return 0;
119} 121}
122static inline int ssb_host_pcmcia_init(void)
123{
124 return 0;
125}
126static inline void ssb_host_pcmcia_exit(void)
127{
128}
120#endif /* CONFIG_SSB_PCMCIAHOST */ 129#endif /* CONFIG_SSB_PCMCIAHOST */
121 130
122/* sdio.c */ 131/* sdio.c */