diff options
-rw-r--r-- | drivers/i2c/busses/i2c-meson.c | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c index 88d15b92ec35..37c4aa76f37a 100644 --- a/drivers/i2c/busses/i2c-meson.c +++ b/drivers/i2c/busses/i2c-meson.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/of.h> | 18 | #include <linux/of.h> |
19 | #include <linux/of_device.h> | ||
19 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
20 | #include <linux/types.h> | 21 | #include <linux/types.h> |
21 | 22 | ||
@@ -57,6 +58,10 @@ enum { | |||
57 | STATE_WRITE, | 58 | STATE_WRITE, |
58 | }; | 59 | }; |
59 | 60 | ||
61 | struct meson_i2c_data { | ||
62 | unsigned char div_factor; | ||
63 | }; | ||
64 | |||
60 | /** | 65 | /** |
61 | * struct meson_i2c - Meson I2C device private data | 66 | * struct meson_i2c - Meson I2C device private data |
62 | * | 67 | * |
@@ -93,6 +98,8 @@ struct meson_i2c { | |||
93 | struct completion done; | 98 | struct completion done; |
94 | u32 tokens[2]; | 99 | u32 tokens[2]; |
95 | int num_tokens; | 100 | int num_tokens; |
101 | |||
102 | const struct meson_i2c_data *data; | ||
96 | }; | 103 | }; |
97 | 104 | ||
98 | static void meson_i2c_set_mask(struct meson_i2c *i2c, int reg, u32 mask, | 105 | static void meson_i2c_set_mask(struct meson_i2c *i2c, int reg, u32 mask, |
@@ -128,7 +135,7 @@ static void meson_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq) | |||
128 | unsigned long clk_rate = clk_get_rate(i2c->clk); | 135 | unsigned long clk_rate = clk_get_rate(i2c->clk); |
129 | unsigned int div; | 136 | unsigned int div; |
130 | 137 | ||
131 | div = DIV_ROUND_UP(clk_rate, freq * 4); | 138 | div = DIV_ROUND_UP(clk_rate, freq * i2c->data->div_factor); |
132 | 139 | ||
133 | /* clock divider has 12 bits */ | 140 | /* clock divider has 12 bits */ |
134 | if (div >= (1 << 12)) { | 141 | if (div >= (1 << 12)) { |
@@ -376,6 +383,9 @@ static int meson_i2c_probe(struct platform_device *pdev) | |||
376 | spin_lock_init(&i2c->lock); | 383 | spin_lock_init(&i2c->lock); |
377 | init_completion(&i2c->done); | 384 | init_completion(&i2c->done); |
378 | 385 | ||
386 | i2c->data = (const struct meson_i2c_data *) | ||
387 | of_device_get_match_data(&pdev->dev); | ||
388 | |||
379 | i2c->clk = devm_clk_get(&pdev->dev, NULL); | 389 | i2c->clk = devm_clk_get(&pdev->dev, NULL); |
380 | if (IS_ERR(i2c->clk)) { | 390 | if (IS_ERR(i2c->clk)) { |
381 | dev_err(&pdev->dev, "can't get device clock\n"); | 391 | dev_err(&pdev->dev, "can't get device clock\n"); |
@@ -440,11 +450,25 @@ static int meson_i2c_remove(struct platform_device *pdev) | |||
440 | return 0; | 450 | return 0; |
441 | } | 451 | } |
442 | 452 | ||
453 | static const struct meson_i2c_data i2c_meson6_data = { | ||
454 | .div_factor = 4, | ||
455 | }; | ||
456 | |||
457 | static const struct meson_i2c_data i2c_gxbb_data = { | ||
458 | .div_factor = 4, | ||
459 | }; | ||
460 | |||
461 | static const struct meson_i2c_data i2c_axg_data = { | ||
462 | .div_factor = 3, | ||
463 | }; | ||
464 | |||
443 | static const struct of_device_id meson_i2c_match[] = { | 465 | static const struct of_device_id meson_i2c_match[] = { |
444 | { .compatible = "amlogic,meson6-i2c" }, | 466 | { .compatible = "amlogic,meson6-i2c", .data = &i2c_meson6_data }, |
445 | { .compatible = "amlogic,meson-gxbb-i2c" }, | 467 | { .compatible = "amlogic,meson-gxbb-i2c", .data = &i2c_gxbb_data }, |
446 | { }, | 468 | { .compatible = "amlogic,meson-axg-i2c", .data = &i2c_axg_data }, |
469 | {}, | ||
447 | }; | 470 | }; |
471 | |||
448 | MODULE_DEVICE_TABLE(of, meson_i2c_match); | 472 | MODULE_DEVICE_TABLE(of, meson_i2c_match); |
449 | 473 | ||
450 | static struct platform_driver meson_i2c_driver = { | 474 | static struct platform_driver meson_i2c_driver = { |