diff options
| -rw-r--r-- | arch/arm/plat-omap/i2c.c | 39 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 24 | ||||
| -rw-r--r-- | include/linux/i2c-omap.h | 9 |
3 files changed, 56 insertions, 16 deletions
diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index 624e26298faa..f044b5927508 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c | |||
| @@ -26,9 +26,12 @@ | |||
| 26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
| 27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
| 28 | #include <linux/i2c.h> | 28 | #include <linux/i2c.h> |
| 29 | #include <linux/i2c-omap.h> | ||
| 30 | |||
| 29 | #include <mach/irqs.h> | 31 | #include <mach/irqs.h> |
| 30 | #include <plat/mux.h> | 32 | #include <plat/mux.h> |
| 31 | #include <plat/i2c.h> | 33 | #include <plat/i2c.h> |
| 34 | #include <plat/omap-pm.h> | ||
| 32 | 35 | ||
| 33 | #define OMAP_I2C_SIZE 0x3f | 36 | #define OMAP_I2C_SIZE 0x3f |
| 34 | #define OMAP1_I2C_BASE 0xfffb3800 | 37 | #define OMAP1_I2C_BASE 0xfffb3800 |
| @@ -70,14 +73,14 @@ static struct resource i2c_resources[][2] = { | |||
| 70 | }, \ | 73 | }, \ |
| 71 | } | 74 | } |
| 72 | 75 | ||
| 73 | static u32 i2c_rate[ARRAY_SIZE(i2c_resources)]; | 76 | static struct omap_i2c_bus_platform_data i2c_pdata[ARRAY_SIZE(i2c_resources)]; |
| 74 | static struct platform_device omap_i2c_devices[] = { | 77 | static struct platform_device omap_i2c_devices[] = { |
| 75 | I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_rate[0]), | 78 | I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_pdata[0]), |
| 76 | #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) | 79 | #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) |
| 77 | I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_rate[1]), | 80 | I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_pdata[1]), |
| 78 | #endif | 81 | #endif |
| 79 | #if defined(CONFIG_ARCH_OMAP3) | 82 | #if defined(CONFIG_ARCH_OMAP3) |
| 80 | I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_rate[2]), | 83 | I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_pdata[2]), |
| 81 | #endif | 84 | #endif |
| 82 | }; | 85 | }; |
| 83 | 86 | ||
| @@ -100,10 +103,12 @@ static int __init omap_i2c_nr_ports(void) | |||
| 100 | static int __init omap_i2c_add_bus(int bus_id) | 103 | static int __init omap_i2c_add_bus(int bus_id) |
| 101 | { | 104 | { |
| 102 | struct platform_device *pdev; | 105 | struct platform_device *pdev; |
| 106 | struct omap_i2c_bus_platform_data *pd; | ||
| 103 | struct resource *res; | 107 | struct resource *res; |
| 104 | resource_size_t base, irq; | 108 | resource_size_t base, irq; |
| 105 | 109 | ||
| 106 | pdev = &omap_i2c_devices[bus_id - 1]; | 110 | pdev = &omap_i2c_devices[bus_id - 1]; |
| 111 | pd = pdev->dev.platform_data; | ||
| 107 | if (bus_id == 1) { | 112 | if (bus_id == 1) { |
| 108 | res = pdev->resource; | 113 | res = pdev->resource; |
| 109 | if (cpu_class_is_omap1()) { | 114 | if (cpu_class_is_omap1()) { |
| @@ -123,6 +128,15 @@ static int __init omap_i2c_add_bus(int bus_id) | |||
| 123 | if (cpu_class_is_omap2()) | 128 | if (cpu_class_is_omap2()) |
| 124 | omap2_i2c_mux_pins(bus_id); | 129 | omap2_i2c_mux_pins(bus_id); |
| 125 | 130 | ||
| 131 | /* | ||
| 132 | * When waiting for completion of a i2c transfer, we need to | ||
| 133 | * set a wake up latency constraint for the MPU. This is to | ||
| 134 | * ensure quick enough wakeup from idle, when transfer | ||
| 135 | * completes. | ||
| 136 | */ | ||
| 137 | if (cpu_is_omap34xx()) | ||
| 138 | pd->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat; | ||
| 139 | |||
| 126 | return platform_device_register(pdev); | 140 | return platform_device_register(pdev); |
| 127 | } | 141 | } |
| 128 | 142 | ||
| @@ -146,8 +160,8 @@ static int __init omap_i2c_bus_setup(char *str) | |||
| 146 | get_options(str, 3, ints); | 160 | get_options(str, 3, ints); |
| 147 | if (ints[0] < 2 || ints[1] < 1 || ints[1] > ports) | 161 | if (ints[0] < 2 || ints[1] < 1 || ints[1] > ports) |
| 148 | return 0; | 162 | return 0; |
| 149 | i2c_rate[ints[1] - 1] = ints[2]; | 163 | i2c_pdata[ints[1] - 1].clkrate = ints[2]; |
| 150 | i2c_rate[ints[1] - 1] |= OMAP_I2C_CMDLINE_SETUP; | 164 | i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP; |
| 151 | 165 | ||
| 152 | return 1; | 166 | return 1; |
| 153 | } | 167 | } |
| @@ -161,9 +175,9 @@ static int __init omap_register_i2c_bus_cmdline(void) | |||
| 161 | { | 175 | { |
| 162 | int i, err = 0; | 176 | int i, err = 0; |
| 163 | 177 | ||
| 164 | for (i = 0; i < ARRAY_SIZE(i2c_rate); i++) | 178 | for (i = 0; i < ARRAY_SIZE(i2c_pdata); i++) |
| 165 | if (i2c_rate[i] & OMAP_I2C_CMDLINE_SETUP) { | 179 | if (i2c_pdata[i].clkrate & OMAP_I2C_CMDLINE_SETUP) { |
| 166 | i2c_rate[i] &= ~OMAP_I2C_CMDLINE_SETUP; | 180 | i2c_pdata[i].clkrate &= ~OMAP_I2C_CMDLINE_SETUP; |
| 167 | err = omap_i2c_add_bus(i + 1); | 181 | err = omap_i2c_add_bus(i + 1); |
| 168 | if (err) | 182 | if (err) |
| 169 | goto out; | 183 | goto out; |
| @@ -197,9 +211,10 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate, | |||
| 197 | return err; | 211 | return err; |
| 198 | } | 212 | } |
| 199 | 213 | ||
| 200 | if (!i2c_rate[bus_id - 1]) | 214 | if (!i2c_pdata[bus_id - 1].clkrate) |
| 201 | i2c_rate[bus_id - 1] = clkrate; | 215 | i2c_pdata[bus_id - 1].clkrate = clkrate; |
| 202 | i2c_rate[bus_id - 1] &= ~OMAP_I2C_CMDLINE_SETUP; | 216 | |
| 217 | i2c_pdata[bus_id - 1].clkrate &= ~OMAP_I2C_CMDLINE_SETUP; | ||
| 203 | 218 | ||
| 204 | return omap_i2c_add_bus(bus_id); | 219 | return omap_i2c_add_bus(bus_id); |
| 205 | } | 220 | } |
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 46111ff18133..42c0b9108c7f 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/clk.h> | 38 | #include <linux/clk.h> |
| 39 | #include <linux/io.h> | 39 | #include <linux/io.h> |
| 40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
| 41 | #include <linux/i2c-omap.h> | ||
| 41 | 42 | ||
| 42 | /* I2C controller revisions */ | 43 | /* I2C controller revisions */ |
| 43 | #define OMAP_I2C_REV_2 0x20 | 44 | #define OMAP_I2C_REV_2 0x20 |
| @@ -175,6 +176,9 @@ struct omap_i2c_dev { | |||
| 175 | struct clk *fclk; /* Functional clock */ | 176 | struct clk *fclk; /* Functional clock */ |
| 176 | struct completion cmd_complete; | 177 | struct completion cmd_complete; |
| 177 | struct resource *ioarea; | 178 | struct resource *ioarea; |
| 179 | u32 latency; /* maximum mpu wkup latency */ | ||
| 180 | void (*set_mpu_wkup_lat)(struct device *dev, | ||
| 181 | long latency); | ||
| 178 | u32 speed; /* Speed of bus in Khz */ | 182 | u32 speed; /* Speed of bus in Khz */ |
| 179 | u16 cmd_err; | 183 | u16 cmd_err; |
| 180 | u8 *buf; | 184 | u8 *buf; |
| @@ -603,8 +607,12 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, | |||
| 603 | * REVISIT: We should abort the transfer on signals, but the bus goes | 607 | * REVISIT: We should abort the transfer on signals, but the bus goes |
| 604 | * into arbitration and we're currently unable to recover from it. | 608 | * into arbitration and we're currently unable to recover from it. |
| 605 | */ | 609 | */ |
| 610 | if (dev->set_mpu_wkup_lat != NULL) | ||
| 611 | dev->set_mpu_wkup_lat(dev->dev, dev->latency); | ||
| 606 | r = wait_for_completion_timeout(&dev->cmd_complete, | 612 | r = wait_for_completion_timeout(&dev->cmd_complete, |
| 607 | OMAP_I2C_TIMEOUT); | 613 | OMAP_I2C_TIMEOUT); |
| 614 | if (dev->set_mpu_wkup_lat != NULL) | ||
| 615 | dev->set_mpu_wkup_lat(dev->dev, -1); | ||
| 608 | dev->buf_len = 0; | 616 | dev->buf_len = 0; |
| 609 | if (r < 0) | 617 | if (r < 0) |
| 610 | return r; | 618 | return r; |
| @@ -927,6 +935,7 @@ omap_i2c_probe(struct platform_device *pdev) | |||
| 927 | struct omap_i2c_dev *dev; | 935 | struct omap_i2c_dev *dev; |
| 928 | struct i2c_adapter *adap; | 936 | struct i2c_adapter *adap; |
| 929 | struct resource *mem, *irq, *ioarea; | 937 | struct resource *mem, *irq, *ioarea; |
| 938 | struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data; | ||
| 930 | irq_handler_t isr; | 939 | irq_handler_t isr; |
| 931 | int r; | 940 | int r; |
| 932 | u32 speed = 0; | 941 | u32 speed = 0; |
| @@ -956,10 +965,13 @@ omap_i2c_probe(struct platform_device *pdev) | |||
| 956 | goto err_release_region; | 965 | goto err_release_region; |
| 957 | } | 966 | } |
| 958 | 967 | ||
| 959 | if (pdev->dev.platform_data != NULL) | 968 | if (pdata != NULL) { |
| 960 | speed = *(u32 *)pdev->dev.platform_data; | 969 | speed = pdata->clkrate; |
| 961 | else | 970 | dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat; |
| 962 | speed = 100; /* Defualt speed */ | 971 | } else { |
| 972 | speed = 100; /* Default speed */ | ||
| 973 | dev->set_mpu_wkup_lat = NULL; | ||
| 974 | } | ||
| 963 | 975 | ||
| 964 | dev->speed = speed; | 976 | dev->speed = speed; |
| 965 | dev->idle = 1; | 977 | dev->idle = 1; |
| @@ -1011,6 +1023,10 @@ omap_i2c_probe(struct platform_device *pdev) | |||
| 1011 | dev->fifo_size = (dev->fifo_size / 2); | 1023 | dev->fifo_size = (dev->fifo_size / 2); |
| 1012 | dev->b_hw = 1; /* Enable hardware fixes */ | 1024 | dev->b_hw = 1; /* Enable hardware fixes */ |
| 1013 | } | 1025 | } |
| 1026 | /* calculate wakeup latency constraint for MPU */ | ||
| 1027 | if (dev->set_mpu_wkup_lat != NULL) | ||
| 1028 | dev->latency = (1000000 * dev->fifo_size) / | ||
| 1029 | (1000 * speed / 8); | ||
| 1014 | } | 1030 | } |
| 1015 | 1031 | ||
| 1016 | /* reset ASAP, clearing any IRQs */ | 1032 | /* reset ASAP, clearing any IRQs */ |
diff --git a/include/linux/i2c-omap.h b/include/linux/i2c-omap.h new file mode 100644 index 000000000000..78ebf507ce56 --- /dev/null +++ b/include/linux/i2c-omap.h | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | #ifndef __I2C_OMAP_H__ | ||
| 2 | #define __I2C_OMAP_H__ | ||
| 3 | |||
| 4 | struct omap_i2c_bus_platform_data { | ||
| 5 | u32 clkrate; | ||
| 6 | void (*set_mpu_wkup_lat)(struct device *dev, long set); | ||
| 7 | }; | ||
| 8 | |||
| 9 | #endif | ||
