| 1 | // SPDX-License-Identifier: MIT | 
|---|
| 2 | /* | 
|---|
| 3 | * Copyright © 2013-2021 Intel Corporation | 
|---|
| 4 | * | 
|---|
| 5 | * LPT/WPT IOSF sideband. | 
|---|
| 6 | */ | 
|---|
| 7 |  | 
|---|
| 8 | #include <drm/drm_print.h> | 
|---|
| 9 |  | 
|---|
| 10 | #include "intel_de.h" | 
|---|
| 11 | #include "intel_display_core.h" | 
|---|
| 12 | #include "intel_sbi.h" | 
|---|
| 13 | #include "intel_sbi_regs.h" | 
|---|
| 14 |  | 
|---|
| 15 | /* SBI access */ | 
|---|
| 16 | static int intel_sbi_rw(struct intel_display *display, u16 reg, | 
|---|
| 17 | enum intel_sbi_destination destination, | 
|---|
| 18 | u32 *val, bool is_read) | 
|---|
| 19 | { | 
|---|
| 20 | u32 cmd; | 
|---|
| 21 |  | 
|---|
| 22 | lockdep_assert_held(&display->sbi.lock); | 
|---|
| 23 |  | 
|---|
| 24 | if (intel_de_wait_fw(display, SBI_CTL_STAT, SBI_STATUS_MASK, SBI_STATUS_READY, timeout_ms: 100, NULL)) { | 
|---|
| 25 | drm_err(display->drm, "timeout waiting for SBI to become ready\n"); | 
|---|
| 26 | return -EBUSY; | 
|---|
| 27 | } | 
|---|
| 28 |  | 
|---|
| 29 | intel_de_write_fw(display, SBI_ADDR, SBI_ADDR_VALUE(reg)); | 
|---|
| 30 | intel_de_write_fw(display, SBI_DATA, val: is_read ? 0 : *val); | 
|---|
| 31 |  | 
|---|
| 32 | if (destination == SBI_ICLK) | 
|---|
| 33 | cmd = SBI_CTL_DEST_ICLK | SBI_CTL_OP_CRRD; | 
|---|
| 34 | else | 
|---|
| 35 | cmd = SBI_CTL_DEST_MPHY | SBI_CTL_OP_IORD; | 
|---|
| 36 | if (!is_read) | 
|---|
| 37 | cmd |= SBI_CTL_OP_WR; | 
|---|
| 38 | intel_de_write_fw(display, SBI_CTL_STAT, val: cmd | SBI_STATUS_BUSY); | 
|---|
| 39 |  | 
|---|
| 40 | if (intel_de_wait_fw(display, SBI_CTL_STAT, SBI_STATUS_MASK, SBI_STATUS_READY, timeout_ms: 100, out_value: &cmd)) { | 
|---|
| 41 | drm_err(display->drm, "timeout waiting for SBI to complete read\n"); | 
|---|
| 42 | return -ETIMEDOUT; | 
|---|
| 43 | } | 
|---|
| 44 |  | 
|---|
| 45 | if (cmd & SBI_RESPONSE_FAIL) { | 
|---|
| 46 | drm_err(display->drm, "error during SBI read of reg %x\n", reg); | 
|---|
| 47 | return -ENXIO; | 
|---|
| 48 | } | 
|---|
| 49 |  | 
|---|
| 50 | if (is_read) | 
|---|
| 51 | *val = intel_de_read_fw(display, SBI_DATA); | 
|---|
| 52 |  | 
|---|
| 53 | return 0; | 
|---|
| 54 | } | 
|---|
| 55 |  | 
|---|
| 56 | void intel_sbi_lock(struct intel_display *display) | 
|---|
| 57 | { | 
|---|
| 58 | mutex_lock(lock: &display->sbi.lock); | 
|---|
| 59 | } | 
|---|
| 60 |  | 
|---|
| 61 | void intel_sbi_unlock(struct intel_display *display) | 
|---|
| 62 | { | 
|---|
| 63 | mutex_unlock(lock: &display->sbi.lock); | 
|---|
| 64 | } | 
|---|
| 65 |  | 
|---|
| 66 | u32 intel_sbi_read(struct intel_display *display, u16 reg, | 
|---|
| 67 | enum intel_sbi_destination destination) | 
|---|
| 68 | { | 
|---|
| 69 | u32 result = 0; | 
|---|
| 70 |  | 
|---|
| 71 | intel_sbi_rw(display, reg, destination, val: &result, is_read: true); | 
|---|
| 72 |  | 
|---|
| 73 | return result; | 
|---|
| 74 | } | 
|---|
| 75 |  | 
|---|
| 76 | void intel_sbi_write(struct intel_display *display, u16 reg, u32 value, | 
|---|
| 77 | enum intel_sbi_destination destination) | 
|---|
| 78 | { | 
|---|
| 79 | intel_sbi_rw(display, reg, destination, val: &value, is_read: false); | 
|---|
| 80 | } | 
|---|
| 81 |  | 
|---|
| 82 | void intel_sbi_init(struct intel_display *display) | 
|---|
| 83 | { | 
|---|
| 84 | mutex_init(&display->sbi.lock); | 
|---|
| 85 | } | 
|---|
| 86 |  | 
|---|
| 87 | void intel_sbi_fini(struct intel_display *display) | 
|---|
| 88 | { | 
|---|
| 89 | mutex_destroy(lock: &display->sbi.lock); | 
|---|
| 90 | } | 
|---|
| 91 |  | 
|---|