0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #include <linux/module.h>
0020 #include <linux/nl80211.h>
0021 #include <linux/platform_device.h>
0022 #include <linux/etherdevice.h>
0023 #include <ath25_platform.h>
0024 #include "ath5k.h"
0025 #include "debug.h"
0026 #include "base.h"
0027 #include "reg.h"
0028
0029
0030 static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz)
0031 {
0032 *csz = L1_CACHE_BYTES >> 2;
0033 }
0034
0035 static bool
0036 ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
0037 {
0038 struct ath5k_hw *ah = common->priv;
0039 struct platform_device *pdev = to_platform_device(ah->dev);
0040 struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
0041 u16 *eeprom, *eeprom_end;
0042
0043 eeprom = (u16 *) bcfg->radio;
0044 eeprom_end = ((void *) bcfg->config) + BOARD_CONFIG_BUFSZ;
0045
0046 eeprom += off;
0047 if (eeprom > eeprom_end)
0048 return false;
0049
0050 *data = *eeprom;
0051 return true;
0052 }
0053
0054 int ath5k_hw_read_srev(struct ath5k_hw *ah)
0055 {
0056 struct platform_device *pdev = to_platform_device(ah->dev);
0057 struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
0058 ah->ah_mac_srev = bcfg->devid;
0059 return 0;
0060 }
0061
0062 static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
0063 {
0064 struct platform_device *pdev = to_platform_device(ah->dev);
0065 struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
0066 u8 *cfg_mac;
0067
0068 if (to_platform_device(ah->dev)->id == 0)
0069 cfg_mac = bcfg->config->wlan0_mac;
0070 else
0071 cfg_mac = bcfg->config->wlan1_mac;
0072
0073 memcpy(mac, cfg_mac, ETH_ALEN);
0074 return 0;
0075 }
0076
0077 static const struct ath_bus_ops ath_ahb_bus_ops = {
0078 .ath_bus_type = ATH_AHB,
0079 .read_cachesize = ath5k_ahb_read_cachesize,
0080 .eeprom_read = ath5k_ahb_eeprom_read,
0081 .eeprom_read_mac = ath5k_ahb_eeprom_read_mac,
0082 };
0083
0084
0085 static int ath_ahb_probe(struct platform_device *pdev)
0086 {
0087 struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
0088 struct ath5k_hw *ah;
0089 struct ieee80211_hw *hw;
0090 struct resource *res;
0091 void __iomem *mem;
0092 int irq;
0093 int ret = 0;
0094 u32 reg;
0095
0096 if (!dev_get_platdata(&pdev->dev)) {
0097 dev_err(&pdev->dev, "no platform data specified\n");
0098 ret = -EINVAL;
0099 goto err_out;
0100 }
0101
0102 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0103 if (res == NULL) {
0104 dev_err(&pdev->dev, "no memory resource found\n");
0105 ret = -ENXIO;
0106 goto err_out;
0107 }
0108
0109 mem = ioremap(res->start, resource_size(res));
0110 if (mem == NULL) {
0111 dev_err(&pdev->dev, "ioremap failed\n");
0112 ret = -ENOMEM;
0113 goto err_out;
0114 }
0115
0116 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
0117 if (res == NULL) {
0118 dev_err(&pdev->dev, "no IRQ resource found\n");
0119 ret = -ENXIO;
0120 goto err_iounmap;
0121 }
0122
0123 irq = res->start;
0124
0125 hw = ieee80211_alloc_hw(sizeof(struct ath5k_hw), &ath5k_hw_ops);
0126 if (hw == NULL) {
0127 dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
0128 ret = -ENOMEM;
0129 goto err_iounmap;
0130 }
0131
0132 ah = hw->priv;
0133 ah->hw = hw;
0134 ah->dev = &pdev->dev;
0135 ah->iobase = mem;
0136 ah->irq = irq;
0137 ah->devid = bcfg->devid;
0138
0139 if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
0140
0141 reg = ioread32((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
0142 reg |= AR5K_AR2315_AHB_ARB_CTL_WLAN;
0143 iowrite32(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
0144
0145
0146 reg = ioread32((void __iomem *) AR5K_AR2315_BYTESWAP);
0147 reg |= AR5K_AR2315_BYTESWAP_WMAC;
0148 iowrite32(reg, (void __iomem *) AR5K_AR2315_BYTESWAP);
0149 } else {
0150
0151
0152 reg = ioread32((void __iomem *) AR5K_AR5312_ENABLE);
0153 if (to_platform_device(ah->dev)->id == 0)
0154 reg |= AR5K_AR5312_ENABLE_WLAN0;
0155 else
0156 reg |= AR5K_AR5312_ENABLE_WLAN1;
0157 iowrite32(reg, (void __iomem *) AR5K_AR5312_ENABLE);
0158
0159
0160
0161
0162
0163
0164 if (to_platform_device(ah->dev)->id == 0 &&
0165 (bcfg->config->flags & (BD_WLAN0 | BD_WLAN1)) ==
0166 (BD_WLAN1 | BD_WLAN0))
0167 ah->ah_capabilities.cap_needs_2GHz_ovr = true;
0168 else
0169 ah->ah_capabilities.cap_needs_2GHz_ovr = false;
0170 }
0171
0172 ret = ath5k_init_ah(ah, &ath_ahb_bus_ops);
0173 if (ret != 0) {
0174 dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
0175 ret = -ENODEV;
0176 goto err_free_hw;
0177 }
0178
0179 platform_set_drvdata(pdev, hw);
0180
0181 return 0;
0182
0183 err_free_hw:
0184 ieee80211_free_hw(hw);
0185 err_iounmap:
0186 iounmap(mem);
0187 err_out:
0188 return ret;
0189 }
0190
0191 static int ath_ahb_remove(struct platform_device *pdev)
0192 {
0193 struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
0194 struct ieee80211_hw *hw = platform_get_drvdata(pdev);
0195 struct ath5k_hw *ah;
0196 u32 reg;
0197
0198 if (!hw)
0199 return 0;
0200
0201 ah = hw->priv;
0202
0203 if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
0204
0205 reg = ioread32((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
0206 reg &= ~AR5K_AR2315_AHB_ARB_CTL_WLAN;
0207 iowrite32(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
0208 } else {
0209
0210 reg = ioread32((void __iomem *) AR5K_AR5312_ENABLE);
0211 if (to_platform_device(ah->dev)->id == 0)
0212 reg &= ~AR5K_AR5312_ENABLE_WLAN0;
0213 else
0214 reg &= ~AR5K_AR5312_ENABLE_WLAN1;
0215 iowrite32(reg, (void __iomem *) AR5K_AR5312_ENABLE);
0216 }
0217
0218 ath5k_deinit_ah(ah);
0219 iounmap(ah->iobase);
0220 ieee80211_free_hw(hw);
0221
0222 return 0;
0223 }
0224
0225 static struct platform_driver ath_ahb_driver = {
0226 .probe = ath_ahb_probe,
0227 .remove = ath_ahb_remove,
0228 .driver = {
0229 .name = "ar231x-wmac",
0230 },
0231 };
0232
0233 module_platform_driver(ath_ahb_driver);