aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorGabor Juhos <juhosg@openwrt.org>2012-12-10 09:30:28 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-12-10 15:49:57 -0500
commitab5c4f71d8c7add173a2d32e5beefdaaf1b7cbbc (patch)
tree6eadeb30e44afd144f270c2cbfe04c70bbbd6ffd /drivers
parent0e4b9f2f12e94686855605eda64ea534a95d77f2 (diff)
ath9k: allow to load EEPROM content via firmware API
The calibration data for devices w/o a separate EEPROM chip can be specified via the 'eeprom_data' field of 'ath9k_platform_data'. The 'eeprom_data' is usually filled from board specific setup functions. It is easy if the EEPROM data is mapped to the memory, but it can be complicated if it is stored elsewhere. The patch adds support for loading of the EEPROM data via the firmware API to avoid this limitation. Signed-off-by: Gabor Juhos <juhosg@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.c19
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c60
3 files changed, 80 insertions, 2 deletions
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c
index eb9ac5ea6180..971d770722cf 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
@@ -113,12 +113,29 @@ void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
113 } 113 }
114} 114}
115 115
116static bool ath9k_hw_nvram_read_blob(struct ath_hw *ah, u32 off,
117 u16 *data)
118{
119 u16 *blob_data;
120
121 if (off * sizeof(u16) > ah->eeprom_blob->size)
122 return false;
123
124 blob_data = (u16 *)ah->eeprom_blob->data;
125 *data = blob_data[off];
126 return true;
127}
128
116bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data) 129bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
117{ 130{
118 struct ath_common *common = ath9k_hw_common(ah); 131 struct ath_common *common = ath9k_hw_common(ah);
119 bool ret; 132 bool ret;
120 133
121 ret = common->bus_ops->eeprom_read(common, off, data); 134 if (ah->eeprom_blob)
135 ret = ath9k_hw_nvram_read_blob(ah, off, data);
136 else
137 ret = common->bus_ops->eeprom_read(common, off, data);
138
122 if (!ret) 139 if (!ret)
123 ath_dbg(common, EEPROM, 140 ath_dbg(common, EEPROM,
124 "unable to read eeprom region at offset %u\n", off); 141 "unable to read eeprom region at offset %u\n", off);
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index eff67592db18..7f1a8e91c908 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -20,6 +20,7 @@
20#include <linux/if_ether.h> 20#include <linux/if_ether.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/io.h> 22#include <linux/io.h>
23#include <linux/firmware.h>
23 24
24#include "mac.h" 25#include "mac.h"
25#include "ani.h" 26#include "ani.h"
@@ -921,6 +922,8 @@ struct ath_hw {
921 bool is_clk_25mhz; 922 bool is_clk_25mhz;
922 int (*get_mac_revision)(void); 923 int (*get_mac_revision)(void);
923 int (*external_reset)(void); 924 int (*external_reset)(void);
925
926 const struct firmware *eeprom_blob;
924}; 927};
925 928
926struct ath_bus_ops { 929struct ath_bus_ops {
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 80cae53a33e5..27703a5e48d6 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -23,6 +23,11 @@
23 23
24#include "ath9k.h" 24#include "ath9k.h"
25 25
26struct ath9k_eeprom_ctx {
27 struct completion complete;
28 struct ath_hw *ah;
29};
30
26static char *dev_info = "ath9k"; 31static char *dev_info = "ath9k";
27 32
28MODULE_AUTHOR("Atheros Communications"); 33MODULE_AUTHOR("Atheros Communications");
@@ -506,6 +511,51 @@ static void ath9k_init_misc(struct ath_softc *sc)
506 sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT; 511 sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
507} 512}
508 513
514static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob,
515 void *ctx)
516{
517 struct ath9k_eeprom_ctx *ec = ctx;
518
519 if (eeprom_blob)
520 ec->ah->eeprom_blob = eeprom_blob;
521
522 complete(&ec->complete);
523}
524
525static int ath9k_eeprom_request(struct ath_softc *sc, const char *name)
526{
527 struct ath9k_eeprom_ctx ec;
528 struct ath_hw *ah = ah = sc->sc_ah;
529 int err;
530
531 /* try to load the EEPROM content asynchronously */
532 init_completion(&ec.complete);
533 ec.ah = sc->sc_ah;
534
535 err = request_firmware_nowait(THIS_MODULE, 1, name, sc->dev, GFP_KERNEL,
536 &ec, ath9k_eeprom_request_cb);
537 if (err < 0) {
538 ath_err(ath9k_hw_common(ah),
539 "EEPROM request failed\n");
540 return err;
541 }
542
543 wait_for_completion(&ec.complete);
544
545 if (!ah->eeprom_blob) {
546 ath_err(ath9k_hw_common(ah),
547 "Unable to load EEPROM file %s\n", name);
548 return -EINVAL;
549 }
550
551 return 0;
552}
553
554static void ath9k_eeprom_release(struct ath_softc *sc)
555{
556 release_firmware(sc->sc_ah->eeprom_blob);
557}
558
509static int ath9k_init_softc(u16 devid, struct ath_softc *sc, 559static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
510 const struct ath_bus_ops *bus_ops) 560 const struct ath_bus_ops *bus_ops)
511{ 561{
@@ -583,6 +633,12 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
583 ath_read_cachesize(common, &csz); 633 ath_read_cachesize(common, &csz);
584 common->cachelsz = csz << 2; /* convert to bytes */ 634 common->cachelsz = csz << 2; /* convert to bytes */
585 635
636 if (pdata->eeprom_name) {
637 ret = ath9k_eeprom_request(sc, pdata->eeprom_name);
638 if (ret)
639 goto err_eeprom;
640 }
641
586 /* Initializes the hardware for all supported chipsets */ 642 /* Initializes the hardware for all supported chipsets */
587 ret = ath9k_hw_init(ah); 643 ret = ath9k_hw_init(ah);
588 if (ret) 644 if (ret)
@@ -619,7 +675,8 @@ err_btcoex:
619err_queues: 675err_queues:
620 ath9k_hw_deinit(ah); 676 ath9k_hw_deinit(ah);
621err_hw: 677err_hw:
622 678 ath9k_eeprom_release(sc);
679err_eeprom:
623 kfree(ah); 680 kfree(ah);
624 sc->sc_ah = NULL; 681 sc->sc_ah = NULL;
625 682
@@ -882,6 +939,7 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
882 if (sc->dfs_detector != NULL) 939 if (sc->dfs_detector != NULL)
883 sc->dfs_detector->exit(sc->dfs_detector); 940 sc->dfs_detector->exit(sc->dfs_detector);
884 941
942 ath9k_eeprom_release(sc);
885 kfree(sc->sc_ah); 943 kfree(sc->sc_ah);
886 sc->sc_ah = NULL; 944 sc->sc_ah = NULL;
887} 945}