Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: 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>

authored by

Gabor Juhos and committed by
John W. Linville
9dbeb91a 09329d37

+77 -48
+27
drivers/net/wireless/ath9k/ahb.c
··· 18 18 19 19 #include <linux/nl80211.h> 20 20 #include <linux/platform_device.h> 21 + #include <linux/ath9k_platform.h> 21 22 #include "core.h" 22 23 #include "reg.h" 23 24 #include "hw.h" ··· 34 33 iounmap(sc->mem); 35 34 } 36 35 36 + static bool ath_ahb_eeprom_read(struct ath_hal *ah, u32 off, u16 *data) 37 + { 38 + struct ath_softc *sc = ah->ah_sc; 39 + struct platform_device *pdev = to_platform_device(sc->dev); 40 + struct ath9k_platform_data *pdata; 41 + 42 + pdata = (struct ath9k_platform_data *) pdev->dev.platform_data; 43 + if (off >= (ARRAY_SIZE(pdata->eeprom_data))) { 44 + DPRINTF(ah->ah_sc, ATH_DBG_FATAL, 45 + "%s: flash read failed, offset %08x is out of range\n", 46 + __func__, off); 47 + return false; 48 + } 49 + 50 + *data = pdata->eeprom_data[off]; 51 + return true; 52 + } 53 + 37 54 static struct ath_bus_ops ath_ahb_bus_ops = { 38 55 .read_cachesize = ath_ahb_read_cachesize, 39 56 .cleanup = ath_ahb_cleanup, 57 + 58 + .eeprom_read = ath_ahb_eeprom_read, 40 59 }; 41 60 42 61 static int ath_ahb_probe(struct platform_device *pdev) ··· 68 47 int irq; 69 48 int ret = 0; 70 49 struct ath_hal *ah; 50 + 51 + if (!pdev->dev.platform_data) { 52 + dev_err(&pdev->dev, "no platform data specified\n"); 53 + ret = -EINVAL; 54 + goto err_out; 55 + } 71 56 72 57 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 73 58 if (res == NULL) {
+1
drivers/net/wireless/ath9k/core.h
··· 696 696 struct ath_bus_ops { 697 697 void (*read_cachesize)(struct ath_softc *sc, int *csz); 698 698 void (*cleanup)(struct ath_softc *sc); 699 + bool (*eeprom_read)(struct ath_hal *ah, u32 off, u16 *data); 699 700 }; 700 701 701 702 struct ath_softc {
+3 -48
drivers/net/wireless/ath9k/eeprom.c
··· 91 91 return false; 92 92 } 93 93 94 - static bool ath9k_hw_eeprom_read(struct ath_hal *ah, u32 off, u16 *data) 95 - { 96 - (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); 97 - 98 - if (!ath9k_hw_wait(ah, 99 - AR_EEPROM_STATUS_DATA, 100 - AR_EEPROM_STATUS_DATA_BUSY | 101 - AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) { 102 - return false; 103 - } 104 - 105 - *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA), 106 - AR_EEPROM_STATUS_DATA_VAL); 107 - 108 - return true; 109 - } 110 - 111 - static int ath9k_hw_flash_map(struct ath_hal *ah) 112 - { 113 - struct ath_hal_5416 *ahp = AH5416(ah); 114 - 115 - ahp->ah_cal_mem = ioremap(AR5416_EEPROM_START_ADDR, AR5416_EEPROM_MAX); 116 - 117 - if (!ahp->ah_cal_mem) { 118 - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, 119 - "cannot remap eeprom region \n"); 120 - return -EIO; 121 - } 122 - 123 - return 0; 124 - } 125 - 126 - static bool ath9k_hw_flash_read(struct ath_hal *ah, u32 off, u16 *data) 127 - { 128 - struct ath_hal_5416 *ahp = AH5416(ah); 129 - 130 - *data = ioread16(ahp->ah_cal_mem + off); 131 - 132 - return true; 133 - } 134 - 135 94 static inline bool ath9k_hw_nvram_read(struct ath_hal *ah, u32 off, u16 *data) 136 95 { 137 - if (ath9k_hw_use_flash(ah)) 138 - return ath9k_hw_flash_read(ah, off, data); 139 - else 140 - return ath9k_hw_eeprom_read(ah, off, data); 96 + struct ath_softc *sc = ah->ah_sc; 97 + 98 + return sc->bus_ops->eeprom_read(ah, off, data); 141 99 } 142 100 143 101 static bool ath9k_hw_fill_4k_eeprom(struct ath_hal *ah) ··· 2782 2824 { 2783 2825 int status; 2784 2826 struct ath_hal_5416 *ahp = AH5416(ah); 2785 - 2786 - if (ath9k_hw_use_flash(ah)) 2787 - ath9k_hw_flash_map(ah); 2788 2827 2789 2828 if (AR_SREV_9285(ah)) 2790 2829 ahp->ah_eep_map = EEP_MAP_4KBITS;
+18
drivers/net/wireless/ath9k/pci.c
··· 58 58 pci_disable_device(pdev); 59 59 } 60 60 61 + static bool ath_pci_eeprom_read(struct ath_hal *ah, u32 off, u16 *data) 62 + { 63 + (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); 64 + 65 + if (!ath9k_hw_wait(ah, 66 + AR_EEPROM_STATUS_DATA, 67 + AR_EEPROM_STATUS_DATA_BUSY | 68 + AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) { 69 + return false; 70 + } 71 + 72 + *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA), 73 + AR_EEPROM_STATUS_DATA_VAL); 74 + 75 + return true; 76 + } 77 + 61 78 static struct ath_bus_ops ath_pci_bus_ops = { 62 79 .read_cachesize = ath_pci_read_cachesize, 63 80 .cleanup = ath_pci_cleanup, 81 + .eeprom_read = ath_pci_eeprom_read, 64 82 }; 65 83 66 84 static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+28
include/linux/ath9k_platform.h
··· 1 + /* 2 + * Copyright (c) 2008 Atheros Communications Inc. 3 + * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org> 4 + * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org> 5 + * 6 + * Permission to use, copy, modify, and/or distribute this software for any 7 + * purpose with or without fee is hereby granted, provided that the above 8 + * copyright notice and this permission notice appear in all copies. 9 + * 10 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 + */ 18 + 19 + #ifndef _LINUX_ATH9K_PLATFORM_H 20 + #define _LINUX_ATH9K_PLATFORM_H 21 + 22 + #define ATH9K_PLAT_EEP_MAX_WORDS 2048 23 + 24 + struct ath9k_platform_data { 25 + u16 eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS]; 26 + }; 27 + 28 + #endif /* _LINUX_ATH9K_PLATFORM_H */