162306a36Sopenharmony_ci// SPDX-License-Identifier: MIT 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright © 2013-2021 Intel Corporation 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * LPT/WPT IOSF sideband. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "i915_drv.h" 962306a36Sopenharmony_ci#include "intel_sbi.h" 1062306a36Sopenharmony_ci#include "i915_reg.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/* SBI access */ 1362306a36Sopenharmony_cistatic int intel_sbi_rw(struct drm_i915_private *i915, u16 reg, 1462306a36Sopenharmony_ci enum intel_sbi_destination destination, 1562306a36Sopenharmony_ci u32 *val, bool is_read) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci struct intel_uncore *uncore = &i915->uncore; 1862306a36Sopenharmony_ci u32 cmd; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci lockdep_assert_held(&i915->sb_lock); 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci if (intel_wait_for_register_fw(uncore, 2362306a36Sopenharmony_ci SBI_CTL_STAT, SBI_BUSY, 0, 2462306a36Sopenharmony_ci 100)) { 2562306a36Sopenharmony_ci drm_err(&i915->drm, 2662306a36Sopenharmony_ci "timeout waiting for SBI to become ready\n"); 2762306a36Sopenharmony_ci return -EBUSY; 2862306a36Sopenharmony_ci } 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci intel_uncore_write_fw(uncore, SBI_ADDR, (u32)reg << 16); 3162306a36Sopenharmony_ci intel_uncore_write_fw(uncore, SBI_DATA, is_read ? 0 : *val); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci if (destination == SBI_ICLK) 3462306a36Sopenharmony_ci cmd = SBI_CTL_DEST_ICLK | SBI_CTL_OP_CRRD; 3562306a36Sopenharmony_ci else 3662306a36Sopenharmony_ci cmd = SBI_CTL_DEST_MPHY | SBI_CTL_OP_IORD; 3762306a36Sopenharmony_ci if (!is_read) 3862306a36Sopenharmony_ci cmd |= BIT(8); 3962306a36Sopenharmony_ci intel_uncore_write_fw(uncore, SBI_CTL_STAT, cmd | SBI_BUSY); 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci if (__intel_wait_for_register_fw(uncore, 4262306a36Sopenharmony_ci SBI_CTL_STAT, SBI_BUSY, 0, 4362306a36Sopenharmony_ci 100, 100, &cmd)) { 4462306a36Sopenharmony_ci drm_err(&i915->drm, 4562306a36Sopenharmony_ci "timeout waiting for SBI to complete read\n"); 4662306a36Sopenharmony_ci return -ETIMEDOUT; 4762306a36Sopenharmony_ci } 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci if (cmd & SBI_RESPONSE_FAIL) { 5062306a36Sopenharmony_ci drm_err(&i915->drm, "error during SBI read of reg %x\n", reg); 5162306a36Sopenharmony_ci return -ENXIO; 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci if (is_read) 5562306a36Sopenharmony_ci *val = intel_uncore_read_fw(uncore, SBI_DATA); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci return 0; 5862306a36Sopenharmony_ci} 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ciu32 intel_sbi_read(struct drm_i915_private *i915, u16 reg, 6162306a36Sopenharmony_ci enum intel_sbi_destination destination) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci u32 result = 0; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci intel_sbi_rw(i915, reg, destination, &result, true); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci return result; 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_civoid intel_sbi_write(struct drm_i915_private *i915, u16 reg, u32 value, 7162306a36Sopenharmony_ci enum intel_sbi_destination destination) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci intel_sbi_rw(i915, reg, destination, &value, false); 7462306a36Sopenharmony_ci} 75