1 /* 2 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <asm/unaligned.h> 19 20 #include "mt76.h" 21 #include "mt76x02_eeprom.h" 22 #include "mt76x02_regs.h" 23 24 static int 25 mt76x02_efuse_read(struct mt76_dev *dev, u16 addr, u8 *data, 26 enum mt76x02_eeprom_modes mode) 27 { 28 u32 val; 29 int i; 30 31 val = __mt76_rr(dev, MT_EFUSE_CTRL); 32 val &= ~(MT_EFUSE_CTRL_AIN | 33 MT_EFUSE_CTRL_MODE); 34 val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf); 35 val |= FIELD_PREP(MT_EFUSE_CTRL_MODE, mode); 36 val |= MT_EFUSE_CTRL_KICK; 37 __mt76_wr(dev, MT_EFUSE_CTRL, val); 38 39 if (!__mt76_poll_msec(dev, MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 40 0, 1000)) 41 return -ETIMEDOUT; 42 43 udelay(2); 44 45 val = __mt76_rr(dev, MT_EFUSE_CTRL); 46 if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT) { 47 memset(data, 0xff, 16); 48 return 0; 49 } 50 51 for (i = 0; i < 4; i++) { 52 val = __mt76_rr(dev, MT_EFUSE_DATA(i)); 53 put_unaligned_le32(val, data + 4 * i); 54 } 55 56 return 0; 57 } 58 59 int mt76x02_get_efuse_data(struct mt76_dev *dev, u16 base, void *buf, 60 int len, enum mt76x02_eeprom_modes mode) 61 { 62 int ret, i; 63 64 for (i = 0; i + 16 <= len; i += 16) { 65 ret = mt76x02_efuse_read(dev, base + i, buf + i, mode); 66 if (ret) 67 return ret; 68 } 69 70 return 0; 71 } 72 EXPORT_SYMBOL_GPL(mt76x02_get_efuse_data); 73