From 5d1646d90e1f2cceb9f0828f4b28318cd0ec7744 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 12:05:51 +0200 Subject: Adding upstream version 5.10.209. Signed-off-by: Daniel Baumann --- drivers/ssb/bridge_pcmcia_80211.c | 133 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 drivers/ssb/bridge_pcmcia_80211.c (limited to 'drivers/ssb/bridge_pcmcia_80211.c') diff --git a/drivers/ssb/bridge_pcmcia_80211.c b/drivers/ssb/bridge_pcmcia_80211.c new file mode 100644 index 000000000..ffa379eff --- /dev/null +++ b/drivers/ssb/bridge_pcmcia_80211.c @@ -0,0 +1,133 @@ +/* + * Broadcom 43xx PCMCIA-SSB bridge module + * + * Copyright (c) 2007 Michael Buesch + * + * Licensed under the GNU/GPL. See COPYING for details. + */ + +#include "ssb_private.h" + +#include +#include +#include + +#include +#include +#include +#include + +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: + dev_err(&dev->dev, "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, +}; + +static int pcmcia_init_failed; + +/* + * These are not module init/exit functions! + * The module_pcmcia_driver() helper cannot be used here. + */ +int ssb_host_pcmcia_init(void) +{ + pcmcia_init_failed = pcmcia_register_driver(&ssb_host_pcmcia_driver); + + return pcmcia_init_failed; +} + +void ssb_host_pcmcia_exit(void) +{ + if (!pcmcia_init_failed) + pcmcia_unregister_driver(&ssb_host_pcmcia_driver); +} -- cgit v1.2.3