^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Thunderbolt driver - eeprom access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2014 Andreas Noever <andreas.noever@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2018, Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/crc32.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/property.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "tb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * tb_eeprom_ctl_write() - write control word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static int tb_eeprom_ctl_write(struct tb_switch *sw, struct tb_eeprom_ctl *ctl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) return tb_sw_write(sw, ctl, TB_CFG_SWITCH, sw->cap_plug_events + 4, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * tb_eeprom_ctl_write() - read control word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static int tb_eeprom_ctl_read(struct tb_switch *sw, struct tb_eeprom_ctl *ctl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) return tb_sw_read(sw, ctl, TB_CFG_SWITCH, sw->cap_plug_events + 4, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) enum tb_eeprom_transfer {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) TB_EEPROM_IN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) TB_EEPROM_OUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * tb_eeprom_active - enable rom access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * WARNING: Always disable access after usage. Otherwise the controller will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * fail to reprobe.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static int tb_eeprom_active(struct tb_switch *sw, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct tb_eeprom_ctl ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int res = tb_eeprom_ctl_read(sw, &ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) ctl.access_high = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) res = tb_eeprom_ctl_write(sw, &ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) ctl.access_low = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return tb_eeprom_ctl_write(sw, &ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) ctl.access_low = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) res = tb_eeprom_ctl_write(sw, &ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) ctl.access_high = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return tb_eeprom_ctl_write(sw, &ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * tb_eeprom_transfer - transfer one bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * If TB_EEPROM_IN is passed, then the bit can be retrieved from ctl->data_in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * If TB_EEPROM_OUT is passed, then ctl->data_out will be written.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static int tb_eeprom_transfer(struct tb_switch *sw, struct tb_eeprom_ctl *ctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) enum tb_eeprom_transfer direction)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (direction == TB_EEPROM_OUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) res = tb_eeprom_ctl_write(sw, ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) ctl->clock = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) res = tb_eeprom_ctl_write(sw, ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (direction == TB_EEPROM_IN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) res = tb_eeprom_ctl_read(sw, ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) ctl->clock = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return tb_eeprom_ctl_write(sw, ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * tb_eeprom_out - write one byte to the bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static int tb_eeprom_out(struct tb_switch *sw, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct tb_eeprom_ctl ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int res = tb_eeprom_ctl_read(sw, &ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ctl.data_out = val & 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) res = tb_eeprom_transfer(sw, &ctl, TB_EEPROM_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) val <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * tb_eeprom_in - read one byte from the bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static int tb_eeprom_in(struct tb_switch *sw, u8 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct tb_eeprom_ctl ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) int res = tb_eeprom_ctl_read(sw, &ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) *val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) *val <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) res = tb_eeprom_transfer(sw, &ctl, TB_EEPROM_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) *val |= ctl.data_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * tb_eeprom_get_drom_offset - get drom offset within eeprom
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static int tb_eeprom_get_drom_offset(struct tb_switch *sw, u16 *offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct tb_cap_plug_events cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (!sw->cap_plug_events) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) tb_sw_warn(sw, "no TB_CAP_PLUG_EVENTS, cannot read eeprom\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) res = tb_sw_read(sw, &cap, TB_CFG_SWITCH, sw->cap_plug_events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) sizeof(cap) / 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (!cap.eeprom_ctl.present || cap.eeprom_ctl.not_present) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) tb_sw_warn(sw, "no NVM\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (cap.drom_offset > 0xffff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) tb_sw_warn(sw, "drom offset is larger than 0xffff: %#x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) cap.drom_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) *offset = cap.drom_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * tb_eeprom_read_n - read count bytes from offset into val
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static int tb_eeprom_read_n(struct tb_switch *sw, u16 offset, u8 *val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) u16 drom_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int i, res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) res = tb_eeprom_get_drom_offset(sw, &drom_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) offset += drom_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) res = tb_eeprom_active(sw, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) res = tb_eeprom_out(sw, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) res = tb_eeprom_out(sw, offset >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) res = tb_eeprom_out(sw, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) res = tb_eeprom_in(sw, val + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return tb_eeprom_active(sw, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static u8 tb_crc8(u8 *data, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) u8 val = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) val ^= data[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) for (j = 0; j < 8; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) val = (val << 1) ^ ((val & 0x80) ? 7 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static u32 tb_crc32(void *data, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return ~__crc32c_le(~0, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) #define TB_DROM_DATA_START 13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct tb_drom_header {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /* BYTE 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) u8 uid_crc8; /* checksum for uid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /* BYTES 1-8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) u64 uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /* BYTES 9-12 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) u32 data_crc32; /* checksum for data_len bytes starting at byte 13 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* BYTE 13 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) u8 device_rom_revision; /* should be <= 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) u16 data_len:10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) u8 __unknown1:6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* BYTES 16-21 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) u16 vendor_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) u16 model_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) u8 model_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) u8 eeprom_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) enum tb_drom_entry_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* force unsigned to prevent "one-bit signed bitfield" warning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) TB_DROM_ENTRY_GENERIC = 0U,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) TB_DROM_ENTRY_PORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct tb_drom_entry_header {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) u8 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) u8 index:6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) bool port_disabled:1; /* only valid if type is TB_DROM_ENTRY_PORT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) enum tb_drom_entry_type type:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct tb_drom_entry_generic {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct tb_drom_entry_header header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) u8 data[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) struct tb_drom_entry_port {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* BYTES 0-1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct tb_drom_entry_header header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /* BYTE 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) u8 dual_link_port_rid:4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) u8 link_nr:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) u8 unknown1:2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) bool has_dual_link_port:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* BYTE 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) u8 dual_link_port_nr:6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) u8 unknown2:2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /* BYTES 4 - 5 TODO decode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) u8 micro2:4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) u8 micro1:4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) u8 micro3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /* BYTES 6-7, TODO: verify (find hardware that has these set) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) u8 peer_port_rid:4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) u8 unknown3:3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) bool has_peer_port:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) u8 peer_port_nr:6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) u8 unknown4:2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * tb_drom_read_uid_only - read uid directly from drom
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * Does not use the cached copy in sw->drom. Used during resume to check switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * identity.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) int tb_drom_read_uid_only(struct tb_switch *sw, u64 *uid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) u8 data[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) u8 crc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /* read uid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) res = tb_eeprom_read_n(sw, 0, data, 9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) crc = tb_crc8(data + 1, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (crc != data[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) tb_sw_warn(sw, "uid crc8 mismatch (expected: %#x, got: %#x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) data[0], crc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) *uid = *(u64 *)(data+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static int tb_drom_parse_entry_generic(struct tb_switch *sw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) struct tb_drom_entry_header *header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) const struct tb_drom_entry_generic *entry =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) (const struct tb_drom_entry_generic *)header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) switch (header->index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /* Length includes 2 bytes header so remove it before copy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) sw->vendor_name = kstrndup(entry->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) header->len - sizeof(*header), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (!sw->vendor_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) sw->device_name = kstrndup(entry->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) header->len - sizeof(*header), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (!sw->device_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static int tb_drom_parse_entry_port(struct tb_switch *sw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct tb_drom_entry_header *header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) struct tb_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) enum tb_port_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * Some DROMs list more ports than the controller actually has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) * so we skip those but allow the parser to continue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (header->index > sw->config.max_port_number) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) dev_info_once(&sw->dev, "ignoring unnecessary extra entries in DROM\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) port = &sw->ports[header->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) port->disabled = header->port_disabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (port->disabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) res = tb_port_read(port, &type, TB_CFG_PORT, 2, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) type &= 0xffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (type == TB_TYPE_PORT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) struct tb_drom_entry_port *entry = (void *) header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (header->len != sizeof(*entry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) tb_sw_warn(sw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) "port entry has size %#x (expected %#zx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) header->len, sizeof(struct tb_drom_entry_port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) port->link_nr = entry->link_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (entry->has_dual_link_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) port->dual_link_port =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) &port->sw->ports[entry->dual_link_port_nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * tb_drom_parse_entries - parse the linked list of drom entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * Drom must have been copied to sw->drom.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static int tb_drom_parse_entries(struct tb_switch *sw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct tb_drom_header *header = (void *) sw->drom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) u16 pos = sizeof(*header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) u16 drom_size = header->data_len + TB_DROM_DATA_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) while (pos < drom_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct tb_drom_entry_header *entry = (void *) (sw->drom + pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (pos + 1 == drom_size || pos + entry->len > drom_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) || !entry->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) tb_sw_warn(sw, "DROM buffer overrun\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return -EILSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) switch (entry->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) case TB_DROM_ENTRY_GENERIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) res = tb_drom_parse_entry_generic(sw, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) case TB_DROM_ENTRY_PORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) res = tb_drom_parse_entry_port(sw, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) pos += entry->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * tb_drom_copy_efi - copy drom supplied by EFI to sw->drom if present
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) static int tb_drom_copy_efi(struct tb_switch *sw, u16 *size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct device *dev = &sw->tb->nhi->pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) int len, res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) len = device_property_count_u8(dev, "ThunderboltDROM");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (len < 0 || len < sizeof(struct tb_drom_header))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) sw->drom = kmalloc(len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (!sw->drom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) res = device_property_read_u8_array(dev, "ThunderboltDROM", sw->drom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) *size = ((struct tb_drom_header *)sw->drom)->data_len +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) TB_DROM_DATA_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (*size > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) kfree(sw->drom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) sw->drom = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) static int tb_drom_copy_nvm(struct tb_switch *sw, u16 *size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) u32 drom_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (!sw->dma_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) ret = tb_sw_read(sw, &drom_offset, TB_CFG_SWITCH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) sw->cap_plug_events + 12, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (!drom_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) ret = dma_port_flash_read(sw->dma_port, drom_offset + 14, size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) sizeof(*size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /* Size includes CRC8 + UID + CRC32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) *size += 1 + 8 + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) sw->drom = kzalloc(*size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (!sw->drom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) ret = dma_port_flash_read(sw->dma_port, drom_offset, sw->drom, *size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * Read UID from the minimal DROM because the one in NVM is just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) * a placeholder.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) tb_drom_read_uid_only(sw, &sw->uid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) err_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) kfree(sw->drom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) sw->drom = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) static int usb4_copy_host_drom(struct tb_switch *sw, u16 *size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) ret = usb4_switch_drom_read(sw, 14, size, sizeof(*size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) /* Size includes CRC8 + UID + CRC32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) *size += 1 + 8 + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) sw->drom = kzalloc(*size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (!sw->drom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) ret = usb4_switch_drom_read(sw, 0, sw->drom, *size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) kfree(sw->drom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) sw->drom = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) static int tb_drom_read_n(struct tb_switch *sw, u16 offset, u8 *val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (tb_switch_is_usb4(sw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return usb4_switch_drom_read(sw, offset, val, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) return tb_eeprom_read_n(sw, offset, val, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * tb_drom_read - copy drom to sw->drom and parse it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) int tb_drom_read(struct tb_switch *sw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) u16 size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) u32 crc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) struct tb_drom_header *header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) int res, retries = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (sw->drom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (tb_route(sw) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * Apple's NHI EFI driver supplies a DROM for the root switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * in a device property. Use it if available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (tb_drom_copy_efi(sw, &size) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) goto parse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) /* Non-Apple hardware has the DROM as part of NVM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (tb_drom_copy_nvm(sw, &size) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) goto parse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * USB4 hosts may support reading DROM through router
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) * operations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (tb_switch_is_usb4(sw)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) usb4_switch_read_uid(sw, &sw->uid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (!usb4_copy_host_drom(sw, &size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) goto parse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * The root switch contains only a dummy drom
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) * (header only, no entries). Hardcode the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) * configuration here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) tb_drom_read_uid_only(sw, &sw->uid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) res = tb_drom_read_n(sw, 14, (u8 *) &size, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) size &= 0x3ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) size += TB_DROM_DATA_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) tb_sw_dbg(sw, "reading drom (length: %#x)\n", size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (size < sizeof(*header)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) tb_sw_warn(sw, "drom too small, aborting\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) sw->drom = kzalloc(size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (!sw->drom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) res = tb_drom_read_n(sw, 0, sw->drom, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) parse:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) header = (void *) sw->drom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (header->data_len + TB_DROM_DATA_START != size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) tb_sw_warn(sw, "drom size mismatch, aborting\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) crc = tb_crc8((u8 *) &header->uid, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (crc != header->uid_crc8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) tb_sw_warn(sw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) "drom uid crc8 mismatch (expected: %#x, got: %#x), aborting\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) header->uid_crc8, crc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (!sw->uid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) sw->uid = header->uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) sw->vendor = header->vendor_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) sw->device = header->model_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) tb_check_quirks(sw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) crc = tb_crc32(sw->drom + TB_DROM_DATA_START, header->data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (crc != header->data_crc32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) tb_sw_warn(sw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) "drom data crc32 mismatch (expected: %#x, got: %#x), continuing\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) header->data_crc32, crc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (header->device_rom_revision > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) tb_sw_warn(sw, "drom device_rom_revision %#x unknown\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) header->device_rom_revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) res = tb_drom_parse_entries(sw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) /* If the DROM parsing fails, wait a moment and retry once */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (res == -EILSEQ && retries--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) tb_sw_warn(sw, "parsing DROM failed, retrying\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) res = tb_drom_read_n(sw, 0, sw->drom, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) goto parse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) kfree(sw->drom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) sw->drom = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }