1 | // SPDX-License-Identifier: MIT |
2 | /* |
3 | * Copyright © 2013-2021 Intel Corporation |
4 | * |
5 | * LPT/WPT IOSF sideband. |
6 | */ |
7 | |
8 | #include "i915_drv.h" |
9 | #include "intel_sbi.h" |
10 | #include "i915_reg.h" |
11 | |
12 | /* SBI access */ |
13 | static int intel_sbi_rw(struct drm_i915_private *i915, u16 reg, |
14 | enum intel_sbi_destination destination, |
15 | u32 *val, bool is_read) |
16 | { |
17 | struct intel_uncore *uncore = &i915->uncore; |
18 | u32 cmd; |
19 | |
20 | lockdep_assert_held(&i915->sb_lock); |
21 | |
22 | if (intel_wait_for_register_fw(uncore, |
23 | SBI_CTL_STAT, SBI_BUSY, value: 0, |
24 | timeout_ms: 100)) { |
25 | drm_err(&i915->drm, |
26 | "timeout waiting for SBI to become ready\n" ); |
27 | return -EBUSY; |
28 | } |
29 | |
30 | intel_uncore_write_fw(uncore, SBI_ADDR, (u32)reg << 16); |
31 | intel_uncore_write_fw(uncore, SBI_DATA, is_read ? 0 : *val); |
32 | |
33 | if (destination == SBI_ICLK) |
34 | cmd = SBI_CTL_DEST_ICLK | SBI_CTL_OP_CRRD; |
35 | else |
36 | cmd = SBI_CTL_DEST_MPHY | SBI_CTL_OP_IORD; |
37 | if (!is_read) |
38 | cmd |= BIT(8); |
39 | intel_uncore_write_fw(uncore, SBI_CTL_STAT, cmd | SBI_BUSY); |
40 | |
41 | if (__intel_wait_for_register_fw(uncore, |
42 | SBI_CTL_STAT, SBI_BUSY, value: 0, |
43 | fast_timeout_us: 100, slow_timeout_ms: 100, out_value: &cmd)) { |
44 | drm_err(&i915->drm, |
45 | "timeout waiting for SBI to complete read\n" ); |
46 | return -ETIMEDOUT; |
47 | } |
48 | |
49 | if (cmd & SBI_RESPONSE_FAIL) { |
50 | drm_err(&i915->drm, "error during SBI read of reg %x\n" , reg); |
51 | return -ENXIO; |
52 | } |
53 | |
54 | if (is_read) |
55 | *val = intel_uncore_read_fw(uncore, SBI_DATA); |
56 | |
57 | return 0; |
58 | } |
59 | |
60 | u32 intel_sbi_read(struct drm_i915_private *i915, u16 reg, |
61 | enum intel_sbi_destination destination) |
62 | { |
63 | u32 result = 0; |
64 | |
65 | intel_sbi_rw(i915, reg, destination, val: &result, is_read: true); |
66 | |
67 | return result; |
68 | } |
69 | |
70 | void intel_sbi_write(struct drm_i915_private *i915, u16 reg, u32 value, |
71 | enum intel_sbi_destination destination) |
72 | { |
73 | intel_sbi_rw(i915, reg, destination, val: &value, is_read: false); |
74 | } |
75 | |