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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'i2c-for-6.13-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c fixes from Wolfram Sang:

- IMX: fix stop condition in single master mode and add compatible
string for errata adherence

- Microchip: Add support for proper repeated sends and fix unnecessary
NAKs on empty messages, which caused false bus detection

* tag 'i2c-for-6.13-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
i2c: microchip-core: fix "ghost" detections
i2c: microchip-core: actually use repeated sends
i2c: imx: add imx7d compatible string for applying erratum ERR007805
i2c: imx: fix missing stop condition in single-master mode

+100 -35
+4 -5
drivers/i2c/busses/i2c-imx.c
··· 335 335 { .compatible = "fsl,imx6sll-i2c", .data = &imx6_i2c_hwdata, }, 336 336 { .compatible = "fsl,imx6sx-i2c", .data = &imx6_i2c_hwdata, }, 337 337 { .compatible = "fsl,imx6ul-i2c", .data = &imx6_i2c_hwdata, }, 338 + { .compatible = "fsl,imx7d-i2c", .data = &imx6_i2c_hwdata, }, 338 339 { .compatible = "fsl,imx7s-i2c", .data = &imx6_i2c_hwdata, }, 339 340 { .compatible = "fsl,imx8mm-i2c", .data = &imx6_i2c_hwdata, }, 340 341 { .compatible = "fsl,imx8mn-i2c", .data = &imx6_i2c_hwdata, }, ··· 533 532 534 533 static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool atomic) 535 534 { 535 + bool multi_master = i2c_imx->multi_master; 536 536 unsigned long orig_jiffies = jiffies; 537 537 unsigned int temp; 538 - 539 - if (!i2c_imx->multi_master) 540 - return 0; 541 538 542 539 while (1) { 543 540 temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); 544 541 545 542 /* check for arbitration lost */ 546 - if (temp & I2SR_IAL) { 543 + if (multi_master && (temp & I2SR_IAL)) { 547 544 i2c_imx_clear_irq(i2c_imx, I2SR_IAL); 548 545 return -EAGAIN; 549 546 } 550 547 551 - if (for_busy && (temp & I2SR_IBB)) { 548 + if (for_busy && (!multi_master || (temp & I2SR_IBB))) { 552 549 i2c_imx->stopped = 0; 553 550 break; 554 551 }
+96 -30
drivers/i2c/busses/i2c-microchip-corei2c.c
··· 93 93 * @base: pointer to register struct 94 94 * @dev: device reference 95 95 * @i2c_clk: clock reference for i2c input clock 96 + * @msg_queue: pointer to the messages requiring sending 96 97 * @buf: pointer to msg buffer for easier use 97 98 * @msg_complete: xfer completion object 98 99 * @adapter: core i2c abstraction 99 100 * @msg_err: error code for completed message 100 101 * @bus_clk_rate: current i2c bus clock rate 101 102 * @isr_status: cached copy of local ISR status 103 + * @total_num: total number of messages to be sent/received 104 + * @current_num: index of the current message being sent/received 102 105 * @msg_len: number of bytes transferred in msg 103 106 * @addr: address of the current slave 107 + * @restart_needed: whether or not a repeated start is required after current message 104 108 */ 105 109 struct mchp_corei2c_dev { 106 110 void __iomem *base; 107 111 struct device *dev; 108 112 struct clk *i2c_clk; 113 + struct i2c_msg *msg_queue; 109 114 u8 *buf; 110 115 struct completion msg_complete; 111 116 struct i2c_adapter adapter; 112 117 int msg_err; 118 + int total_num; 119 + int current_num; 113 120 u32 bus_clk_rate; 114 121 u32 isr_status; 115 122 u16 msg_len; 116 123 u8 addr; 124 + bool restart_needed; 117 125 }; 118 126 119 127 static void mchp_corei2c_core_disable(struct mchp_corei2c_dev *idev) ··· 230 222 return 0; 231 223 } 232 224 225 + static void mchp_corei2c_next_msg(struct mchp_corei2c_dev *idev) 226 + { 227 + struct i2c_msg *this_msg; 228 + u8 ctrl; 229 + 230 + if (idev->current_num >= idev->total_num) { 231 + complete(&idev->msg_complete); 232 + return; 233 + } 234 + 235 + /* 236 + * If there's been an error, the isr needs to return control 237 + * to the "main" part of the driver, so as not to keep sending 238 + * messages once it completes and clears the SI bit. 239 + */ 240 + if (idev->msg_err) { 241 + complete(&idev->msg_complete); 242 + return; 243 + } 244 + 245 + this_msg = idev->msg_queue++; 246 + 247 + if (idev->current_num < (idev->total_num - 1)) { 248 + struct i2c_msg *next_msg = idev->msg_queue; 249 + 250 + idev->restart_needed = next_msg->flags & I2C_M_RD; 251 + } else { 252 + idev->restart_needed = false; 253 + } 254 + 255 + idev->addr = i2c_8bit_addr_from_msg(this_msg); 256 + idev->msg_len = this_msg->len; 257 + idev->buf = this_msg->buf; 258 + 259 + ctrl = readb(idev->base + CORE_I2C_CTRL); 260 + ctrl |= CTRL_STA; 261 + writeb(ctrl, idev->base + CORE_I2C_CTRL); 262 + 263 + idev->current_num++; 264 + } 265 + 233 266 static irqreturn_t mchp_corei2c_handle_isr(struct mchp_corei2c_dev *idev) 234 267 { 235 268 u32 status = idev->isr_status; ··· 287 238 ctrl &= ~CTRL_STA; 288 239 writeb(idev->addr, idev->base + CORE_I2C_DATA); 289 240 writeb(ctrl, idev->base + CORE_I2C_CTRL); 290 - if (idev->msg_len == 0) 291 - finished = true; 292 241 break; 293 242 case STATUS_M_ARB_LOST: 294 243 idev->msg_err = -EAGAIN; ··· 294 247 break; 295 248 case STATUS_M_SLAW_ACK: 296 249 case STATUS_M_TX_DATA_ACK: 297 - if (idev->msg_len > 0) 250 + if (idev->msg_len > 0) { 298 251 mchp_corei2c_fill_tx(idev); 299 - else 300 - last_byte = true; 252 + } else { 253 + if (idev->restart_needed) 254 + finished = true; 255 + else 256 + last_byte = true; 257 + } 301 258 break; 302 259 case STATUS_M_TX_DATA_NACK: 303 260 case STATUS_M_SLAR_NACK: ··· 338 287 mchp_corei2c_stop(idev); 339 288 340 289 if (last_byte || finished) 341 - complete(&idev->msg_complete); 290 + mchp_corei2c_next_msg(idev); 342 291 343 292 return IRQ_HANDLED; 344 293 } ··· 362 311 return ret; 363 312 } 364 313 365 - static int mchp_corei2c_xfer_msg(struct mchp_corei2c_dev *idev, 366 - struct i2c_msg *msg) 314 + static int mchp_corei2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, 315 + int num) 367 316 { 368 - u8 ctrl; 317 + struct mchp_corei2c_dev *idev = i2c_get_adapdata(adap); 318 + struct i2c_msg *this_msg = msgs; 369 319 unsigned long time_left; 370 - 371 - idev->addr = i2c_8bit_addr_from_msg(msg); 372 - idev->msg_len = msg->len; 373 - idev->buf = msg->buf; 374 - idev->msg_err = 0; 375 - 376 - reinit_completion(&idev->msg_complete); 320 + u8 ctrl; 377 321 378 322 mchp_corei2c_core_enable(idev); 379 323 324 + /* 325 + * The isr controls the flow of a transfer, this info needs to be saved 326 + * to a location that it can access the queue information from. 327 + */ 328 + idev->restart_needed = false; 329 + idev->msg_queue = msgs; 330 + idev->total_num = num; 331 + idev->current_num = 0; 332 + 333 + /* 334 + * But the first entry to the isr is triggered by the start in this 335 + * function, so the first message needs to be "dequeued". 336 + */ 337 + idev->addr = i2c_8bit_addr_from_msg(this_msg); 338 + idev->msg_len = this_msg->len; 339 + idev->buf = this_msg->buf; 340 + idev->msg_err = 0; 341 + 342 + if (idev->total_num > 1) { 343 + struct i2c_msg *next_msg = msgs + 1; 344 + 345 + idev->restart_needed = next_msg->flags & I2C_M_RD; 346 + } 347 + 348 + idev->current_num++; 349 + idev->msg_queue++; 350 + 351 + reinit_completion(&idev->msg_complete); 352 + 353 + /* 354 + * Send the first start to pass control to the isr 355 + */ 380 356 ctrl = readb(idev->base + CORE_I2C_CTRL); 381 357 ctrl |= CTRL_STA; 382 358 writeb(ctrl, idev->base + CORE_I2C_CTRL); ··· 413 335 if (!time_left) 414 336 return -ETIMEDOUT; 415 337 416 - return idev->msg_err; 417 - } 418 - 419 - static int mchp_corei2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, 420 - int num) 421 - { 422 - struct mchp_corei2c_dev *idev = i2c_get_adapdata(adap); 423 - int i, ret; 424 - 425 - for (i = 0; i < num; i++) { 426 - ret = mchp_corei2c_xfer_msg(idev, msgs++); 427 - if (ret) 428 - return ret; 429 - } 338 + if (idev->msg_err) 339 + return idev->msg_err; 430 340 431 341 return num; 432 342 }