Re: [PATCH v3 2/3] i2c: add support for HiSilicon I2C controller

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.

Parens around DIV_ROUND_UP_ULL aren't needed.

...
> +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?

> +}
> +
> +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.

...
> +/*
> + * 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.



[Index of Archives]     [Linux GPIO]     [Linux SPI]     [Linux Hardward Monitoring]     [LM Sensors]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux