1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2022 Intel Corporation
4  */
5 
6 #include "i915_drv.h"
7 #include "i915_reg.h"
8 
9 #include "intel_de.h"
10 #include "intel_display.h"
11 #include "intel_dkl_phy.h"
12 #include "intel_dkl_phy_regs.h"
13 
14 static void
dkl_phy_set_hip_idx(struct drm_i915_private * i915,struct intel_dkl_phy_reg reg)15 dkl_phy_set_hip_idx(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg)
16 {
17 	enum tc_port tc_port = DKL_REG_TC_PORT(reg);
18 
19 	drm_WARN_ON(&i915->drm, tc_port < TC_PORT_1 || tc_port >= I915_MAX_TC_PORTS);
20 
21 	intel_de_write(i915,
22 		       HIP_INDEX_REG(tc_port),
23 		       HIP_INDEX_VAL(tc_port, reg.bank_idx));
24 }
25 
26 /**
27  * intel_dkl_phy_read - read a Dekel PHY register
28  * @i915: i915 device instance
29  * @reg: Dekel PHY register
30  *
31  * Read the @reg Dekel PHY register.
32  *
33  * Returns the read value.
34  */
35 u32
intel_dkl_phy_read(struct drm_i915_private * i915,struct intel_dkl_phy_reg reg)36 intel_dkl_phy_read(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg)
37 {
38 	u32 val;
39 
40 	spin_lock(&i915->display.dkl.phy_lock);
41 
42 	dkl_phy_set_hip_idx(i915, reg);
43 	val = intel_de_read(i915, DKL_REG_MMIO(reg));
44 
45 	spin_unlock(&i915->display.dkl.phy_lock);
46 
47 	return val;
48 }
49 
50 /**
51  * intel_dkl_phy_write - write a Dekel PHY register
52  * @i915: i915 device instance
53  * @reg: Dekel PHY register
54  * @val: value to write
55  *
56  * Write @val to the @reg Dekel PHY register.
57  */
58 void
intel_dkl_phy_write(struct drm_i915_private * i915,struct intel_dkl_phy_reg reg,u32 val)59 intel_dkl_phy_write(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg, u32 val)
60 {
61 	spin_lock(&i915->display.dkl.phy_lock);
62 
63 	dkl_phy_set_hip_idx(i915, reg);
64 	intel_de_write(i915, DKL_REG_MMIO(reg), val);
65 
66 	spin_unlock(&i915->display.dkl.phy_lock);
67 }
68 
69 /**
70  * intel_dkl_phy_rmw - read-modify-write a Dekel PHY register
71  * @i915: i915 device instance
72  * @reg: Dekel PHY register
73  * @clear: mask to clear
74  * @set: mask to set
75  *
76  * Read the @reg Dekel PHY register, clearing then setting the @clear/@set bits in it, and writing
77  * this value back to the register if the value differs from the read one.
78  */
79 void
intel_dkl_phy_rmw(struct drm_i915_private * i915,struct intel_dkl_phy_reg reg,u32 clear,u32 set)80 intel_dkl_phy_rmw(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg, u32 clear, u32 set)
81 {
82 	spin_lock(&i915->display.dkl.phy_lock);
83 
84 	dkl_phy_set_hip_idx(i915, reg);
85 	intel_de_rmw(i915, DKL_REG_MMIO(reg), clear, set);
86 
87 	spin_unlock(&i915->display.dkl.phy_lock);
88 }
89 
90 /**
91  * intel_dkl_phy_posting_read - do a posting read from a Dekel PHY register
92  * @i915: i915 device instance
93  * @reg: Dekel PHY register
94  *
95  * Read the @reg Dekel PHY register without returning the read value.
96  */
97 void
intel_dkl_phy_posting_read(struct drm_i915_private * i915,struct intel_dkl_phy_reg reg)98 intel_dkl_phy_posting_read(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg)
99 {
100 	spin_lock(&i915->display.dkl.phy_lock);
101 
102 	dkl_phy_set_hip_idx(i915, reg);
103 	intel_de_posting_read(i915, DKL_REG_MMIO(reg));
104 
105 	spin_unlock(&i915->display.dkl.phy_lock);
106 }
107