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
13 static void
dkl_phy_set_hip_idx(struct drm_i915_private * i915,i915_reg_t reg,int idx)14 dkl_phy_set_hip_idx(struct drm_i915_private *i915, i915_reg_t reg, int idx)
15 {
16 enum tc_port tc_port = DKL_REG_TC_PORT(reg);
17
18 drm_WARN_ON(&i915->drm, tc_port < TC_PORT_1 || tc_port >= I915_MAX_TC_PORTS);
19
20 intel_de_write(i915,
21 HIP_INDEX_REG(tc_port),
22 HIP_INDEX_VAL(tc_port, idx));
23 }
24
25 /**
26 * intel_dkl_phy_read - read a Dekel PHY register
27 * @i915: i915 device instance
28 * @reg: Dekel PHY register
29 * @ln: lane instance of @reg
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,i915_reg_t reg,int ln)36 intel_dkl_phy_read(struct drm_i915_private *i915, i915_reg_t reg, int ln)
37 {
38 u32 val;
39
40 spin_lock(&i915->display.dkl.phy_lock);
41
42 dkl_phy_set_hip_idx(i915, reg, ln);
43 val = intel_de_read(i915, 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 * @ln: lane instance of @reg
55 * @val: value to write
56 *
57 * Write @val to the @reg Dekel PHY register.
58 */
59 void
intel_dkl_phy_write(struct drm_i915_private * i915,i915_reg_t reg,int ln,u32 val)60 intel_dkl_phy_write(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 val)
61 {
62 spin_lock(&i915->display.dkl.phy_lock);
63
64 dkl_phy_set_hip_idx(i915, reg, ln);
65 intel_de_write(i915, reg, val);
66
67 spin_unlock(&i915->display.dkl.phy_lock);
68 }
69
70 /**
71 * intel_dkl_phy_rmw - read-modify-write a Dekel PHY register
72 * @i915: i915 device instance
73 * @reg: Dekel PHY register
74 * @ln: lane instance of @reg
75 * @clear: mask to clear
76 * @set: mask to set
77 *
78 * Read the @reg Dekel PHY register, clearing then setting the @clear/@set bits in it, and writing
79 * this value back to the register if the value differs from the read one.
80 */
81 void
intel_dkl_phy_rmw(struct drm_i915_private * i915,i915_reg_t reg,int ln,u32 clear,u32 set)82 intel_dkl_phy_rmw(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 clear, u32 set)
83 {
84 spin_lock(&i915->display.dkl.phy_lock);
85
86 dkl_phy_set_hip_idx(i915, reg, ln);
87 intel_de_rmw(i915, reg, clear, set);
88
89 spin_unlock(&i915->display.dkl.phy_lock);
90 }
91
92 /**
93 * intel_dkl_phy_posting_read - do a posting read from a Dekel PHY register
94 * @i915: i915 device instance
95 * @reg: Dekel PHY register
96 * @ln: lane instance of @reg
97 *
98 * Read the @reg Dekel PHY register without returning the read value.
99 */
100 void
intel_dkl_phy_posting_read(struct drm_i915_private * i915,i915_reg_t reg,int ln)101 intel_dkl_phy_posting_read(struct drm_i915_private *i915, i915_reg_t reg, int ln)
102 {
103 spin_lock(&i915->display.dkl.phy_lock);
104
105 dkl_phy_set_hip_idx(i915, reg, ln);
106 intel_de_posting_read(i915, reg);
107
108 spin_unlock(&i915->display.dkl.phy_lock);
109 }
110