const: constify remaining dev_pm_ops
[safe/jmp/linux-2.6] / drivers / i2c / busses / i2c-s3c2410.c
index 9d79756..1d8c986 100644 (file)
@@ -1,6 +1,6 @@
 /* linux/drivers/i2c/busses/i2c-s3c2410.c
  *
- * Copyright (C) 2004,2005 Simtec Electronics
+ * Copyright (C) 2004,2005,2009 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
  *
  * S3C2410 I2C Controller
@@ -51,6 +51,11 @@ enum s3c24xx_i2c_state {
        STATE_STOP
 };
 
+enum s3c24xx_i2c_type {
+       TYPE_S3C2410,
+       TYPE_S3C2440,
+};
+
 struct s3c24xx_i2c {
        spinlock_t              lock;
        wait_queue_head_t       wait;
@@ -88,8 +93,10 @@ struct s3c24xx_i2c {
 static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *i2c)
 {
        struct platform_device *pdev = to_platform_device(i2c->dev);
+       enum s3c24xx_i2c_type type;
 
-       return !strcmp(pdev->name, "s3c2440-i2c");
+       type = platform_get_device_id(pdev)->driver_data;
+       return type == TYPE_S3C2440;
 }
 
 /* s3c24xx_i2c_master_complete
@@ -590,18 +597,6 @@ static int s3c24xx_i2c_calcdivisor(unsigned long clkin, unsigned int wanted,
        return clkin / (calc_divs * calc_div1);
 }
 
-/* freq_acceptable
- *
- * test wether a frequency is within the acceptable range of error
-*/
-
-static inline int freq_acceptable(unsigned int freq, unsigned int wanted)
-{
-       int diff = freq - wanted;
-
-       return diff >= -2 && diff <= 2;
-}
-
 /* s3c24xx_i2c_clockrate
  *
  * work out a divisor for the user requested frequency setting,
@@ -614,44 +609,28 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
        struct s3c2410_platform_i2c *pdata = i2c->dev->platform_data;
        unsigned long clkin = clk_get_rate(i2c->clk);
        unsigned int divs, div1;
+       unsigned long target_frequency;
        u32 iiccon;
        int freq;
-       int start, end;
 
        i2c->clkrate = clkin;
        clkin /= 1000;          /* clkin now in KHz */
 
-       dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n",
-                pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq);
+       dev_dbg(i2c->dev, "pdata desired frequency %lu\n", pdata->frequency);
 
-       if (pdata->bus_freq != 0) {
-               freq = s3c24xx_i2c_calcdivisor(clkin, pdata->bus_freq/1000,
-                                              &div1, &divs);
-               if (freq_acceptable(freq, pdata->bus_freq/1000))
-                       goto found;
-       }
-
-       /* ok, we may have to search for something suitable... */
+       target_frequency = pdata->frequency ? pdata->frequency : 100000;
 
-       start = (pdata->max_freq == 0) ? pdata->bus_freq : pdata->max_freq;
-       end = pdata->min_freq;
+       target_frequency /= 1000; /* Target frequency now in KHz */
 
-       start /= 1000;
-       end /= 1000;
+       freq = s3c24xx_i2c_calcdivisor(clkin, target_frequency, &div1, &divs);
 
-       /* search loop... */
-
-       for (; start > end; start--) {
-               freq = s3c24xx_i2c_calcdivisor(clkin, start, &div1, &divs);
-               if (freq_acceptable(freq, start))
-                       goto found;
+       if (freq > target_frequency) {
+               dev_err(i2c->dev,
+                       "Unable to achieve desired frequency %luKHz."   \
+                       " Lowest achievable %dKHz\n", target_frequency, freq);
+               return -EINVAL;
        }
 
-       /* cannot find frequency spec */
-
-       return -EINVAL;
-
- found:
        *got = freq;
 
        iiccon = readl(i2c->regs + S3C2410_IICCON);
@@ -784,11 +763,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
        dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq);
        dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon);
 
-       /* check for s3c2440 i2c controller  */
-
-       if (s3c24xx_i2c_is2440(i2c))
-               writel(0x0, i2c->regs + S3C2440_IICLC);
-
        return 0;
 }
 
@@ -849,7 +823,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
                goto err_clk;
        }
 
-       i2c->ioarea = request_mem_region(res->start, (res->end-res->start)+1,
+       i2c->ioarea = request_mem_region(res->start, resource_size(res),
                                         pdev->name);
 
        if (i2c->ioarea == NULL) {
@@ -858,7 +832,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
                goto err_clk;
        }
 
-       i2c->regs = ioremap(res->start, (res->end-res->start)+1);
+       i2c->regs = ioremap(res->start, resource_size(res));
 
        if (i2c->regs == NULL) {
                dev_err(&pdev->dev, "cannot map IO\n");
@@ -972,17 +946,20 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
-static int s3c24xx_i2c_suspend_late(struct platform_device *dev,
-                                   pm_message_t msg)
+static int s3c24xx_i2c_suspend_noirq(struct device *dev)
 {
-       struct s3c24xx_i2c *i2c = platform_get_drvdata(dev);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
+
        i2c->suspended = 1;
+
        return 0;
 }
 
-static int s3c24xx_i2c_resume(struct platform_device *dev)
+static int s3c24xx_i2c_resume(struct device *dev)
 {
-       struct s3c24xx_i2c *i2c = platform_get_drvdata(dev);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
 
        i2c->suspended = 0;
        s3c24xx_i2c_init(i2c);
@@ -990,60 +967,52 @@ static int s3c24xx_i2c_resume(struct platform_device *dev)
        return 0;
 }
 
+static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = {
+       .suspend_noirq = s3c24xx_i2c_suspend_noirq,
+       .resume = s3c24xx_i2c_resume,
+};
+
+#define S3C24XX_DEV_PM_OPS (&s3c24xx_i2c_dev_pm_ops)
 #else
-#define s3c24xx_i2c_suspend_late NULL
-#define s3c24xx_i2c_resume NULL
+#define S3C24XX_DEV_PM_OPS NULL
 #endif
 
 /* device driver for platform bus bits */
 
-static struct platform_driver s3c2410_i2c_driver = {
-       .probe          = s3c24xx_i2c_probe,
-       .remove         = s3c24xx_i2c_remove,
-       .suspend_late   = s3c24xx_i2c_suspend_late,
-       .resume         = s3c24xx_i2c_resume,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "s3c2410-i2c",
-       },
+static struct platform_device_id s3c24xx_driver_ids[] = {
+       {
+               .name           = "s3c2410-i2c",
+               .driver_data    = TYPE_S3C2410,
+       }, {
+               .name           = "s3c2440-i2c",
+               .driver_data    = TYPE_S3C2440,
+       }, { },
 };
+MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
 
-static struct platform_driver s3c2440_i2c_driver = {
+static struct platform_driver s3c24xx_i2c_driver = {
        .probe          = s3c24xx_i2c_probe,
        .remove         = s3c24xx_i2c_remove,
-       .suspend_late   = s3c24xx_i2c_suspend_late,
-       .resume         = s3c24xx_i2c_resume,
+       .id_table       = s3c24xx_driver_ids,
        .driver         = {
                .owner  = THIS_MODULE,
-               .name   = "s3c2440-i2c",
+               .name   = "s3c-i2c",
+               .pm     = S3C24XX_DEV_PM_OPS,
        },
 };
 
 static int __init i2c_adap_s3c_init(void)
 {
-       int ret;
-
-       ret = platform_driver_register(&s3c2410_i2c_driver);
-       if (ret == 0) {
-               ret = platform_driver_register(&s3c2440_i2c_driver);
-               if (ret)
-                       platform_driver_unregister(&s3c2410_i2c_driver);
-       }
-
-       return ret;
+       return platform_driver_register(&s3c24xx_i2c_driver);
 }
+subsys_initcall(i2c_adap_s3c_init);
 
 static void __exit i2c_adap_s3c_exit(void)
 {
-       platform_driver_unregister(&s3c2410_i2c_driver);
-       platform_driver_unregister(&s3c2440_i2c_driver);
+       platform_driver_unregister(&s3c24xx_i2c_driver);
 }
-
-module_init(i2c_adap_s3c_init);
 module_exit(i2c_adap_s3c_exit);
 
 MODULE_DESCRIPTION("S3C24XX I2C Bus driver");
 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:s3c2410-i2c");
-MODULE_ALIAS("platform:s3c2440-i2c");