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