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 87fb3a1f7SJani Nikula #include "i915_drv.h" 97fb3a1f7SJani Nikula #include "i915_reg.h" 10*a737ab4aSJani Nikula #include "intel_display_core.h" 11*a737ab4aSJani Nikula #include "intel_sbi.h" 127fb3a1f7SJani Nikula 137fb3a1f7SJani Nikula /* SBI access */ 14*a737ab4aSJani Nikula static int intel_sbi_rw(struct intel_display *display, u16 reg, 157fb3a1f7SJani Nikula enum intel_sbi_destination destination, 167fb3a1f7SJani Nikula u32 *val, bool is_read) 177fb3a1f7SJani Nikula { 18*a737ab4aSJani Nikula struct drm_i915_private *i915 = to_i915(display->drm); 197fb3a1f7SJani Nikula struct intel_uncore *uncore = &i915->uncore; 207fb3a1f7SJani Nikula u32 cmd; 217fb3a1f7SJani Nikula 227fb3a1f7SJani Nikula lockdep_assert_held(&i915->sbi_lock); 237fb3a1f7SJani Nikula 247fb3a1f7SJani Nikula if (intel_wait_for_register_fw(uncore, 257fb3a1f7SJani Nikula SBI_CTL_STAT, SBI_BUSY, 0, 267fb3a1f7SJani Nikula 100)) { 27*a737ab4aSJani Nikula drm_err(display->drm, "timeout waiting for SBI to become ready\n"); 287fb3a1f7SJani Nikula return -EBUSY; 297fb3a1f7SJani Nikula } 307fb3a1f7SJani Nikula 317fb3a1f7SJani Nikula intel_uncore_write_fw(uncore, SBI_ADDR, (u32)reg << 16); 327fb3a1f7SJani Nikula intel_uncore_write_fw(uncore, SBI_DATA, is_read ? 0 : *val); 337fb3a1f7SJani Nikula 347fb3a1f7SJani Nikula if (destination == SBI_ICLK) 357fb3a1f7SJani Nikula cmd = SBI_CTL_DEST_ICLK | SBI_CTL_OP_CRRD; 367fb3a1f7SJani Nikula else 377fb3a1f7SJani Nikula cmd = SBI_CTL_DEST_MPHY | SBI_CTL_OP_IORD; 387fb3a1f7SJani Nikula if (!is_read) 397fb3a1f7SJani Nikula cmd |= BIT(8); 407fb3a1f7SJani Nikula intel_uncore_write_fw(uncore, SBI_CTL_STAT, cmd | SBI_BUSY); 417fb3a1f7SJani Nikula 427fb3a1f7SJani Nikula if (__intel_wait_for_register_fw(uncore, 437fb3a1f7SJani Nikula SBI_CTL_STAT, SBI_BUSY, 0, 447fb3a1f7SJani Nikula 100, 100, &cmd)) { 45*a737ab4aSJani Nikula drm_err(display->drm, "timeout waiting for SBI to complete read\n"); 467fb3a1f7SJani Nikula return -ETIMEDOUT; 477fb3a1f7SJani Nikula } 487fb3a1f7SJani Nikula 497fb3a1f7SJani Nikula if (cmd & SBI_RESPONSE_FAIL) { 50*a737ab4aSJani Nikula drm_err(display->drm, "error during SBI read of reg %x\n", reg); 517fb3a1f7SJani Nikula return -ENXIO; 527fb3a1f7SJani Nikula } 537fb3a1f7SJani Nikula 547fb3a1f7SJani Nikula if (is_read) 557fb3a1f7SJani Nikula *val = intel_uncore_read_fw(uncore, SBI_DATA); 567fb3a1f7SJani Nikula 577fb3a1f7SJani Nikula return 0; 587fb3a1f7SJani Nikula } 597fb3a1f7SJani Nikula 60*a737ab4aSJani Nikula void intel_sbi_lock(struct intel_display *display) 617fb3a1f7SJani Nikula { 62*a737ab4aSJani Nikula struct drm_i915_private *i915 = to_i915(display->drm); 63*a737ab4aSJani Nikula 647fb3a1f7SJani Nikula mutex_lock(&i915->sbi_lock); 657fb3a1f7SJani Nikula } 667fb3a1f7SJani Nikula 67*a737ab4aSJani Nikula void intel_sbi_unlock(struct intel_display *display) 687fb3a1f7SJani Nikula { 69*a737ab4aSJani Nikula struct drm_i915_private *i915 = to_i915(display->drm); 70*a737ab4aSJani Nikula 717fb3a1f7SJani Nikula mutex_unlock(&i915->sbi_lock); 727fb3a1f7SJani Nikula } 737fb3a1f7SJani Nikula 74*a737ab4aSJani Nikula u32 intel_sbi_read(struct intel_display *display, u16 reg, 757fb3a1f7SJani Nikula enum intel_sbi_destination destination) 767fb3a1f7SJani Nikula { 777fb3a1f7SJani Nikula u32 result = 0; 787fb3a1f7SJani Nikula 79*a737ab4aSJani Nikula intel_sbi_rw(display, reg, destination, &result, true); 807fb3a1f7SJani Nikula 817fb3a1f7SJani Nikula return result; 827fb3a1f7SJani Nikula } 837fb3a1f7SJani Nikula 84*a737ab4aSJani Nikula void intel_sbi_write(struct intel_display *display, u16 reg, u32 value, 857fb3a1f7SJani Nikula enum intel_sbi_destination destination) 867fb3a1f7SJani Nikula { 87*a737ab4aSJani Nikula intel_sbi_rw(display, reg, destination, &value, false); 887fb3a1f7SJani Nikula } 897fb3a1f7SJani Nikula 90*a737ab4aSJani Nikula void intel_sbi_init(struct intel_display *display) 917fb3a1f7SJani Nikula { 92*a737ab4aSJani Nikula struct drm_i915_private *i915 = to_i915(display->drm); 93*a737ab4aSJani Nikula 947fb3a1f7SJani Nikula mutex_init(&i915->sbi_lock); 957fb3a1f7SJani Nikula } 967fb3a1f7SJani Nikula 97*a737ab4aSJani Nikula void intel_sbi_fini(struct intel_display *display) 987fb3a1f7SJani Nikula { 99*a737ab4aSJani Nikula struct drm_i915_private *i915 = to_i915(display->drm); 100*a737ab4aSJani Nikula 1017fb3a1f7SJani Nikula mutex_destroy(&i915->sbi_lock); 1027fb3a1f7SJani Nikula } 103