1/* 2 * Atheros AR71XX/AR724X/AR913X Calibration data in NAND flash fixup 3 * 4 * Copyright (c) 2012 The Linux Foundation. All rights reserved. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 as published 8 * by the Free Software Foundation. 9 */ 10 11#include <linux/types.h> 12#include <linux/ath9k_platform.h> 13#include <linux/mtd/mtd.h> 14 15#include "dev-ap9x-pci.h" 16#include "dev-wmac.h" 17#include "dev-eth.h" 18#include "nand-caldata-fixup.h" 19 20static struct ath79_caldata_fixup *ath79_caldata; 21 22static void mtd_caldata_add(struct mtd_info *mtd) 23{ 24 int i, ret; 25 size_t retlen; 26 struct ath9k_platform_data *wmac_pdata; 27 struct ag71xx_platform_data *eth_pdata; 28 29 /* If the device added doesn't match the name of the device containing 30 * caldata, then we do nothing; just return */ 31 if (strcmp(mtd->name, ath79_caldata->name)) 32 return; 33 34 /* If the caldata PCIe address provided by the platform is non-null, 35 * then fetch the data from MTD and fill it into the platform 36 * structure */ 37 for (i = 0; 38 i < sizeof(ath79_caldata->pcie_caldata_addr) / sizeof(loff_t); 39 i++) { 40 if (ath79_caldata->pcie_caldata_addr[i] == FIXUP_UNDEFINED) 41 continue; 42 43 wmac_pdata = ap9x_pci_get_wmac_data(i); 44 45 ret = 46 mtd_read(mtd, ath79_caldata->pcie_caldata_addr[i], 47 sizeof(wmac_pdata->eeprom_data), &retlen, 48 (u_char *) wmac_pdata->eeprom_data); 49 if (retlen != sizeof(wmac_pdata->eeprom_data) || ret < 0) { 50 pr_err("%s: Error while reading %dB at offset 0x%08x\n", 51 mtd->name, sizeof(wmac_pdata->eeprom_data), 52 (u_int) ath79_caldata->pcie_caldata_addr[i]); 53 } 54 } 55 56 /* Same here for WMAC caldata */ 57 if (ath79_caldata->wmac_caldata_addr != FIXUP_UNDEFINED) { 58 wmac_pdata = ath79_get_wmac_data(); 59 60 ret = 61 mtd_read(mtd, ath79_caldata->wmac_caldata_addr, 62 sizeof(wmac_pdata->eeprom_data), &retlen, 63 (u_char *) wmac_pdata->eeprom_data); 64 if (retlen != sizeof(wmac_pdata->eeprom_data) || ret < 0) { 65 pr_err("%s: Error while reading %dB at offset 0x%08x\n", 66 mtd->name, sizeof(wmac_pdata->eeprom_data), 67 (u_int) ath79_caldata->wmac_caldata_addr); 68 } 69 } 70 71 /* Same here for Ethernet MAC@ */ 72 for (i = 0; i < sizeof(ath79_caldata->mac_addr) / sizeof(loff_t); i++) { 73 switch (i) { 74 case 0: 75 eth_pdata = &ath79_eth0_data; 76 break; 77 case 1: 78 eth_pdata = &ath79_eth1_data; 79 break; 80 default: 81 eth_pdata = NULL; 82 } 83 84 if (ath79_caldata->mac_addr[i] == FIXUP_UNDEFINED) 85 continue; 86 87 ret = 88 mtd_read(mtd, ath79_caldata->mac_addr[i], 89 sizeof(eth_pdata->mac_addr), &retlen, 90 (u_char *) eth_pdata->mac_addr); 91 if (retlen != sizeof(eth_pdata->mac_addr) || ret < 0) { 92 pr_err("%s: Error while reading %dB at offset 0x%08x\n", 93 mtd->name, sizeof(eth_pdata->mac_addr), 94 (u_int) ath79_caldata->mac_addr[i]); 95 } 96 } 97} 98 99static void mtd_caldata_remove(struct mtd_info *mtd) 100{ 101 return; 102} 103 104static void add_mtd_caldata_notifier(void) 105{ 106 static struct mtd_notifier not = { 107 .add = mtd_caldata_add, 108 .remove = mtd_caldata_remove, 109 }; 110 111 register_mtd_user(¬); 112} 113 114void __init ath79_mtd_caldata_fixup(struct ath79_caldata_fixup 115 *platform_caldata) 116{ 117 ath79_caldata = platform_caldata; 118 add_mtd_caldata_notifier(); 119} 120