xref: /linux/drivers/gpu/drm/i915/display/intel_sbi.c (revision a737ab4a87cb4a58b564a97bf313c8dfc15c7c53)
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