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