Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }