Hi Dmitry, Thanks for reviewing this. On 2021/3/22 23:21, Dmitry Osipenko wrote: > Hello Yicong, > > 22.03.2021 14:10, Yicong Yang пишет: >> Add HiSilicon I2C controller driver for the Kunpeng SoC. It provides >> the access to the i2c busses, which connects to the eeprom, rtc, etc. >> >> The driver works with IRQ mode, and supports basic I2C features and 10bit >> address. The DMA is not supported. >> >> Signed-off-by: Yicong Yang <yangyicong@xxxxxxxxxxxxx> >> --- >> drivers/i2c/busses/Kconfig | 10 + >> drivers/i2c/busses/Makefile | 1 + >> drivers/i2c/busses/i2c-hisi.c | 525 ++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 536 insertions(+) >> create mode 100644 drivers/i2c/busses/i2c-hisi.c > > ... >> + >> +#define NSEC_TO_CYCLES(ns, clk_rate_khz) (DIV_ROUND_UP_ULL((clk_rate_khz) * (ns), NSEC_PER_MSEC)) > > This is a very long line, you should split it into two. will split. > > Parens around DIV_ROUND_UP_ULL aren't needed. > will drop the parens. > ... >> +static void hisi_i2c_enable_int(struct hisi_i2c_controller *ctlr, u32 mask) >> +{ >> + writel(mask, ctlr->iobase + HISI_I2C_INT_MASK); > > Why you don't use relaxed versions of readl/writel? Do you really need > to insert memory barriers? > this will not be used during the transfer process, so a relaxed version of readl/writel will not have performance enhancement. the barriers are necessary as i want to make the operations in order to avoid potential problems caused by reordering. >> +} >> + >> +static void hisi_i2c_disable_int(struct hisi_i2c_controller *ctlr, u32 mask) >> +{ >> + writel((~mask) & HISI_I2C_INT_ALL, ctlr->iobase + HISI_I2C_INT_MASK); >> +} >> + >> +static void hisi_i2c_clear_int(struct hisi_i2c_controller *ctlr, u32 mask) >> +{ >> + writel(mask, ctlr->iobase + HISI_I2C_INT_CLR); >> +} >> + >> +static void hisi_i2c_handle_errors(struct hisi_i2c_controller *ctlr) >> +{ >> + u32 int_err = ctlr->xfer_err, reg; >> + >> + if (int_err & HISI_I2C_INT_FIFO_ERR) { >> + reg = readl(ctlr->iobase + HISI_I2C_FIFO_STATE); >> + >> + if (reg & HISI_I2C_FIFO_STATE_RX_RERR) >> + dev_err(ctlr->dev, "rx fifo error read.\n"); > > The dot "." in the end of error messages is unnecessary. > i'd like to keep this, as i think this is rather driver specific and not violating any rules. > ... >> +/* >> + * Initialize the transfer information and start the I2C bus transfer. >> + * We only configure the transfer and do some pre/post works here, and >> + * wait for the transfer done. The major transfer process is performed >> + * in the IRQ handler. >> + */ >> +static int hisi_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, >> + int num) >> +{ >> + struct hisi_i2c_controller *ctlr = i2c_get_adapdata(adap); >> + DECLARE_COMPLETION_ONSTACK(done); >> + int ret = num; >> + >> + hisi_i2c_reset_xfer(ctlr); >> + ctlr->completion = &done; >> + ctlr->msg_num = num; >> + ctlr->msgs = msgs; >> + >> + hisi_i2c_start_xfer(ctlr); >> + >> + if (!wait_for_completion_timeout(ctlr->completion, adap->timeout)) { >> + hisi_i2c_disable_int(ctlr, HISI_I2C_INT_ALL); > > This doesn't save you from racing with the interrupt handler. It looks > like you need to enable/disable IRQ around the completion, similarly to > what NVIDIA Tegra I2C driver does. > thanks for suggestion. the hardware between tegra and this one is a little different as we don't provide a way to reinit the controller. so {synchronize,disable}_irq() after mask the interrupt here will avoid the race. Thanks, Yicong > . >