1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2026 David Yang 4 */ 5 6 #include <linux/iopoll.h> 7 8 #include "chip.h" 9 #include "smi.h" 10 11 #define YT921X_POLL_SLEEP_US 10000 12 #define YT921X_POLL_TIMEOUT_US 100000 13 14 int yt921x_reg_read(struct yt921x_priv *priv, u32 reg, u32 *valp) 15 { 16 lockdep_assert_held_once(&priv->reg_lock); 17 18 return priv->reg_ops->read(priv->reg_ctx, reg, valp); 19 } 20 21 int yt921x_reg_write(struct yt921x_priv *priv, u32 reg, u32 val) 22 { 23 lockdep_assert_held_once(&priv->reg_lock); 24 25 return priv->reg_ops->write(priv->reg_ctx, reg, val); 26 } 27 28 int yt921x_reg_wait(struct yt921x_priv *priv, u32 reg, u32 mask, u32 *valp) 29 { 30 u32 val; 31 int res; 32 int ret; 33 34 ret = read_poll_timeout(yt921x_reg_read, res, 35 res || (val & mask) == *valp, 36 YT921X_POLL_SLEEP_US, YT921X_POLL_TIMEOUT_US, 37 false, priv, reg, &val); 38 if (ret) 39 return ret; 40 if (res) 41 return res; 42 43 *valp = val; 44 return 0; 45 } 46 47 int yt921x_reg_update_bits(struct yt921x_priv *priv, u32 reg, u32 mask, u32 val) 48 { 49 int res; 50 u32 v; 51 u32 u; 52 53 res = yt921x_reg_read(priv, reg, &v); 54 if (res) 55 return res; 56 57 u = v; 58 u &= ~mask; 59 u |= val; 60 if (u == v) 61 return 0; 62 63 return yt921x_reg_write(priv, reg, u); 64 } 65 66 static int 67 yt921x_regs_read(struct yt921x_priv *priv, u32 reg, u32 *vals, 68 unsigned int num_regs) 69 { 70 int res; 71 72 for (unsigned int i = 0; i < num_regs; i++) { 73 res = yt921x_reg_read(priv, reg + 4 * i, &vals[i]); 74 if (res) 75 return res; 76 } 77 78 return 0; 79 } 80 81 static int 82 yt921x_regs_write(struct yt921x_priv *priv, u32 reg, const u32 *vals, 83 unsigned int num_regs) 84 { 85 int res; 86 87 for (unsigned int i = 0; i < num_regs; i++) { 88 res = yt921x_reg_write(priv, reg + 4 * i, vals[i]); 89 if (res) 90 return res; 91 } 92 93 return 0; 94 } 95 96 static int 97 yt921x_regs_update_bits(struct yt921x_priv *priv, u32 reg, const u32 *masks, 98 const u32 *vals, unsigned int num_regs) 99 { 100 bool changed = false; 101 u32 vs[4]; 102 int res; 103 104 BUILD_BUG_ON(num_regs > ARRAY_SIZE(vs)); 105 106 res = yt921x_regs_read(priv, reg, vs, num_regs); 107 if (res) 108 return res; 109 110 for (unsigned int i = 0; i < num_regs; i++) { 111 u32 u = vs[i]; 112 113 u &= ~masks[i]; 114 u |= vals[i]; 115 if (u != vs[i]) 116 changed = true; 117 118 vs[i] = u; 119 } 120 121 if (!changed) 122 return 0; 123 124 return yt921x_regs_write(priv, reg, vs, num_regs); 125 } 126 127 static int 128 yt921x_regs_clear_bits(struct yt921x_priv *priv, u32 reg, const u32 *masks, 129 unsigned int num_regs) 130 { 131 bool changed = false; 132 u32 vs[4]; 133 int res; 134 135 BUILD_BUG_ON(num_regs > ARRAY_SIZE(vs)); 136 137 res = yt921x_regs_read(priv, reg, vs, num_regs); 138 if (res) 139 return res; 140 141 for (unsigned int i = 0; i < num_regs; i++) { 142 u32 u = vs[i]; 143 144 u &= ~masks[i]; 145 if (u != vs[i]) 146 changed = true; 147 148 vs[i] = u; 149 } 150 151 if (!changed) 152 return 0; 153 154 return yt921x_regs_write(priv, reg, vs, num_regs); 155 } 156 157 int 158 yt921x_reg64_write(struct yt921x_priv *priv, u32 reg, const u32 *vals) 159 { 160 return yt921x_regs_write(priv, reg, vals, 2); 161 } 162 163 int 164 yt921x_reg64_update_bits(struct yt921x_priv *priv, u32 reg, const u32 *masks, 165 const u32 *vals) 166 { 167 return yt921x_regs_update_bits(priv, reg, masks, vals, 2); 168 } 169 170 int 171 yt921x_reg64_clear_bits(struct yt921x_priv *priv, u32 reg, const u32 *masks) 172 { 173 return yt921x_regs_clear_bits(priv, reg, masks, 2); 174 } 175 176 int 177 yt921x_reg96_write(struct yt921x_priv *priv, u32 reg, const u32 *vals) 178 { 179 return yt921x_regs_write(priv, reg, vals, 3); 180 } 181