aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-ocores.c138
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
74static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) 79#define TYPE_OCORES 0
80#define TYPE_GRLIB 1
81
82static 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)); 87static void oc_setreg_16(struct ocores_i2c *i2c, int reg, u8 value)
88{
89 iowrite16(value, i2c->base + (reg << i2c->reg_shift));
90}
91
92static void oc_setreg_32(struct ocores_i2c *i2c, int reg, u8 value)
93{
94 iowrite32(value, i2c->base + (reg << i2c->reg_shift));
95}
96
97static inline u8 oc_getreg_8(struct ocores_i2c *i2c, int reg)
98{
99 return ioread8(i2c->base + (reg << i2c->reg_shift));
100}
101
102static inline u8 oc_getreg_16(struct ocores_i2c *i2c, int reg)
103{
104 return ioread16(i2c->base + (reg << i2c->reg_shift));
105}
106
107static 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. */
115static 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
128static 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
146static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value)
147{
148 i2c->setreg(i2c, reg, value);
82} 149}
83 150
84static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg) 151static 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
94static void ocores_process(struct ocores_i2c *i2c) 156static 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
292static 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};
303MODULE_DEVICE_TABLE(of, ocores_i2c_match);
304
230#ifdef CONFIG_OF 305#ifdef CONFIG_OF
231static int ocores_i2c_of_probe(struct platform_device *pdev, 306static 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
382static struct of_device_id ocores_i2c_match[] = {
383 { .compatible = "opencores,i2c-ocores", },
384 {},
385};
386MODULE_DEVICE_TABLE(of, ocores_i2c_match);
387
388static struct platform_driver ocores_i2c_driver = { 490static 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),