17fb3a1f7SJani Nikula // SPDX-License-Identifier: MIT 27fb3a1f7SJani Nikula /* 37fb3a1f7SJani Nikula * Copyright © 2013-2021 Intel Corporation 47fb3a1f7SJani Nikula * 57fb3a1f7SJani Nikula * LPT/WPT IOSF sideband. 67fb3a1f7SJani Nikula */ 77fb3a1f7SJani Nikula 8ad3cfb65SJani Nikula #include <drm/drm_print.h> 9ad3cfb65SJani Nikula 10ad3cfb65SJani Nikula #include "intel_de.h" 11a737ab4aSJani Nikula #include "intel_display_core.h" 12a737ab4aSJani Nikula #include "intel_sbi.h" 13*0b6d7dbfSJani Nikula #include "intel_sbi_regs.h" 147fb3a1f7SJani Nikula 157fb3a1f7SJani Nikula /* SBI access */ 16a737ab4aSJani Nikula static int intel_sbi_rw(struct intel_display *display, u16 reg, 177fb3a1f7SJani Nikula enum intel_sbi_destination destination, 187fb3a1f7SJani Nikula u32 *val, bool is_read) 197fb3a1f7SJani Nikula { 207fb3a1f7SJani Nikula u32 cmd; 217fb3a1f7SJani Nikula 229ab17edeSJani Nikula lockdep_assert_held(&display->sbi.lock); 237fb3a1f7SJani Nikula 24ad3cfb65SJani Nikula if (intel_de_wait_fw(display, SBI_CTL_STAT, SBI_BUSY, 0, 100, NULL)) { 25a737ab4aSJani Nikula drm_err(display->drm, "timeout waiting for SBI to become ready\n"); 267fb3a1f7SJani Nikula return -EBUSY; 277fb3a1f7SJani Nikula } 287fb3a1f7SJani Nikula 29ad3cfb65SJani Nikula intel_de_write_fw(display, SBI_ADDR, (u32)reg << 16); 30ad3cfb65SJani Nikula intel_de_write_fw(display, SBI_DATA, is_read ? 0 : *val); 317fb3a1f7SJani Nikula 327fb3a1f7SJani Nikula if (destination == SBI_ICLK) 337fb3a1f7SJani Nikula cmd = SBI_CTL_DEST_ICLK | SBI_CTL_OP_CRRD; 347fb3a1f7SJani Nikula else 357fb3a1f7SJani Nikula cmd = SBI_CTL_DEST_MPHY | SBI_CTL_OP_IORD; 367fb3a1f7SJani Nikula if (!is_read) 377fb3a1f7SJani Nikula cmd |= BIT(8); 38ad3cfb65SJani Nikula intel_de_write_fw(display, SBI_CTL_STAT, cmd | SBI_BUSY); 397fb3a1f7SJani Nikula 40ad3cfb65SJani Nikula if (intel_de_wait_fw(display, SBI_CTL_STAT, SBI_BUSY, 0, 100, &cmd)) { 41a737ab4aSJani Nikula drm_err(display->drm, "timeout waiting for SBI to complete read\n"); 427fb3a1f7SJani Nikula return -ETIMEDOUT; 437fb3a1f7SJani Nikula } 447fb3a1f7SJani Nikula 457fb3a1f7SJani Nikula if (cmd & SBI_RESPONSE_FAIL) { 46a737ab4aSJani Nikula drm_err(display->drm, "error during SBI read of reg %x\n", reg); 477fb3a1f7SJani Nikula return -ENXIO; 487fb3a1f7SJani Nikula } 497fb3a1f7SJani Nikula 507fb3a1f7SJani Nikula if (is_read) 51ad3cfb65SJani Nikula *val = intel_de_read_fw(display, SBI_DATA); 527fb3a1f7SJani Nikula 537fb3a1f7SJani Nikula return 0; 547fb3a1f7SJani Nikula } 557fb3a1f7SJani Nikula 56a737ab4aSJani Nikula void intel_sbi_lock(struct intel_display *display) 577fb3a1f7SJani Nikula { 589ab17edeSJani Nikula mutex_lock(&display->sbi.lock); 597fb3a1f7SJani Nikula } 607fb3a1f7SJani Nikula 61a737ab4aSJani Nikula void intel_sbi_unlock(struct intel_display *display) 627fb3a1f7SJani Nikula { 639ab17edeSJani Nikula mutex_unlock(&display->sbi.lock); 647fb3a1f7SJani Nikula } 657fb3a1f7SJani Nikula 66a737ab4aSJani Nikula u32 intel_sbi_read(struct intel_display *display, u16 reg, 677fb3a1f7SJani Nikula enum intel_sbi_destination destination) 687fb3a1f7SJani Nikula { 697fb3a1f7SJani Nikula u32 result = 0; 707fb3a1f7SJani Nikula 71a737ab4aSJani Nikula intel_sbi_rw(display, reg, destination, &result, true); 727fb3a1f7SJani Nikula 737fb3a1f7SJani Nikula return result; 747fb3a1f7SJani Nikula } 757fb3a1f7SJani Nikula 76a737ab4aSJani Nikula void intel_sbi_write(struct intel_display *display, u16 reg, u32 value, 777fb3a1f7SJani Nikula enum intel_sbi_destination destination) 787fb3a1f7SJani Nikula { 79a737ab4aSJani Nikula intel_sbi_rw(display, reg, destination, &value, false); 807fb3a1f7SJani Nikula } 817fb3a1f7SJani Nikula 82a737ab4aSJani Nikula void intel_sbi_init(struct intel_display *display) 837fb3a1f7SJani Nikula { 849ab17edeSJani Nikula mutex_init(&display->sbi.lock); 857fb3a1f7SJani Nikula } 867fb3a1f7SJani Nikula 87a737ab4aSJani Nikula void intel_sbi_fini(struct intel_display *display) 887fb3a1f7SJani Nikula { 899ab17edeSJani Nikula mutex_destroy(&display->sbi.lock); 907fb3a1f7SJani Nikula } 91