aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorAndreas Larsson <andreas@gaisler.com>2012-11-15 10:50:59 -0500
committerWolfram Sang <w.sang@pengutronix.de>2012-11-16 12:22:35 -0500
commita000b8c1e30115800d3de86b4b058cadd9cba59d (patch)
tree2ddea497c45de6078738975e89b3954e305b7ddd /drivers/i2c
parentf5f35a92e44a1f70fd8c77a42339318a5c8d9eb7 (diff)
i2c: ocores: Add support for the GRLIB port of the controller and use function pointers for getreg and setreg functions
The registers in the GRLIB port of the controller are 32-bit and in big endian byte order. The PRELOW and PREHIGH registers are merged into one register. The subsequent registers have their offset decreased accordingly. Hence the register access needs to be handled in a non-standard manner using custom getreg and setreg functions. Add setreg and getreg functions for different register widths and let oc_setreg and oc_getreg use function pointers to call the appropriate functions. A type is added as the data of the of match table entries. A new entry with a different compatible string is added to the table. The type of that entry triggers usage of the custom grlib functions by setting the setreg and getreg function pointers. Signed-off-by: Andreas Larsson <andreas@gaisler.com> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
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),