summaryrefslogtreecommitdiff
path: root/drivers/i2c/busses/i2c-mpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-mpc.c')
-rw-r--r--drivers/i2c/busses/i2c-mpc.c92
1 files changed, 41 insertions, 51 deletions
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 81ac92bb4f6f..28c5c5c1fb7a 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -11,9 +11,10 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched/signal.h>
+#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
-#include <linux/of_platform.h>
+#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/slab.h>
@@ -29,8 +30,6 @@
#include <asm/mpc85xx.h>
#include <sysdev/fsl_soc.h>
-#define DRV_NAME "mpc-i2c"
-
#define MPC_I2C_CLOCK_LEGACY 0
#define MPC_I2C_CLOCK_PRESERVE (~0U)
@@ -89,7 +88,6 @@ struct mpc_i2c {
int irq;
u32 real_clk;
u8 fdr, dfsrr;
- struct clk *clk_per;
u32 cntl_bits;
enum mpc_i2c_action action;
struct i2c_msg *msgs;
@@ -116,7 +114,7 @@ static inline void writeccr(struct mpc_i2c *i2c, u32 x)
writeb(x, i2c->base + MPC_I2C_CR);
}
-/* Sometimes 9th clock pulse isn't generated, and slave doesn't release
+/* Sometimes 9th clock pulse isn't generated, and target doesn't release
* the bus, because it wants to send ACK.
* Following sequence of enabling/disabling and sending start/stop generates
* the 9 pulses, each with a START then ending with STOP, so it's all OK.
@@ -305,24 +303,22 @@ static void mpc_i2c_setup_512x(struct device_node *node,
struct mpc_i2c *i2c,
u32 clock)
{
- struct device_node *node_ctrl;
void __iomem *ctrl;
- const u32 *pval;
u32 idx;
/* Enable I2C interrupts for mpc5121 */
- node_ctrl = of_find_compatible_node(NULL, NULL,
- "fsl,mpc5121-i2c-ctrl");
+ struct device_node *node_ctrl __free(device_node) =
+ of_find_compatible_node(NULL, NULL, "fsl,mpc5121-i2c-ctrl");
if (node_ctrl) {
ctrl = of_iomap(node_ctrl, 0);
if (ctrl) {
+ u64 addr;
/* Interrupt enable bits for i2c-0/1/2: bit 24/26/28 */
- pval = of_get_property(node, "reg", NULL);
- idx = (*pval & 0xff) / 0x20;
+ of_property_read_reg(node, 0, &addr, NULL);
+ idx = (addr & 0xff) / 0x20;
setbits32(ctrl, 1 << (24 + idx * 2));
iounmap(ctrl);
}
- of_node_put(node_ctrl);
}
/* The clock setup for the 52xx works also fine for the 512x */
@@ -359,11 +355,11 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] = {
static u32 mpc_i2c_get_sec_cfg_8xxx(void)
{
- struct device_node *node;
u32 __iomem *reg;
u32 val = 0;
- node = of_find_node_by_name(NULL, "global-utilities");
+ struct device_node *node __free(device_node) =
+ of_find_node_by_name(NULL, "global-utilities");
if (node) {
const u32 *prop = of_get_property(node, "reg", NULL);
if (prop) {
@@ -384,7 +380,6 @@ static u32 mpc_i2c_get_sec_cfg_8xxx(void)
iounmap(reg);
}
}
- of_node_put(node);
return val;
}
@@ -763,14 +758,13 @@ static int fsl_i2c_bus_recovery(struct i2c_adapter *adap)
}
static const struct i2c_algorithm mpc_algo = {
- .master_xfer = mpc_xfer,
+ .xfer = mpc_xfer,
.functionality = mpc_functionality,
};
static struct i2c_adapter mpc_ops = {
.owner = THIS_MODULE,
.algo = &mpc_algo,
- .timeout = HZ,
};
static struct i2c_bus_recovery_info fsl_i2c_recovery_info = {
@@ -781,12 +775,9 @@ static int fsl_i2c_probe(struct platform_device *op)
{
const struct mpc_i2c_data *data;
struct mpc_i2c *i2c;
- const u32 *prop;
- u32 clock = MPC_I2C_CLOCK_LEGACY;
- int result = 0;
- int plen;
struct clk *clk;
- int err;
+ int result;
+ u32 clock;
i2c = devm_kzalloc(&op->dev, sizeof(*i2c), GFP_KERNEL);
if (!i2c)
@@ -816,25 +807,19 @@ static int fsl_i2c_probe(struct platform_device *op)
* enable clock for the I2C peripheral (non fatal),
* keep a reference upon successful allocation
*/
- clk = devm_clk_get_optional(&op->dev, NULL);
- if (IS_ERR(clk))
- return PTR_ERR(clk);
-
- err = clk_prepare_enable(clk);
- if (err) {
+ clk = devm_clk_get_optional_enabled(&op->dev, NULL);
+ if (IS_ERR(clk)) {
dev_err(&op->dev, "failed to enable clock\n");
- return err;
+ return PTR_ERR(clk);
}
- i2c->clk_per = clk;
-
if (of_property_read_bool(op->dev.of_node, "fsl,preserve-clocking")) {
clock = MPC_I2C_CLOCK_PRESERVE;
} else {
- prop = of_get_property(op->dev.of_node, "clock-frequency",
- &plen);
- if (prop && plen == sizeof(u32))
- clock = *prop;
+ result = of_property_read_u32(op->dev.of_node,
+ "clock-frequency", &clock);
+ if (result)
+ clock = MPC_I2C_CLOCK_LEGACY;
}
data = device_get_match_data(&op->dev);
@@ -842,16 +827,30 @@ static int fsl_i2c_probe(struct platform_device *op)
data->setup(op->dev.of_node, i2c, clock);
} else {
/* Backwards compatibility */
- if (of_get_property(op->dev.of_node, "dfsrr", NULL))
+ if (of_property_read_bool(op->dev.of_node, "dfsrr"))
mpc_i2c_setup_8xxx(op->dev.of_node, i2c, clock);
}
- prop = of_get_property(op->dev.of_node, "fsl,timeout", &plen);
- if (prop && plen == sizeof(u32)) {
- mpc_ops.timeout = *prop * HZ / 1000000;
+ /* Sadly, we have to support two deprecated bindings here */
+ result = of_property_read_u32(op->dev.of_node,
+ "i2c-transfer-timeout-us",
+ &mpc_ops.timeout);
+ if (result == -EINVAL)
+ result = of_property_read_u32(op->dev.of_node,
+ "i2c-scl-clk-low-timeout-us",
+ &mpc_ops.timeout);
+ if (result == -EINVAL)
+ result = of_property_read_u32(op->dev.of_node,
+ "fsl,timeout", &mpc_ops.timeout);
+
+ if (!result) {
+ mpc_ops.timeout *= HZ / 1000000;
if (mpc_ops.timeout < 5)
mpc_ops.timeout = 5;
+ } else {
+ mpc_ops.timeout = HZ;
}
+
dev_info(i2c->dev, "timeout %u us\n", mpc_ops.timeout * 1000000 / HZ);
if (of_property_read_bool(op->dev.of_node, "fsl,i2c-erratum-a004447"))
@@ -869,25 +868,16 @@ static int fsl_i2c_probe(struct platform_device *op)
result = i2c_add_numbered_adapter(&i2c->adap);
if (result)
- goto fail_add;
+ return result;
return 0;
-
- fail_add:
- clk_disable_unprepare(i2c->clk_per);
-
- return result;
};
-static int fsl_i2c_remove(struct platform_device *op)
+static void fsl_i2c_remove(struct platform_device *op)
{
struct mpc_i2c *i2c = platform_get_drvdata(op);
i2c_del_adapter(&i2c->adap);
-
- clk_disable_unprepare(i2c->clk_per);
-
- return 0;
};
static int __maybe_unused mpc_i2c_suspend(struct device *dev)
@@ -950,7 +940,7 @@ static struct platform_driver mpc_i2c_driver = {
.probe = fsl_i2c_probe,
.remove = fsl_i2c_remove,
.driver = {
- .name = DRV_NAME,
+ .name = "mpc-i2c",
.of_match_table = mpc_i2c_of_match,
.pm = &mpc_i2c_pm_ops,
},