aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGanesan Ramalingam <ganesanr@broadcom.com>2012-07-13 09:44:25 -0400
committerWolfram Sang <w.sang@pengutronix.de>2012-07-14 07:30:25 -0400
commit7326e38ffe894d0cd2904704b7d8c53d4a55d752 (patch)
tree7261b5bad76ce15dbad07f78a5b5e4b210f6d634
parentd739a464f3b83cc879a2ba6aec33634c44068531 (diff)
i2c: i2c-ocores: support for 16bit and 32bit IO
Some architectures supports only 16-bit or 32-bit read/write access to their IO space. Add a 'reg-io-width' platform and OF parameter which specifies the IO width to support these platforms. reg-io-width can be specified as 1, 2 or 4, and has a default value of 1 if it is unspecified. Signed-off-by: Ganesan Ramalingam <ganesanr@broadcom.com> Signed-off-by: Jayachandran C <jayachandranc@netlogicmicro.com> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-ocores.txt2
-rw-r--r--drivers/i2c/busses/i2c-ocores.c21
-rw-r--r--include/linux/i2c-ocores.h1
3 files changed, 22 insertions, 2 deletions
diff --git a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt
index 1c9334bfc39c..c15781f4dc8c 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt
@@ -10,6 +10,7 @@ Required properties:
10 10
11Optional properties: 11Optional properties:
12- reg-shift : device register offsets are shifted by this value 12- reg-shift : device register offsets are shifted by this value
13- reg-io-width : io register width in bytes (1, 2 or 4)
13- regstep : deprecated, use reg-shift above 14- regstep : deprecated, use reg-shift above
14 15
15Example: 16Example:
@@ -23,6 +24,7 @@ Example:
23 clock-frequency = <20000000>; 24 clock-frequency = <20000000>;
24 25
25 reg-shift = <0>; /* 8 bit registers */ 26 reg-shift = <0>; /* 8 bit registers */
27 reg-io-width = <1>; /* 8 bit read/write */
26 28
27 dummy@60 { 29 dummy@60 {
28 compatible = "dummy"; 30 compatible = "dummy";
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index 9e0709d5fb36..bffd5501ac2d 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -30,6 +30,7 @@
30struct ocores_i2c { 30struct ocores_i2c {
31 void __iomem *base; 31 void __iomem *base;
32 u32 reg_shift; 32 u32 reg_shift;
33 u32 reg_io_width;
33 wait_queue_head_t wait; 34 wait_queue_head_t wait;
34 struct i2c_adapter adap; 35 struct i2c_adapter adap;
35 struct i2c_msg *msg; 36 struct i2c_msg *msg;
@@ -72,12 +73,22 @@ struct ocores_i2c {
72 73
73static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) 74static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value)
74{ 75{
75 iowrite8(value, i2c->base + (reg << i2c->reg_shift)); 76 if (i2c->reg_io_width == 4)
77 iowrite32(value, i2c->base + (reg << i2c->reg_shift));
78 else if (i2c->reg_io_width == 2)
79 iowrite16(value, i2c->base + (reg << i2c->reg_shift));
80 else
81 iowrite8(value, i2c->base + (reg << i2c->reg_shift));
76} 82}
77 83
78static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg) 84static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg)
79{ 85{
80 return ioread8(i2c->base + (reg << i2c->reg_shift)); 86 if (i2c->reg_io_width == 4)
87 return ioread32(i2c->base + (reg << i2c->reg_shift));
88 else if (i2c->reg_io_width == 2)
89 return ioread16(i2c->base + (reg << i2c->reg_shift));
90 else
91 return ioread8(i2c->base + (reg << i2c->reg_shift));
81} 92}
82 93
83static void ocores_process(struct ocores_i2c *i2c) 94static void ocores_process(struct ocores_i2c *i2c)
@@ -244,6 +255,8 @@ static int ocores_i2c_of_probe(struct platform_device *pdev,
244 } 255 }
245 i2c->clock_khz = val / 1000; 256 i2c->clock_khz = val / 1000;
246 257
258 of_property_read_u32(pdev->dev.of_node, "reg-io-width",
259 &i2c->reg_io_width);
247 return 0; 260 return 0;
248} 261}
249#else 262#else
@@ -286,6 +299,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
286 pdata = pdev->dev.platform_data; 299 pdata = pdev->dev.platform_data;
287 if (pdata) { 300 if (pdata) {
288 i2c->reg_shift = pdata->reg_shift; 301 i2c->reg_shift = pdata->reg_shift;
302 i2c->reg_io_width = pdata->reg_io_width;
289 i2c->clock_khz = pdata->clock_khz; 303 i2c->clock_khz = pdata->clock_khz;
290 } else { 304 } else {
291 ret = ocores_i2c_of_probe(pdev, i2c); 305 ret = ocores_i2c_of_probe(pdev, i2c);
@@ -293,6 +307,9 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
293 return ret; 307 return ret;
294 } 308 }
295 309
310 if (i2c->reg_io_width == 0)
311 i2c->reg_io_width = 1; /* Set to default value */
312
296 ocores_init(i2c); 313 ocores_init(i2c);
297 314
298 init_waitqueue_head(&i2c->wait); 315 init_waitqueue_head(&i2c->wait);
diff --git a/include/linux/i2c-ocores.h b/include/linux/i2c-ocores.h
index 5d95df2436f4..1c06b5c7c308 100644
--- a/include/linux/i2c-ocores.h
+++ b/include/linux/i2c-ocores.h
@@ -13,6 +13,7 @@
13 13
14struct ocores_i2c_platform_data { 14struct ocores_i2c_platform_data {
15 u32 reg_shift; /* register offset shift value */ 15 u32 reg_shift; /* register offset shift value */
16 u32 reg_io_width; /* register io read/write width */
16 u32 clock_khz; /* input clock in kHz */ 17 u32 clock_khz; /* input clock in kHz */
17 u8 num_devices; /* number of devices in the devices list */ 18 u8 num_devices; /* number of devices in the devices list */
18 struct i2c_board_info const *devices; /* devices connected to the bus */ 19 struct i2c_board_info const *devices; /* devices connected to the bus */