diff options
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-ocores.c | 138 |
1 files changed, 120 insertions, 18 deletions
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index dafd26beecbb..0ea84199b507 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c | |||
@@ -4,6 +4,9 @@ | |||
4 | * | 4 | * |
5 | * Peter Korsgaard <jacmet@sunsite.dk> | 5 | * Peter Korsgaard <jacmet@sunsite.dk> |
6 | * | 6 | * |
7 | * Support for the GRLIB port of the controller by | ||
8 | * Andreas Larsson <andreas@gaisler.com> | ||
9 | * | ||
7 | * This file is licensed under the terms of the GNU General Public License | 10 | * This file is licensed under the terms of the GNU General Public License |
8 | * version 2. This program is licensed "as is" without any warranty of any | 11 | * version 2. This program is licensed "as is" without any warranty of any |
9 | * kind, whether express or implied. | 12 | * kind, whether express or implied. |
@@ -38,6 +41,8 @@ struct ocores_i2c { | |||
38 | int nmsgs; | 41 | int nmsgs; |
39 | int state; /* see STATE_ */ | 42 | int state; /* see STATE_ */ |
40 | int clock_khz; | 43 | int clock_khz; |
44 | void (*setreg)(struct ocores_i2c *i2c, int reg, u8 value); | ||
45 | u8 (*getreg)(struct ocores_i2c *i2c, int reg); | ||
41 | }; | 46 | }; |
42 | 47 | ||
43 | /* registers */ | 48 | /* registers */ |
@@ -71,24 +76,81 @@ struct ocores_i2c { | |||
71 | #define STATE_READ 3 | 76 | #define STATE_READ 3 |
72 | #define STATE_ERROR 4 | 77 | #define STATE_ERROR 4 |
73 | 78 | ||
74 | static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) | 79 | #define TYPE_OCORES 0 |
80 | #define TYPE_GRLIB 1 | ||
81 | |||
82 | static void oc_setreg_8(struct ocores_i2c *i2c, int reg, u8 value) | ||
75 | { | 83 | { |
76 | if (i2c->reg_io_width == 4) | 84 | iowrite8(value, i2c->base + (reg << i2c->reg_shift)); |
77 | iowrite32(value, i2c->base + (reg << i2c->reg_shift)); | 85 | } |
78 | else if (i2c->reg_io_width == 2) | 86 | |
79 | iowrite16(value, i2c->base + (reg << i2c->reg_shift)); | 87 | static void oc_setreg_16(struct ocores_i2c *i2c, int reg, u8 value) |
88 | { | ||
89 | iowrite16(value, i2c->base + (reg << i2c->reg_shift)); | ||
90 | } | ||
91 | |||
92 | static void oc_setreg_32(struct ocores_i2c *i2c, int reg, u8 value) | ||
93 | { | ||
94 | iowrite32(value, i2c->base + (reg << i2c->reg_shift)); | ||
95 | } | ||
96 | |||
97 | static inline u8 oc_getreg_8(struct ocores_i2c *i2c, int reg) | ||
98 | { | ||
99 | return ioread8(i2c->base + (reg << i2c->reg_shift)); | ||
100 | } | ||
101 | |||
102 | static inline u8 oc_getreg_16(struct ocores_i2c *i2c, int reg) | ||
103 | { | ||
104 | return ioread16(i2c->base + (reg << i2c->reg_shift)); | ||
105 | } | ||
106 | |||
107 | static inline u8 oc_getreg_32(struct ocores_i2c *i2c, int reg) | ||
108 | { | ||
109 | return ioread32(i2c->base + (reg << i2c->reg_shift)); | ||
110 | } | ||
111 | |||
112 | /* Read and write functions for the GRLIB port of the controller. Registers are | ||
113 | * 32-bit big endian and the PRELOW and PREHIGH registers are merged into one | ||
114 | * register. The subsequent registers has their offset decreased accordingly. */ | ||
115 | static u8 oc_getreg_grlib(struct ocores_i2c *i2c, int reg) | ||
116 | { | ||
117 | u32 rd; | ||
118 | int rreg = reg; | ||
119 | if (reg != OCI2C_PRELOW) | ||
120 | rreg--; | ||
121 | rd = ioread32be(i2c->base + (rreg << i2c->reg_shift)); | ||
122 | if (reg == OCI2C_PREHIGH) | ||
123 | return (u8)(rd >> 8); | ||
80 | else | 124 | else |
81 | iowrite8(value, i2c->base + (reg << i2c->reg_shift)); | 125 | return (u8)rd; |
126 | } | ||
127 | |||
128 | static void oc_setreg_grlib(struct ocores_i2c *i2c, int reg, u8 value) | ||
129 | { | ||
130 | u32 curr, wr; | ||
131 | int rreg = reg; | ||
132 | if (reg != OCI2C_PRELOW) | ||
133 | rreg--; | ||
134 | if (reg == OCI2C_PRELOW || reg == OCI2C_PREHIGH) { | ||
135 | curr = ioread32be(i2c->base + (rreg << i2c->reg_shift)); | ||
136 | if (reg == OCI2C_PRELOW) | ||
137 | wr = (curr & 0xff00) | value; | ||
138 | else | ||
139 | wr = (((u32)value) << 8) | (curr & 0xff); | ||
140 | } else { | ||
141 | wr = value; | ||
142 | } | ||
143 | iowrite32be(wr, i2c->base + (rreg << i2c->reg_shift)); | ||
144 | } | ||
145 | |||
146 | static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) | ||
147 | { | ||
148 | i2c->setreg(i2c, reg, value); | ||
82 | } | 149 | } |
83 | 150 | ||
84 | static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg) | 151 | static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg) |
85 | { | 152 | { |
86 | if (i2c->reg_io_width == 4) | 153 | return i2c->getreg(i2c, reg); |
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)); | ||
92 | } | 154 | } |
93 | 155 | ||
94 | static void ocores_process(struct ocores_i2c *i2c) | 156 | static void ocores_process(struct ocores_i2c *i2c) |
@@ -227,11 +289,25 @@ static struct i2c_adapter ocores_adapter = { | |||
227 | .algo = &ocores_algorithm, | 289 | .algo = &ocores_algorithm, |
228 | }; | 290 | }; |
229 | 291 | ||
292 | static struct of_device_id ocores_i2c_match[] = { | ||
293 | { | ||
294 | .compatible = "opencores,i2c-ocores", | ||
295 | .data = (void *)TYPE_OCORES, | ||
296 | }, | ||
297 | { | ||
298 | .compatible = "aeroflexgaisler,i2cmst", | ||
299 | .data = (void *)TYPE_GRLIB, | ||
300 | }, | ||
301 | {}, | ||
302 | }; | ||
303 | MODULE_DEVICE_TABLE(of, ocores_i2c_match); | ||
304 | |||
230 | #ifdef CONFIG_OF | 305 | #ifdef CONFIG_OF |
231 | static int ocores_i2c_of_probe(struct platform_device *pdev, | 306 | static int ocores_i2c_of_probe(struct platform_device *pdev, |
232 | struct ocores_i2c *i2c) | 307 | struct ocores_i2c *i2c) |
233 | { | 308 | { |
234 | struct device_node *np = pdev->dev.of_node; | 309 | struct device_node *np = pdev->dev.of_node; |
310 | const struct of_device_id *match; | ||
235 | u32 val; | 311 | u32 val; |
236 | 312 | ||
237 | if (of_property_read_u32(np, "reg-shift", &i2c->reg_shift)) { | 313 | if (of_property_read_u32(np, "reg-shift", &i2c->reg_shift)) { |
@@ -257,6 +333,14 @@ static int ocores_i2c_of_probe(struct platform_device *pdev, | |||
257 | 333 | ||
258 | of_property_read_u32(pdev->dev.of_node, "reg-io-width", | 334 | of_property_read_u32(pdev->dev.of_node, "reg-io-width", |
259 | &i2c->reg_io_width); | 335 | &i2c->reg_io_width); |
336 | |||
337 | match = of_match_node(ocores_i2c_match, pdev->dev.of_node); | ||
338 | if (match && (int)match->data == TYPE_GRLIB) { | ||
339 | dev_dbg(&pdev->dev, "GRLIB variant of i2c-ocores\n"); | ||
340 | i2c->setreg = oc_setreg_grlib; | ||
341 | i2c->getreg = oc_getreg_grlib; | ||
342 | } | ||
343 | |||
260 | return 0; | 344 | return 0; |
261 | } | 345 | } |
262 | #else | 346 | #else |
@@ -302,6 +386,30 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) | |||
302 | if (i2c->reg_io_width == 0) | 386 | if (i2c->reg_io_width == 0) |
303 | i2c->reg_io_width = 1; /* Set to default value */ | 387 | i2c->reg_io_width = 1; /* Set to default value */ |
304 | 388 | ||
389 | if (!i2c->setreg || !i2c->getreg) { | ||
390 | switch (i2c->reg_io_width) { | ||
391 | case 1: | ||
392 | i2c->setreg = oc_setreg_8; | ||
393 | i2c->getreg = oc_getreg_8; | ||
394 | break; | ||
395 | |||
396 | case 2: | ||
397 | i2c->setreg = oc_setreg_16; | ||
398 | i2c->getreg = oc_getreg_16; | ||
399 | break; | ||
400 | |||
401 | case 4: | ||
402 | i2c->setreg = oc_setreg_32; | ||
403 | i2c->getreg = oc_getreg_32; | ||
404 | break; | ||
405 | |||
406 | default: | ||
407 | dev_err(&pdev->dev, "Unsupported I/O width (%d)\n", | ||
408 | i2c->reg_io_width); | ||
409 | return -EINVAL; | ||
410 | } | ||
411 | } | ||
412 | |||
305 | ocores_init(i2c); | 413 | ocores_init(i2c); |
306 | 414 | ||
307 | init_waitqueue_head(&i2c->wait); | 415 | init_waitqueue_head(&i2c->wait); |
@@ -379,12 +487,6 @@ static SIMPLE_DEV_PM_OPS(ocores_i2c_pm, ocores_i2c_suspend, ocores_i2c_resume); | |||
379 | #define OCORES_I2C_PM NULL | 487 | #define OCORES_I2C_PM NULL |
380 | #endif | 488 | #endif |
381 | 489 | ||
382 | static struct of_device_id ocores_i2c_match[] = { | ||
383 | { .compatible = "opencores,i2c-ocores", }, | ||
384 | {}, | ||
385 | }; | ||
386 | MODULE_DEVICE_TABLE(of, ocores_i2c_match); | ||
387 | |||
388 | static struct platform_driver ocores_i2c_driver = { | 490 | static struct platform_driver ocores_i2c_driver = { |
389 | .probe = ocores_i2c_probe, | 491 | .probe = ocores_i2c_probe, |
390 | .remove = __devexit_p(ocores_i2c_remove), | 492 | .remove = __devexit_p(ocores_i2c_remove), |