Commit 9dbeb91a authored by Gabor Juhos's avatar Gabor Juhos Committed by John W. Linville

ath9k: get EEPROM contents from platform data on AHB bus

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: default avatarGabor Juhos <juhosg@openwrt.org>
Signed-off-by: default avatarImre Kaloz <kaloz@openwrt.org>
Tested-by: default avatarPavel Roskin <proski@gnu.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 09329d37
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/nl80211.h> #include <linux/nl80211.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/ath9k_platform.h>
#include "core.h" #include "core.h"
#include "reg.h" #include "reg.h"
#include "hw.h" #include "hw.h"
...@@ -33,9 +34,29 @@ static void ath_ahb_cleanup(struct ath_softc *sc) ...@@ -33,9 +34,29 @@ static void ath_ahb_cleanup(struct ath_softc *sc)
iounmap(sc->mem); 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 = { static struct ath_bus_ops ath_ahb_bus_ops = {
.read_cachesize = ath_ahb_read_cachesize, .read_cachesize = ath_ahb_read_cachesize,
.cleanup = ath_ahb_cleanup, .cleanup = ath_ahb_cleanup,
.eeprom_read = ath_ahb_eeprom_read,
}; };
static int ath_ahb_probe(struct platform_device *pdev) static int ath_ahb_probe(struct platform_device *pdev)
...@@ -48,6 +69,12 @@ 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; int ret = 0;
struct ath_hal *ah; 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); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) { if (res == NULL) {
dev_err(&pdev->dev, "no memory resource found\n"); dev_err(&pdev->dev, "no memory resource found\n");
......
...@@ -696,6 +696,7 @@ enum PROT_MODE { ...@@ -696,6 +696,7 @@ enum PROT_MODE {
struct ath_bus_ops { struct ath_bus_ops {
void (*read_cachesize)(struct ath_softc *sc, int *csz); void (*read_cachesize)(struct ath_softc *sc, int *csz);
void (*cleanup)(struct ath_softc *sc); void (*cleanup)(struct ath_softc *sc);
bool (*eeprom_read)(struct ath_hal *ah, u32 off, u16 *data);
}; };
struct ath_softc { struct ath_softc {
......
...@@ -91,53 +91,11 @@ static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, ...@@ -91,53 +91,11 @@ static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList,
return false; 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) static inline bool ath9k_hw_nvram_read(struct ath_hal *ah, u32 off, u16 *data)
{ {
if (ath9k_hw_use_flash(ah)) struct ath_softc *sc = ah->ah_sc;
return ath9k_hw_flash_read(ah, off, data);
else return sc->bus_ops->eeprom_read(ah, off, data);
return ath9k_hw_eeprom_read(ah, off, data);
} }
static bool ath9k_hw_fill_4k_eeprom(struct ath_hal *ah) static bool ath9k_hw_fill_4k_eeprom(struct ath_hal *ah)
...@@ -2825,9 +2783,6 @@ int ath9k_hw_eeprom_attach(struct ath_hal *ah) ...@@ -2825,9 +2783,6 @@ int ath9k_hw_eeprom_attach(struct ath_hal *ah)
int status; int status;
struct ath_hal_5416 *ahp = AH5416(ah); struct ath_hal_5416 *ahp = AH5416(ah);
if (ath9k_hw_use_flash(ah))
ath9k_hw_flash_map(ah);
if (AR_SREV_9285(ah)) if (AR_SREV_9285(ah))
ahp->ah_eep_map = EEP_MAP_4KBITS; ahp->ah_eep_map = EEP_MAP_4KBITS;
else else
......
...@@ -58,9 +58,27 @@ static void ath_pci_cleanup(struct ath_softc *sc) ...@@ -58,9 +58,27 @@ static void ath_pci_cleanup(struct ath_softc *sc)
pci_disable_device(pdev); 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 = { static struct ath_bus_ops ath_pci_bus_ops = {
.read_cachesize = ath_pci_read_cachesize, .read_cachesize = ath_pci_read_cachesize,
.cleanup = ath_pci_cleanup, .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) static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
......
/*
* 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 */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment