Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ptp: ptp_clockmatrix: use i2c_master_send for i2c write

The old code for i2c write would break on some controllers, which fails
at handling Repeated Start Condition. So we will just use i2c_master_send
to handle write in one transanction.

Changes since v1:
- Remove indentation change

Signed-off-by: Min Li <min.li.xe@renesas.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Min Li and committed by
David S. Miller
957ff427 d1fb5559

+45 -13
+43 -13
drivers/ptp/ptp_clockmatrix.c
··· 142 142 return result; 143 143 } 144 144 145 - static int idtcm_xfer(struct idtcm *idtcm, 146 - u8 regaddr, 147 - u8 *buf, 148 - u16 count, 149 - bool write) 145 + static int idtcm_xfer_read(struct idtcm *idtcm, 146 + u8 regaddr, 147 + u8 *buf, 148 + u16 count) 150 149 { 151 150 struct i2c_client *client = idtcm->client; 152 151 struct i2c_msg msg[2]; 153 152 int cnt; 154 - char *fmt = "i2c_transfer failed at %d in %s for %s, at addr: %04X!\n"; 153 + char *fmt = "i2c_transfer failed at %d in %s, at addr: %04X!\n"; 155 154 156 155 msg[0].addr = client->addr; 157 156 msg[0].flags = 0; ··· 158 159 msg[0].buf = &regaddr; 159 160 160 161 msg[1].addr = client->addr; 161 - msg[1].flags = write ? 0 : I2C_M_RD; 162 + msg[1].flags = I2C_M_RD; 162 163 msg[1].len = count; 163 164 msg[1].buf = buf; 164 165 ··· 169 170 fmt, 170 171 __LINE__, 171 172 __func__, 172 - write ? "write" : "read", 173 173 regaddr); 174 174 return cnt; 175 175 } else if (cnt != 2) { 176 176 dev_err(&client->dev, 177 177 "i2c_transfer sent only %d of %d messages\n", cnt, 2); 178 178 return -EIO; 179 + } 180 + 181 + return 0; 182 + } 183 + 184 + static int idtcm_xfer_write(struct idtcm *idtcm, 185 + u8 regaddr, 186 + u8 *buf, 187 + u16 count) 188 + { 189 + struct i2c_client *client = idtcm->client; 190 + /* we add 1 byte for device register */ 191 + u8 msg[IDTCM_MAX_WRITE_COUNT + 1]; 192 + int cnt; 193 + char *fmt = "i2c_master_send failed at %d in %s, at addr: %04X!\n"; 194 + 195 + if (count > IDTCM_MAX_WRITE_COUNT) 196 + return -EINVAL; 197 + 198 + msg[0] = regaddr; 199 + memcpy(&msg[1], buf, count); 200 + 201 + cnt = i2c_master_send(client, msg, count + 1); 202 + 203 + if (cnt < 0) { 204 + dev_err(&client->dev, 205 + fmt, 206 + __LINE__, 207 + __func__, 208 + regaddr); 209 + return cnt; 179 210 } 180 211 181 212 return 0; ··· 224 195 buf[2] = 0x10; 225 196 buf[3] = 0x20; 226 197 227 - err = idtcm_xfer(idtcm, PAGE_ADDR, buf, sizeof(buf), 1); 198 + err = idtcm_xfer_write(idtcm, PAGE_ADDR, buf, sizeof(buf)); 228 199 229 200 if (err) { 230 201 idtcm->page_offset = 0xff; ··· 252 223 err = idtcm_page_offset(idtcm, hi); 253 224 254 225 if (err) 255 - goto out; 226 + return err; 256 227 257 - err = idtcm_xfer(idtcm, lo, buf, count, write); 258 - out: 259 - return err; 228 + if (write) 229 + return idtcm_xfer_write(idtcm, lo, buf, count); 230 + 231 + return idtcm_xfer_read(idtcm, lo, buf, count); 260 232 } 261 233 262 234 static int idtcm_read(struct idtcm *idtcm,
+2
drivers/ptp/ptp_clockmatrix.h
··· 55 55 56 56 #define PEROUT_ENABLE_OUTPUT_MASK (0xdeadbeef) 57 57 58 + #define IDTCM_MAX_WRITE_COUNT (512) 59 + 58 60 /* Values of DPLL_N.DPLL_MODE.PLL_MODE */ 59 61 enum pll_mode { 60 62 PLL_MODE_MIN = 0,