mirror of
https://github.com/linux-sunxi/meta-sunxi.git
synced 2024-11-16 10:18:23 +01:00
linux-mainline: Backport fixes for mv64xxx PMIC
For details please see: https://github.com/linux-sunxi/meta-sunxi/issues/397 Signed-off-by: Marek Belisko <marek.belisko@open-nandra.com>
This commit is contained in:
parent
3fce491bba
commit
ce4a0294c3
@ -26,6 +26,8 @@ SRC_URI = "https://www.kernel.org/pub/linux/kernel/v5.x/linux-${PV}.tar.xz \
|
||||
file://0001-dts-orange-pi-zero-Add-wifi-support.patch \
|
||||
file://0002-dts-nanopi-neo-air-add-camera.patch \
|
||||
file://0003-dts-allwinner-bananapi-m2-zreo-Enforce-consistent-MM.patch \
|
||||
file://0004-i2c-mv64xxx-Add-atomic_xfer-method-to-driver.patch \
|
||||
file://0005-i2c-mv64xxx-Remove-shutdown-method-from-driver.patch \
|
||||
file://defconfig \
|
||||
"
|
||||
|
||||
|
@ -0,0 +1,145 @@
|
||||
From 544a8d75f3d6e60e160cd92dc56321484598a993 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Morgan <macromorgan@hotmail.com>
|
||||
Date: Wed, 30 Mar 2022 12:16:57 -0500
|
||||
Subject: [PATCH] i2c: mv64xxx: Add atomic_xfer method to driver
|
||||
|
||||
Add an atomic_xfer method to the driver so that it behaves correctly
|
||||
when controlling a PMIC that is responsible for device shutdown.
|
||||
|
||||
The atomic_xfer method added is similar to the one from the i2c-rk3x
|
||||
driver. When running an atomic_xfer a bool flag in the driver data is
|
||||
set, the interrupt is not unmasked on transfer start, and the IRQ
|
||||
handler is manually invoked while waiting for pending transfers to
|
||||
complete.
|
||||
|
||||
Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
|
||||
Acked-by: Gregory CLEMENT <gregory.clement@bootlin.com>
|
||||
Signed-off-by: Wolfram Sang <wsa@kernel.org>
|
||||
---
|
||||
drivers/i2c/busses/i2c-mv64xxx.c | 52 ++++++++++++++++++++++++++++----
|
||||
1 file changed, 46 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
|
||||
index 424c53e4c513..103a05ecc3d6 100644
|
||||
--- a/drivers/i2c/busses/i2c-mv64xxx.c
|
||||
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
|
||||
@@ -150,6 +150,7 @@ struct mv64xxx_i2c_data {
|
||||
/* Clk div is 2 to the power n, not 2 to the power n + 1 */
|
||||
bool clk_n_base_0;
|
||||
struct i2c_bus_recovery_info rinfo;
|
||||
+ bool atomic;
|
||||
};
|
||||
|
||||
static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = {
|
||||
@@ -179,7 +180,10 @@ mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data,
|
||||
u32 dir = 0;
|
||||
|
||||
drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK |
|
||||
- MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN;
|
||||
+ MV64XXX_I2C_REG_CONTROL_TWSIEN;
|
||||
+
|
||||
+ if (!drv_data->atomic)
|
||||
+ drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_INTEN;
|
||||
|
||||
if (msg->flags & I2C_M_RD)
|
||||
dir = 1;
|
||||
@@ -409,7 +413,8 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
|
||||
case MV64XXX_I2C_ACTION_RCV_DATA_STOP:
|
||||
drv_data->msg->buf[drv_data->byte_posn++] =
|
||||
readl(drv_data->reg_base + drv_data->reg_offsets.data);
|
||||
- drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;
|
||||
+ if (!drv_data->atomic)
|
||||
+ drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;
|
||||
writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP,
|
||||
drv_data->reg_base + drv_data->reg_offsets.control);
|
||||
drv_data->block = 0;
|
||||
@@ -427,7 +432,8 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
|
||||
drv_data->rc = -EIO;
|
||||
fallthrough;
|
||||
case MV64XXX_I2C_ACTION_SEND_STOP:
|
||||
- drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;
|
||||
+ if (!drv_data->atomic)
|
||||
+ drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;
|
||||
writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP,
|
||||
drv_data->reg_base + drv_data->reg_offsets.control);
|
||||
drv_data->block = 0;
|
||||
@@ -575,6 +581,17 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data)
|
||||
spin_unlock_irqrestore(&drv_data->lock, flags);
|
||||
}
|
||||
|
||||
+static void mv64xxx_i2c_wait_polling(struct mv64xxx_i2c_data *drv_data)
|
||||
+{
|
||||
+ ktime_t timeout = ktime_add_ms(ktime_get(), drv_data->adapter.timeout);
|
||||
+
|
||||
+ while (READ_ONCE(drv_data->block) &&
|
||||
+ ktime_compare(ktime_get(), timeout) < 0) {
|
||||
+ udelay(5);
|
||||
+ mv64xxx_i2c_intr(0, drv_data);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int
|
||||
mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg,
|
||||
int is_last)
|
||||
@@ -590,7 +607,11 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg,
|
||||
mv64xxx_i2c_send_start(drv_data);
|
||||
spin_unlock_irqrestore(&drv_data->lock, flags);
|
||||
|
||||
- mv64xxx_i2c_wait_for_completion(drv_data);
|
||||
+ if (!drv_data->atomic)
|
||||
+ mv64xxx_i2c_wait_for_completion(drv_data);
|
||||
+ else
|
||||
+ mv64xxx_i2c_wait_polling(drv_data);
|
||||
+
|
||||
return drv_data->rc;
|
||||
}
|
||||
|
||||
@@ -717,7 +738,7 @@ mv64xxx_i2c_functionality(struct i2c_adapter *adap)
|
||||
}
|
||||
|
||||
static int
|
||||
-mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
||||
+mv64xxx_i2c_xfer_core(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
||||
{
|
||||
struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap);
|
||||
int rc, ret = num;
|
||||
@@ -730,7 +751,7 @@ mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
||||
drv_data->msgs = msgs;
|
||||
drv_data->num_msgs = num;
|
||||
|
||||
- if (mv64xxx_i2c_can_offload(drv_data))
|
||||
+ if (mv64xxx_i2c_can_offload(drv_data) && !drv_data->atomic)
|
||||
rc = mv64xxx_i2c_offload_xfer(drv_data);
|
||||
else
|
||||
rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[0], num == 1);
|
||||
@@ -747,8 +768,27 @@ mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int
|
||||
+mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
||||
+{
|
||||
+ struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap);
|
||||
+
|
||||
+ drv_data->atomic = 0;
|
||||
+ return mv64xxx_i2c_xfer_core(adap, msgs, num);
|
||||
+}
|
||||
+
|
||||
+static int mv64xxx_i2c_xfer_atomic(struct i2c_adapter *adap,
|
||||
+ struct i2c_msg msgs[], int num)
|
||||
+{
|
||||
+ struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap);
|
||||
+
|
||||
+ drv_data->atomic = 1;
|
||||
+ return mv64xxx_i2c_xfer_core(adap, msgs, num);
|
||||
+}
|
||||
+
|
||||
static const struct i2c_algorithm mv64xxx_i2c_algo = {
|
||||
.master_xfer = mv64xxx_i2c_xfer,
|
||||
+ .master_xfer_atomic = mv64xxx_i2c_xfer_atomic,
|
||||
.functionality = mv64xxx_i2c_functionality,
|
||||
};
|
||||
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,56 @@
|
||||
From 09b343038e3470e4d0da45f0ee09fb42107e5314 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Morgan <macromorgan@hotmail.com>
|
||||
Date: Fri, 25 Mar 2022 13:06:25 -0500
|
||||
Subject: [PATCH] i2c: mv64xxx: Remove shutdown method from driver
|
||||
|
||||
When I attempt to shut down (or reboot) my R8 based NTC CHIP with this
|
||||
i2c driver I get the following error: "i2c i2c-0: mv64xxx: I2C bus
|
||||
locked, block: 1, time_left: 0". Reboots are successful but shutdowns
|
||||
freeze. If I comment out the shutdown routine the device both reboots
|
||||
and shuts down successfully without receiving this error (however it
|
||||
does receive a warning of missing atomic_xfer).
|
||||
|
||||
It appears that very few i2c drivers have a shutdown method, I assume
|
||||
because these devices are often used to communicate with PMICs (such
|
||||
as in my case with the R8 based NTC CHIP). I'm proposing we simply
|
||||
remove this method so long as it doesn't cause trouble for others
|
||||
downstream. I'll work on an atomic_xfer method and submit that in
|
||||
a different patch.
|
||||
|
||||
Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
|
||||
Acked-by: Gregory CLEMENT <gregory.clement@bootlin.com>
|
||||
Signed-off-by: Wolfram Sang <wsa@kernel.org>
|
||||
---
|
||||
drivers/i2c/busses/i2c-mv64xxx.c | 9 ---------
|
||||
1 file changed, 9 deletions(-)
|
||||
|
||||
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
|
||||
index 5c8e94b6cdb5..424c53e4c513 100644
|
||||
--- a/drivers/i2c/busses/i2c-mv64xxx.c
|
||||
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
|
||||
@@ -1047,14 +1047,6 @@ mv64xxx_i2c_remove(struct platform_device *pd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void
|
||||
-mv64xxx_i2c_shutdown(struct platform_device *pd)
|
||||
-{
|
||||
- pm_runtime_disable(&pd->dev);
|
||||
- if (!pm_runtime_status_suspended(&pd->dev))
|
||||
- mv64xxx_i2c_runtime_suspend(&pd->dev);
|
||||
-}
|
||||
-
|
||||
static const struct dev_pm_ops mv64xxx_i2c_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(mv64xxx_i2c_runtime_suspend,
|
||||
mv64xxx_i2c_runtime_resume, NULL)
|
||||
@@ -1065,7 +1057,6 @@ static const struct dev_pm_ops mv64xxx_i2c_pm_ops = {
|
||||
static struct platform_driver mv64xxx_i2c_driver = {
|
||||
.probe = mv64xxx_i2c_probe,
|
||||
.remove = mv64xxx_i2c_remove,
|
||||
- .shutdown = mv64xxx_i2c_shutdown,
|
||||
.driver = {
|
||||
.name = MV64XXX_I2C_CTLR_NAME,
|
||||
.pm = &mv64xxx_i2c_pm_ops,
|
||||
--
|
||||
2.25.1
|
||||
|
Loading…
Reference in New Issue
Block a user