Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Mac80211 SDIO driver for ST-Ericsson CW1200 device
0004  *
0005  * Copyright (c) 2010, ST-Ericsson
0006  * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
0007  */
0008 
0009 #include <linux/module.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/gpio.h>
0012 #include <linux/delay.h>
0013 #include <linux/mmc/host.h>
0014 #include <linux/mmc/sdio_func.h>
0015 #include <linux/mmc/card.h>
0016 #include <linux/mmc/sdio.h>
0017 #include <linux/mmc/sdio_ids.h>
0018 #include <net/mac80211.h>
0019 
0020 #include "cw1200.h"
0021 #include "hwbus.h"
0022 #include <linux/platform_data/net-cw1200.h>
0023 #include "hwio.h"
0024 
0025 MODULE_AUTHOR("Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>");
0026 MODULE_DESCRIPTION("mac80211 ST-Ericsson CW1200 SDIO driver");
0027 MODULE_LICENSE("GPL");
0028 
0029 #define SDIO_BLOCK_SIZE (512)
0030 
0031 /* Default platform data for Sagrad modules */
0032 static struct cw1200_platform_data_sdio sagrad_109x_evk_platform_data = {
0033     .ref_clk = 38400,
0034     .have_5ghz = false,
0035     .sdd_file = "sdd_sagrad_1091_1098.bin",
0036 };
0037 
0038 /* Allow platform data to be overridden */
0039 static struct cw1200_platform_data_sdio *global_plat_data = &sagrad_109x_evk_platform_data;
0040 
0041 void __init cw1200_sdio_set_platform_data(struct cw1200_platform_data_sdio *pdata)
0042 {
0043     global_plat_data = pdata;
0044 }
0045 
0046 struct hwbus_priv {
0047     struct sdio_func    *func;
0048     struct cw1200_common    *core;
0049     const struct cw1200_platform_data_sdio *pdata;
0050 };
0051 
0052 static const struct sdio_device_id cw1200_sdio_ids[] = {
0053     { SDIO_DEVICE(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200) },
0054     { /* end: all zeroes */         },
0055 };
0056 MODULE_DEVICE_TABLE(sdio, cw1200_sdio_ids);
0057 
0058 /* hwbus_ops implemetation */
0059 
0060 static int cw1200_sdio_memcpy_fromio(struct hwbus_priv *self,
0061                      unsigned int addr,
0062                      void *dst, int count)
0063 {
0064     return sdio_memcpy_fromio(self->func, dst, addr, count);
0065 }
0066 
0067 static int cw1200_sdio_memcpy_toio(struct hwbus_priv *self,
0068                    unsigned int addr,
0069                    const void *src, int count)
0070 {
0071     return sdio_memcpy_toio(self->func, addr, (void *)src, count);
0072 }
0073 
0074 static void cw1200_sdio_lock(struct hwbus_priv *self)
0075 {
0076     sdio_claim_host(self->func);
0077 }
0078 
0079 static void cw1200_sdio_unlock(struct hwbus_priv *self)
0080 {
0081     sdio_release_host(self->func);
0082 }
0083 
0084 static void cw1200_sdio_irq_handler(struct sdio_func *func)
0085 {
0086     struct hwbus_priv *self = sdio_get_drvdata(func);
0087 
0088     /* note:  sdio_host already claimed here. */
0089     if (self->core)
0090         cw1200_irq_handler(self->core);
0091 }
0092 
0093 static irqreturn_t cw1200_gpio_hardirq(int irq, void *dev_id)
0094 {
0095     return IRQ_WAKE_THREAD;
0096 }
0097 
0098 static irqreturn_t cw1200_gpio_irq(int irq, void *dev_id)
0099 {
0100     struct hwbus_priv *self = dev_id;
0101 
0102     if (self->core) {
0103         cw1200_sdio_lock(self);
0104         cw1200_irq_handler(self->core);
0105         cw1200_sdio_unlock(self);
0106         return IRQ_HANDLED;
0107     } else {
0108         return IRQ_NONE;
0109     }
0110 }
0111 
0112 static int cw1200_request_irq(struct hwbus_priv *self)
0113 {
0114     int ret;
0115     u8 cccr;
0116 
0117     cccr = sdio_f0_readb(self->func, SDIO_CCCR_IENx, &ret);
0118     if (WARN_ON(ret))
0119         goto err;
0120 
0121     /* Master interrupt enable ... */
0122     cccr |= BIT(0);
0123 
0124     /* ... for our function */
0125     cccr |= BIT(self->func->num);
0126 
0127     sdio_f0_writeb(self->func, cccr, SDIO_CCCR_IENx, &ret);
0128     if (WARN_ON(ret))
0129         goto err;
0130 
0131     ret = enable_irq_wake(self->pdata->irq);
0132     if (WARN_ON(ret))
0133         goto err;
0134 
0135     /* Request the IRQ */
0136     ret =  request_threaded_irq(self->pdata->irq, cw1200_gpio_hardirq,
0137                     cw1200_gpio_irq,
0138                     IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
0139                     "cw1200_wlan_irq", self);
0140     if (WARN_ON(ret))
0141         goto err;
0142 
0143     return 0;
0144 
0145 err:
0146     return ret;
0147 }
0148 
0149 static int cw1200_sdio_irq_subscribe(struct hwbus_priv *self)
0150 {
0151     int ret = 0;
0152 
0153     pr_debug("SW IRQ subscribe\n");
0154     sdio_claim_host(self->func);
0155     if (self->pdata->irq)
0156         ret = cw1200_request_irq(self);
0157     else
0158         ret = sdio_claim_irq(self->func, cw1200_sdio_irq_handler);
0159 
0160     sdio_release_host(self->func);
0161     return ret;
0162 }
0163 
0164 static int cw1200_sdio_irq_unsubscribe(struct hwbus_priv *self)
0165 {
0166     int ret = 0;
0167 
0168     pr_debug("SW IRQ unsubscribe\n");
0169 
0170     if (self->pdata->irq) {
0171         disable_irq_wake(self->pdata->irq);
0172         free_irq(self->pdata->irq, self);
0173     } else {
0174         sdio_claim_host(self->func);
0175         ret = sdio_release_irq(self->func);
0176         sdio_release_host(self->func);
0177     }
0178     return ret;
0179 }
0180 
0181 static int cw1200_sdio_off(const struct cw1200_platform_data_sdio *pdata)
0182 {
0183     if (pdata->reset) {
0184         gpio_set_value(pdata->reset, 0);
0185         msleep(30); /* Min is 2 * CLK32K cycles */
0186         gpio_free(pdata->reset);
0187     }
0188 
0189     if (pdata->power_ctrl)
0190         pdata->power_ctrl(pdata, false);
0191     if (pdata->clk_ctrl)
0192         pdata->clk_ctrl(pdata, false);
0193 
0194     return 0;
0195 }
0196 
0197 static int cw1200_sdio_on(const struct cw1200_platform_data_sdio *pdata)
0198 {
0199     /* Ensure I/Os are pulled low */
0200     if (pdata->reset) {
0201         gpio_request(pdata->reset, "cw1200_wlan_reset");
0202         gpio_direction_output(pdata->reset, 0);
0203     }
0204     if (pdata->powerup) {
0205         gpio_request(pdata->powerup, "cw1200_wlan_powerup");
0206         gpio_direction_output(pdata->powerup, 0);
0207     }
0208     if (pdata->reset || pdata->powerup)
0209         msleep(10); /* Settle time? */
0210 
0211     /* Enable 3v3 and 1v8 to hardware */
0212     if (pdata->power_ctrl) {
0213         if (pdata->power_ctrl(pdata, true)) {
0214             pr_err("power_ctrl() failed!\n");
0215             return -1;
0216         }
0217     }
0218 
0219     /* Enable CLK32K */
0220     if (pdata->clk_ctrl) {
0221         if (pdata->clk_ctrl(pdata, true)) {
0222             pr_err("clk_ctrl() failed!\n");
0223             return -1;
0224         }
0225         msleep(10); /* Delay until clock is stable for 2 cycles */
0226     }
0227 
0228     /* Enable POWERUP signal */
0229     if (pdata->powerup) {
0230         gpio_set_value(pdata->powerup, 1);
0231         msleep(250); /* or more..? */
0232     }
0233     /* Enable RSTn signal */
0234     if (pdata->reset) {
0235         gpio_set_value(pdata->reset, 1);
0236         msleep(50); /* Or more..? */
0237     }
0238     return 0;
0239 }
0240 
0241 static size_t cw1200_sdio_align_size(struct hwbus_priv *self, size_t size)
0242 {
0243     if (self->pdata->no_nptb)
0244         size = round_up(size, SDIO_BLOCK_SIZE);
0245     else
0246         size = sdio_align_size(self->func, size);
0247 
0248     return size;
0249 }
0250 
0251 static int cw1200_sdio_pm(struct hwbus_priv *self, bool suspend)
0252 {
0253     int ret = 0;
0254 
0255     if (self->pdata->irq)
0256         ret = irq_set_irq_wake(self->pdata->irq, suspend);
0257     return ret;
0258 }
0259 
0260 static const struct hwbus_ops cw1200_sdio_hwbus_ops = {
0261     .hwbus_memcpy_fromio    = cw1200_sdio_memcpy_fromio,
0262     .hwbus_memcpy_toio  = cw1200_sdio_memcpy_toio,
0263     .lock           = cw1200_sdio_lock,
0264     .unlock         = cw1200_sdio_unlock,
0265     .align_size     = cw1200_sdio_align_size,
0266     .power_mgmt     = cw1200_sdio_pm,
0267 };
0268 
0269 /* Probe Function to be called by SDIO stack when device is discovered */
0270 static int cw1200_sdio_probe(struct sdio_func *func,
0271                  const struct sdio_device_id *id)
0272 {
0273     struct hwbus_priv *self;
0274     int status;
0275 
0276     pr_info("cw1200_wlan_sdio: Probe called\n");
0277 
0278     /* We are only able to handle the wlan function */
0279     if (func->num != 0x01)
0280         return -ENODEV;
0281 
0282     self = kzalloc(sizeof(*self), GFP_KERNEL);
0283     if (!self) {
0284         pr_err("Can't allocate SDIO hwbus_priv.\n");
0285         return -ENOMEM;
0286     }
0287 
0288     func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
0289 
0290     self->pdata = global_plat_data; /* FIXME */
0291     self->func = func;
0292     sdio_set_drvdata(func, self);
0293     sdio_claim_host(func);
0294     sdio_enable_func(func);
0295     sdio_release_host(func);
0296 
0297     status = cw1200_sdio_irq_subscribe(self);
0298 
0299     status = cw1200_core_probe(&cw1200_sdio_hwbus_ops,
0300                    self, &func->dev, &self->core,
0301                    self->pdata->ref_clk,
0302                    self->pdata->macaddr,
0303                    self->pdata->sdd_file,
0304                    self->pdata->have_5ghz);
0305     if (status) {
0306         cw1200_sdio_irq_unsubscribe(self);
0307         sdio_claim_host(func);
0308         sdio_disable_func(func);
0309         sdio_release_host(func);
0310         sdio_set_drvdata(func, NULL);
0311         kfree(self);
0312     }
0313 
0314     return status;
0315 }
0316 
0317 /* Disconnect Function to be called by SDIO stack when
0318  * device is disconnected
0319  */
0320 static void cw1200_sdio_disconnect(struct sdio_func *func)
0321 {
0322     struct hwbus_priv *self = sdio_get_drvdata(func);
0323 
0324     if (self) {
0325         cw1200_sdio_irq_unsubscribe(self);
0326         if (self->core) {
0327             cw1200_core_release(self->core);
0328             self->core = NULL;
0329         }
0330         sdio_claim_host(func);
0331         sdio_disable_func(func);
0332         sdio_release_host(func);
0333         sdio_set_drvdata(func, NULL);
0334         kfree(self);
0335     }
0336 }
0337 
0338 #ifdef CONFIG_PM
0339 static int cw1200_sdio_suspend(struct device *dev)
0340 {
0341     int ret;
0342     struct sdio_func *func = dev_to_sdio_func(dev);
0343     struct hwbus_priv *self = sdio_get_drvdata(func);
0344 
0345     if (!cw1200_can_suspend(self->core))
0346         return -EAGAIN;
0347 
0348     /* Notify SDIO that CW1200 will remain powered during suspend */
0349     ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
0350     if (ret)
0351         pr_err("Error setting SDIO pm flags: %i\n", ret);
0352 
0353     return ret;
0354 }
0355 
0356 static int cw1200_sdio_resume(struct device *dev)
0357 {
0358     return 0;
0359 }
0360 
0361 static const struct dev_pm_ops cw1200_pm_ops = {
0362     .suspend = cw1200_sdio_suspend,
0363     .resume = cw1200_sdio_resume,
0364 };
0365 #endif
0366 
0367 static struct sdio_driver sdio_driver = {
0368     .name       = "cw1200_wlan_sdio",
0369     .id_table   = cw1200_sdio_ids,
0370     .probe      = cw1200_sdio_probe,
0371     .remove     = cw1200_sdio_disconnect,
0372 #ifdef CONFIG_PM
0373     .drv = {
0374         .pm = &cw1200_pm_ops,
0375     }
0376 #endif
0377 };
0378 
0379 /* Init Module function -> Called by insmod */
0380 static int __init cw1200_sdio_init(void)
0381 {
0382     const struct cw1200_platform_data_sdio *pdata;
0383     int ret;
0384 
0385     /* FIXME -- this won't support multiple devices */
0386     pdata = global_plat_data;
0387 
0388     if (cw1200_sdio_on(pdata)) {
0389         ret = -1;
0390         goto err;
0391     }
0392 
0393     ret = sdio_register_driver(&sdio_driver);
0394     if (ret)
0395         goto err;
0396 
0397     return 0;
0398 
0399 err:
0400     cw1200_sdio_off(pdata);
0401     return ret;
0402 }
0403 
0404 /* Called at Driver Unloading */
0405 static void __exit cw1200_sdio_exit(void)
0406 {
0407     const struct cw1200_platform_data_sdio *pdata;
0408 
0409     /* FIXME -- this won't support multiple devices */
0410     pdata = global_plat_data;
0411     sdio_unregister_driver(&sdio_driver);
0412     cw1200_sdio_off(pdata);
0413 }
0414 
0415 
0416 module_init(cw1200_sdio_init);
0417 module_exit(cw1200_sdio_exit);