diff options
author | Nguyen Viet Dung <nv-dung@jinso.co.jp> | 2013-09-02 20:09:25 -0400 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2013-09-04 06:49:16 -0400 |
commit | b720423a2627f045133bec39a31fe2bc0dab86f3 (patch) | |
tree | 8b75444c4c435016fd24646a7ac64b9c452522c0 /drivers/i2c/busses | |
parent | 617da00cb11b75a17a271147e616296f754f591b (diff) |
i2c: rcar: add rcar-H2 support
This patch modify I2C driver of rcar-H1 to usable on both rcar-H1 and rcar-H2.
Signed-off-by: Nguyen Viet Dung <nv-dung@jinso.co.jp>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c/busses')
-rw-r--r-- | drivers/i2c/busses/i2c-rcar.c | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index e59c3f618542..d2fe11da5e82 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c | |||
@@ -101,6 +101,11 @@ enum { | |||
101 | #define ID_ARBLOST (1 << 3) | 101 | #define ID_ARBLOST (1 << 3) |
102 | #define ID_NACK (1 << 4) | 102 | #define ID_NACK (1 << 4) |
103 | 103 | ||
104 | enum rcar_i2c_type { | ||
105 | I2C_RCAR_H1, | ||
106 | I2C_RCAR_H2, | ||
107 | }; | ||
108 | |||
104 | struct rcar_i2c_priv { | 109 | struct rcar_i2c_priv { |
105 | void __iomem *io; | 110 | void __iomem *io; |
106 | struct i2c_adapter adap; | 111 | struct i2c_adapter adap; |
@@ -113,6 +118,7 @@ struct rcar_i2c_priv { | |||
113 | int irq; | 118 | int irq; |
114 | u32 icccr; | 119 | u32 icccr; |
115 | u32 flags; | 120 | u32 flags; |
121 | enum rcar_i2c_type devtype; | ||
116 | }; | 122 | }; |
117 | 123 | ||
118 | #define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent) | 124 | #define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent) |
@@ -224,12 +230,25 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, | |||
224 | u32 scgd, cdf; | 230 | u32 scgd, cdf; |
225 | u32 round, ick; | 231 | u32 round, ick; |
226 | u32 scl; | 232 | u32 scl; |
233 | u32 cdf_width; | ||
227 | 234 | ||
228 | if (!clkp) { | 235 | if (!clkp) { |
229 | dev_err(dev, "there is no peripheral_clk\n"); | 236 | dev_err(dev, "there is no peripheral_clk\n"); |
230 | return -EIO; | 237 | return -EIO; |
231 | } | 238 | } |
232 | 239 | ||
240 | switch (priv->devtype) { | ||
241 | case I2C_RCAR_H1: | ||
242 | cdf_width = 2; | ||
243 | break; | ||
244 | case I2C_RCAR_H2: | ||
245 | cdf_width = 3; | ||
246 | break; | ||
247 | default: | ||
248 | dev_err(dev, "device type error\n"); | ||
249 | return -EIO; | ||
250 | } | ||
251 | |||
233 | /* | 252 | /* |
234 | * calculate SCL clock | 253 | * calculate SCL clock |
235 | * see | 254 | * see |
@@ -245,7 +264,7 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, | |||
245 | * clkp : peripheral_clk | 264 | * clkp : peripheral_clk |
246 | * F[] : integer up-valuation | 265 | * F[] : integer up-valuation |
247 | */ | 266 | */ |
248 | for (cdf = 0; cdf < 4; cdf++) { | 267 | for (cdf = 0; cdf < (1 << cdf_width); cdf++) { |
249 | ick = clk_get_rate(clkp) / (1 + cdf); | 268 | ick = clk_get_rate(clkp) / (1 + cdf); |
250 | if (ick < 20000000) | 269 | if (ick < 20000000) |
251 | goto ick_find; | 270 | goto ick_find; |
@@ -287,7 +306,7 @@ scgd_find: | |||
287 | /* | 306 | /* |
288 | * keep icccr value | 307 | * keep icccr value |
289 | */ | 308 | */ |
290 | priv->icccr = (scgd << 2 | cdf); | 309 | priv->icccr = (scgd << (cdf_width) | cdf); |
291 | 310 | ||
292 | return 0; | 311 | return 0; |
293 | } | 312 | } |
@@ -632,6 +651,9 @@ static int rcar_i2c_probe(struct platform_device *pdev) | |||
632 | bus_speed = 100000; /* default 100 kHz */ | 651 | bus_speed = 100000; /* default 100 kHz */ |
633 | if (pdata && pdata->bus_speed) | 652 | if (pdata && pdata->bus_speed) |
634 | bus_speed = pdata->bus_speed; | 653 | bus_speed = pdata->bus_speed; |
654 | |||
655 | priv->devtype = platform_get_device_id(pdev)->driver_data; | ||
656 | |||
635 | ret = rcar_i2c_clock_calculate(priv, bus_speed, dev); | 657 | ret = rcar_i2c_clock_calculate(priv, bus_speed, dev); |
636 | if (ret < 0) | 658 | if (ret < 0) |
637 | return ret; | 659 | return ret; |
@@ -686,6 +708,14 @@ static int rcar_i2c_remove(struct platform_device *pdev) | |||
686 | return 0; | 708 | return 0; |
687 | } | 709 | } |
688 | 710 | ||
711 | static struct platform_device_id rcar_i2c_id_table[] = { | ||
712 | { "i2c-rcar", I2C_RCAR_H1 }, | ||
713 | { "i2c-rcar_h1", I2C_RCAR_H1 }, | ||
714 | { "i2c-rcar_h2", I2C_RCAR_H2 }, | ||
715 | {}, | ||
716 | }; | ||
717 | MODULE_DEVICE_TABLE(platform, rcar_i2c_id_table); | ||
718 | |||
689 | static struct platform_driver rcar_i2c_driver = { | 719 | static struct platform_driver rcar_i2c_driver = { |
690 | .driver = { | 720 | .driver = { |
691 | .name = "i2c-rcar", | 721 | .name = "i2c-rcar", |
@@ -693,6 +723,7 @@ static struct platform_driver rcar_i2c_driver = { | |||
693 | }, | 723 | }, |
694 | .probe = rcar_i2c_probe, | 724 | .probe = rcar_i2c_probe, |
695 | .remove = rcar_i2c_remove, | 725 | .remove = rcar_i2c_remove, |
726 | .id_table = rcar_i2c_id_table, | ||
696 | }; | 727 | }; |
697 | 728 | ||
698 | module_platform_driver(rcar_i2c_driver); | 729 | module_platform_driver(rcar_i2c_driver); |