diff options
author | Ganesan Ramalingam <ganesanr@broadcom.com> | 2012-07-13 09:44:25 -0400 |
---|---|---|
committer | Wolfram Sang <w.sang@pengutronix.de> | 2012-07-14 07:30:25 -0400 |
commit | 7326e38ffe894d0cd2904704b7d8c53d4a55d752 (patch) | |
tree | 7261b5bad76ce15dbad07f78a5b5e4b210f6d634 | |
parent | d739a464f3b83cc879a2ba6aec33634c44068531 (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.txt | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-ocores.c | 21 | ||||
-rw-r--r-- | include/linux/i2c-ocores.h | 1 |
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 | ||
11 | Optional properties: | 11 | Optional 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 | ||
15 | Example: | 16 | Example: |
@@ -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 @@ | |||
30 | struct ocores_i2c { | 30 | struct 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 | ||
73 | static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) | 74 | static 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 | ||
78 | static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg) | 84 | static 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 | ||
83 | static void ocores_process(struct ocores_i2c *i2c) | 94 | static 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 | ||
14 | struct ocores_i2c_platform_data { | 14 | struct 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 */ |