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