#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/sched.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/i2c-ocores.h>
+#include <linux/slab.h>
#include <asm/io.h>
struct ocores_i2c {
int pos;
int nmsgs;
int state; /* see STATE_ */
+ int clock_khz;
};
/* registers */
return -ETIMEDOUT;
}
-static void ocores_init(struct ocores_i2c *i2c,
- struct ocores_i2c_platform_data *pdata)
+static void ocores_init(struct ocores_i2c *i2c)
{
int prescale;
u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);
/* make sure the device is disabled */
oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
- prescale = (pdata->clock_khz / (5*100)) - 1;
+ prescale = (i2c->clock_khz / (5*100)) - 1;
oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff);
oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8);
static struct i2c_adapter ocores_adapter = {
.owner = THIS_MODULE,
.name = "i2c-ocores",
- .class = I2C_CLASS_HWMON,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &ocores_algorithm,
};
struct ocores_i2c_platform_data *pdata;
struct resource *res, *res2;
int ret;
+ int i;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
if (!i2c)
return -ENOMEM;
- if (!request_mem_region(res->start, res->end - res->start + 1,
+ if (!request_mem_region(res->start, resource_size(res),
pdev->name)) {
dev_err(&pdev->dev, "Memory region busy\n");
ret = -EBUSY;
goto request_mem_failed;
}
- i2c->base = ioremap(res->start, res->end - res->start + 1);
+ i2c->base = ioremap(res->start, resource_size(res));
if (!i2c->base) {
dev_err(&pdev->dev, "Unable to map registers\n");
ret = -EIO;
}
i2c->regstep = pdata->regstep;
- ocores_init(i2c, pdata);
+ i2c->clock_khz = pdata->clock_khz;
+ ocores_init(i2c);
init_waitqueue_head(&i2c->wait);
ret = request_irq(res2->start, ocores_isr, 0, pdev->name, i2c);
goto add_adapter_failed;
}
+ /* add in known devices to the bus */
+ for (i = 0; i < pdata->num_devices; i++)
+ i2c_new_device(&i2c->adap, pdata->devices + i);
+
return 0;
add_adapter_failed:
request_irq_failed:
iounmap(i2c->base);
map_failed:
- release_mem_region(res->start, res->end - res->start + 1);
+ release_mem_region(res->start, resource_size(res));
request_mem_failed:
kfree(i2c);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res)
- release_mem_region(res->start, res->end - res->start + 1);
+ release_mem_region(res->start, resource_size(res));
kfree(i2c);
return 0;
}
+#ifdef CONFIG_PM
+static int ocores_i2c_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct ocores_i2c *i2c = platform_get_drvdata(pdev);
+ u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);
+
+ /* make sure the device is disabled */
+ oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
+
+ return 0;
+}
+
+static int ocores_i2c_resume(struct platform_device *pdev)
+{
+ struct ocores_i2c *i2c = platform_get_drvdata(pdev);
+
+ ocores_init(i2c);
+
+ return 0;
+}
+#else
+#define ocores_i2c_suspend NULL
+#define ocores_i2c_resume NULL
+#endif
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:ocores-i2c");
+
static struct platform_driver ocores_i2c_driver = {
- .probe = ocores_i2c_probe,
- .remove = __devexit_p(ocores_i2c_remove),
- .driver = {
+ .probe = ocores_i2c_probe,
+ .remove = __devexit_p(ocores_i2c_remove),
+ .suspend = ocores_i2c_suspend,
+ .resume = ocores_i2c_resume,
+ .driver = {
.owner = THIS_MODULE,
.name = "ocores-i2c",
},