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