pidns: rewrite copy_pid_ns()
[safe/jmp/linux-2.6] / drivers / mfd / sm501.c
index be87139..4c7b796 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/pci.h>
-#include <linux/gpio.h>
+#include <linux/i2c-gpio.h>
 
 #include <linux/sm501.h>
 #include <linux/sm501-regs.h>
@@ -34,10 +34,14 @@ struct sm501_device {
 
 struct sm501_gpio;
 
+#ifdef CONFIG_MFD_SM501_GPIO
+#include <linux/gpio.h>
+
 struct sm501_gpio_chip {
        struct gpio_chip        gpio;
        struct sm501_gpio       *ourgpio;       /* to get back to parent. */
        void __iomem            *regbase;
+       void __iomem            *control;       /* address of control reg. */
 };
 
 struct sm501_gpio {
@@ -49,6 +53,11 @@ struct sm501_gpio {
        void __iomem            *regs;
        struct resource         *regs_res;
 };
+#else
+struct sm501_gpio {
+       /* no gpio support, empty definition for sm501_devdata. */
+};
+#endif
 
 struct sm501_devdata {
        spinlock_t                       reg_lock;
@@ -615,8 +624,8 @@ unsigned long sm501_set_clock(struct device *dev,
 
        sm501_sync_regs(sm);
 
-       dev_info(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
-                gate, clock, mode);
+       dev_dbg(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
+               gate, clock, mode);
 
        sm501_mdelay(sm, 16);
        mutex_unlock(&sm->clock_lock);
@@ -734,7 +743,7 @@ static int sm501_register_device(struct sm501_devdata *sm,
        int ret;
 
        for (ptr = 0; ptr < pdev->num_resources; ptr++) {
-               printk("%s[%d] flags %08lx: %08llx..%08llx\n",
+               printk(KERN_DEBUG "%s[%d] flags %08lx: %08llx..%08llx\n",
                       pdev->name, ptr,
                       pdev->resource[ptr].flags,
                       (unsigned long long)pdev->resource[ptr].start,
@@ -900,6 +909,25 @@ static int sm501_gpio_get(struct gpio_chip *chip, unsigned offset)
        return result & 1UL;
 }
 
+static void sm501_gpio_ensure_gpio(struct sm501_gpio_chip *smchip,
+                                  unsigned long bit)
+{
+       unsigned long ctrl;
+
+       /* check and modify if this pin is not set as gpio. */
+
+       if (readl(smchip->control) & bit) {
+               dev_info(sm501_gpio_to_dev(smchip->ourgpio)->dev,
+                        "changing mode of gpio, bit %08lx\n", bit);
+
+               ctrl = readl(smchip->control);
+               ctrl &= ~bit;
+               writel(ctrl, smchip->control);
+
+               sm501_sync_regs(sm501_gpio_to_dev(smchip->ourgpio));
+       }
+}
+
 static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 
 {
@@ -921,6 +949,8 @@ static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
        writel(val, regs);
 
        sm501_sync_regs(sm501_gpio_to_dev(smgpio));
+       sm501_gpio_ensure_gpio(smchip, bit);
+
        spin_unlock_irqrestore(&smgpio->lock, save);
 }
 
@@ -933,8 +963,8 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
        unsigned long save;
        unsigned long ddr;
 
-       dev_info(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d)\n",
-                __func__, chip, offset);
+       dev_dbg(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d)\n",
+               __func__, chip, offset);
 
        spin_lock_irqsave(&smgpio->lock, save);
 
@@ -942,6 +972,8 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
        writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW);
 
        sm501_sync_regs(sm501_gpio_to_dev(smgpio));
+       sm501_gpio_ensure_gpio(smchip, bit);
+
        spin_unlock_irqrestore(&smgpio->lock, save);
 
        return 0;
@@ -996,16 +1028,19 @@ static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm,
 {
        struct sm501_platdata *pdata = sm->platdata;
        struct gpio_chip *gchip = &chip->gpio;
-       unsigned base = pdata->gpio_base;
+       int base = pdata->gpio_base;
 
-       memcpy(chip, &gpio_chip_template, sizeof(struct gpio_chip));
+       chip->gpio = gpio_chip_template;
 
        if (chip == &gpio->high) {
-               base += 32;
+               if (base > 0)
+                       base += 32;
                chip->regbase = gpio->regs + SM501_GPIO_DATA_HIGH;
+               chip->control = sm->regs + SM501_GPIO63_32_CONTROL;
                gchip->label  = "SM501-HIGH";
        } else {
                chip->regbase = gpio->regs + SM501_GPIO_DATA_LOW;
+               chip->control = sm->regs + SM501_GPIO31_0_CONTROL;
                gchip->label  = "SM501-LOW";
        }
 
@@ -1015,7 +1050,7 @@ static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm,
        return gpiochip_add(gchip);
 }
 
-static int sm501_register_gpio(struct sm501_devdata *sm)
+static int __devinit sm501_register_gpio(struct sm501_devdata *sm)
 {
        struct sm501_gpio *gpio = &sm->gpio;
        resource_size_t iobase = sm->io_res->start + SM501_GPIO;
@@ -1037,7 +1072,7 @@ static int sm501_register_gpio(struct sm501_devdata *sm)
        if (gpio->regs == NULL) {
                dev_err(sm->dev, "gpio: failed to remap registers\n");
                ret = -ENXIO;
-               goto err_mapped;
+               goto err_claimed;
        }
 
        /* Register both our chips. */
@@ -1066,6 +1101,9 @@ static int sm501_register_gpio(struct sm501_devdata *sm)
        }
 
  err_mapped:
+       iounmap(gpio->regs);
+
+ err_claimed:
        release_resource(gpio->regs_res);
        kfree(gpio->regs_res);
 
@@ -1074,28 +1112,111 @@ static int sm501_register_gpio(struct sm501_devdata *sm)
 
 static void sm501_gpio_remove(struct sm501_devdata *sm)
 {
+       struct sm501_gpio *gpio = &sm->gpio;
        int ret;
 
-       ret = gpiochip_remove(&sm->gpio.low.gpio);
+       if (!sm->gpio.registered)
+               return;
+
+       ret = gpiochip_remove(&gpio->low.gpio);
        if (ret)
                dev_err(sm->dev, "cannot remove low chip, cannot tidy up\n");
 
-       ret = gpiochip_remove(&sm->gpio.high.gpio);
+       ret = gpiochip_remove(&gpio->high.gpio);
        if (ret)
                dev_err(sm->dev, "cannot remove high chip, cannot tidy up\n");
+
+       iounmap(gpio->regs);
+       release_resource(gpio->regs_res);
+       kfree(gpio->regs_res);
 }
 
+static inline int sm501_gpio_pin2nr(struct sm501_devdata *sm, unsigned int pin)
+{
+       struct sm501_gpio *gpio = &sm->gpio;
+       int base = (pin < 32) ? gpio->low.gpio.base : gpio->high.gpio.base;
+
+       return (pin % 32) + base;
+}
+
+static inline int sm501_gpio_isregistered(struct sm501_devdata *sm)
+{
+       return sm->gpio.registered;
+}
 #else
-static int sm501_register_gpio(struct sm501_devdata *sm)
+static inline int sm501_register_gpio(struct sm501_devdata *sm)
 {
        return 0;
 }
 
-static void sm501_gpio_remove(struct sm501_devdata *sm)
+static inline void sm501_gpio_remove(struct sm501_devdata *sm)
 {
 }
+
+static inline int sm501_gpio_pin2nr(struct sm501_devdata *sm, unsigned int pin)
+{
+       return -1;
+}
+
+static inline int sm501_gpio_isregistered(struct sm501_devdata *sm)
+{
+       return 0;
+}
 #endif
 
+static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm,
+                                           struct sm501_platdata_gpio_i2c *iic)
+{
+       struct i2c_gpio_platform_data *icd;
+       struct platform_device *pdev;
+
+       pdev = sm501_create_subdev(sm, "i2c-gpio", 0,
+                                  sizeof(struct i2c_gpio_platform_data));
+       if (!pdev)
+               return -ENOMEM;
+
+       icd = pdev->dev.platform_data;
+
+       /* We keep the pin_sda and pin_scl fields relative in case the
+        * same platform data is passed to >1 SM501.
+        */
+
+       icd->sda_pin = sm501_gpio_pin2nr(sm, iic->pin_sda);
+       icd->scl_pin = sm501_gpio_pin2nr(sm, iic->pin_scl);
+       icd->timeout = iic->timeout;
+       icd->udelay = iic->udelay;
+
+       /* note, we can't use either of the pin numbers, as the i2c-gpio
+        * driver uses the platform.id field to generate the bus number
+        * to register with the i2c core; The i2c core doesn't have enough
+        * entries to deal with anything we currently use.
+       */
+
+       pdev->id = iic->bus_num;
+
+       dev_info(sm->dev, "registering i2c-%d: sda=%d (%d), scl=%d (%d)\n",
+                iic->bus_num,
+                icd->sda_pin, iic->pin_sda, icd->scl_pin, iic->pin_scl);
+
+       return sm501_register_device(sm, pdev);
+}
+
+static int sm501_register_gpio_i2c(struct sm501_devdata *sm,
+                                  struct sm501_platdata *pdata)
+{
+       struct sm501_platdata_gpio_i2c *iic = pdata->gpio_i2c;
+       int index;
+       int ret;
+
+       for (index = 0; index < pdata->gpio_i2c_nr; index++, iic++) {
+               ret = sm501_register_gpio_i2c_instance(sm, iic);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
 /* sm501_dbg_regs
  *
  * Debug attribute to attach to parent device to show core registers
@@ -1200,9 +1321,10 @@ static unsigned int sm501_mem_local[] = {
  * Common init code for an SM501
 */
 
-static int sm501_init_dev(struct sm501_devdata *sm)
+static int __devinit sm501_init_dev(struct sm501_devdata *sm)
 {
        struct sm501_initdata *idata;
+       struct sm501_platdata *pdata;
        resource_size_t mem_avail;
        unsigned long dramctrl;
        unsigned long devid;
@@ -1241,7 +1363,9 @@ static int sm501_init_dev(struct sm501_devdata *sm)
 
        /* check to see if we have some device initialisation */
 
-       idata = sm->platdata ? sm->platdata->init : NULL;
+       pdata = sm->platdata;
+       idata = pdata ? pdata->init : NULL;
+
        if (idata) {
                sm501_init_regs(sm, idata);
 
@@ -1253,6 +1377,13 @@ static int sm501_init_dev(struct sm501_devdata *sm)
                        sm501_register_gpio(sm);
        }
 
+       if (pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
+               if (!sm501_gpio_isregistered(sm))
+                       dev_err(sm->dev, "no gpio available for i2c gpio.\n");
+               else
+                       sm501_register_gpio_i2c(sm, pdata);
+       }
+
        ret = sm501_check_clocks(sm);
        if (ret) {
                dev_err(sm->dev, "M1X and M clocks sourced from different "
@@ -1266,34 +1397,34 @@ static int sm501_init_dev(struct sm501_devdata *sm)
        return 0;
 }
 
-static int sm501_plat_probe(struct platform_device *dev)
+static int __devinit sm501_plat_probe(struct platform_device *dev)
 {
        struct sm501_devdata *sm;
-       int err;
+       int ret;
 
        sm = kzalloc(sizeof(struct sm501_devdata), GFP_KERNEL);
        if (sm == NULL) {
                dev_err(&dev->dev, "no memory for device data\n");
-               err = -ENOMEM;
+               ret = -ENOMEM;
                goto err1;
        }
 
        sm->dev = &dev->dev;
        sm->pdev_id = dev->id;
-       sm->irq = platform_get_irq(dev, 0);
-       sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
-       sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
        sm->platdata = dev->dev.platform_data;
 
-       if (sm->irq < 0) {
+       ret = platform_get_irq(dev, 0);
+       if (ret < 0) {
                dev_err(&dev->dev, "failed to get irq resource\n");
-               err = sm->irq;
                goto err_res;
        }
+       sm->irq = ret;
 
+       sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
+       sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
        if (sm->io_res == NULL || sm->mem_res == NULL) {
                dev_err(&dev->dev, "failed to get IO resource\n");
-               err = -ENOENT;
+               ret = -ENOENT;
                goto err_res;
        }
 
@@ -1302,7 +1433,7 @@ static int sm501_plat_probe(struct platform_device *dev)
 
        if (sm->regs_claim == NULL) {
                dev_err(&dev->dev, "cannot claim registers\n");
-               err= -EBUSY;
+               ret = -EBUSY;
                goto err_res;
        }
 
@@ -1313,7 +1444,7 @@ static int sm501_plat_probe(struct platform_device *dev)
 
        if (sm->regs == NULL) {
                dev_err(&dev->dev, "cannot remap registers\n");
-               err = -EIO;
+               ret = -EIO;
                goto err_claim;
        }
 
@@ -1325,7 +1456,7 @@ static int sm501_plat_probe(struct platform_device *dev)
  err_res:
        kfree(sm);
  err1:
-       return err;
+       return ret;
 
 }
 
@@ -1452,10 +1583,11 @@ static struct sm501_platdata_fb sm501_fb_pdata = {
 static struct sm501_platdata sm501_pci_platdata = {
        .init           = &sm501_pci_initdata,
        .fb             = &sm501_fb_pdata,
+       .gpio_base      = -1,
 };
 
-static int sm501_pci_probe(struct pci_dev *dev,
-                          const struct pci_device_id *id)
+static int __devinit sm501_pci_probe(struct pci_dev *dev,
+                                    const struct pci_device_id *id)
 {
        struct sm501_devdata *sm;
        int err;
@@ -1519,8 +1651,7 @@ static int sm501_pci_probe(struct pci_dev *dev,
                goto err3;
        }
 
-       sm->regs = ioremap(pci_resource_start(dev, 1),
-                          pci_resource_len(dev, 1));
+       sm->regs = pci_ioremap_bar(dev, 1);
 
        if (sm->regs == NULL) {
                dev_err(&dev->dev, "cannot remap registers\n");
@@ -1559,11 +1690,10 @@ static void sm501_dev_remove(struct sm501_devdata *sm)
 
        device_remove_file(sm->dev, &dev_attr_dbg_regs);
 
-       if (sm->gpio.registered)
-               sm501_gpio_remove(sm);
+       sm501_gpio_remove(sm);
 }
 
-static void sm501_pci_remove(struct pci_dev *dev)
+static void __devexit sm501_pci_remove(struct pci_dev *dev)
 {
        struct sm501_devdata *sm = pci_get_drvdata(dev);
 
@@ -1597,16 +1727,16 @@ static struct pci_device_id sm501_pci_tbl[] = {
 
 MODULE_DEVICE_TABLE(pci, sm501_pci_tbl);
 
-static struct pci_driver sm501_pci_drv = {
+static struct pci_driver sm501_pci_driver = {
        .name           = "sm501",
        .id_table       = sm501_pci_tbl,
        .probe          = sm501_pci_probe,
-       .remove         = sm501_pci_remove,
+       .remove         = __devexit_p(sm501_pci_remove),
 };
 
 MODULE_ALIAS("platform:sm501");
 
-static struct platform_driver sm501_plat_drv = {
+static struct platform_driver sm501_plat_driver = {
        .driver         = {
                .name   = "sm501",
                .owner  = THIS_MODULE,
@@ -1619,14 +1749,14 @@ static struct platform_driver sm501_plat_drv = {
 
 static int __init sm501_base_init(void)
 {
-       platform_driver_register(&sm501_plat_drv);
-       return pci_register_driver(&sm501_pci_drv);
+       platform_driver_register(&sm501_plat_driver);
+       return pci_register_driver(&sm501_pci_driver);
 }
 
 static void __exit sm501_base_exit(void)
 {
-       platform_driver_unregister(&sm501_plat_drv);
-       pci_unregister_driver(&sm501_pci_drv);
+       platform_driver_unregister(&sm501_plat_driver);
+       pci_unregister_driver(&sm501_pci_driver);
 }
 
 module_init(sm501_base_init);