imx-i2c frequency scaling issue imx6ull + edt-ft5x06
Michael Nazzareno Trimarchi
michael at amarulasolutions.com
Wed Dec 2 17:13:08 EST 2020
Hi
On Wed, Dec 2, 2020 at 11:24 AM Michael Nazzareno Trimarchi
<michael at amarulasolutions.com> wrote:
>
> Hi all
>
> I'm trying to find the best way to fix a problem connected with the
> touch screen controller on i2c imx6ull bus. Now
> according to what I understand sdma can not be connected to the i2c
> peripheral so it works in pio mode and that's fine.
> During the frequency scaling a new clock register is computed but can
> not be applied to the register until the next start as
> reported by the datasheet. The problem here is that if the i2c
> transaction is around PRE_CHANGE and POST_CHANGE of the
> rate touchscreen starts to fail and swipe can not be performed until
> we get a pen up event (edf- has crc error). Is there any suggestion
> based on your experience? In the oscilloscope I can see this effect too
>
> Michael
I get something like this at the moment. I think that it is needed
only in pio mode
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index d7267dd9c7bf..07511a8a79a6 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -31,6 +31,7 @@
#include <linux/clk.h>
#include <linux/completion.h>
+#include <linux/cpufreq.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
@@ -210,6 +211,9 @@ struct imx_i2c_struct {
struct pinctrl_state *pinctrl_pins_default;
struct pinctrl_state *pinctrl_pins_gpio;
+#ifdef CONFIG_CPU_FREQ
+ struct notifier_block freq_transition;
+#endif
struct imx_i2c_dma *dma;
};
@@ -510,6 +514,51 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
#endif
}
+#ifdef CONFIG_CPU_FREQ
+static int i2c_imx_cpufreq_transition(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct imx_i2c_struct *i2c_imx;
+ i2c_imx = container_of(nb, struct imx_i2c_struct, freq_transition);
+
+ switch (action) {
+ case CPUFREQ_PRECHANGE:
+ i2c_lock_bus(&i2c_imx->adapter, I2C_LOCK_ROOT_ADAPTER);
+ break;
+ case CPUFREQ_POSTCHANGE:
+ i2c_unlock_bus(&i2c_imx->adapter, I2C_LOCK_ROOT_ADAPTER);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static inline int i2c_imx_cpufreq_register(struct imx_i2c_struct *dev)
+{
+ dev->freq_transition.notifier_call = i2c_imx_cpufreq_transition;
+
+ return cpufreq_register_notifier(&dev->freq_transition,
+ CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+static inline void i2c_imx_cpufreq_deregister(struct imx_i2c_struct *dev)
+{
+ cpufreq_unregister_notifier(&dev->freq_transition,
+ CPUFREQ_TRANSITION_NOTIFIER);
+}
+#else
+static inline int i2c_imx_cpufreq_register(struct imx_i2c_struct *dev)
+{
+ return 0;
+}
+
+static inline void i2c_imx_cpufreq_deregister(struct imx_i2c_struct *dev)
+{
+}
+#endif
+
static int i2c_imx_clk_notifier_call(struct notifier_block *nb,
unsigned long action, void *data)
{
@@ -1172,6 +1221,12 @@ static int i2c_imx_probe(struct platform_device *pdev)
i2c_imx->adapter.name);
dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");
+ ret = i2c_imx_cpufreq_register(i2c_imx);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register cpufreq\n");
+ goto clk_notifier_unregister;
+ }
+
/* Init DMA config if supported */
i2c_imx_dma_request(i2c_imx, phy_addr);
@@ -1199,6 +1254,8 @@ static int i2c_imx_remove(struct platform_device *pdev)
if (ret < 0)
return ret;
+ i2c_imx_cpufreq_deregister(i2c_imx);
+
/* remove adapter */
dev_dbg(&i2c_imx->adapter.dev, "adapter removed\n");
i2c_del_adapter(&i2c_imx->adapter);
--
2.25.1
--
Michael Nazzareno Trimarchi
Amarula Solutions BV
COO Co-Founder
Cruquiuskade 47 Amsterdam 1018 AM NL
T. +31(0)851119172
M. +39(0)3479132170
[`as] https://www.amarulasolutions.com
More information about the linux-arm-kernel
mailing list