diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-stm32f7.c')
| -rw-r--r-- | drivers/i2c/busses/i2c-stm32f7.c | 82 | 
1 files changed, 42 insertions, 40 deletions
| diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index c62c815b88eb..0138317ea600 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -164,7 +164,6 @@ enum {  #define STM32F7_I2C_DNF_DEFAULT			0  #define STM32F7_I2C_DNF_MAX			15 -#define STM32F7_I2C_ANALOG_FILTER_ENABLE	1  #define STM32F7_I2C_ANALOG_FILTER_DELAY_MIN	50	/* ns */  #define STM32F7_I2C_ANALOG_FILTER_DELAY_MAX	260	/* ns */ @@ -223,8 +222,6 @@ struct stm32f7_i2c_spec {   * @clock_src: I2C clock source frequency (Hz)   * @rise_time: Rise time (ns)   * @fall_time: Fall time (ns) - * @dnf: Digital filter coefficient (0-16) - * @analog_filter: Analog filter delay (On/Off)   * @fmp_clr_offset: Fast Mode Plus clear register offset from set register   */  struct stm32f7_i2c_setup { @@ -232,8 +229,6 @@ struct stm32f7_i2c_setup {  	u32 clock_src;  	u32 rise_time;  	u32 fall_time; -	u8 dnf; -	bool analog_filter;  	u32 fmp_clr_offset;  }; @@ -312,6 +307,9 @@ struct stm32f7_i2c_msg {   * @wakeup_src: boolean to know if the device is a wakeup source   * @smbus_mode: states that the controller is configured in SMBus mode   * @host_notify_client: SMBus host-notify client + * @analog_filter: boolean to indicate enabling of the analog filter + * @dnf_dt: value of digital filter requested via dt + * @dnf: value of digital filter to apply   */  struct stm32f7_i2c_dev {  	struct i2c_adapter adap; @@ -340,6 +338,9 @@ struct stm32f7_i2c_dev {  	bool wakeup_src;  	bool smbus_mode;  	struct i2c_client *host_notify_client; +	bool analog_filter; +	u32 dnf_dt; +	u32 dnf;  };  /* @@ -385,15 +386,11 @@ static struct stm32f7_i2c_spec stm32f7_i2c_specs[] = {  static const struct stm32f7_i2c_setup stm32f7_setup = {  	.rise_time = STM32F7_I2C_RISE_TIME_DEFAULT,  	.fall_time = STM32F7_I2C_FALL_TIME_DEFAULT, -	.dnf = STM32F7_I2C_DNF_DEFAULT, -	.analog_filter = STM32F7_I2C_ANALOG_FILTER_ENABLE,  };  static const struct stm32f7_i2c_setup stm32mp15_setup = {  	.rise_time = STM32F7_I2C_RISE_TIME_DEFAULT,  	.fall_time = STM32F7_I2C_FALL_TIME_DEFAULT, -	.dnf = STM32F7_I2C_DNF_DEFAULT, -	.analog_filter = STM32F7_I2C_ANALOG_FILTER_ENABLE,  	.fmp_clr_offset = 0x40,  }; @@ -462,27 +459,28 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev,  		return -EINVAL;  	} -	if (setup->dnf > STM32F7_I2C_DNF_MAX) { +	i2c_dev->dnf = DIV_ROUND_CLOSEST(i2c_dev->dnf_dt, i2cclk); +	if (i2c_dev->dnf > STM32F7_I2C_DNF_MAX) {  		dev_err(i2c_dev->dev,  			"DNF out of bound %d/%d\n", -			setup->dnf, STM32F7_I2C_DNF_MAX); +			i2c_dev->dnf * i2cclk, STM32F7_I2C_DNF_MAX * i2cclk);  		return -EINVAL;  	}  	/*  Analog and Digital Filters */  	af_delay_min = -		(setup->analog_filter ? +		(i2c_dev->analog_filter ?  		 STM32F7_I2C_ANALOG_FILTER_DELAY_MIN : 0);  	af_delay_max = -		(setup->analog_filter ? +		(i2c_dev->analog_filter ?  		 STM32F7_I2C_ANALOG_FILTER_DELAY_MAX : 0); -	dnf_delay = setup->dnf * i2cclk; +	dnf_delay = i2c_dev->dnf * i2cclk;  	sdadel_min = specs->hddat_min + setup->fall_time - -		af_delay_min - (setup->dnf + 3) * i2cclk; +		af_delay_min - (i2c_dev->dnf + 3) * i2cclk;  	sdadel_max = specs->vddat_max - setup->rise_time - -		af_delay_max - (setup->dnf + 4) * i2cclk; +		af_delay_max - (i2c_dev->dnf + 4) * i2cclk;  	scldel_min = setup->rise_time + specs->sudat_min; @@ -648,6 +646,7 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev,  	setup->speed_freq = t->bus_freq_hz;  	i2c_dev->setup.rise_time = t->scl_rise_ns;  	i2c_dev->setup.fall_time = t->scl_fall_ns; +	i2c_dev->dnf_dt = t->digital_filter_width_ns;  	setup->clock_src = clk_get_rate(i2c_dev->clk);  	if (!setup->clock_src) { @@ -655,6 +654,9 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev,  		return -EINVAL;  	} +	if (!of_property_read_bool(i2c_dev->dev->of_node, "i2c-digital-filter")) +		i2c_dev->dnf_dt = STM32F7_I2C_DNF_DEFAULT; +  	do {  		ret = stm32f7_i2c_compute_timing(i2c_dev, setup,  						 &i2c_dev->timing); @@ -676,12 +678,15 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev,  		return ret;  	} +	i2c_dev->analog_filter = of_property_read_bool(i2c_dev->dev->of_node, +						       "i2c-analog-filter"); +  	dev_dbg(i2c_dev->dev, "I2C Speed(%i), Clk Source(%i)\n",  		setup->speed_freq, setup->clock_src);  	dev_dbg(i2c_dev->dev, "I2C Rise(%i) and Fall(%i) Time\n",  		setup->rise_time, setup->fall_time);  	dev_dbg(i2c_dev->dev, "I2C Analog Filter(%s), DNF(%i)\n", -		(setup->analog_filter ? "On" : "Off"), setup->dnf); +		(i2c_dev->analog_filter ? "On" : "Off"), i2c_dev->dnf);  	i2c_dev->bus_rate = setup->speed_freq; @@ -720,8 +725,8 @@ static void stm32f7_i2c_hw_config(struct stm32f7_i2c_dev *i2c_dev)  	timing |= STM32F7_I2C_TIMINGR_SCLL(t->scll);  	writel_relaxed(timing, i2c_dev->base + STM32F7_I2C_TIMINGR); -	/* Enable I2C */ -	if (i2c_dev->setup.analog_filter) +	/* Configure the Analog Filter */ +	if (i2c_dev->analog_filter)  		stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1,  				     STM32F7_I2C_CR1_ANFOFF);  	else @@ -732,7 +737,7 @@ static void stm32f7_i2c_hw_config(struct stm32f7_i2c_dev *i2c_dev)  	stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1,  			     STM32F7_I2C_CR1_DNF_MASK);  	stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1, -			     STM32F7_I2C_CR1_DNF(i2c_dev->setup.dnf)); +			     STM32F7_I2C_CR1_DNF(i2c_dev->dnf));  	stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1,  			     STM32F7_I2C_CR1_PE); @@ -1597,7 +1602,8 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)  	/* Bus error */  	if (status & STM32F7_I2C_ISR_BERR) { -		dev_err(dev, "<%s>: Bus error\n", __func__); +		dev_err(dev, "<%s>: Bus error accessing addr 0x%x\n", +			__func__, f7_msg->addr);  		writel_relaxed(STM32F7_I2C_ICR_BERRCF, base + STM32F7_I2C_ICR);  		stm32f7_i2c_release_bus(&i2c_dev->adap);  		f7_msg->result = -EIO; @@ -1605,13 +1611,15 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)  	/* Arbitration loss */  	if (status & STM32F7_I2C_ISR_ARLO) { -		dev_dbg(dev, "<%s>: Arbitration loss\n", __func__); +		dev_dbg(dev, "<%s>: Arbitration loss accessing addr 0x%x\n", +			__func__, f7_msg->addr);  		writel_relaxed(STM32F7_I2C_ICR_ARLOCF, base + STM32F7_I2C_ICR);  		f7_msg->result = -EAGAIN;  	}  	if (status & STM32F7_I2C_ISR_PECERR) { -		dev_err(dev, "<%s>: PEC error in reception\n", __func__); +		dev_err(dev, "<%s>: PEC error in reception accessing addr 0x%x\n", +			__func__, f7_msg->addr);  		writel_relaxed(STM32F7_I2C_ICR_PECCF, base + STM32F7_I2C_ICR);  		f7_msg->result = -EINVAL;  	} @@ -1652,7 +1660,7 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,  	i2c_dev->msg_id = 0;  	f7_msg->smbus = false; -	ret = pm_runtime_get_sync(i2c_dev->dev); +	ret = pm_runtime_resume_and_get(i2c_dev->dev);  	if (ret < 0)  		return ret; @@ -1698,7 +1706,7 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,  	f7_msg->read_write = read_write;  	f7_msg->smbus = true; -	ret = pm_runtime_get_sync(dev); +	ret = pm_runtime_resume_and_get(dev);  	if (ret < 0)  		return ret; @@ -1799,7 +1807,7 @@ static int stm32f7_i2c_reg_slave(struct i2c_client *slave)  	if (ret)  		return ret; -	ret = pm_runtime_get_sync(dev); +	ret = pm_runtime_resume_and_get(dev);  	if (ret < 0)  		return ret; @@ -1880,7 +1888,7 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)  	WARN_ON(!i2c_dev->slave[id]); -	ret = pm_runtime_get_sync(i2c_dev->dev); +	ret = pm_runtime_resume_and_get(i2c_dev->dev);  	if (ret < 0)  		return ret; @@ -2027,12 +2035,8 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)  	phy_addr = (dma_addr_t)res->start;  	irq_event = platform_get_irq(pdev, 0); -	if (irq_event <= 0) { -		if (irq_event != -EPROBE_DEFER) -			dev_err(&pdev->dev, "Failed to get IRQ event: %d\n", -				irq_event); +	if (irq_event <= 0)  		return irq_event ? : -ENOENT; -	}  	irq_error = platform_get_irq(pdev, 1);  	if (irq_error <= 0) @@ -2267,13 +2271,12 @@ static int __maybe_unused stm32f7_i2c_runtime_resume(struct device *dev)  	return 0;  } -#ifdef CONFIG_PM_SLEEP -static int stm32f7_i2c_regs_backup(struct stm32f7_i2c_dev *i2c_dev) +static int __maybe_unused stm32f7_i2c_regs_backup(struct stm32f7_i2c_dev *i2c_dev)  {  	int ret;  	struct stm32f7_i2c_regs *backup_regs = &i2c_dev->backup_regs; -	ret = pm_runtime_get_sync(i2c_dev->dev); +	ret = pm_runtime_resume_and_get(i2c_dev->dev);  	if (ret < 0)  		return ret; @@ -2289,13 +2292,13 @@ static int stm32f7_i2c_regs_backup(struct stm32f7_i2c_dev *i2c_dev)  	return ret;  } -static int stm32f7_i2c_regs_restore(struct stm32f7_i2c_dev *i2c_dev) +static int __maybe_unused stm32f7_i2c_regs_restore(struct stm32f7_i2c_dev *i2c_dev)  {  	u32 cr1;  	int ret;  	struct stm32f7_i2c_regs *backup_regs = &i2c_dev->backup_regs; -	ret = pm_runtime_get_sync(i2c_dev->dev); +	ret = pm_runtime_resume_and_get(i2c_dev->dev);  	if (ret < 0)  		return ret; @@ -2320,7 +2323,7 @@ static int stm32f7_i2c_regs_restore(struct stm32f7_i2c_dev *i2c_dev)  	return ret;  } -static int stm32f7_i2c_suspend(struct device *dev) +static int __maybe_unused stm32f7_i2c_suspend(struct device *dev)  {  	struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);  	int ret; @@ -2341,7 +2344,7 @@ static int stm32f7_i2c_suspend(struct device *dev)  	return 0;  } -static int stm32f7_i2c_resume(struct device *dev) +static int __maybe_unused stm32f7_i2c_resume(struct device *dev)  {  	struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);  	int ret; @@ -2361,7 +2364,6 @@ static int stm32f7_i2c_resume(struct device *dev)  	return 0;  } -#endif  static const struct dev_pm_ops stm32f7_i2c_pm_ops = {  	SET_RUNTIME_PM_OPS(stm32f7_i2c_runtime_suspend, | 
