/** * tb_eeprom_get_drom_offset - get drom offset within eeprom */ static int tb_eeprom_get_drom_offset(struct tb_switch *sw, u16 *offset) { struct tb_cap_plug_events cap; int res; if (!sw->cap_plug_events) { tb_sw_warn(sw, "no TB_CAP_PLUG_EVENTS, cannot read eeprom\n"); return -ENOSYS; } res = tb_sw_read(sw, &cap, TB_CFG_SWITCH, sw->cap_plug_events, sizeof(cap) / 4); if (res) return res; if (!cap.eeprom_ctl.present || cap.eeprom_ctl.not_present) { tb_sw_warn(sw, "no NVM\n"); return -ENOSYS; } if (cap.drom_offset > 0xffff) { tb_sw_warn(sw, "drom offset is larger than 0xffff: %#x\n", cap.drom_offset); return -ENXIO; } *offset = cap.drom_offset; return 0; }
/** * tb_plug_events_active() - enable/disable plug events on a switch * * Also configures a sane plug_events_delay of 255ms. * * Return: Returns 0 on success or an error code on failure. */ static int tb_plug_events_active(struct tb_switch *sw, bool active) { u32 data; int res; sw->config.plug_events_delay = 0xff; res = tb_sw_write(sw, ((u32 *) &sw->config) + 4, TB_CFG_SWITCH, 4, 1); if (res) return res; res = tb_sw_read(sw, &data, TB_CFG_SWITCH, sw->cap_plug_events + 1, 1); if (res) return res; if (active) { data = data & 0xFFFFFF83; switch (sw->config.device_id) { case PCI_DEVICE_ID_INTEL_LIGHT_RIDGE: case PCI_DEVICE_ID_INTEL_EAGLE_RIDGE: case PCI_DEVICE_ID_INTEL_PORT_RIDGE: break; default: data |= 4; } } else { data = data | 0x7c; } return tb_sw_write(sw, &data, TB_CFG_SWITCH, sw->cap_plug_events + 1, 1); }
/** * tb_eeprom_ctl_write() - read control word */ static int tb_eeprom_ctl_read(struct tb_switch *sw, struct tb_eeprom_ctl *ctl) { return tb_sw_read(sw, ctl, TB_CFG_SWITCH, sw->cap_plug_events + 4, 1); }