root/drivers/net/wireless/broadcom/b43/sdio.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. b43_sdio_get_quirks
  2. b43_sdio_interrupt_dispatcher
  3. b43_sdio_request_irq
  4. b43_sdio_free_irq
  5. b43_sdio_probe
  6. b43_sdio_remove
  7. b43_sdio_init
  8. b43_sdio_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Broadcom B43 wireless driver
   4  *
   5  * SDIO over Sonics Silicon Backplane bus glue for b43.
   6  *
   7  * Copyright (C) 2009 Albert Herranz
   8  * Copyright (C) 2009 Michael Buesch <m@bues.ch>
   9  */
  10 
  11 #include <linux/kernel.h>
  12 #include <linux/mmc/card.h>
  13 #include <linux/mmc/sdio_func.h>
  14 #include <linux/mmc/sdio_ids.h>
  15 #include <linux/slab.h>
  16 #include <linux/ssb/ssb.h>
  17 
  18 #include "sdio.h"
  19 #include "b43.h"
  20 
  21 
  22 #define HNBU_CHIPID             0x01    /* vendor & device id */
  23 
  24 #define B43_SDIO_BLOCK_SIZE     64      /* rx fifo max size in bytes */
  25 
  26 
  27 static const struct b43_sdio_quirk {
  28         u16 vendor;
  29         u16 device;
  30         unsigned int quirks;
  31 } b43_sdio_quirks[] = {
  32         { 0x14E4, 0x4318, SSB_QUIRK_SDIO_READ_AFTER_WRITE32, },
  33         { },
  34 };
  35 
  36 
  37 static unsigned int b43_sdio_get_quirks(u16 vendor, u16 device)
  38 {
  39         const struct b43_sdio_quirk *q;
  40 
  41         for (q = b43_sdio_quirks; q->quirks; q++) {
  42                 if (vendor == q->vendor && device == q->device)
  43                         return q->quirks;
  44         }
  45 
  46         return 0;
  47 }
  48 
  49 static void b43_sdio_interrupt_dispatcher(struct sdio_func *func)
  50 {
  51         struct b43_sdio *sdio = sdio_get_drvdata(func);
  52         struct b43_wldev *dev = sdio->irq_handler_opaque;
  53 
  54         if (unlikely(b43_status(dev) < B43_STAT_STARTED))
  55                 return;
  56 
  57         sdio_release_host(func);
  58         sdio->irq_handler(dev);
  59         sdio_claim_host(func);
  60 }
  61 
  62 int b43_sdio_request_irq(struct b43_wldev *dev,
  63                          void (*handler)(struct b43_wldev *dev))
  64 {
  65         struct ssb_bus *bus = dev->dev->sdev->bus;
  66         struct sdio_func *func = bus->host_sdio;
  67         struct b43_sdio *sdio = sdio_get_drvdata(func);
  68         int err;
  69 
  70         sdio->irq_handler_opaque = dev;
  71         sdio->irq_handler = handler;
  72         sdio_claim_host(func);
  73         err = sdio_claim_irq(func, b43_sdio_interrupt_dispatcher);
  74         sdio_release_host(func);
  75 
  76         return err;
  77 }
  78 
  79 void b43_sdio_free_irq(struct b43_wldev *dev)
  80 {
  81         struct ssb_bus *bus = dev->dev->sdev->bus;
  82         struct sdio_func *func = bus->host_sdio;
  83         struct b43_sdio *sdio = sdio_get_drvdata(func);
  84 
  85         sdio_claim_host(func);
  86         sdio_release_irq(func);
  87         sdio_release_host(func);
  88         sdio->irq_handler_opaque = NULL;
  89         sdio->irq_handler = NULL;
  90 }
  91 
  92 static int b43_sdio_probe(struct sdio_func *func,
  93                                     const struct sdio_device_id *id)
  94 {
  95         struct b43_sdio *sdio;
  96         struct sdio_func_tuple *tuple;
  97         u16 vendor = 0, device = 0;
  98         int error;
  99 
 100         /* Look for the card chip identifier. */
 101         tuple = func->tuples;
 102         while (tuple) {
 103                 switch (tuple->code) {
 104                 case 0x80:
 105                         switch (tuple->data[0]) {
 106                         case HNBU_CHIPID:
 107                                 if (tuple->size != 5)
 108                                         break;
 109                                 vendor = tuple->data[1] | (tuple->data[2]<<8);
 110                                 device = tuple->data[3] | (tuple->data[4]<<8);
 111                                 dev_info(&func->dev, "Chip ID %04x:%04x\n",
 112                                          vendor, device);
 113                                 break;
 114                         default:
 115                                 break;
 116                         }
 117                         break;
 118                 default:
 119                         break;
 120                 }
 121                 tuple = tuple->next;
 122         }
 123         if (!vendor || !device) {
 124                 error = -ENODEV;
 125                 goto out;
 126         }
 127 
 128         sdio_claim_host(func);
 129         error = sdio_set_block_size(func, B43_SDIO_BLOCK_SIZE);
 130         if (error) {
 131                 dev_err(&func->dev, "failed to set block size to %u bytes,"
 132                         " error %d\n", B43_SDIO_BLOCK_SIZE, error);
 133                 goto err_release_host;
 134         }
 135         error = sdio_enable_func(func);
 136         if (error) {
 137                 dev_err(&func->dev, "failed to enable func, error %d\n", error);
 138                 goto err_release_host;
 139         }
 140         sdio_release_host(func);
 141 
 142         sdio = kzalloc(sizeof(*sdio), GFP_KERNEL);
 143         if (!sdio) {
 144                 error = -ENOMEM;
 145                 dev_err(&func->dev, "failed to allocate ssb bus\n");
 146                 goto err_disable_func;
 147         }
 148         error = ssb_bus_sdiobus_register(&sdio->ssb, func,
 149                                          b43_sdio_get_quirks(vendor, device));
 150         if (error) {
 151                 dev_err(&func->dev, "failed to register ssb sdio bus,"
 152                         " error %d\n", error);
 153                 goto err_free_ssb;
 154         }
 155         sdio_set_drvdata(func, sdio);
 156 
 157         return 0;
 158 
 159 err_free_ssb:
 160         kfree(sdio);
 161 err_disable_func:
 162         sdio_claim_host(func);
 163         sdio_disable_func(func);
 164 err_release_host:
 165         sdio_release_host(func);
 166 out:
 167         return error;
 168 }
 169 
 170 static void b43_sdio_remove(struct sdio_func *func)
 171 {
 172         struct b43_sdio *sdio = sdio_get_drvdata(func);
 173 
 174         ssb_bus_unregister(&sdio->ssb);
 175         sdio_claim_host(func);
 176         sdio_disable_func(func);
 177         sdio_release_host(func);
 178         kfree(sdio);
 179         sdio_set_drvdata(func, NULL);
 180 }
 181 
 182 static const struct sdio_device_id b43_sdio_ids[] = {
 183         { SDIO_DEVICE(0x02d0, 0x044b) }, /* Nintendo Wii WLAN daughter card */
 184         { SDIO_DEVICE(0x0092, 0x0004) }, /* C-guys, Inc. EW-CG1102GC */
 185         { },
 186 };
 187 
 188 static struct sdio_driver b43_sdio_driver = {
 189         .name           = "b43-sdio",
 190         .id_table       = b43_sdio_ids,
 191         .probe          = b43_sdio_probe,
 192         .remove         = b43_sdio_remove,
 193 };
 194 
 195 int b43_sdio_init(void)
 196 {
 197         return sdio_register_driver(&b43_sdio_driver);
 198 }
 199 
 200 void b43_sdio_exit(void)
 201 {
 202         sdio_unregister_driver(&b43_sdio_driver);
 203 }

/* [<][>][^][v][top][bottom][index][help] */