diff options
| -rw-r--r-- | Documentation/devicetree/bindings/i2c/i2c-ocores.txt | 2 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-ocores.c | 138 |
2 files changed, 121 insertions, 19 deletions
diff --git a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt index c15781f4dc8c..1637c298a1b3 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | Device tree configuration for i2c-ocores | 1 | Device tree configuration for i2c-ocores |
| 2 | 2 | ||
| 3 | Required properties: | 3 | Required properties: |
| 4 | - compatible : "opencores,i2c-ocores" | 4 | - compatible : "opencores,i2c-ocores" or "aeroflexgaisler,i2cmst" |
| 5 | - reg : bus address start and address range size of device | 5 | - reg : bus address start and address range size of device |
| 6 | - interrupts : interrupt number | 6 | - interrupts : interrupt number |
| 7 | - clock-frequency : frequency of bus clock in Hz | 7 | - clock-frequency : frequency of bus clock in Hz |
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), |
