Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2008-2011 Atheros Communications Inc.
0003  * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
0004  * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
0005  *
0006  * Permission to use, copy, modify, and/or distribute this software for any
0007  * purpose with or without fee is hereby granted, provided that the above
0008  * copyright notice and this permission notice appear in all copies.
0009  *
0010  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0011  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0012  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
0013  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0014  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
0015  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
0016  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0017  */
0018 
0019 #include <linux/nl80211.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/module.h>
0022 #include <linux/mod_devicetable.h>
0023 #include "ath9k.h"
0024 
0025 static const struct platform_device_id ath9k_platform_id_table[] = {
0026     {
0027         .name = "ath9k",
0028         .driver_data = AR5416_AR9100_DEVID,
0029     },
0030     {
0031         .name = "ar933x_wmac",
0032         .driver_data = AR9300_DEVID_AR9330,
0033     },
0034     {
0035         .name = "ar934x_wmac",
0036         .driver_data = AR9300_DEVID_AR9340,
0037     },
0038     {
0039         .name = "qca955x_wmac",
0040         .driver_data = AR9300_DEVID_QCA955X,
0041     },
0042     {
0043         .name = "qca953x_wmac",
0044         .driver_data = AR9300_DEVID_AR953X,
0045     },
0046     {
0047         .name = "qca956x_wmac",
0048         .driver_data = AR9300_DEVID_QCA956X,
0049     },
0050     {},
0051 };
0052 
0053 /* return bus cachesize in 4B word units */
0054 static void ath_ahb_read_cachesize(struct ath_common *common, int *csz)
0055 {
0056     *csz = L1_CACHE_BYTES >> 2;
0057 }
0058 
0059 static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
0060 {
0061     ath_err(common, "%s: eeprom data has to be provided externally\n",
0062         __func__);
0063     return false;
0064 }
0065 
0066 static const struct ath_bus_ops ath_ahb_bus_ops  = {
0067     .ath_bus_type = ATH_AHB,
0068     .read_cachesize = ath_ahb_read_cachesize,
0069     .eeprom_read = ath_ahb_eeprom_read,
0070 };
0071 
0072 static int ath_ahb_probe(struct platform_device *pdev)
0073 {
0074     void __iomem *mem;
0075     struct ath_softc *sc;
0076     struct ieee80211_hw *hw;
0077     struct resource *res;
0078     const struct platform_device_id *id = platform_get_device_id(pdev);
0079     int irq;
0080     int ret = 0;
0081     struct ath_hw *ah;
0082     char hw_name[64];
0083 
0084     if (!dev_get_platdata(&pdev->dev)) {
0085         dev_err(&pdev->dev, "no platform data specified\n");
0086         return -EINVAL;
0087     }
0088 
0089     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0090     if (res == NULL) {
0091         dev_err(&pdev->dev, "no memory resource found\n");
0092         return -ENXIO;
0093     }
0094 
0095     mem = devm_ioremap(&pdev->dev, res->start, resource_size(res));
0096     if (mem == NULL) {
0097         dev_err(&pdev->dev, "ioremap failed\n");
0098         return -ENOMEM;
0099     }
0100 
0101     irq = platform_get_irq(pdev, 0);
0102     if (irq < 0)
0103         return irq;
0104 
0105     ath9k_fill_chanctx_ops();
0106     hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
0107     if (hw == NULL) {
0108         dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
0109         return -ENOMEM;
0110     }
0111 
0112     SET_IEEE80211_DEV(hw, &pdev->dev);
0113     platform_set_drvdata(pdev, hw);
0114 
0115     sc = hw->priv;
0116     sc->hw = hw;
0117     sc->dev = &pdev->dev;
0118     sc->mem = mem;
0119     sc->irq = irq;
0120 
0121     ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc);
0122     if (ret) {
0123         dev_err(&pdev->dev, "request_irq failed\n");
0124         goto err_free_hw;
0125     }
0126 
0127     ret = ath9k_init_device(id->driver_data, sc, &ath_ahb_bus_ops);
0128     if (ret) {
0129         dev_err(&pdev->dev, "failed to initialize device\n");
0130         goto err_irq;
0131     }
0132 
0133     ah = sc->sc_ah;
0134     ath9k_hw_name(ah, hw_name, sizeof(hw_name));
0135     wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
0136            hw_name, (unsigned long)mem, irq);
0137 
0138     return 0;
0139 
0140  err_irq:
0141     free_irq(irq, sc);
0142  err_free_hw:
0143     ieee80211_free_hw(hw);
0144     return ret;
0145 }
0146 
0147 static int ath_ahb_remove(struct platform_device *pdev)
0148 {
0149     struct ieee80211_hw *hw = platform_get_drvdata(pdev);
0150 
0151     if (hw) {
0152         struct ath_softc *sc = hw->priv;
0153 
0154         ath9k_deinit_device(sc);
0155         free_irq(sc->irq, sc);
0156         ieee80211_free_hw(sc->hw);
0157     }
0158 
0159     return 0;
0160 }
0161 
0162 static struct platform_driver ath_ahb_driver = {
0163     .probe      = ath_ahb_probe,
0164     .remove     = ath_ahb_remove,
0165     .driver     = {
0166         .name   = "ath9k",
0167     },
0168     .id_table    = ath9k_platform_id_table,
0169 };
0170 
0171 MODULE_DEVICE_TABLE(platform, ath9k_platform_id_table);
0172 
0173 int ath_ahb_init(void)
0174 {
0175     return platform_driver_register(&ath_ahb_driver);
0176 }
0177 
0178 void ath_ahb_exit(void)
0179 {
0180     platform_driver_unregister(&ath_ahb_driver);
0181 }