ath9k: get EEPROM contents from platform data on AHB bus
authorGabor Juhos <juhosg@openwrt.org>
Wed, 14 Jan 2009 19:17:08 +0000 (20:17 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 29 Jan 2009 21:00:33 +0000 (16:00 -0500)
On the AR913x SOCs we have to provide EEPROM contents via platform_data,
because accessing the flash via MMIO is not safe. Additionally different
boards may store the radio calibration data at different locations.

Changes-licensed-under: ISC

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
Tested-by: Pavel Roskin <proski@gnu.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath9k/ahb.c
drivers/net/wireless/ath9k/core.h
drivers/net/wireless/ath9k/eeprom.c
drivers/net/wireless/ath9k/pci.c
include/linux/ath9k_platform.h [new file with mode: 0644]

index 8cbd4c2a7fa0072ebe6f793356c5a70d0ec65e87..7f2c3a09bcace6dfc9c7921ec01f9a57cb05df7b 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <linux/nl80211.h>
 #include <linux/platform_device.h>
+#include <linux/ath9k_platform.h>
 #include "core.h"
 #include "reg.h"
 #include "hw.h"
@@ -33,9 +34,29 @@ static void ath_ahb_cleanup(struct ath_softc *sc)
        iounmap(sc->mem);
 }
 
+static bool ath_ahb_eeprom_read(struct ath_hal *ah, u32 off, u16 *data)
+{
+       struct ath_softc *sc = ah->ah_sc;
+       struct platform_device *pdev = to_platform_device(sc->dev);
+       struct ath9k_platform_data *pdata;
+
+       pdata = (struct ath9k_platform_data *) pdev->dev.platform_data;
+       if (off >= (ARRAY_SIZE(pdata->eeprom_data))) {
+               DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+                       "%s: flash read failed, offset %08x is out of range\n",
+                               __func__, off);
+               return false;
+       }
+
+       *data = pdata->eeprom_data[off];
+       return true;
+}
+
 static struct ath_bus_ops ath_ahb_bus_ops  = {
        .read_cachesize = ath_ahb_read_cachesize,
        .cleanup = ath_ahb_cleanup,
+
+       .eeprom_read = ath_ahb_eeprom_read,
 };
 
 static int ath_ahb_probe(struct platform_device *pdev)
@@ -48,6 +69,12 @@ static int ath_ahb_probe(struct platform_device *pdev)
        int ret = 0;
        struct ath_hal *ah;
 
+       if (!pdev->dev.platform_data) {
+               dev_err(&pdev->dev, "no platform data specified\n");
+               ret = -EINVAL;
+               goto err_out;
+       }
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (res == NULL) {
                dev_err(&pdev->dev, "no memory resource found\n");
index c5dae11d608647c4aa4929c4f4ffc851ad8609c6..b687ae9c9e175fc71fac83cc4ea1256a833de88d 100644 (file)
@@ -696,6 +696,7 @@ enum PROT_MODE {
 struct ath_bus_ops {
        void            (*read_cachesize)(struct ath_softc *sc, int *csz);
        void            (*cleanup)(struct ath_softc *sc);
+       bool            (*eeprom_read)(struct ath_hal *ah, u32 off, u16 *data);
 };
 
 struct ath_softc {
index 1ef8b5a70e5b2d71ca89d38e3c960b393395d741..50cb3883416aafeeb6078ce083659fec9c088181 100644 (file)
@@ -91,53 +91,11 @@ static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList,
        return false;
 }
 
-static bool ath9k_hw_eeprom_read(struct ath_hal *ah, u32 off, u16 *data)
-{
-       (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
-
-       if (!ath9k_hw_wait(ah,
-                          AR_EEPROM_STATUS_DATA,
-                          AR_EEPROM_STATUS_DATA_BUSY |
-                          AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) {
-               return false;
-       }
-
-       *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
-                  AR_EEPROM_STATUS_DATA_VAL);
-
-       return true;
-}
-
-static int ath9k_hw_flash_map(struct ath_hal *ah)
-{
-       struct ath_hal_5416 *ahp = AH5416(ah);
-
-       ahp->ah_cal_mem = ioremap(AR5416_EEPROM_START_ADDR, AR5416_EEPROM_MAX);
-
-       if (!ahp->ah_cal_mem) {
-               DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-                       "cannot remap eeprom region \n");
-               return -EIO;
-       }
-
-       return 0;
-}
-
-static bool ath9k_hw_flash_read(struct ath_hal *ah, u32 off, u16 *data)
-{
-       struct ath_hal_5416 *ahp = AH5416(ah);
-
-       *data = ioread16(ahp->ah_cal_mem + off);
-
-       return true;
-}
-
 static inline bool ath9k_hw_nvram_read(struct ath_hal *ah, u32 off, u16 *data)
 {
-       if (ath9k_hw_use_flash(ah))
-               return ath9k_hw_flash_read(ah, off, data);
-       else
-               return ath9k_hw_eeprom_read(ah, off, data);
+       struct ath_softc *sc = ah->ah_sc;
+
+       return sc->bus_ops->eeprom_read(ah, off, data);
 }
 
 static bool ath9k_hw_fill_4k_eeprom(struct ath_hal *ah)
@@ -2825,9 +2783,6 @@ int ath9k_hw_eeprom_attach(struct ath_hal *ah)
        int status;
        struct ath_hal_5416 *ahp = AH5416(ah);
 
-       if (ath9k_hw_use_flash(ah))
-               ath9k_hw_flash_map(ah);
-
        if (AR_SREV_9285(ah))
                ahp->ah_eep_map = EEP_MAP_4KBITS;
        else
index 4ff1caa9ba993f938c597bfbea00fedff6b51912..05612bf28360c2ca46dfeaf3bd923ca5d0c7c57f 100644 (file)
@@ -58,9 +58,27 @@ static void ath_pci_cleanup(struct ath_softc *sc)
        pci_disable_device(pdev);
 }
 
+static bool ath_pci_eeprom_read(struct ath_hal *ah, u32 off, u16 *data)
+{
+       (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
+
+       if (!ath9k_hw_wait(ah,
+                          AR_EEPROM_STATUS_DATA,
+                          AR_EEPROM_STATUS_DATA_BUSY |
+                          AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) {
+               return false;
+       }
+
+       *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
+                  AR_EEPROM_STATUS_DATA_VAL);
+
+       return true;
+}
+
 static struct ath_bus_ops ath_pci_bus_ops = {
        .read_cachesize = ath_pci_read_cachesize,
        .cleanup = ath_pci_cleanup,
+       .eeprom_read = ath_pci_eeprom_read,
 };
 
 static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h
new file mode 100644 (file)
index 0000000..b847fc7
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2008 Atheros Communications Inc.
+ * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LINUX_ATH9K_PLATFORM_H
+#define _LINUX_ATH9K_PLATFORM_H
+
+#define ATH9K_PLAT_EEP_MAX_WORDS       2048
+
+struct ath9k_platform_data {
+       u16 eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS];
+};
+
+#endif /* _LINUX_ATH9K_PLATFORM_H */