Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 1 Aug 2011 16:14:25 +0000 (06:14 -1000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 1 Aug 2011 16:14:25 +0000 (06:14 -1000)
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  CIFS: Cleanup demupltiplex thread exiting code
  CIFS: Move mid search to a separate function
  CIFS: Move RFC1002 check to a separate function
  CIFS: Simplify socket reading in demultiplex thread
  CIFS: Move buffer allocation to a separate function
  cifs: remove unneeded variable initialization in cifs_reconnect_tcon
  cifs: simplify refcounting for oplock breaks
  cifs: fix compiler warning in CIFSSMBQAllEAs
  cifs: fix name parsing in CIFSSMBQAllEAs
  cifs: don't start signing too early
  cifs: trivial: goto out here is unnecessary
  cifs: advertise the right receive buffer size to the server

151 files changed:
arch/arm/mach-msm/Kconfig
arch/arm/mach-msm/Makefile
arch/arm/mach-msm/gpio.c [deleted file]
arch/arm/mach-msm/gpio_hw.h [deleted file]
arch/arm/mach-msm/gpiomux.h
arch/arm/mach-msm/include/mach/msm_gpiomux.h [new file with mode: 0644]
arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
arch/arm/mach-msm/include/mach/msm_iomap.h
arch/arm/mach-msm/io.c
arch/arm/mach-omap2/display.c
arch/arm/mach-shmobile/clock-sh7367.c
arch/arm/mach-shmobile/clock-sh7372.c
arch/arm/mach-shmobile/clock-sh7377.c
arch/arm/mach-shmobile/clock-sh73a0.c
arch/m68k/Kconfig.mmu
arch/m68k/amiga/chipram.c
arch/m68k/atari/stram.c
arch/m68k/include/asm/atari_stram.h
arch/m68k/include/asm/atarihw.h
arch/m68k/kernel/setup_mm.c
arch/m68k/math-emu/fp_log.c
arch/m68k/math-emu/multi_arith.h
arch/m68k/mm/init_mm.c
arch/sh/Makefile
arch/sh/boards/board-apsh4a3a.c
arch/sh/boards/board-apsh4ad0a.c
arch/sh/boards/board-sh7785lcr.c
arch/sh/boards/board-urquell.c
arch/sh/boards/mach-highlander/setup.c
arch/sh/boards/mach-sdk7786/setup.c
arch/sh/include/cpu-sh3/cpu/serial.h [new file with mode: 0644]
arch/sh/include/cpu-sh4a/cpu/serial.h [new file with mode: 0644]
arch/sh/kernel/cpu/clock-cpg.c
arch/sh/kernel/cpu/sh3/Makefile
arch/sh/kernel/cpu/sh3/serial-sh770x.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/serial-sh7710.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/serial-sh7720.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/setup-sh7705.c
arch/sh/kernel/cpu/sh3/setup-sh770x.c
arch/sh/kernel/cpu/sh3/setup-sh7720.c
arch/sh/kernel/cpu/sh4/clock-sh4-202.c
arch/sh/kernel/cpu/sh4/setup-sh7750.c
arch/sh/kernel/cpu/sh4/setup-sh7760.c
arch/sh/kernel/cpu/sh4a/Makefile
arch/sh/kernel/cpu/sh4a/clock-sh7343.c
arch/sh/kernel/cpu/sh4a/clock-sh7366.c
arch/sh/kernel/cpu/sh4a/clock-sh7722.c
arch/sh/kernel/cpu/sh4a/clock-sh7723.c
arch/sh/kernel/cpu/sh4a/clock-sh7724.c
arch/sh/kernel/cpu/sh4a/clock-sh7757.c
arch/sh/kernel/cpu/sh4a/clock-sh7763.c
arch/sh/kernel/cpu/sh4a/clock-sh7780.c
arch/sh/kernel/cpu/sh4a/clock-sh7785.c
arch/sh/kernel/cpu/sh4a/clock-sh7786.c
arch/sh/kernel/cpu/sh4a/clock-shx3.c
arch/sh/kernel/cpu/sh4a/serial-sh7722.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/setup-sh7366.c
arch/sh/kernel/cpu/sh4a/setup-sh7722.c
arch/sh/kernel/cpu/sh4a/setup-sh7723.c
arch/sh/kernel/cpu/sh4a/setup-sh7724.c
arch/sh/kernel/cpu/sh4a/setup-sh7763.c
arch/sh/kernel/cpu/sh4a/setup-sh7780.c
arch/sh/kernel/cpu/sh4a/setup-sh7785.c
arch/sh/kernel/cpu/sh4a/setup-sh7786.c
arch/sparc/kernel/ioport.c
drivers/dma/shdma.c
drivers/dma/shdma.h
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-ab8500.c
drivers/gpio/gpio-msm-v1.c [new file with mode: 0644]
drivers/gpio/gpio-msm-v2.c [moved from arch/arm/mach-msm/gpio-v2.c with 99% similarity]
drivers/gpio/gpio-tps65912.c [new file with mode: 0644]
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/aat2870-core.c [new file with mode: 0644]
drivers/mfd/ab3550-core.c
drivers/mfd/ab8500-core.c
drivers/mfd/ab8500-debugfs.c
drivers/mfd/jz4740-adc.c
drivers/mfd/lpc_sch.c
drivers/mfd/max8997-irq.c
drivers/mfd/omap-usb-host.c
drivers/mfd/stmpe.c
drivers/mfd/stmpe.h
drivers/mfd/tps65910.c
drivers/mfd/tps65911-comparator.c
drivers/mfd/tps65912-core.c [new file with mode: 0644]
drivers/mfd/tps65912-i2c.c [new file with mode: 0644]
drivers/mfd/tps65912-irq.c [new file with mode: 0644]
drivers/mfd/tps65912-spi.c [new file with mode: 0644]
drivers/mfd/twl-core.c
drivers/mfd/twl4030-madc.c
drivers/mfd/twl6030-pwm.c
drivers/mfd/wm831x-auxadc.c [new file with mode: 0644]
drivers/mfd/wm831x-core.c
drivers/mfd/wm831x-irq.c
drivers/mfd/wm8350-irq.c
drivers/mfd/wm8994-core.c
drivers/mfd/wm8994-irq.c
drivers/of/gpio.c
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/aat2870-regulator.c [new file with mode: 0644]
drivers/regulator/tps65912-regulator.c [new file with mode: 0644]
drivers/sh/clk/core.c
drivers/tty/serial/Kconfig
drivers/tty/serial/sh-sci.c
drivers/tty/serial/sh-sci.h
drivers/video/backlight/Kconfig
drivers/video/backlight/Makefile
drivers/video/backlight/aat2870_bl.c [new file with mode: 0644]
drivers/video/omap2/displays/panel-taal.c
drivers/video/omap2/dss/Kconfig
drivers/video/omap2/dss/core.c
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/display.c
drivers/video/omap2/dss/dpi.c
drivers/video/omap2/dss/dsi.c
drivers/video/omap2/dss/dss.c
drivers/video/omap2/dss/dss.h
drivers/video/omap2/dss/dss_features.c
drivers/video/omap2/dss/dss_features.h
drivers/video/omap2/dss/hdmi.c
drivers/video/omap2/dss/manager.c
drivers/video/omap2/dss/overlay.c
drivers/video/omap2/dss/rfbi.c
drivers/video/omap2/dss/sdi.c
drivers/video/omap2/dss/venc.c
drivers/video/omap2/omapfb/omapfb-ioctl.c
drivers/video/omap2/omapfb/omapfb-main.c
drivers/video/omap2/omapfb/omapfb-sysfs.c
drivers/video/omap2/omapfb/omapfb.h
fs/nfs/pnfs.h
include/linux/ioport.h
include/linux/mfd/aat2870.h [new file with mode: 0644]
include/linux/mfd/ab8500.h
include/linux/mfd/stmpe.h
include/linux/mfd/tps65910.h
include/linux/mfd/tps65912.h [new file with mode: 0644]
include/linux/mfd/wm831x/core.h
include/linux/mfd/wm831x/pdata.h
include/linux/nfs_fs_sb.h
include/linux/of_gpio.h
include/linux/serial_sci.h
include/linux/sh_clk.h
include/linux/sh_dma.h
include/video/omapdss.h
kernel/resource.c

index 888e925..ebde97f 100644 (file)
@@ -11,6 +11,7 @@ config ARCH_MSM7X00A
        select MSM_SMD
        select MSM_SMD_PKG3
        select CPU_V6
+       select GPIO_MSM_V1
        select MSM_PROC_COMM
        select HAS_MSM_DEBUG_UART_PHYS
 
@@ -22,6 +23,7 @@ config ARCH_MSM7X30
        select MSM_VIC
        select CPU_V7
        select MSM_GPIOMUX
+       select GPIO_MSM_V1
        select MSM_PROC_COMM
        select HAS_MSM_DEBUG_UART_PHYS
 
@@ -33,6 +35,7 @@ config ARCH_QSD8X50
        select MSM_VIC
        select CPU_V7
        select MSM_GPIOMUX
+       select GPIO_MSM_V1
        select MSM_PROC_COMM
        select HAS_MSM_DEBUG_UART_PHYS
 
@@ -44,6 +47,7 @@ config ARCH_MSM8X60
        select ARM_GIC
        select CPU_V7
        select MSM_V2_TLMM
+       select GPIO_MSM_V2
        select MSM_GPIOMUX
        select MSM_SCM if SMP
 
index b70658c..4285dfd 100644 (file)
@@ -29,11 +29,3 @@ obj-$(CONFIG_ARCH_MSM8960) += board-msm8960.o devices-msm8960.o
 obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-v1.o gpiomux.o
 obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o gpiomux-v1.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM8X60) += gpiomux-8x60.o gpiomux-v2.o gpiomux.o
-ifdef CONFIG_MSM_V2_TLMM
-ifndef CONFIG_ARCH_MSM8960
-# TODO: TLMM Mapping issues need to be resolved
-obj-y  += gpio-v2.o
-endif
-else
-obj-y  += gpio.o
-endif
diff --git a/arch/arm/mach-msm/gpio.c b/arch/arm/mach-msm/gpio.c
deleted file mode 100644 (file)
index 5ea273b..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-/* linux/arch/arm/mach-msm/gpio.c
- *
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/bitops.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-#include "gpio_hw.h"
-#include "gpiomux.h"
-
-#define FIRST_GPIO_IRQ MSM_GPIO_TO_INT(0)
-
-#define MSM_GPIO_BANK(bank, first, last)                               \
-       {                                                               \
-               .regs = {                                               \
-                       .out =         MSM_GPIO_OUT_##bank,             \
-                       .in =          MSM_GPIO_IN_##bank,              \
-                       .int_status =  MSM_GPIO_INT_STATUS_##bank,      \
-                       .int_clear =   MSM_GPIO_INT_CLEAR_##bank,       \
-                       .int_en =      MSM_GPIO_INT_EN_##bank,          \
-                       .int_edge =    MSM_GPIO_INT_EDGE_##bank,        \
-                       .int_pos =     MSM_GPIO_INT_POS_##bank,         \
-                       .oe =          MSM_GPIO_OE_##bank,              \
-               },                                                      \
-               .chip = {                                               \
-                       .base = (first),                                \
-                       .ngpio = (last) - (first) + 1,                  \
-                       .get = msm_gpio_get,                            \
-                       .set = msm_gpio_set,                            \
-                       .direction_input = msm_gpio_direction_input,    \
-                       .direction_output = msm_gpio_direction_output,  \
-                       .to_irq = msm_gpio_to_irq,                      \
-                       .request = msm_gpio_request,                    \
-                       .free = msm_gpio_free,                          \
-               }                                                       \
-       }
-
-#define MSM_GPIO_BROKEN_INT_CLEAR 1
-
-struct msm_gpio_regs {
-       void __iomem *out;
-       void __iomem *in;
-       void __iomem *int_status;
-       void __iomem *int_clear;
-       void __iomem *int_en;
-       void __iomem *int_edge;
-       void __iomem *int_pos;
-       void __iomem *oe;
-};
-
-struct msm_gpio_chip {
-       spinlock_t              lock;
-       struct gpio_chip        chip;
-       struct msm_gpio_regs    regs;
-#if MSM_GPIO_BROKEN_INT_CLEAR
-       unsigned                int_status_copy;
-#endif
-       unsigned int            both_edge_detect;
-       unsigned int            int_enable[2]; /* 0: awake, 1: sleep */
-};
-
-static int msm_gpio_write(struct msm_gpio_chip *msm_chip,
-                         unsigned offset, unsigned on)
-{
-       unsigned mask = BIT(offset);
-       unsigned val;
-
-       val = readl(msm_chip->regs.out);
-       if (on)
-               writel(val | mask, msm_chip->regs.out);
-       else
-               writel(val & ~mask, msm_chip->regs.out);
-       return 0;
-}
-
-static void msm_gpio_update_both_edge_detect(struct msm_gpio_chip *msm_chip)
-{
-       int loop_limit = 100;
-       unsigned pol, val, val2, intstat;
-       do {
-               val = readl(msm_chip->regs.in);
-               pol = readl(msm_chip->regs.int_pos);
-               pol = (pol & ~msm_chip->both_edge_detect) |
-                     (~val & msm_chip->both_edge_detect);
-               writel(pol, msm_chip->regs.int_pos);
-               intstat = readl(msm_chip->regs.int_status);
-               val2 = readl(msm_chip->regs.in);
-               if (((val ^ val2) & msm_chip->both_edge_detect & ~intstat) == 0)
-                       return;
-       } while (loop_limit-- > 0);
-       printk(KERN_ERR "msm_gpio_update_both_edge_detect, "
-              "failed to reach stable state %x != %x\n", val, val2);
-}
-
-static int msm_gpio_clear_detect_status(struct msm_gpio_chip *msm_chip,
-                                       unsigned offset)
-{
-       unsigned bit = BIT(offset);
-
-#if MSM_GPIO_BROKEN_INT_CLEAR
-       /* Save interrupts that already triggered before we loose them. */
-       /* Any interrupt that triggers between the read of int_status */
-       /* and the write to int_clear will still be lost though. */
-       msm_chip->int_status_copy |= readl(msm_chip->regs.int_status);
-       msm_chip->int_status_copy &= ~bit;
-#endif
-       writel(bit, msm_chip->regs.int_clear);
-       msm_gpio_update_both_edge_detect(msm_chip);
-       return 0;
-}
-
-static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-       struct msm_gpio_chip *msm_chip;
-       unsigned long irq_flags;
-
-       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       writel(readl(msm_chip->regs.oe) & ~BIT(offset), msm_chip->regs.oe);
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-       return 0;
-}
-
-static int
-msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct msm_gpio_chip *msm_chip;
-       unsigned long irq_flags;
-
-       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       msm_gpio_write(msm_chip, offset, value);
-       writel(readl(msm_chip->regs.oe) | BIT(offset), msm_chip->regs.oe);
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-       return 0;
-}
-
-static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct msm_gpio_chip *msm_chip;
-
-       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
-       return (readl(msm_chip->regs.in) & (1U << offset)) ? 1 : 0;
-}
-
-static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct msm_gpio_chip *msm_chip;
-       unsigned long irq_flags;
-
-       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       msm_gpio_write(msm_chip, offset, value);
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-}
-
-static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       return MSM_GPIO_TO_INT(chip->base + offset);
-}
-
-#ifdef CONFIG_MSM_GPIOMUX
-static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-       return msm_gpiomux_get(chip->base + offset);
-}
-
-static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
-       msm_gpiomux_put(chip->base + offset);
-}
-#else
-#define msm_gpio_request NULL
-#define msm_gpio_free NULL
-#endif
-
-struct msm_gpio_chip msm_gpio_chips[] = {
-#if defined(CONFIG_ARCH_MSM7X00A)
-       MSM_GPIO_BANK(0,   0,  15),
-       MSM_GPIO_BANK(1,  16,  42),
-       MSM_GPIO_BANK(2,  43,  67),
-       MSM_GPIO_BANK(3,  68,  94),
-       MSM_GPIO_BANK(4,  95, 106),
-       MSM_GPIO_BANK(5, 107, 121),
-#elif defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X27)
-       MSM_GPIO_BANK(0,   0,  15),
-       MSM_GPIO_BANK(1,  16,  42),
-       MSM_GPIO_BANK(2,  43,  67),
-       MSM_GPIO_BANK(3,  68,  94),
-       MSM_GPIO_BANK(4,  95, 106),
-       MSM_GPIO_BANK(5, 107, 132),
-#elif defined(CONFIG_ARCH_MSM7X30)
-       MSM_GPIO_BANK(0,   0,  15),
-       MSM_GPIO_BANK(1,  16,  43),
-       MSM_GPIO_BANK(2,  44,  67),
-       MSM_GPIO_BANK(3,  68,  94),
-       MSM_GPIO_BANK(4,  95, 106),
-       MSM_GPIO_BANK(5, 107, 133),
-       MSM_GPIO_BANK(6, 134, 150),
-       MSM_GPIO_BANK(7, 151, 181),
-#elif defined(CONFIG_ARCH_QSD8X50)
-       MSM_GPIO_BANK(0,   0,  15),
-       MSM_GPIO_BANK(1,  16,  42),
-       MSM_GPIO_BANK(2,  43,  67),
-       MSM_GPIO_BANK(3,  68,  94),
-       MSM_GPIO_BANK(4,  95, 103),
-       MSM_GPIO_BANK(5, 104, 121),
-       MSM_GPIO_BANK(6, 122, 152),
-       MSM_GPIO_BANK(7, 153, 164),
-#endif
-};
-
-static void msm_gpio_irq_ack(struct irq_data *d)
-{
-       unsigned long irq_flags;
-       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       msm_gpio_clear_detect_status(msm_chip,
-                                    d->irq - gpio_to_irq(msm_chip->chip.base));
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-}
-
-static void msm_gpio_irq_mask(struct irq_data *d)
-{
-       unsigned long irq_flags;
-       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
-       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
-
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       /* level triggered interrupts are also latched */
-       if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
-               msm_gpio_clear_detect_status(msm_chip, offset);
-       msm_chip->int_enable[0] &= ~BIT(offset);
-       writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-}
-
-static void msm_gpio_irq_unmask(struct irq_data *d)
-{
-       unsigned long irq_flags;
-       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
-       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
-
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       /* level triggered interrupts are also latched */
-       if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
-               msm_gpio_clear_detect_status(msm_chip, offset);
-       msm_chip->int_enable[0] |= BIT(offset);
-       writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-}
-
-static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
-{
-       unsigned long irq_flags;
-       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
-       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
-
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-
-       if (on)
-               msm_chip->int_enable[1] |= BIT(offset);
-       else
-               msm_chip->int_enable[1] &= ~BIT(offset);
-
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-       return 0;
-}
-
-static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-       unsigned long irq_flags;
-       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
-       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
-       unsigned val, mask = BIT(offset);
-
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       val = readl(msm_chip->regs.int_edge);
-       if (flow_type & IRQ_TYPE_EDGE_BOTH) {
-               writel(val | mask, msm_chip->regs.int_edge);
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
-       } else {
-               writel(val & ~mask, msm_chip->regs.int_edge);
-               __irq_set_handler_locked(d->irq, handle_level_irq);
-       }
-       if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
-               msm_chip->both_edge_detect |= mask;
-               msm_gpio_update_both_edge_detect(msm_chip);
-       } else {
-               msm_chip->both_edge_detect &= ~mask;
-               val = readl(msm_chip->regs.int_pos);
-               if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH))
-                       writel(val | mask, msm_chip->regs.int_pos);
-               else
-                       writel(val & ~mask, msm_chip->regs.int_pos);
-       }
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-       return 0;
-}
-
-static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
-       int i, j, mask;
-       unsigned val;
-
-       for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
-               struct msm_gpio_chip *msm_chip = &msm_gpio_chips[i];
-               val = readl(msm_chip->regs.int_status);
-               val &= msm_chip->int_enable[0];
-               while (val) {
-                       mask = val & -val;
-                       j = fls(mask) - 1;
-                       /* printk("%s %08x %08x bit %d gpio %d irq %d\n",
-                               __func__, v, m, j, msm_chip->chip.start + j,
-                               FIRST_GPIO_IRQ + msm_chip->chip.start + j); */
-                       val &= ~mask;
-                       generic_handle_irq(FIRST_GPIO_IRQ +
-                                          msm_chip->chip.base + j);
-               }
-       }
-       desc->irq_data.chip->irq_ack(&desc->irq_data);
-}
-
-static struct irq_chip msm_gpio_irq_chip = {
-       .name          = "msmgpio",
-       .irq_ack       = msm_gpio_irq_ack,
-       .irq_mask      = msm_gpio_irq_mask,
-       .irq_unmask    = msm_gpio_irq_unmask,
-       .irq_set_wake  = msm_gpio_irq_set_wake,
-       .irq_set_type  = msm_gpio_irq_set_type,
-};
-
-static int __init msm_init_gpio(void)
-{
-       int i, j = 0;
-
-       for (i = FIRST_GPIO_IRQ; i < FIRST_GPIO_IRQ + NR_GPIO_IRQS; i++) {
-               if (i - FIRST_GPIO_IRQ >=
-                       msm_gpio_chips[j].chip.base +
-                       msm_gpio_chips[j].chip.ngpio)
-                       j++;
-               irq_set_chip_data(i, &msm_gpio_chips[j]);
-               irq_set_chip_and_handler(i, &msm_gpio_irq_chip,
-                                        handle_edge_irq);
-               set_irq_flags(i, IRQF_VALID);
-       }
-
-       for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
-               spin_lock_init(&msm_gpio_chips[i].lock);
-               writel(0, msm_gpio_chips[i].regs.int_en);
-               gpiochip_add(&msm_gpio_chips[i].chip);
-       }
-
-       irq_set_chained_handler(INT_GPIO_GROUP1, msm_gpio_irq_handler);
-       irq_set_chained_handler(INT_GPIO_GROUP2, msm_gpio_irq_handler);
-       irq_set_irq_wake(INT_GPIO_GROUP1, 1);
-       irq_set_irq_wake(INT_GPIO_GROUP2, 2);
-       return 0;
-}
-
-postcore_initcall(msm_init_gpio);
diff --git a/arch/arm/mach-msm/gpio_hw.h b/arch/arm/mach-msm/gpio_hw.h
deleted file mode 100644 (file)
index 6b50660..0000000
+++ /dev/null
@@ -1,278 +0,0 @@
-/* arch/arm/mach-msm/gpio_hw.h
- *
- * Copyright (C) 2007 Google, Inc.
- * Author: Brian Swetland <swetland@google.com>
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __ARCH_ARM_MACH_MSM_GPIO_HW_H
-#define __ARCH_ARM_MACH_MSM_GPIO_HW_H
-
-#include <mach/msm_iomap.h>
-
-/* see 80-VA736-2 Rev C pp 695-751
-**
-** These are actually the *shadow* gpio registers, since the
-** real ones (which allow full access) are only available to the
-** ARM9 side of the world.
-**
-** Since the _BASE need to be page-aligned when we're mapping them
-** to virtual addresses, adjust for the additional offset in these
-** macros.
-*/
-
-#if defined(CONFIG_ARCH_MSM7X30)
-#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + (off))
-#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0x400 + (off))
-#else
-#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + 0x800 + (off))
-#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0xC00 + (off))
-#endif
-
-#if defined(CONFIG_ARCH_MSM7X00A) || defined(CONFIG_ARCH_MSM7X25) ||\
-    defined(CONFIG_ARCH_MSM7X27)
-
-/* output value */
-#define MSM_GPIO_OUT_0         MSM_GPIO1_REG(0x00)  /* gpio  15-0  */
-#define MSM_GPIO_OUT_1         MSM_GPIO2_REG(0x00)  /* gpio  42-16 */
-#define MSM_GPIO_OUT_2         MSM_GPIO1_REG(0x04)  /* gpio  67-43 */
-#define MSM_GPIO_OUT_3         MSM_GPIO1_REG(0x08)  /* gpio  94-68 */
-#define MSM_GPIO_OUT_4         MSM_GPIO1_REG(0x0C)  /* gpio 106-95 */
-#define MSM_GPIO_OUT_5         MSM_GPIO1_REG(0x50)  /* gpio 107-121 */
-
-/* same pin map as above, output enable */
-#define MSM_GPIO_OE_0          MSM_GPIO1_REG(0x10)
-#define MSM_GPIO_OE_1          MSM_GPIO2_REG(0x08)
-#define MSM_GPIO_OE_2          MSM_GPIO1_REG(0x14)
-#define MSM_GPIO_OE_3          MSM_GPIO1_REG(0x18)
-#define MSM_GPIO_OE_4          MSM_GPIO1_REG(0x1C)
-#define MSM_GPIO_OE_5          MSM_GPIO1_REG(0x54)
-
-/* same pin map as above, input read */
-#define MSM_GPIO_IN_0          MSM_GPIO1_REG(0x34)
-#define MSM_GPIO_IN_1          MSM_GPIO2_REG(0x20)
-#define MSM_GPIO_IN_2          MSM_GPIO1_REG(0x38)
-#define MSM_GPIO_IN_3          MSM_GPIO1_REG(0x3C)
-#define MSM_GPIO_IN_4          MSM_GPIO1_REG(0x40)
-#define MSM_GPIO_IN_5          MSM_GPIO1_REG(0x44)
-
-/* same pin map as above, 1=edge 0=level interrup */
-#define MSM_GPIO_INT_EDGE_0    MSM_GPIO1_REG(0x60)
-#define MSM_GPIO_INT_EDGE_1    MSM_GPIO2_REG(0x50)
-#define MSM_GPIO_INT_EDGE_2    MSM_GPIO1_REG(0x64)
-#define MSM_GPIO_INT_EDGE_3    MSM_GPIO1_REG(0x68)
-#define MSM_GPIO_INT_EDGE_4    MSM_GPIO1_REG(0x6C)
-#define MSM_GPIO_INT_EDGE_5    MSM_GPIO1_REG(0xC0)
-
-/* same pin map as above, 1=positive 0=negative */
-#define MSM_GPIO_INT_POS_0     MSM_GPIO1_REG(0x70)
-#define MSM_GPIO_INT_POS_1     MSM_GPIO2_REG(0x58)
-#define MSM_GPIO_INT_POS_2     MSM_GPIO1_REG(0x74)
-#define MSM_GPIO_INT_POS_3     MSM_GPIO1_REG(0x78)
-#define MSM_GPIO_INT_POS_4     MSM_GPIO1_REG(0x7C)
-#define MSM_GPIO_INT_POS_5     MSM_GPIO1_REG(0xBC)
-
-/* same pin map as above, interrupt enable */
-#define MSM_GPIO_INT_EN_0      MSM_GPIO1_REG(0x80)
-#define MSM_GPIO_INT_EN_1      MSM_GPIO2_REG(0x60)
-#define MSM_GPIO_INT_EN_2      MSM_GPIO1_REG(0x84)
-#define MSM_GPIO_INT_EN_3      MSM_GPIO1_REG(0x88)
-#define MSM_GPIO_INT_EN_4      MSM_GPIO1_REG(0x8C)
-#define MSM_GPIO_INT_EN_5      MSM_GPIO1_REG(0xB8)
-
-/* same pin map as above, write 1 to clear interrupt */
-#define MSM_GPIO_INT_CLEAR_0   MSM_GPIO1_REG(0x90)
-#define MSM_GPIO_INT_CLEAR_1   MSM_GPIO2_REG(0x68)
-#define MSM_GPIO_INT_CLEAR_2   MSM_GPIO1_REG(0x94)
-#define MSM_GPIO_INT_CLEAR_3   MSM_GPIO1_REG(0x98)
-#define MSM_GPIO_INT_CLEAR_4   MSM_GPIO1_REG(0x9C)
-#define MSM_GPIO_INT_CLEAR_5   MSM_GPIO1_REG(0xB4)
-
-/* same pin map as above, 1=interrupt pending */
-#define MSM_GPIO_INT_STATUS_0  MSM_GPIO1_REG(0xA0)
-#define MSM_GPIO_INT_STATUS_1  MSM_GPIO2_REG(0x70)
-#define MSM_GPIO_INT_STATUS_2  MSM_GPIO1_REG(0xA4)
-#define MSM_GPIO_INT_STATUS_3  MSM_GPIO1_REG(0xA8)
-#define MSM_GPIO_INT_STATUS_4  MSM_GPIO1_REG(0xAC)
-#define MSM_GPIO_INT_STATUS_5  MSM_GPIO1_REG(0xB0)
-
-#endif
-
-#if defined(CONFIG_ARCH_QSD8X50)
-/* output value */
-#define MSM_GPIO_OUT_0         MSM_GPIO1_REG(0x00)  /* gpio  15-0   */
-#define MSM_GPIO_OUT_1         MSM_GPIO2_REG(0x00)  /* gpio  42-16  */
-#define MSM_GPIO_OUT_2         MSM_GPIO1_REG(0x04)  /* gpio  67-43  */
-#define MSM_GPIO_OUT_3         MSM_GPIO1_REG(0x08)  /* gpio  94-68  */
-#define MSM_GPIO_OUT_4         MSM_GPIO1_REG(0x0C)  /* gpio 103-95  */
-#define MSM_GPIO_OUT_5         MSM_GPIO1_REG(0x10)  /* gpio 121-104 */
-#define MSM_GPIO_OUT_6         MSM_GPIO1_REG(0x14)  /* gpio 152-122 */
-#define MSM_GPIO_OUT_7         MSM_GPIO1_REG(0x18)  /* gpio 164-153 */
-
-/* same pin map as above, output enable */
-#define MSM_GPIO_OE_0          MSM_GPIO1_REG(0x20)
-#define MSM_GPIO_OE_1          MSM_GPIO2_REG(0x08)
-#define MSM_GPIO_OE_2          MSM_GPIO1_REG(0x24)
-#define MSM_GPIO_OE_3          MSM_GPIO1_REG(0x28)
-#define MSM_GPIO_OE_4          MSM_GPIO1_REG(0x2C)
-#define MSM_GPIO_OE_5          MSM_GPIO1_REG(0x30)
-#define MSM_GPIO_OE_6          MSM_GPIO1_REG(0x34)
-#define MSM_GPIO_OE_7          MSM_GPIO1_REG(0x38)
-
-/* same pin map as above, input read */
-#define MSM_GPIO_IN_0          MSM_GPIO1_REG(0x50)
-#define MSM_GPIO_IN_1          MSM_GPIO2_REG(0x20)
-#define MSM_GPIO_IN_2          MSM_GPIO1_REG(0x54)
-#define MSM_GPIO_IN_3          MSM_GPIO1_REG(0x58)
-#define MSM_GPIO_IN_4          MSM_GPIO1_REG(0x5C)
-#define MSM_GPIO_IN_5          MSM_GPIO1_REG(0x60)
-#define MSM_GPIO_IN_6          MSM_GPIO1_REG(0x64)
-#define MSM_GPIO_IN_7          MSM_GPIO1_REG(0x68)
-
-/* same pin map as above, 1=edge 0=level interrup */
-#define MSM_GPIO_INT_EDGE_0    MSM_GPIO1_REG(0x70)
-#define MSM_GPIO_INT_EDGE_1    MSM_GPIO2_REG(0x50)
-#define MSM_GPIO_INT_EDGE_2    MSM_GPIO1_REG(0x74)
-#define MSM_GPIO_INT_EDGE_3    MSM_GPIO1_REG(0x78)
-#define MSM_GPIO_INT_EDGE_4    MSM_GPIO1_REG(0x7C)
-#define MSM_GPIO_INT_EDGE_5    MSM_GPIO1_REG(0x80)
-#define MSM_GPIO_INT_EDGE_6    MSM_GPIO1_REG(0x84)
-#define MSM_GPIO_INT_EDGE_7    MSM_GPIO1_REG(0x88)
-
-/* same pin map as above, 1=positive 0=negative */
-#define MSM_GPIO_INT_POS_0     MSM_GPIO1_REG(0x90)
-#define MSM_GPIO_INT_POS_1     MSM_GPIO2_REG(0x58)
-#define MSM_GPIO_INT_POS_2     MSM_GPIO1_REG(0x94)
-#define MSM_GPIO_INT_POS_3     MSM_GPIO1_REG(0x98)
-#define MSM_GPIO_INT_POS_4     MSM_GPIO1_REG(0x9C)
-#define MSM_GPIO_INT_POS_5     MSM_GPIO1_REG(0xA0)
-#define MSM_GPIO_INT_POS_6     MSM_GPIO1_REG(0xA4)
-#define MSM_GPIO_INT_POS_7     MSM_GPIO1_REG(0xA8)
-
-/* same pin map as above, interrupt enable */
-#define MSM_GPIO_INT_EN_0      MSM_GPIO1_REG(0xB0)
-#define MSM_GPIO_INT_EN_1      MSM_GPIO2_REG(0x60)
-#define MSM_GPIO_INT_EN_2      MSM_GPIO1_REG(0xB4)
-#define MSM_GPIO_INT_EN_3      MSM_GPIO1_REG(0xB8)
-#define MSM_GPIO_INT_EN_4      MSM_GPIO1_REG(0xBC)
-#define MSM_GPIO_INT_EN_5      MSM_GPIO1_REG(0xC0)
-#define MSM_GPIO_INT_EN_6      MSM_GPIO1_REG(0xC4)
-#define MSM_GPIO_INT_EN_7      MSM_GPIO1_REG(0xC8)
-
-/* same pin map as above, write 1 to clear interrupt */
-#define MSM_GPIO_INT_CLEAR_0   MSM_GPIO1_REG(0xD0)
-#define MSM_GPIO_INT_CLEAR_1   MSM_GPIO2_REG(0x68)
-#define MSM_GPIO_INT_CLEAR_2   MSM_GPIO1_REG(0xD4)
-#define MSM_GPIO_INT_CLEAR_3   MSM_GPIO1_REG(0xD8)
-#define MSM_GPIO_INT_CLEAR_4   MSM_GPIO1_REG(0xDC)
-#define MSM_GPIO_INT_CLEAR_5   MSM_GPIO1_REG(0xE0)
-#define MSM_GPIO_INT_CLEAR_6   MSM_GPIO1_REG(0xE4)
-#define MSM_GPIO_INT_CLEAR_7   MSM_GPIO1_REG(0xE8)
-
-/* same pin map as above, 1=interrupt pending */
-#define MSM_GPIO_INT_STATUS_0  MSM_GPIO1_REG(0xF0)
-#define MSM_GPIO_INT_STATUS_1  MSM_GPIO2_REG(0x70)
-#define MSM_GPIO_INT_STATUS_2  MSM_GPIO1_REG(0xF4)
-#define MSM_GPIO_INT_STATUS_3  MSM_GPIO1_REG(0xF8)
-#define MSM_GPIO_INT_STATUS_4  MSM_GPIO1_REG(0xFC)
-#define MSM_GPIO_INT_STATUS_5  MSM_GPIO1_REG(0x100)
-#define MSM_GPIO_INT_STATUS_6  MSM_GPIO1_REG(0x104)
-#define MSM_GPIO_INT_STATUS_7  MSM_GPIO1_REG(0x108)
-
-#endif
-
-#if defined(CONFIG_ARCH_MSM7X30)
-
-/* output value */
-#define MSM_GPIO_OUT_0         MSM_GPIO1_REG(0x00)   /* gpio  15-0   */
-#define MSM_GPIO_OUT_1         MSM_GPIO2_REG(0x00)   /* gpio  43-16  */
-#define MSM_GPIO_OUT_2         MSM_GPIO1_REG(0x04)   /* gpio  67-44  */
-#define MSM_GPIO_OUT_3         MSM_GPIO1_REG(0x08)   /* gpio  94-68  */
-#define MSM_GPIO_OUT_4         MSM_GPIO1_REG(0x0C)   /* gpio 106-95  */
-#define MSM_GPIO_OUT_5         MSM_GPIO1_REG(0x50)   /* gpio 133-107 */
-#define MSM_GPIO_OUT_6         MSM_GPIO1_REG(0xC4)   /* gpio 150-134 */
-#define MSM_GPIO_OUT_7         MSM_GPIO1_REG(0x214)  /* gpio 181-151 */
-
-/* same pin map as above, output enable */
-#define MSM_GPIO_OE_0          MSM_GPIO1_REG(0x10)
-#define MSM_GPIO_OE_1          MSM_GPIO2_REG(0x08)
-#define MSM_GPIO_OE_2          MSM_GPIO1_REG(0x14)
-#define MSM_GPIO_OE_3          MSM_GPIO1_REG(0x18)
-#define MSM_GPIO_OE_4          MSM_GPIO1_REG(0x1C)
-#define MSM_GPIO_OE_5          MSM_GPIO1_REG(0x54)
-#define MSM_GPIO_OE_6          MSM_GPIO1_REG(0xC8)
-#define MSM_GPIO_OE_7          MSM_GPIO1_REG(0x218)
-
-/* same pin map as above, input read */
-#define MSM_GPIO_IN_0          MSM_GPIO1_REG(0x34)
-#define MSM_GPIO_IN_1          MSM_GPIO2_REG(0x20)
-#define MSM_GPIO_IN_2          MSM_GPIO1_REG(0x38)
-#define MSM_GPIO_IN_3          MSM_GPIO1_REG(0x3C)
-#define MSM_GPIO_IN_4          MSM_GPIO1_REG(0x40)
-#define MSM_GPIO_IN_5          MSM_GPIO1_REG(0x44)
-#define MSM_GPIO_IN_6          MSM_GPIO1_REG(0xCC)
-#define MSM_GPIO_IN_7          MSM_GPIO1_REG(0x21C)
-
-/* same pin map as above, 1=edge 0=level interrup */
-#define MSM_GPIO_INT_EDGE_0    MSM_GPIO1_REG(0x60)
-#define MSM_GPIO_INT_EDGE_1    MSM_GPIO2_REG(0x50)
-#define MSM_GPIO_INT_EDGE_2    MSM_GPIO1_REG(0x64)
-#define MSM_GPIO_INT_EDGE_3    MSM_GPIO1_REG(0x68)
-#define MSM_GPIO_INT_EDGE_4    MSM_GPIO1_REG(0x6C)
-#define MSM_GPIO_INT_EDGE_5    MSM_GPIO1_REG(0xC0)
-#define MSM_GPIO_INT_EDGE_6    MSM_GPIO1_REG(0xD0)
-#define MSM_GPIO_INT_EDGE_7    MSM_GPIO1_REG(0x240)
-
-/* same pin map as above, 1=positive 0=negative */
-#define MSM_GPIO_INT_POS_0     MSM_GPIO1_REG(0x70)
-#define MSM_GPIO_INT_POS_1     MSM_GPIO2_REG(0x58)
-#define MSM_GPIO_INT_POS_2     MSM_GPIO1_REG(0x74)
-#define MSM_GPIO_INT_POS_3     MSM_GPIO1_REG(0x78)
-#define MSM_GPIO_INT_POS_4     MSM_GPIO1_REG(0x7C)
-#define MSM_GPIO_INT_POS_5     MSM_GPIO1_REG(0xBC)
-#define MSM_GPIO_INT_POS_6     MSM_GPIO1_REG(0xD4)
-#define MSM_GPIO_INT_POS_7     MSM_GPIO1_REG(0x228)
-
-/* same pin map as above, interrupt enable */
-#define MSM_GPIO_INT_EN_0      MSM_GPIO1_REG(0x80)
-#define MSM_GPIO_INT_EN_1      MSM_GPIO2_REG(0x60)
-#define MSM_GPIO_INT_EN_2      MSM_GPIO1_REG(0x84)
-#define MSM_GPIO_INT_EN_3      MSM_GPIO1_REG(0x88)
-#define MSM_GPIO_INT_EN_4      MSM_GPIO1_REG(0x8C)
-#define MSM_GPIO_INT_EN_5      MSM_GPIO1_REG(0xB8)
-#define MSM_GPIO_INT_EN_6      MSM_GPIO1_REG(0xD8)
-#define MSM_GPIO_INT_EN_7      MSM_GPIO1_REG(0x22C)
-
-/* same pin map as above, write 1 to clear interrupt */
-#define MSM_GPIO_INT_CLEAR_0   MSM_GPIO1_REG(0x90)
-#define MSM_GPIO_INT_CLEAR_1   MSM_GPIO2_REG(0x68)
-#define MSM_GPIO_INT_CLEAR_2   MSM_GPIO1_REG(0x94)
-#define MSM_GPIO_INT_CLEAR_3   MSM_GPIO1_REG(0x98)
-#define MSM_GPIO_INT_CLEAR_4   MSM_GPIO1_REG(0x9C)
-#define MSM_GPIO_INT_CLEAR_5   MSM_GPIO1_REG(0xB4)
-#define MSM_GPIO_INT_CLEAR_6   MSM_GPIO1_REG(0xDC)
-#define MSM_GPIO_INT_CLEAR_7   MSM_GPIO1_REG(0x230)
-
-/* same pin map as above, 1=interrupt pending */
-#define MSM_GPIO_INT_STATUS_0  MSM_GPIO1_REG(0xA0)
-#define MSM_GPIO_INT_STATUS_1  MSM_GPIO2_REG(0x70)
-#define MSM_GPIO_INT_STATUS_2  MSM_GPIO1_REG(0xA4)
-#define MSM_GPIO_INT_STATUS_3  MSM_GPIO1_REG(0xA8)
-#define MSM_GPIO_INT_STATUS_4  MSM_GPIO1_REG(0xAC)
-#define MSM_GPIO_INT_STATUS_5  MSM_GPIO1_REG(0xB0)
-#define MSM_GPIO_INT_STATUS_6  MSM_GPIO1_REG(0xE0)
-#define MSM_GPIO_INT_STATUS_7  MSM_GPIO1_REG(0x234)
-
-#endif
-
-#endif
index b178d9c..00459f6 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/bitops.h>
 #include <linux/errno.h>
+#include <mach/msm_gpiomux.h>
 
 #if defined(CONFIG_MSM_V2_TLMM)
 #include "gpiomux-v2.h"
@@ -71,12 +72,6 @@ enum {
  */
 extern struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS];
 
-/* Increment a gpio's reference count, possibly activating the line. */
-int __must_check msm_gpiomux_get(unsigned gpio);
-
-/* Decrement a gpio's reference count, possibly suspending the line. */
-int msm_gpiomux_put(unsigned gpio);
-
 /* Install a new configuration to the gpio line.  To avoid overwriting
  * a configuration, leave the VALID bit out.
  */
@@ -94,16 +89,6 @@ int msm_gpiomux_write(unsigned gpio,
  */
 void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val);
 #else
-static inline int __must_check msm_gpiomux_get(unsigned gpio)
-{
-       return -ENOSYS;
-}
-
-static inline int msm_gpiomux_put(unsigned gpio)
-{
-       return -ENOSYS;
-}
-
 static inline int msm_gpiomux_write(unsigned gpio,
                                    gpiomux_config_t active,
                                    gpiomux_config_t suspended)
diff --git a/arch/arm/mach-msm/include/mach/msm_gpiomux.h b/arch/arm/mach-msm/include/mach/msm_gpiomux.h
new file mode 100644 (file)
index 0000000..0c7d393
--- /dev/null
@@ -0,0 +1,38 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _LINUX_MSM_GPIOMUX_H
+#define _LINUX_MSM_GPIOMUX_H
+
+#ifdef CONFIG_MSM_GPIOMUX
+
+/* Increment a gpio's reference count, possibly activating the line. */
+int __must_check msm_gpiomux_get(unsigned gpio);
+
+/* Decrement a gpio's reference count, possibly suspending the line. */
+int msm_gpiomux_put(unsigned gpio);
+
+#else
+
+static inline int __must_check msm_gpiomux_get(unsigned gpio)
+{
+       return -ENOSYS;
+}
+
+static inline int msm_gpiomux_put(unsigned gpio)
+{
+       return -ENOSYS;
+}
+
+#endif
+
+#endif /* _LINUX_MSM_GPIOMUX_H */
index 8f99d97..94fe9fe 100644 (file)
 #define MSM_DMOV_PHYS         0xA9700000
 #define MSM_DMOV_SIZE         SZ_4K
 
-#define MSM_GPIO1_BASE        IOMEM(0xE0003000)
-#define MSM_GPIO1_PHYS        0xA9200000
-#define MSM_GPIO1_SIZE        SZ_4K
+#define MSM7X00_GPIO1_PHYS        0xA9200000
+#define MSM7X00_GPIO1_SIZE        SZ_4K
 
-#define MSM_GPIO2_BASE        IOMEM(0xE0004000)
-#define MSM_GPIO2_PHYS        0xA9300000
-#define MSM_GPIO2_SIZE        SZ_4K
+#define MSM7X00_GPIO2_PHYS        0xA9300000
+#define MSM7X00_GPIO2_SIZE        SZ_4K
 
 #define MSM_CLK_CTL_BASE      IOMEM(0xE0005000)
 #define MSM_CLK_CTL_PHYS      0xA8600000
index 4d84be1..3769444 100644 (file)
 #define MSM_DMOV_PHYS         0xAC400000
 #define MSM_DMOV_SIZE         SZ_4K
 
-#define MSM_GPIO1_BASE        IOMEM(0xE0003000)
-#define MSM_GPIO1_PHYS        0xAC001000
-#define MSM_GPIO1_SIZE        SZ_4K
+#define MSM7X30_GPIO1_PHYS        0xAC001000
+#define MSM7X30_GPIO1_SIZE        SZ_4K
 
-#define MSM_GPIO2_BASE        IOMEM(0xE0004000)
-#define MSM_GPIO2_PHYS        0xAC101000
-#define MSM_GPIO2_SIZE        SZ_4K
+#define MSM7X30_GPIO2_PHYS        0xAC101000
+#define MSM7X30_GPIO2_SIZE        SZ_4K
 
 #define MSM_CLK_CTL_BASE      IOMEM(0xE0005000)
 #define MSM_CLK_CTL_PHYS      0xAB800000
index d414320..d67cd73 100644 (file)
 #define MSM_DMOV_PHYS         0xA9700000
 #define MSM_DMOV_SIZE         SZ_4K
 
-#define MSM_GPIO1_BASE        IOMEM(0xE0003000)
-#define MSM_GPIO1_PHYS        0xA9000000
-#define MSM_GPIO1_SIZE        SZ_4K
+#define QSD8X50_GPIO1_PHYS        0xA9000000
+#define QSD8X50_GPIO1_SIZE        SZ_4K
 
-#define MSM_GPIO2_BASE        IOMEM(0xE0004000)
-#define MSM_GPIO2_PHYS        0xA9100000
-#define MSM_GPIO2_SIZE        SZ_4K
+#define QSD8X50_GPIO2_PHYS        0xA9100000
+#define QSD8X50_GPIO2_SIZE        SZ_4K
 
 #define MSM_CLK_CTL_BASE      IOMEM(0xE0005000)
 #define MSM_CLK_CTL_PHYS      0xA8600000
index 2f494b6..4ded152 100644 (file)
@@ -61,5 +61,7 @@
 #define MSM_QGIC_CPU_BASE      IOMEM(0xF0001000)
 #define MSM_TMR_BASE           IOMEM(0xF0200000)
 #define MSM_TMR0_BASE          IOMEM(0xF0201000)
+#define MSM_GPIO1_BASE         IOMEM(0xE0003000)
+#define MSM_GPIO2_BASE         IOMEM(0xE0004000)
 
 #endif
index cec6ed1..140ddbb 100644 (file)
@@ -43,8 +43,8 @@ static struct map_desc msm_io_desc[] __initdata = {
        MSM_DEVICE(VIC),
        MSM_CHIP_DEVICE(CSR, MSM7X00),
        MSM_DEVICE(DMOV),
-       MSM_DEVICE(GPIO1),
-       MSM_DEVICE(GPIO2),
+       MSM_CHIP_DEVICE(GPIO1, MSM7X00),
+       MSM_CHIP_DEVICE(GPIO2, MSM7X00),
        MSM_DEVICE(CLK_CTL),
 #ifdef CONFIG_MSM_DEBUG_UART
        MSM_DEVICE(DEBUG_UART),
@@ -76,8 +76,8 @@ static struct map_desc qsd8x50_io_desc[] __initdata = {
        MSM_DEVICE(VIC),
        MSM_CHIP_DEVICE(CSR, QSD8X50),
        MSM_DEVICE(DMOV),
-       MSM_DEVICE(GPIO1),
-       MSM_DEVICE(GPIO2),
+       MSM_CHIP_DEVICE(GPIO1, QSD8X50),
+       MSM_CHIP_DEVICE(GPIO2, QSD8X50),
        MSM_DEVICE(CLK_CTL),
        MSM_DEVICE(SIRC),
        MSM_DEVICE(SCPLL),
@@ -135,8 +135,8 @@ static struct map_desc msm7x30_io_desc[] __initdata = {
        MSM_DEVICE(VIC),
        MSM_CHIP_DEVICE(CSR, MSM7X30),
        MSM_DEVICE(DMOV),
-       MSM_DEVICE(GPIO1),
-       MSM_DEVICE(GPIO2),
+       MSM_CHIP_DEVICE(GPIO1, MSM7X30),
+       MSM_CHIP_DEVICE(GPIO2, MSM7X30),
        MSM_DEVICE(CLK_CTL),
        MSM_DEVICE(CLK_CTL_SH2),
        MSM_DEVICE(AD5),
index 543fcb8..a5b7a23 100644 (file)
@@ -25,6 +25,7 @@
 #include <video/omapdss.h>
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
+#include <plat/omap-pm.h>
 
 static struct platform_device omap_display_device = {
        .name          = "omapdss",
@@ -42,20 +43,6 @@ static struct omap_device_pm_latency omap_dss_latency[] = {
        },
 };
 
-/* oh_core is used for getting opt-clocks */
-static struct omap_hwmod       *oh_core;
-
-static bool opt_clock_available(const char *clk_role)
-{
-       int i;
-
-       for (i = 0; i < oh_core->opt_clks_cnt; i++) {
-               if (!strcmp(oh_core->opt_clks[i].role, clk_role))
-                       return true;
-       }
-       return false;
-}
-
 struct omap_dss_hwmod_data {
        const char *oh_name;
        const char *dev_name;
@@ -109,16 +96,9 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
                oh_count = ARRAY_SIZE(omap4_dss_hwmod_data);
        }
 
-       /* opt_clks are always associated with dss hwmod */
-       oh_core = omap_hwmod_lookup("dss_core");
-       if (!oh_core) {
-               pr_err("Could not look up dss_core.\n");
-               return -ENODEV;
-       }
-
        pdata.board_data = board_data;
-       pdata.board_data->get_last_off_on_transaction_id = NULL;
-       pdata.opt_clock_available = opt_clock_available;
+       pdata.board_data->get_context_loss_count =
+               omap_pm_get_dev_context_loss_count;
 
        for (i = 0; i < oh_count; i++) {
                oh = omap_hwmod_lookup(curr_dss_hwmod[i].oh_name);
index 6b186ae..5218c34 100644 (file)
@@ -259,9 +259,6 @@ static struct clk mstp_clks[MSTP_NR] = {
        [CMMSTP003] = MSTP(&r_clk, CMMSTPCR0, 3, 0), /* KEYSC */
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("r_clk", &r_clk),
index 91f5779..6b1619a 100644 (file)
@@ -561,10 +561,6 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
-#define CLKDEV_ICK_ID(_cid, _did, _clk) { .con_id = _cid, .dev_id = _did, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("dv_clki_div2_clk", &sh7372_dv_clki_div2_clk),
index 9594246..8cee7b1 100644 (file)
@@ -267,9 +267,6 @@ static struct clk mstp_clks[] = {
        [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("r_clk", &r_clk),
index bcacb1e..6db2cca 100644 (file)
@@ -306,10 +306,6 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
-#define CLKDEV_ICK_ID(_cid, _did, _clk) { .con_id = _cid, .dev_id = _did, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("r_clk", &r_clk),
index 16539b1..13e20bb 100644 (file)
@@ -372,12 +372,6 @@ config AMIGA_PCMCIA
          Include support in the kernel for pcmcia on Amiga 1200 and Amiga
          600. If you intend to use pcmcia cards say Y; otherwise say N.
 
-config STRAM_PROC
-       bool "ST-RAM statistics in /proc"
-       depends on ATARI
-       help
-         Say Y here to report ST-RAM usage statistics in /proc/stram.
-
 config HEARTBEAT
        bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
        default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
index dd0447d..99449fb 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/string.h>
 #include <linux/module.h>
 
+#include <asm/atomic.h>
 #include <asm/page.h>
 #include <asm/amigahw.h>
 
@@ -23,111 +24,100 @@ unsigned long amiga_chip_size;
 EXPORT_SYMBOL(amiga_chip_size);
 
 static struct resource chipram_res = {
-    .name = "Chip RAM", .start = CHIP_PHYSADDR
+       .name = "Chip RAM", .start = CHIP_PHYSADDR
 };
-static unsigned long chipavail;
+static atomic_t chipavail;
 
 
 void __init amiga_chip_init(void)
 {
-    if (!AMIGAHW_PRESENT(CHIP_RAM))
-       return;
+       if (!AMIGAHW_PRESENT(CHIP_RAM))
+               return;
 
-    chipram_res.end = amiga_chip_size-1;
-    request_resource(&iomem_resource, &chipram_res);
+       chipram_res.end = CHIP_PHYSADDR + amiga_chip_size - 1;
+       request_resource(&iomem_resource, &chipram_res);
 
-    chipavail = amiga_chip_size;
+       atomic_set(&chipavail, amiga_chip_size);
 }
 
 
 void *amiga_chip_alloc(unsigned long size, const char *name)
 {
-    struct resource *res;
+       struct resource *res;
+       void *p;
 
-    /* round up */
-    size = PAGE_ALIGN(size);
+       res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+       if (!res)
+               return NULL;
 
-#ifdef DEBUG
-    printk("amiga_chip_alloc: allocate %ld bytes\n", size);
-#endif
-    res = kzalloc(sizeof(struct resource), GFP_KERNEL);
-    if (!res)
-       return NULL;
-    res->name = name;
+       res->name = name;
+       p = amiga_chip_alloc_res(size, res);
+       if (!p) {
+               kfree(res);
+               return NULL;
+       }
 
-    if (allocate_resource(&chipram_res, res, size, 0, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) {
-       kfree(res);
-       return NULL;
-    }
-    chipavail -= size;
-#ifdef DEBUG
-    printk("amiga_chip_alloc: returning %lx\n", res->start);
-#endif
-    return (void *)ZTWO_VADDR(res->start);
+       return p;
 }
 EXPORT_SYMBOL(amiga_chip_alloc);
 
 
-    /*
-     *  Warning:
-     *  amiga_chip_alloc_res is meant only for drivers that need to allocate
-     *  Chip RAM before kmalloc() is functional. As a consequence, those
-      drivers must not free that Chip RAM afterwards.
-     */
+       /*
+        *  Warning:
+        *  amiga_chip_alloc_res is meant only for drivers that need to
+        *  allocate Chip RAM before kmalloc() is functional. As a consequence,
+        *  those drivers must not free that Chip RAM afterwards.
+        */
 
-void * __init amiga_chip_alloc_res(unsigned long size, struct resource *res)
+void *amiga_chip_alloc_res(unsigned long size, struct resource *res)
 {
-    unsigned long start;
-
-    /* round up */
-    size = PAGE_ALIGN(size);
-    /* dmesg into chipmem prefers memory at the safe end */
-    start = CHIP_PHYSADDR + chipavail - size;
-
-#ifdef DEBUG
-    printk("amiga_chip_alloc_res: allocate %ld bytes\n", size);
-#endif
-    if (allocate_resource(&chipram_res, res, size, start, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) {
-       printk("amiga_chip_alloc_res: first alloc failed!\n");
-       if (allocate_resource(&chipram_res, res, size, 0, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0)
-           return NULL;
-    }
-    chipavail -= size;
-#ifdef DEBUG
-    printk("amiga_chip_alloc_res: returning %lx\n", res->start);
-#endif
-    return (void *)ZTWO_VADDR(res->start);
+       int error;
+
+       /* round up */
+       size = PAGE_ALIGN(size);
+
+       pr_debug("amiga_chip_alloc_res: allocate %lu bytes\n", size);
+       error = allocate_resource(&chipram_res, res, size, 0, UINT_MAX,
+                                 PAGE_SIZE, NULL, NULL);
+       if (error < 0) {
+               pr_err("amiga_chip_alloc_res: allocate_resource() failed %d!\n",
+                      error);
+               return NULL;
+       }
+
+       atomic_sub(size, &chipavail);
+       pr_debug("amiga_chip_alloc_res: returning %pR\n", res);
+       return (void *)ZTWO_VADDR(res->start);
 }
 
 void amiga_chip_free(void *ptr)
 {
-    unsigned long start = ZTWO_PADDR(ptr);
-    struct resource **p, *res;
-    unsigned long size;
-
-    for (p = &chipram_res.child; (res = *p); p = &res->sibling) {
-       if (res->start != start)
-           continue;
-       *p = res->sibling;
-       size = res->end-start;
-#ifdef DEBUG
-       printk("amiga_chip_free: free %ld bytes at %p\n", size, ptr);
-#endif
-       chipavail += size;
+       unsigned long start = ZTWO_PADDR(ptr);
+       struct resource *res;
+       unsigned long size;
+
+       res = lookup_resource(&chipram_res, start);
+       if (!res) {
+               pr_err("amiga_chip_free: trying to free nonexistent region at "
+                      "%p\n", ptr);
+               return;
+       }
+
+       size = resource_size(res);
+       pr_debug("amiga_chip_free: free %lu bytes at %p\n", size, ptr);
+       atomic_add(size, &chipavail);
+       release_resource(res);
        kfree(res);
-       return;
-    }
-    printk("amiga_chip_free: trying to free nonexistent region at %p\n", ptr);
 }
 EXPORT_SYMBOL(amiga_chip_free);
 
 
 unsigned long amiga_chip_avail(void)
 {
-#ifdef DEBUG
-       printk("amiga_chip_avail : %ld bytes\n", chipavail);
-#endif
-       return chipavail;
+       unsigned long n = atomic_read(&chipavail);
+
+       pr_debug("amiga_chip_avail : %lu bytes\n", n);
+       return n;
 }
 EXPORT_SYMBOL(amiga_chip_avail);
 
index 6ec3b7f..0810c8d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/m68k/atari/stram.c: Functions for ST-RAM allocations
+ * Functions for ST-RAM allocations
  *
  * Copyright 1994-97 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
  *
 #include <asm/atari_stram.h>
 #include <asm/io.h>
 
-#undef DEBUG
-
-#ifdef DEBUG
-#define        DPRINTK(fmt,args...) printk( fmt, ##args )
-#else
-#define DPRINTK(fmt,args...)
-#endif
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_STRAM_PROC)
-/* abbrev for the && above... */
-#define DO_PROC
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#endif
 
 /*
- * ++roman:
- *
- * New version of ST-Ram buffer allocation. Instead of using the
- * 1 MB - 4 KB that remain when the ST-Ram chunk starts at $1000
- * (1 MB granularity!), such buffers are reserved like this:
- *
- *  - If the kernel resides in ST-Ram anyway, we can take the buffer
- *    from behind the current kernel data space the normal way
- *    (incrementing start_mem).
- *
- *  - If the kernel is in TT-Ram, stram_init() initializes start and
- *    end of the available region. Buffers are allocated from there
- *    and mem_init() later marks the such used pages as reserved.
- *    Since each TT-Ram chunk is at least 4 MB in size, I hope there
- *    won't be an overrun of the ST-Ram region by normal kernel data
- *    space.
- *
- * For that, ST-Ram may only be allocated while kernel initialization
- * is going on, or exactly: before mem_init() is called. There is also
- * no provision now for freeing ST-Ram buffers. It seems that isn't
- * really needed.
- *
+ * The ST-RAM allocator allocates memory from a pool of reserved ST-RAM of
+ * configurable size, set aside on ST-RAM init.
+ * As long as this pool is not exhausted, allocation of real ST-RAM can be
+ * guaranteed.
  */
 
-/* Start and end (virtual) of ST-RAM */
-static void *stram_start, *stram_end;
-
-/* set after memory_init() executed and allocations via start_mem aren't
- * possible anymore */
-static int mem_init_done;
-
 /* set if kernel is in ST-RAM */
 static int kernel_in_stram;
 
-typedef struct stram_block {
-       struct stram_block *next;
-       void *start;
-       unsigned long size;
-       unsigned flags;
-       const char *owner;
-} BLOCK;
-
-/* values for flags field */
-#define BLOCK_FREE     0x01    /* free structure in the BLOCKs pool */
-#define BLOCK_KMALLOCED        0x02    /* structure allocated by kmalloc() */
-#define BLOCK_GFP      0x08    /* block allocated with __get_dma_pages() */
+static struct resource stram_pool = {
+       .name = "ST-RAM Pool"
+};
 
-/* list of allocated blocks */
-static BLOCK *alloc_list;
+static unsigned long pool_size = 1024*1024;
 
-/* We can't always use kmalloc() to allocate BLOCK structures, since
- * stram_alloc() can be called rather early. So we need some pool of
- * statically allocated structures. 20 of them is more than enough, so in most
- * cases we never should need to call kmalloc(). */
-#define N_STATIC_BLOCKS        20
-static BLOCK static_blocks[N_STATIC_BLOCKS];
 
-/***************************** Prototypes *****************************/
+static int __init atari_stram_setup(char *arg)
+{
+       if (!MACH_IS_ATARI)
+               return 0;
 
-static BLOCK *add_region( void *addr, unsigned long size );
-static BLOCK *find_region( void *addr );
-static int remove_region( BLOCK *block );
+       pool_size = memparse(arg, NULL);
+       return 0;
+}
 
-/************************* End of Prototypes **************************/
+early_param("stram_pool", atari_stram_setup);
 
-\f
-/* ------------------------------------------------------------------------ */
-/*                                                        Public Interface                                                             */
-/* ------------------------------------------------------------------------ */
 
 /*
  * This init function is called very early by atari/config.c
@@ -123,25 +67,23 @@ static int remove_region( BLOCK *block );
 void __init atari_stram_init(void)
 {
        int i;
+       void *stram_start;
 
-       /* initialize static blocks */
-       for( i = 0; i < N_STATIC_BLOCKS; ++i )
-               static_blocks[i].flags = BLOCK_FREE;
-
-       /* determine whether kernel code resides in ST-RAM (then ST-RAM is the
-        * first memory block at virtual 0x0) */
+       /*
+        * determine whether kernel code resides in ST-RAM
+        * (then ST-RAM is the first memory block at virtual 0x0)
+        */
        stram_start = phys_to_virt(0);
        kernel_in_stram = (stram_start == 0);
 
-       for( i = 0; i < m68k_num_memory; ++i ) {
+       for (i = 0; i < m68k_num_memory; ++i) {
                if (m68k_memory[i].addr == 0) {
-                       /* skip first 2kB or page (supervisor-only!) */
-                       stram_end = stram_start + m68k_memory[i].size;
                        return;
                }
        }
+
        /* Should never come here! (There is always ST-Ram!) */
-       panic( "atari_stram_init: no ST-RAM found!" );
+       panic("atari_stram_init: no ST-RAM found!");
 }
 
 
@@ -151,226 +93,68 @@ void __init atari_stram_init(void)
  */
 void __init atari_stram_reserve_pages(void *start_mem)
 {
-       /* always reserve first page of ST-RAM, the first 2 kB are
-        * supervisor-only! */
+       /*
+        * always reserve first page of ST-RAM, the first 2 KiB are
+        * supervisor-only!
+        */
        if (!kernel_in_stram)
                reserve_bootmem(0, PAGE_SIZE, BOOTMEM_DEFAULT);
 
-}
+       stram_pool.start = (resource_size_t)alloc_bootmem_low_pages(pool_size);
+       stram_pool.end = stram_pool.start + pool_size - 1;
+       request_resource(&iomem_resource, &stram_pool);
 
-void atari_stram_mem_init_hook (void)
-{
-       mem_init_done = 1;
+       pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n",
+                pool_size, &stram_pool);
 }
 
 
-/*
- * This is main public interface: somehow allocate a ST-RAM block
- *
- *  - If we're before mem_init(), we have to make a static allocation. The
- *    region is taken in the kernel data area (if the kernel is in ST-RAM) or
- *    from the start of ST-RAM (if the kernel is in TT-RAM) and added to the
- *    rsvd_stram_* region. The ST-RAM is somewhere in the middle of kernel
- *    address space in the latter case.
- *
- *  - If mem_init() already has been called, try with __get_dma_pages().
- *    This has the disadvantage that it's very hard to get more than 1 page,
- *    and it is likely to fail :-(
- *
- */
-void *atari_stram_alloc(long size, const char *owner)
+void *atari_stram_alloc(unsigned long size, const char *owner)
 {
-       void *addr = NULL;
-       BLOCK *block;
-       int flags;
-
-       DPRINTK("atari_stram_alloc(size=%08lx,owner=%s)\n", size, owner);
-
-       if (!mem_init_done)
-               return alloc_bootmem_low(size);
-       else {
-               /* After mem_init(): can only resort to __get_dma_pages() */
-               addr = (void *)__get_dma_pages(GFP_KERNEL, get_order(size));
-               flags = BLOCK_GFP;
-               DPRINTK( "atari_stram_alloc: after mem_init, "
-                                "get_pages=%p\n", addr );
+       struct resource *res;
+       int error;
+
+       pr_debug("atari_stram_alloc: allocate %lu bytes\n", size);
+
+       /* round up */
+       size = PAGE_ALIGN(size);
+
+       res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+       if (!res)
+               return NULL;
+
+       res->name = owner;
+       error = allocate_resource(&stram_pool, res, size, 0, UINT_MAX,
+                                 PAGE_SIZE, NULL, NULL);
+       if (error < 0) {
+               pr_err("atari_stram_alloc: allocate_resource() failed %d!\n",
+                      error);
+               kfree(res);
+               return NULL;
        }
 
-       if (addr) {
-               if (!(block = add_region( addr, size ))) {
-                       /* out of memory for BLOCK structure :-( */
-                       DPRINTK( "atari_stram_alloc: out of mem for BLOCK -- "
-                                        "freeing again\n" );
-                       free_pages((unsigned long)addr, get_order(size));
-                       return( NULL );
-               }
-               block->owner = owner;
-               block->flags |= flags;
-       }
-       return( addr );
+       pr_debug("atari_stram_alloc: returning %pR\n", res);
+       return (void *)res->start;
 }
 EXPORT_SYMBOL(atari_stram_alloc);
 
-void atari_stram_free( void *addr )
 
+void atari_stram_free(void *addr)
 {
-       BLOCK *block;
-
-       DPRINTK( "atari_stram_free(addr=%p)\n", addr );
+       unsigned long start = (unsigned long)addr;
+       struct resource *res;
+       unsigned long size;
 
-       if (!(block = find_region( addr ))) {
-               printk( KERN_ERR "Attempt to free non-allocated ST-RAM block at %p "
-                               "from %p\n", addr, __builtin_return_address(0) );
+       res = lookup_resource(&stram_pool, start);
+       if (!res) {
+               pr_err("atari_stram_free: trying to free nonexistent region "
+                      "at %p\n", addr);
                return;
        }
-       DPRINTK( "atari_stram_free: found block (%p): size=%08lx, owner=%s, "
-                        "flags=%02x\n", block, block->size, block->owner, block->flags );
-
-       if (!(block->flags & BLOCK_GFP))
-               goto fail;
 
-       DPRINTK("atari_stram_free: is kmalloced, order_size=%d\n",
-               get_order(block->size));
-       free_pages((unsigned long)addr, get_order(block->size));
-       remove_region( block );
-       return;
-
-  fail:
-       printk( KERN_ERR "atari_stram_free: cannot free block at %p "
-                       "(called from %p)\n", addr, __builtin_return_address(0) );
+       size = resource_size(res);
+       pr_debug("atari_stram_free: free %lu bytes at %p\n", size, addr);
+       release_resource(res);
+       kfree(res);
 }
 EXPORT_SYMBOL(atari_stram_free);
-
-\f
-/* ------------------------------------------------------------------------ */
-/*                                                       Region Management                                                             */
-/* ------------------------------------------------------------------------ */
-
-
-/* insert a region into the alloced list (sorted) */
-static BLOCK *add_region( void *addr, unsigned long size )
-{
-       BLOCK **p, *n = NULL;
-       int i;
-
-       for( i = 0; i < N_STATIC_BLOCKS; ++i ) {
-               if (static_blocks[i].flags & BLOCK_FREE) {
-                       n = &static_blocks[i];
-                       n->flags = 0;
-                       break;
-               }
-       }
-       if (!n && mem_init_done) {
-               /* if statics block pool exhausted and we can call kmalloc() already
-                * (after mem_init()), try that */
-               n = kmalloc( sizeof(BLOCK), GFP_KERNEL );
-               if (n)
-                       n->flags = BLOCK_KMALLOCED;
-       }
-       if (!n) {
-               printk( KERN_ERR "Out of memory for ST-RAM descriptor blocks\n" );
-               return( NULL );
-       }
-       n->start = addr;
-       n->size  = size;
-
-       for( p = &alloc_list; *p; p = &((*p)->next) )
-               if ((*p)->start > addr) break;
-       n->next = *p;
-       *p = n;
-
-       return( n );
-}
-
-
-/* find a region (by start addr) in the alloced list */
-static BLOCK *find_region( void *addr )
-{
-       BLOCK *p;
-
-       for( p = alloc_list; p; p = p->next ) {
-               if (p->start == addr)
-                       return( p );
-               if (p->start > addr)
-                       break;
-       }
-       return( NULL );
-}
-
-
-/* remove a block from the alloced list */
-static int remove_region( BLOCK *block )
-{
-       BLOCK **p;
-
-       for( p = &alloc_list; *p; p = &((*p)->next) )
-               if (*p == block) break;
-       if (!*p)
-               return( 0 );
-
-       *p = block->next;
-       if (block->flags & BLOCK_KMALLOCED)
-               kfree( block );
-       else
-               block->flags |= BLOCK_FREE;
-       return( 1 );
-}
-
-
-\f
-/* ------------------------------------------------------------------------ */
-/*                                              /proc statistics file stuff                                            */
-/* ------------------------------------------------------------------------ */
-
-#ifdef DO_PROC
-
-#define        PRINT_PROC(fmt,args...) seq_printf( m, fmt, ##args )
-
-static int stram_proc_show(struct seq_file *m, void *v)
-{
-       BLOCK *p;
-
-       PRINT_PROC("Total ST-RAM:      %8u kB\n",
-                          (stram_end - stram_start) >> 10);
-       PRINT_PROC( "Allocated regions:\n" );
-       for( p = alloc_list; p; p = p->next ) {
-               PRINT_PROC("0x%08lx-0x%08lx: %s (",
-                          virt_to_phys(p->start),
-                          virt_to_phys(p->start+p->size-1),
-                          p->owner);
-               if (p->flags & BLOCK_GFP)
-                       PRINT_PROC( "page-alloced)\n" );
-               else
-                       PRINT_PROC( "??)\n" );
-       }
-
-       return 0;
-}
-
-static int stram_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, stram_proc_show, NULL);
-}
-
-static const struct file_operations stram_proc_fops = {
-       .open           = stram_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-static int __init proc_stram_init(void)
-{
-       proc_create("stram", 0, NULL, &stram_proc_fops);
-       return 0;
-}
-module_init(proc_stram_init);
-#endif
-
-
-/*
- * Local variables:
- *  c-indent-level: 4
- *  tab-width: 4
- * End:
- */
index 7546d13..62e2759 100644 (file)
@@ -6,12 +6,11 @@
  */
 
 /* public interface */
-void *atari_stram_alloc(long size, const char *owner);
+void *atari_stram_alloc(unsigned long size, const char *owner);
 void atari_stram_free(void *);
 
 /* functions called internally by other parts of the kernel */
 void atari_stram_init(void);
 void atari_stram_reserve_pages(void *start_mem);
-void atari_stram_mem_init_hook (void);
 
 #endif /*_M68K_ATARI_STRAM_H */
index f51f709..0392b28 100644 (file)
@@ -399,8 +399,8 @@ struct CODEC
 #define CODEC_OVERFLOW_LEFT     2
   u_char unused2, unused3, unused4, unused5;
   u_char gpio_directions;
-#define GPIO_IN                 0
-#define GPIO_OUT                1
+#define CODEC_GPIO_IN           0
+#define CODEC_GPIO_OUT          1
   u_char unused6;
   u_char gpio_data;
 };
index 334d836..c3b4506 100644 (file)
@@ -216,7 +216,9 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
 
 void __init setup_arch(char **cmdline_p)
 {
+#ifndef CONFIG_SUN3
        int i;
+#endif
 
        /* The bootinfo is located right after the kernel bss */
        m68k_parse_bootinfo((const struct bi_record *)_end);
index 367ecee..3384a52 100644 (file)
@@ -105,9 +105,6 @@ fp_fetoxm1(struct fp_ext *dest, struct fp_ext *src)
 
        fp_monadic_check(dest, src);
 
-       if (IS_ZERO(dest))
-               return dest;
-
        return dest;
 }
 
index 4ad0ca9..4b5eb3d 100644 (file)
 #ifndef MULTI_ARITH_H
 #define MULTI_ARITH_H
 
-#if 0  /* old code... */
-
-/* Unsigned only, because we don't need signs to multiply and divide. */
-typedef unsigned int int128[4];
-
-/* Word order */
-enum {
-       MSW128,
-       NMSW128,
-       NLSW128,
-       LSW128
-};
-
-/* big-endian */
-#define LO_WORD(ll) (((unsigned int *) &ll)[1])
-#define HI_WORD(ll) (((unsigned int *) &ll)[0])
-
-/* Convenience functions to stuff various integer values into int128s */
-
-static inline void zero128(int128 a)
-{
-       a[LSW128] = a[NLSW128] = a[NMSW128] = a[MSW128] = 0;
-}
-
-/* Human-readable word order in the arguments */
-static inline void set128(unsigned int i3, unsigned int i2, unsigned int i1,
-                         unsigned int i0, int128 a)
-{
-       a[LSW128] = i0;
-       a[NLSW128] = i1;
-       a[NMSW128] = i2;
-       a[MSW128] = i3;
-}
-
-/* Convenience functions (for testing as well) */
-static inline void int64_to_128(unsigned long long src, int128 dest)
-{
-       dest[LSW128] = (unsigned int) src;
-       dest[NLSW128] = src >> 32;
-       dest[NMSW128] = dest[MSW128] = 0;
-}
-
-static inline void int128_to_64(const int128 src, unsigned long long *dest)
-{
-       *dest = src[LSW128] | (long long) src[NLSW128] << 32;
-}
-
-static inline void put_i128(const int128 a)
-{
-       printk("%08x %08x %08x %08x\n", a[MSW128], a[NMSW128],
-              a[NLSW128], a[LSW128]);
-}
-
-/* Internal shifters:
-
-   Note that these are only good for 0 < count < 32.
- */
-
-static inline void _lsl128(unsigned int count, int128 a)
-{
-       a[MSW128] = (a[MSW128] << count) | (a[NMSW128] >> (32 - count));
-       a[NMSW128] = (a[NMSW128] << count) | (a[NLSW128] >> (32 - count));
-       a[NLSW128] = (a[NLSW128] << count) | (a[LSW128] >> (32 - count));
-       a[LSW128] <<= count;
-}
-
-static inline void _lsr128(unsigned int count, int128 a)
-{
-       a[LSW128] = (a[LSW128] >> count) | (a[NLSW128] << (32 - count));
-       a[NLSW128] = (a[NLSW128] >> count) | (a[NMSW128] << (32 - count));
-       a[NMSW128] = (a[NMSW128] >> count) | (a[MSW128] << (32 - count));
-       a[MSW128] >>= count;
-}
-
-/* Should be faster, one would hope */
-
-static inline void lslone128(int128 a)
-{
-       asm volatile ("lsl.l #1,%0\n"
-                     "roxl.l #1,%1\n"
-                     "roxl.l #1,%2\n"
-                     "roxl.l #1,%3\n"
-                     :
-                     "=d" (a[LSW128]),
-                     "=d"(a[NLSW128]),
-                     "=d"(a[NMSW128]),
-                     "=d"(a[MSW128])
-                     :
-                     "0"(a[LSW128]),
-                     "1"(a[NLSW128]),
-                     "2"(a[NMSW128]),
-                     "3"(a[MSW128]));
-}
-
-static inline void lsrone128(int128 a)
-{
-       asm volatile ("lsr.l #1,%0\n"
-                     "roxr.l #1,%1\n"
-                     "roxr.l #1,%2\n"
-                     "roxr.l #1,%3\n"
-                     :
-                     "=d" (a[MSW128]),
-                     "=d"(a[NMSW128]),
-                     "=d"(a[NLSW128]),
-                     "=d"(a[LSW128])
-                     :
-                     "0"(a[MSW128]),
-                     "1"(a[NMSW128]),
-                     "2"(a[NLSW128]),
-                     "3"(a[LSW128]));
-}
-
-/* Generalized 128-bit shifters:
-
-   These bit-shift to a multiple of 32, then move whole longwords.  */
-
-static inline void lsl128(unsigned int count, int128 a)
-{
-       int wordcount, i;
-
-       if (count % 32)
-               _lsl128(count % 32, a);
-
-       if (0 == (wordcount = count / 32))
-               return;
-
-       /* argh, gak, endian-sensitive */
-       for (i = 0; i < 4 - wordcount; i++) {
-               a[i] = a[i + wordcount];
-       }
-       for (i = 3; i >= 4 - wordcount; --i) {
-               a[i] = 0;
-       }
-}
-
-static inline void lsr128(unsigned int count, int128 a)
-{
-       int wordcount, i;
-
-       if (count % 32)
-               _lsr128(count % 32, a);
-
-       if (0 == (wordcount = count / 32))
-               return;
-
-       for (i = 3; i >= wordcount; --i) {
-               a[i] = a[i - wordcount];
-       }
-       for (i = 0; i < wordcount; i++) {
-               a[i] = 0;
-       }
-}
-
-static inline int orl128(int a, int128 b)
-{
-       b[LSW128] |= a;
-}
-
-static inline int btsthi128(const int128 a)
-{
-       return a[MSW128] & 0x80000000;
-}
-
-/* test bits (numbered from 0 = LSB) up to and including "top" */
-static inline int bftestlo128(int top, const int128 a)
-{
-       int r = 0;
-
-       if (top > 31)
-               r |= a[LSW128];
-       if (top > 63)
-               r |= a[NLSW128];
-       if (top > 95)
-               r |= a[NMSW128];
-
-       r |= a[3 - (top / 32)] & ((1 << (top % 32 + 1)) - 1);
-
-       return (r != 0);
-}
-
-/* Aargh.  We need these because GCC is broken */
-/* FIXME: do them in assembly, for goodness' sake! */
-static inline void mask64(int pos, unsigned long long *mask)
-{
-       *mask = 0;
-
-       if (pos < 32) {
-               LO_WORD(*mask) = (1 << pos) - 1;
-               return;
-       }
-       LO_WORD(*mask) = -1;
-       HI_WORD(*mask) = (1 << (pos - 32)) - 1;
-}
-
-static inline void bset64(int pos, unsigned long long *dest)
-{
-       /* This conditional will be optimized away.  Thanks, GCC! */
-       if (pos < 32)
-               asm volatile ("bset %1,%0":"=m"
-                             (LO_WORD(*dest)):"id"(pos));
-       else
-               asm volatile ("bset %1,%0":"=m"
-                             (HI_WORD(*dest)):"id"(pos - 32));
-}
-
-static inline int btst64(int pos, unsigned long long dest)
-{
-       if (pos < 32)
-               return (0 != (LO_WORD(dest) & (1 << pos)));
-       else
-               return (0 != (HI_WORD(dest) & (1 << (pos - 32))));
-}
-
-static inline void lsl64(int count, unsigned long long *dest)
-{
-       if (count < 32) {
-               HI_WORD(*dest) = (HI_WORD(*dest) << count)
-                   | (LO_WORD(*dest) >> count);
-               LO_WORD(*dest) <<= count;
-               return;
-       }
-       count -= 32;
-       HI_WORD(*dest) = LO_WORD(*dest) << count;
-       LO_WORD(*dest) = 0;
-}
-
-static inline void lsr64(int count, unsigned long long *dest)
-{
-       if (count < 32) {
-               LO_WORD(*dest) = (LO_WORD(*dest) >> count)
-                   | (HI_WORD(*dest) << (32 - count));
-               HI_WORD(*dest) >>= count;
-               return;
-       }
-       count -= 32;
-       LO_WORD(*dest) = HI_WORD(*dest) >> count;
-       HI_WORD(*dest) = 0;
-}
-#endif
-
 static inline void fp_denormalize(struct fp_ext *reg, unsigned int cnt)
 {
        reg->exp += cnt;
@@ -481,117 +241,6 @@ static inline void fp_dividemant(union fp_mant128 *dest, struct fp_ext *src,
        }
 }
 
-#if 0
-static inline unsigned int fp_fls128(union fp_mant128 *src)
-{
-       unsigned long data;
-       unsigned int res, off;
-
-       if ((data = src->m32[0]))
-               off = 0;
-       else if ((data = src->m32[1]))
-               off = 32;
-       else if ((data = src->m32[2]))
-               off = 64;
-       else if ((data = src->m32[3]))
-               off = 96;
-       else
-               return 128;
-
-       asm ("bfffo %1{#0,#32},%0" : "=d" (res) : "dm" (data));
-       return res + off;
-}
-
-static inline void fp_shiftmant128(union fp_mant128 *src, int shift)
-{
-       unsigned long sticky;
-
-       switch (shift) {
-       case 0:
-               return;
-       case 1:
-               asm volatile ("lsl.l #1,%0"
-                       : "=d" (src->m32[3]) : "0" (src->m32[3]));
-               asm volatile ("roxl.l #1,%0"
-                       : "=d" (src->m32[2]) : "0" (src->m32[2]));
-               asm volatile ("roxl.l #1,%0"
-                       : "=d" (src->m32[1]) : "0" (src->m32[1]));
-               asm volatile ("roxl.l #1,%0"
-                       : "=d" (src->m32[0]) : "0" (src->m32[0]));
-               return;
-       case 2 ... 31:
-               src->m32[0] = (src->m32[0] << shift) | (src->m32[1] >> (32 - shift));
-               src->m32[1] = (src->m32[1] << shift) | (src->m32[2] >> (32 - shift));
-               src->m32[2] = (src->m32[2] << shift) | (src->m32[3] >> (32 - shift));
-               src->m32[3] = (src->m32[3] << shift);
-               return;
-       case 32 ... 63:
-               shift -= 32;
-               src->m32[0] = (src->m32[1] << shift) | (src->m32[2] >> (32 - shift));
-               src->m32[1] = (src->m32[2] << shift) | (src->m32[3] >> (32 - shift));
-               src->m32[2] = (src->m32[3] << shift);
-               src->m32[3] = 0;
-               return;
-       case 64 ... 95:
-               shift -= 64;
-               src->m32[0] = (src->m32[2] << shift) | (src->m32[3] >> (32 - shift));
-               src->m32[1] = (src->m32[3] << shift);
-               src->m32[2] = src->m32[3] = 0;
-               return;
-       case 96 ... 127:
-               shift -= 96;
-               src->m32[0] = (src->m32[3] << shift);
-               src->m32[1] = src->m32[2] = src->m32[3] = 0;
-               return;
-       case -31 ... -1:
-               shift = -shift;
-               sticky = 0;
-               if (src->m32[3] << (32 - shift))
-                       sticky = 1;
-               src->m32[3] = (src->m32[3] >> shift) | (src->m32[2] << (32 - shift)) | sticky;
-               src->m32[2] = (src->m32[2] >> shift) | (src->m32[1] << (32 - shift));
-               src->m32[1] = (src->m32[1] >> shift) | (src->m32[0] << (32 - shift));
-               src->m32[0] = (src->m32[0] >> shift);
-               return;
-       case -63 ... -32:
-               shift = -shift - 32;
-               sticky = 0;
-               if ((src->m32[2] << (32 - shift)) || src->m32[3])
-                       sticky = 1;
-               src->m32[3] = (src->m32[2] >> shift) | (src->m32[1] << (32 - shift)) | sticky;
-               src->m32[2] = (src->m32[1] >> shift) | (src->m32[0] << (32 - shift));
-               src->m32[1] = (src->m32[0] >> shift);
-               src->m32[0] = 0;
-               return;
-       case -95 ... -64:
-               shift = -shift - 64;
-               sticky = 0;
-               if ((src->m32[1] << (32 - shift)) || src->m32[2] || src->m32[3])
-                       sticky = 1;
-               src->m32[3] = (src->m32[1] >> shift) | (src->m32[0] << (32 - shift)) | sticky;
-               src->m32[2] = (src->m32[0] >> shift);
-               src->m32[1] = src->m32[0] = 0;
-               return;
-       case -127 ... -96:
-               shift = -shift - 96;
-               sticky = 0;
-               if ((src->m32[0] << (32 - shift)) || src->m32[1] || src->m32[2] || src->m32[3])
-                       sticky = 1;
-               src->m32[3] = (src->m32[0] >> shift) | sticky;
-               src->m32[2] = src->m32[1] = src->m32[0] = 0;
-               return;
-       }
-
-       if (shift < 0 && (src->m32[0] || src->m32[1] || src->m32[2] || src->m32[3]))
-               src->m32[3] = 1;
-       else
-               src->m32[3] = 0;
-       src->m32[2] = 0;
-       src->m32[1] = 0;
-       src->m32[0] = 0;
-}
-#endif
-
 static inline void fp_putmant128(struct fp_ext *dest, union fp_mant128 *src,
                                 int shift)
 {
@@ -637,183 +286,4 @@ static inline void fp_putmant128(struct fp_ext *dest, union fp_mant128 *src,
        }
 }
 
-#if 0 /* old code... */
-static inline int fls(unsigned int a)
-{
-       int r;
-
-       asm volatile ("bfffo %1{#0,#32},%0"
-                     : "=d" (r) : "md" (a));
-       return r;
-}
-
-/* fls = "find last set" (cf. ffs(3)) */
-static inline int fls128(const int128 a)
-{
-       if (a[MSW128])
-               return fls(a[MSW128]);
-       if (a[NMSW128])
-               return fls(a[NMSW128]) + 32;
-       /* XXX: it probably never gets beyond this point in actual
-          use, but that's indicative of a more general problem in the
-          algorithm (i.e. as per the actual 68881 implementation, we
-          really only need at most 67 bits of precision [plus
-          overflow]) so I'm not going to fix it. */
-       if (a[NLSW128])
-               return fls(a[NLSW128]) + 64;
-       if (a[LSW128])
-               return fls(a[LSW128]) + 96;
-       else
-               return -1;
-}
-
-static inline int zerop128(const int128 a)
-{
-       return !(a[LSW128] | a[NLSW128] | a[NMSW128] | a[MSW128]);
-}
-
-static inline int nonzerop128(const int128 a)
-{
-       return (a[LSW128] | a[NLSW128] | a[NMSW128] | a[MSW128]);
-}
-
-/* Addition and subtraction */
-/* Do these in "pure" assembly, because "extended" asm is unmanageable
-   here */
-static inline void add128(const int128 a, int128 b)
-{
-       /* rotating carry flags */
-       unsigned int carry[2];
-
-       carry[0] = a[LSW128] > (0xffffffff - b[LSW128]);
-       b[LSW128] += a[LSW128];
-
-       carry[1] = a[NLSW128] > (0xffffffff - b[NLSW128] - carry[0]);
-       b[NLSW128] = a[NLSW128] + b[NLSW128] + carry[0];
-
-       carry[0] = a[NMSW128] > (0xffffffff - b[NMSW128] - carry[1]);
-       b[NMSW128] = a[NMSW128] + b[NMSW128] + carry[1];
-
-       b[MSW128] = a[MSW128] + b[MSW128] + carry[0];
-}
-
-/* Note: assembler semantics: "b -= a" */
-static inline void sub128(const int128 a, int128 b)
-{
-       /* rotating borrow flags */
-       unsigned int borrow[2];
-
-       borrow[0] = b[LSW128] < a[LSW128];
-       b[LSW128] -= a[LSW128];
-
-       borrow[1] = b[NLSW128] < a[NLSW128] + borrow[0];
-       b[NLSW128] = b[NLSW128] - a[NLSW128] - borrow[0];
-
-       borrow[0] = b[NMSW128] < a[NMSW128] + borrow[1];
-       b[NMSW128] = b[NMSW128] - a[NMSW128] - borrow[1];
-
-       b[MSW128] = b[MSW128] - a[MSW128] - borrow[0];
-}
-
-/* Poor man's 64-bit expanding multiply */
-static inline void mul64(unsigned long long a, unsigned long long b, int128 c)
-{
-       unsigned long long acc;
-       int128 acc128;
-
-       zero128(acc128);
-       zero128(c);
-
-       /* first the low words */
-       if (LO_WORD(a) && LO_WORD(b)) {
-               acc = (long long) LO_WORD(a) * LO_WORD(b);
-               c[NLSW128] = HI_WORD(acc);
-               c[LSW128] = LO_WORD(acc);
-       }
-       /* Next the high words */
-       if (HI_WORD(a) && HI_WORD(b)) {
-               acc = (long long) HI_WORD(a) * HI_WORD(b);
-               c[MSW128] = HI_WORD(acc);
-               c[NMSW128] = LO_WORD(acc);
-       }
-       /* The middle words */
-       if (LO_WORD(a) && HI_WORD(b)) {
-               acc = (long long) LO_WORD(a) * HI_WORD(b);
-               acc128[NMSW128] = HI_WORD(acc);
-               acc128[NLSW128] = LO_WORD(acc);
-               add128(acc128, c);
-       }
-       /* The first and last words */
-       if (HI_WORD(a) && LO_WORD(b)) {
-               acc = (long long) HI_WORD(a) * LO_WORD(b);
-               acc128[NMSW128] = HI_WORD(acc);
-               acc128[NLSW128] = LO_WORD(acc);
-               add128(acc128, c);
-       }
-}
-
-/* Note: unsigned */
-static inline int cmp128(int128 a, int128 b)
-{
-       if (a[MSW128] < b[MSW128])
-               return -1;
-       if (a[MSW128] > b[MSW128])
-               return 1;
-       if (a[NMSW128] < b[NMSW128])
-               return -1;
-       if (a[NMSW128] > b[NMSW128])
-               return 1;
-       if (a[NLSW128] < b[NLSW128])
-               return -1;
-       if (a[NLSW128] > b[NLSW128])
-               return 1;
-
-       return (signed) a[LSW128] - b[LSW128];
-}
-
-inline void div128(int128 a, int128 b, int128 c)
-{
-       int128 mask;
-
-       /* Algorithm:
-
-          Shift the divisor until it's at least as big as the
-          dividend, keeping track of the position to which we've
-          shifted it, i.e. the power of 2 which we've multiplied it
-          by.
-
-          Then, for this power of 2 (the mask), and every one smaller
-          than it, subtract the mask from the dividend and add it to
-          the quotient until the dividend is smaller than the raised
-          divisor.  At this point, divide the dividend and the mask
-          by 2 (i.e. shift one place to the right).  Lather, rinse,
-          and repeat, until there are no more powers of 2 left. */
-
-       /* FIXME: needless to say, there's room for improvement here too. */
-
-       /* Shift up */
-       /* XXX: since it just has to be "at least as big", we can
-          probably eliminate this horribly wasteful loop.  I will
-          have to prove this first, though */
-       set128(0, 0, 0, 1, mask);
-       while (cmp128(b, a) < 0 && !btsthi128(b)) {
-               lslone128(b);
-               lslone128(mask);
-       }
-
-       /* Shift down */
-       zero128(c);
-       do {
-               if (cmp128(a, b) >= 0) {
-                       sub128(b, a);
-                       add128(mask, c);
-               }
-               lsrone128(mask);
-               lsrone128(b);
-       } while (nonzerop128(mask));
-
-       /* The remainder is in a... */
-}
-#endif
-
 #endif /* MULTI_ARITH_H */
index 9113c2f..bbe5254 100644 (file)
@@ -83,11 +83,6 @@ void __init mem_init(void)
        int initpages = 0;
        int i;
 
-#ifdef CONFIG_ATARI
-       if (MACH_IS_ATARI)
-               atari_stram_mem_init_hook();
-#endif
-
        /* this will put all memory onto the freelists */
        totalram_pages = num_physpages = 0;
        for_each_online_pgdat(pgdat) {
index e3d8170..99385d0 100644 (file)
@@ -173,6 +173,7 @@ core-$(CONFIG_HD6446X_SERIES)       += arch/sh/cchips/hd6446x/
 cpuincdir-$(CONFIG_CPU_SH2A)   += cpu-sh2a
 cpuincdir-$(CONFIG_CPU_SH2)    += cpu-sh2
 cpuincdir-$(CONFIG_CPU_SH3)    += cpu-sh3
+cpuincdir-$(CONFIG_CPU_SH4A)   += cpu-sh4a
 cpuincdir-$(CONFIG_CPU_SH4)    += cpu-sh4
 cpuincdir-$(CONFIG_CPU_SH5)    += cpu-sh5
 cpuincdir-y                    += cpu-common   # Must be last
index 8e2a270..2823619 100644 (file)
@@ -116,7 +116,7 @@ static int apsh4a3a_clk_init(void)
        int ret;
 
        clk = clk_get(NULL, "extal");
-       if (!clk || IS_ERR(clk))
+       if (IS_ERR(clk))
                return PTR_ERR(clk);
        ret = clk_set_rate(clk, 33333000);
        clk_put(clk);
index e2bd218..b4d6292 100644 (file)
@@ -94,7 +94,7 @@ static int apsh4ad0a_clk_init(void)
        int ret;
 
        clk = clk_get(NULL, "extal");
-       if (!clk || IS_ERR(clk))
+       if (IS_ERR(clk))
                return PTR_ERR(clk);
        ret = clk_set_rate(clk, 33333000);
        clk_put(clk);
index ee65ff0..d879848 100644 (file)
@@ -299,7 +299,7 @@ static int sh7785lcr_clk_init(void)
        int ret;
 
        clk = clk_get(NULL, "extal");
-       if (!clk || IS_ERR(clk))
+       if (IS_ERR(clk))
                return PTR_ERR(clk);
        ret = clk_set_rate(clk, 33333333);
        clk_put(clk);
index d81c609..24e3316 100644 (file)
@@ -190,7 +190,7 @@ static int urquell_clk_init(void)
                return -EINVAL;
 
        clk = clk_get(NULL, "extal");
-       if (!clk || IS_ERR(clk))
+       if (IS_ERR(clk))
                return PTR_ERR(clk);
        ret = clk_set_rate(clk, 33333333);
        clk_put(clk);
index 87618c9..74b8db1 100644 (file)
@@ -335,8 +335,6 @@ static struct clk *r7780rp_clocks[] = {
        &ivdr_clk,
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("ivdr_clk", &ivdr_clk),
index 1521aa7..486d1ac 100644 (file)
@@ -194,7 +194,7 @@ static int sdk7786_clk_init(void)
                return -EINVAL;
 
        clk = clk_get(NULL, "extal");
-       if (!clk || IS_ERR(clk))
+       if (IS_ERR(clk))
                return PTR_ERR(clk);
        ret = clk_set_rate(clk, 33333333);
        clk_put(clk);
diff --git a/arch/sh/include/cpu-sh3/cpu/serial.h b/arch/sh/include/cpu-sh3/cpu/serial.h
new file mode 100644 (file)
index 0000000..7766329
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __CPU_SH3_SERIAL_H
+#define __CPU_SH3_SERIAL_H
+
+#include <linux/serial_sci.h>
+
+extern struct plat_sci_port_ops sh770x_sci_port_ops;
+extern struct plat_sci_port_ops sh7710_sci_port_ops;
+extern struct plat_sci_port_ops sh7720_sci_port_ops;
+
+#endif /* __CPU_SH3_SERIAL_H */
diff --git a/arch/sh/include/cpu-sh4a/cpu/serial.h b/arch/sh/include/cpu-sh4a/cpu/serial.h
new file mode 100644 (file)
index 0000000..ff1bc27
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __CPU_SH4A_SERIAL_H
+#define __CPU_SH4A_SERIAL_H
+
+/* arch/sh/kernel/cpu/sh4a/serial-sh7722.c */
+extern struct plat_sci_port_ops sh7722_sci_port_ops;
+
+#endif /* __CPU_SH4A_SERIAL_H */
index 8f63a26..f59b1f3 100644 (file)
@@ -35,8 +35,6 @@ static struct clk *onchip_clocks[] = {
        &cpu_clk,
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("master_clk", &master_clk),
index ecab274..6f13f33 100644 (file)
@@ -7,15 +7,15 @@ obj-y := ex.o probe.o entry.o setup-sh3.o
 obj-$(CONFIG_HIBERNATION)              += swsusp.o
 
 # CPU subtype setup
-obj-$(CONFIG_CPU_SUBTYPE_SH7705)       += setup-sh7705.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7706)       += setup-sh770x.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7707)       += setup-sh770x.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7708)       += setup-sh770x.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7709)       += setup-sh770x.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7710)       += setup-sh7710.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7712)       += setup-sh7710.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7720)       += setup-sh7720.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7721)       += setup-sh7720.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7705)       += setup-sh7705.o serial-sh770x.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7706)       += setup-sh770x.o serial-sh770x.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7707)       += setup-sh770x.o serial-sh770x.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7708)       += setup-sh770x.o serial-sh770x.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7709)       += setup-sh770x.o serial-sh770x.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7710)       += setup-sh7710.o serial-sh7710.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7712)       += setup-sh7710.o serial-sh7710.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7720)       += setup-sh7720.o serial-sh7720.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7721)       += setup-sh7720.o serial-sh7720.o
 
 # Primary on-chip clocks (common)
 clock-$(CONFIG_CPU_SH3)                        := clock-sh3.o
diff --git a/arch/sh/kernel/cpu/sh3/serial-sh770x.c b/arch/sh/kernel/cpu/sh3/serial-sh770x.c
new file mode 100644 (file)
index 0000000..4f7242c
--- /dev/null
@@ -0,0 +1,33 @@
+#include <linux/serial_sci.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+#include <cpu/serial.h>
+
+#define SCPCR 0xA4000116
+#define SCPDR 0xA4000136
+
+static void sh770x_sci_init_pins(struct uart_port *port, unsigned int cflag)
+{
+       unsigned short data;
+
+       /* We need to set SCPCR to enable RTS/CTS */
+       data = __raw_readw(SCPCR);
+       /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/
+       __raw_writew(data & 0x0fcf, SCPCR);
+
+       if (!(cflag & CRTSCTS)) {
+               /* We need to set SCPCR to enable RTS/CTS */
+               data = __raw_readw(SCPCR);
+               /* Clear out SCP7MD1,0, SCP4MD1,0,
+                  Set SCP6MD1,0 = {01} (output)  */
+               __raw_writew((data & 0x0fcf) | 0x1000, SCPCR);
+
+               data = __raw_readb(SCPDR);
+               /* Set /RTS2 (bit6) = 0 */
+               __raw_writeb(data & 0xbf, SCPDR);
+       }
+}
+
+struct plat_sci_port_ops sh770x_sci_port_ops = {
+       .init_pins      = sh770x_sci_init_pins,
+};
diff --git a/arch/sh/kernel/cpu/sh3/serial-sh7710.c b/arch/sh/kernel/cpu/sh3/serial-sh7710.c
new file mode 100644 (file)
index 0000000..42190ef
--- /dev/null
@@ -0,0 +1,20 @@
+#include <linux/serial_sci.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+#include <cpu/serial.h>
+
+#define PACR 0xa4050100
+#define PBCR 0xa4050102
+
+static void sh7710_sci_init_pins(struct uart_port *port, unsigned int cflag)
+{
+       if (port->mapbase == 0xA4400000) {
+               __raw_writew(__raw_readw(PACR) & 0xffc0, PACR);
+               __raw_writew(__raw_readw(PBCR) & 0x0fff, PBCR);
+       } else if (port->mapbase == 0xA4410000)
+               __raw_writew(__raw_readw(PBCR) & 0xf003, PBCR);
+}
+
+struct plat_sci_port_ops sh7710_sci_port_ops = {
+       .init_pins      = sh7710_sci_init_pins,
+};
diff --git a/arch/sh/kernel/cpu/sh3/serial-sh7720.c b/arch/sh/kernel/cpu/sh3/serial-sh7720.c
new file mode 100644 (file)
index 0000000..8832c52
--- /dev/null
@@ -0,0 +1,37 @@
+#include <linux/serial_sci.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+#include <cpu/serial.h>
+#include <asm/gpio.h>
+
+static void sh7720_sci_init_pins(struct uart_port *port, unsigned int cflag)
+{
+       unsigned short data;
+
+       if (cflag & CRTSCTS) {
+               /* enable RTS/CTS */
+               if (port->mapbase == 0xa4430000) { /* SCIF0 */
+                       /* Clear PTCR bit 9-2; enable all scif pins but sck */
+                       data = __raw_readw(PORT_PTCR);
+                       __raw_writew((data & 0xfc03), PORT_PTCR);
+               } else if (port->mapbase == 0xa4438000) { /* SCIF1 */
+                       /* Clear PVCR bit 9-2 */
+                       data = __raw_readw(PORT_PVCR);
+                       __raw_writew((data & 0xfc03), PORT_PVCR);
+               }
+       } else {
+               if (port->mapbase == 0xa4430000) { /* SCIF0 */
+                       /* Clear PTCR bit 5-2; enable only tx and rx  */
+                       data = __raw_readw(PORT_PTCR);
+                       __raw_writew((data & 0xffc3), PORT_PTCR);
+               } else if (port->mapbase == 0xa4438000) { /* SCIF1 */
+                       /* Clear PVCR bit 5-2 */
+                       data = __raw_readw(PORT_PVCR);
+                       __raw_writew((data & 0xffc3), PORT_PVCR);
+               }
+       }
+}
+
+struct plat_sci_port_ops sh7720_sci_port_ops = {
+       .init_pins      = sh7720_sci_init_pins,
+};
index cd2e702..2309618 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/serial_sci.h>
 #include <linux/sh_timer.h>
 #include <asm/rtc.h>
+#include <cpu/serial.h>
 
 enum {
        UNUSED = 0,
@@ -75,6 +76,8 @@ static struct plat_sci_port scif0_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_4,
        .type           = PORT_SCIF,
        .irqs           = { 56, 56, 56 },
+       .ops            = &sh770x_sci_port_ops,
+       .regtype        = SCIx_SH7705_SCIF_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -92,6 +95,8 @@ static struct plat_sci_port scif1_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_4,
        .type           = PORT_SCIF,
        .irqs           = { 52, 52, 52 },
+       .ops            = &sh770x_sci_port_ops,
+       .regtype        = SCIx_SH7705_SCIF_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
index 4551ad6..3f3d5fe 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
 #include <linux/sh_timer.h>
+#include <cpu/serial.h>
 
 enum {
        UNUSED = 0,
@@ -108,11 +109,14 @@ static struct platform_device rtc_device = {
 
 static struct plat_sci_port scif0_platform_data = {
        .mapbase        = 0xfffffe80,
+       .port_reg       = 0xa4000136,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_TE | SCSCR_RE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCI,
        .irqs           = { 23, 23, 23, 0 },
+       .ops            = &sh770x_sci_port_ops,
+       .regshift       = 1,
 };
 
 static struct platform_device scif0_device = {
@@ -132,6 +136,8 @@ static struct plat_sci_port scif1_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 56, 56, 56, 56 },
+       .ops            = &sh770x_sci_port_ops,
+       .regtype        = SCIx_SH3_SCIF_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -146,11 +152,14 @@ static struct platform_device scif1_device = {
     defined(CONFIG_CPU_SUBTYPE_SH7709)
 static struct plat_sci_port scif2_platform_data = {
        .mapbase        = 0xa4000140,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_TE | SCSCR_RE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_IRDA,
        .irqs           = { 52, 52, 52, 52 },
+       .ops            = &sh770x_sci_port_ops,
+       .regshift       = 1,
 };
 
 static struct platform_device scif2_device = {
index 365b94a..9492034 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/serial_sci.h>
 #include <linux/sh_timer.h>
 #include <asm/rtc.h>
+#include <cpu/serial.h>
 
 static struct resource rtc_resources[] = {
        [0] = {
@@ -55,6 +56,8 @@ static struct plat_sci_port scif0_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_4,
        .type           = PORT_SCIF,
        .irqs           = { 80, 80, 80, 80 },
+       .ops            = &sh7720_sci_port_ops,
+       .regtype        = SCIx_SH7705_SCIF_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -72,6 +75,8 @@ static struct plat_sci_port scif1_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_4,
        .type           = PORT_SCIF,
        .irqs           = { 81, 81, 81, 81 },
+       .ops            = &sh7720_sci_port_ops,
+       .regtype        = SCIx_SH7705_SCIF_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
index 3f6f8e9..f4e262a 100644 (file)
@@ -147,8 +147,6 @@ static struct clk *sh4202_onchip_clocks[] = {
        &sh4202_shoc_clk,
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("emi_clk", &sh4202_emi_clk),
index e53b4b3..98cc0c7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SH7750/SH7751 Setup
+ * SH7091/SH7750/SH7750S/SH7750R/SH7751/SH7751R Setup
  *
  *  Copyright (C) 2006  Paul Mundt
  *  Copyright (C) 2006  Jamie Lenehan
@@ -38,11 +38,13 @@ static struct platform_device rtc_device = {
 
 static struct plat_sci_port sci_platform_data = {
        .mapbase        = 0xffe00000,
+       .port_reg       = 0xffe0001C,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_TE | SCSCR_RE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCI,
        .irqs           = { 23, 23, 23, 0 },
+       .regshift       = 2,
 };
 
 static struct platform_device sci_device = {
index 78bbf23..c0b4c77 100644 (file)
@@ -133,6 +133,7 @@ static struct plat_sci_port scif0_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 52, 53, 55, 54 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -150,6 +151,7 @@ static struct plat_sci_port scif1_platform_data = {
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .irqs           = { 72, 73, 75, 74 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -167,6 +169,7 @@ static struct plat_sci_port scif2_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 76, 77, 79, 78 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif2_device = {
@@ -184,6 +187,7 @@ static struct plat_sci_port scif3_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCI,
        .irqs           = { 80, 81, 82, 0 },
+       .regshift       = 2,
 };
 
 static struct platform_device scif3_device = {
index cc122b1..c57fb28 100644 (file)
@@ -10,7 +10,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7780)      += setup-sh7780.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7785)       += setup-sh7785.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7786)       += setup-sh7786.o intc-shx3.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7343)       += setup-sh7343.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7722)       += setup-sh7722.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7722)       += setup-sh7722.o serial-sh7722.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7723)       += setup-sh7723.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7724)       += setup-sh7724.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7366)       += setup-sh7366.o
index 93c6460..70e45bd 100644 (file)
@@ -194,8 +194,6 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP200] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 0, 0),
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("rclk", &r_clk),
@@ -233,32 +231,17 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("rwdt0", &mstp_clks[MSTP013]),
        CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]),
        CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]),
-       {
-               /* SCIF0 */
-               .dev_id         = "sh-sci.0",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP007],
-       }, {
-               /* SCIF1 */
-               .dev_id         = "sh-sci.1",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP006],
-       }, {
-               /* SCIF2 */
-               .dev_id         = "sh-sci.2",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP005],
-       }, {
-               /* SCIF3 */
-               .dev_id         = "sh-sci.3",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP004],
-       },
+
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP007]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP006]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP005]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP004]),
+
        CLKDEV_CON_ID("sio0", &mstp_clks[MSTP003]),
        CLKDEV_CON_ID("siof0", &mstp_clks[MSTP002]),
        CLKDEV_CON_ID("siof1", &mstp_clks[MSTP001]),
-       CLKDEV_CON_ID("i2c0", &mstp_clks[MSTP109]),
-       CLKDEV_CON_ID("i2c1", &mstp_clks[MSTP108]),
+       CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP109]),
+       CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP108]),
        CLKDEV_CON_ID("tpu0", &mstp_clks[MSTP225]),
        CLKDEV_CON_ID("irda0", &mstp_clks[MSTP224]),
        CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP218]),
index 049dc06..3c31650 100644 (file)
@@ -192,8 +192,6 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP200] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 0, 0),
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("rclk", &r_clk),
@@ -231,25 +229,14 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("rwdt0", &mstp_clks[MSTP013]),
        CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]),
        CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]),
-       {
-               /* SCIF0 */
-               .dev_id         = "sh-sci.0",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP007],
-       }, {
-               /* SCIF1 */
-               .dev_id         = "sh-sci.1",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP006],
-       }, {
-               /* SCIF2 */
-               .dev_id         = "sh-sci.2",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP005],
-       },
+
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP007]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP006]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP005]),
+
        CLKDEV_CON_ID("msiof0", &mstp_clks[MSTP002]),
        CLKDEV_CON_ID("sbr0", &mstp_clks[MSTP001]),
-       CLKDEV_CON_ID("i2c0", &mstp_clks[MSTP109]),
+       CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP109]),
        CLKDEV_CON_ID("icb0", &mstp_clks[MSTP227]),
        CLKDEV_CON_ID("meram0", &mstp_clks[MSTP226]),
        CLKDEV_CON_ID("dacy1", &mstp_clks[MSTP224]),
index 9d23a36..c9a4808 100644 (file)
@@ -175,8 +175,6 @@ static struct clk mstp_clks[HWBLK_NR] = {
        SH_HWBLK_CLK(HWBLK_LCDC, &div4_clks[DIV4_P], 0),
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("rclk", &r_clk),
@@ -201,42 +199,20 @@ static struct clk_lookup lookups[] = {
        /* MSTP clocks */
        CLKDEV_CON_ID("uram0", &mstp_clks[HWBLK_URAM]),
        CLKDEV_CON_ID("xymem0", &mstp_clks[HWBLK_XYMEM]),
-       {
-               /* TMU0 */
-               .dev_id         = "sh_tmu.0",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU],
-       }, {
-               /* TMU1 */
-               .dev_id         = "sh_tmu.1",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU],
-       }, {
-               /* TMU2 */
-               .dev_id         = "sh_tmu.2",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU],
-       },
+
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.0", &mstp_clks[HWBLK_TMU]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[HWBLK_TMU]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.2", &mstp_clks[HWBLK_TMU]),
+
        CLKDEV_CON_ID("cmt_fck", &mstp_clks[HWBLK_CMT]),
        CLKDEV_CON_ID("rwdt0", &mstp_clks[HWBLK_RWDT]),
        CLKDEV_CON_ID("flctl0", &mstp_clks[HWBLK_FLCTL]),
-       {
-               /* SCIF0 */
-               .dev_id         = "sh-sci.0",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF0],
-       }, {
-               /* SCIF1 */
-               .dev_id         = "sh-sci.1",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF1],
-       }, {
-               /* SCIF2 */
-               .dev_id         = "sh-sci.2",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF2],
-       },
-       CLKDEV_CON_ID("i2c0", &mstp_clks[HWBLK_IIC]),
+
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[HWBLK_SCIF0]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[HWBLK_SCIF1]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[HWBLK_SCIF2]),
+
+       CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[HWBLK_IIC]),
        CLKDEV_CON_ID("rtc0", &mstp_clks[HWBLK_RTC]),
        CLKDEV_CON_ID("sdhi0", &mstp_clks[HWBLK_SDHI]),
        CLKDEV_CON_ID("keysc0", &mstp_clks[HWBLK_KEYSC]),
index 55493cd..3cc3827 100644 (file)
@@ -200,8 +200,6 @@ static struct clk mstp_clks[] = {
        SH_HWBLK_CLK(HWBLK_LCDC, &div4_clks[DIV4_B], 0),
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("rclk", &r_clk),
@@ -305,7 +303,7 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("msiof0", &mstp_clks[HWBLK_MSIOF0]),
        CLKDEV_CON_ID("msiof1", &mstp_clks[HWBLK_MSIOF1]),
        CLKDEV_CON_ID("meram0", &mstp_clks[HWBLK_MERAM]),
-       CLKDEV_CON_ID("i2c0", &mstp_clks[HWBLK_IIC]),
+       CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[HWBLK_IIC]),
        CLKDEV_CON_ID("rtc0", &mstp_clks[HWBLK_RTC]),
        CLKDEV_CON_ID("atapi0", &mstp_clks[HWBLK_ATAPI]),
        CLKDEV_CON_ID("adc0", &mstp_clks[HWBLK_ADC]),
index d08fa95..8668f55 100644 (file)
@@ -252,8 +252,6 @@ static struct clk mstp_clks[HWBLK_NR] = {
        SH_HWBLK_CLK(HWBLK_LCDC, &div4_clks[DIV4_B], 0),
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("rclk", &r_clk),
@@ -289,77 +287,31 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("sh0", &mstp_clks[HWBLK_SHYWAY]),
        CLKDEV_CON_ID("hudi0", &mstp_clks[HWBLK_HUDI]),
        CLKDEV_CON_ID("ubc0", &mstp_clks[HWBLK_UBC]),
-       {
-               /* TMU0 */
-               .dev_id         = "sh_tmu.0",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU0],
-       }, {
-               /* TMU1 */
-               .dev_id         = "sh_tmu.1",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU0],
-       }, {
-               /* TMU2 */
-               .dev_id         = "sh_tmu.2",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU0],
-       }, {
-               /* TMU3 */
-               .dev_id         = "sh_tmu.3",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU1],
-       },
+
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.0", &mstp_clks[HWBLK_TMU0]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[HWBLK_TMU0]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.2", &mstp_clks[HWBLK_TMU0]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.3", &mstp_clks[HWBLK_TMU1]),
+
        CLKDEV_CON_ID("cmt_fck", &mstp_clks[HWBLK_CMT]),
        CLKDEV_CON_ID("rwdt0", &mstp_clks[HWBLK_RWDT]),
        CLKDEV_CON_ID("dmac1", &mstp_clks[HWBLK_DMAC1]),
-       {
-               /* TMU4 */
-               .dev_id         = "sh_tmu.4",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU1],
-       }, {
-               /* TMU5 */
-               .dev_id         = "sh_tmu.5",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU1],
-       }, {
-               /* SCIF0 */
-               .dev_id         = "sh-sci.0",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF0],
-       }, {
-               /* SCIF1 */
-               .dev_id         = "sh-sci.1",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF1],
-       }, {
-               /* SCIF2 */
-               .dev_id         = "sh-sci.2",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF2],
-       }, {
-               /* SCIF3 */
-               .dev_id         = "sh-sci.3",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF3],
-       }, {
-               /* SCIF4 */
-               .dev_id         = "sh-sci.4",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF4],
-       }, {
-               /* SCIF5 */
-               .dev_id         = "sh-sci.5",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF5],
-       },
+
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.4", &mstp_clks[HWBLK_TMU1]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.5", &mstp_clks[HWBLK_TMU1]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[HWBLK_SCIF0]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[HWBLK_SCIF1]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[HWBLK_SCIF2]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[HWBLK_SCIF3]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[HWBLK_SCIF4]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[HWBLK_SCIF5]),
+
        CLKDEV_CON_ID("msiof0", &mstp_clks[HWBLK_MSIOF0]),
        CLKDEV_CON_ID("msiof1", &mstp_clks[HWBLK_MSIOF1]),
        CLKDEV_CON_ID("keysc0", &mstp_clks[HWBLK_KEYSC]),
        CLKDEV_CON_ID("rtc0", &mstp_clks[HWBLK_RTC]),
-       CLKDEV_CON_ID("i2c0", &mstp_clks[HWBLK_IIC0]),
-       CLKDEV_CON_ID("i2c1", &mstp_clks[HWBLK_IIC1]),
+       CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[HWBLK_IIC0]),
+       CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[HWBLK_IIC1]),
        CLKDEV_CON_ID("mmc0", &mstp_clks[HWBLK_MMC]),
        CLKDEV_CON_ID("eth0", &mstp_clks[HWBLK_ETHER]),
        CLKDEV_CON_ID("atapi0", &mstp_clks[HWBLK_ATAPI]),
index eedddad..3b097b0 100644 (file)
@@ -101,8 +101,6 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP220] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 20, 0),
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("extal", &extal_clk),
@@ -116,33 +114,13 @@ static struct clk_lookup lookups[] = {
        /* MSTP32 clocks */
        CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP004]),
        CLKDEV_CON_ID("riic", &mstp_clks[MSTP000]),
-       {
-               /* TMU0 */
-               .dev_id         = "sh_tmu.0",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP113],
-       }, {
-               /* TMU1 */
-               .dev_id         = "sh_tmu.1",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP114],
-       },
-       {
-               /* SCIF4 (But, ID is 2) */
-               .dev_id         = "sh-sci.2",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP112],
-       }, {
-               /* SCIF3 */
-               .dev_id         = "sh-sci.1",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP111],
-       }, {
-               /* SCIF2 */
-               .dev_id         = "sh-sci.0",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP110],
-       },
+
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.0", &mstp_clks[MSTP113]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[MSTP114]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP112]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP111]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP110]),
+
        CLKDEV_CON_ID("usb0", &mstp_clks[MSTP102]),
        CLKDEV_CON_ID("mmc0", &mstp_clks[MSTP220]),
 };
index 599630f..2d4c7fd 100644 (file)
@@ -91,8 +91,6 @@ static struct clk *sh7763_onchip_clocks[] = {
        &sh7763_shyway_clk,
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("shyway_clk", &sh7763_shyway_clk),
index 8894926..3b53348 100644 (file)
@@ -97,8 +97,6 @@ static struct clk *sh7780_onchip_clocks[] = {
        &sh7780_shyway_clk,
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("shyway_clk", &sh7780_shyway_clk),
index 2d96024..e5b420c 100644 (file)
@@ -116,8 +116,6 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP100] = SH_CLK_MSTP32(NULL, MSTPCR1, 0, 0),
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("extal", &extal_clk),
@@ -134,74 +132,27 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
 
        /* MSTP32 clocks */
-       {
-               /* SCIF5 */
-               .dev_id         = "sh-sci.5",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP029],
-       }, {
-               /* SCIF4 */
-               .dev_id         = "sh-sci.4",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP028],
-       }, {
-               /* SCIF3 */
-               .dev_id         = "sh-sci.3",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP027],
-       }, {
-               /* SCIF2 */
-               .dev_id         = "sh-sci.2",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP026],
-       }, {
-               /* SCIF1 */
-               .dev_id         = "sh-sci.1",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP025],
-       }, {
-               /* SCIF0 */
-               .dev_id         = "sh-sci.0",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP024],
-       },
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP029]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP028]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP027]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP026]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP024]),
+
        CLKDEV_CON_ID("ssi1_fck", &mstp_clks[MSTP021]),
        CLKDEV_CON_ID("ssi0_fck", &mstp_clks[MSTP020]),
        CLKDEV_CON_ID("hac1_fck", &mstp_clks[MSTP017]),
        CLKDEV_CON_ID("hac0_fck", &mstp_clks[MSTP016]),
        CLKDEV_CON_ID("mmcif_fck", &mstp_clks[MSTP013]),
        CLKDEV_CON_ID("flctl_fck", &mstp_clks[MSTP012]),
-       {
-               /* TMU0 */
-               .dev_id         = "sh_tmu.0",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP008],
-       }, {
-               /* TMU1 */
-               .dev_id         = "sh_tmu.1",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP008],
-       }, {
-               /* TMU2 */
-               .dev_id         = "sh_tmu.2",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP008],
-       }, {
-               /* TMU3 */
-               .dev_id         = "sh_tmu.3",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP009],
-       }, {
-               /* TMU4 */
-               .dev_id         = "sh_tmu.4",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP009],
-       }, {
-               /* TMU5 */
-               .dev_id         = "sh_tmu.5",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP009],
-       },
+
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.0", &mstp_clks[MSTP008]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[MSTP008]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.2", &mstp_clks[MSTP008]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.3", &mstp_clks[MSTP009]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.4", &mstp_clks[MSTP009]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.5", &mstp_clks[MSTP009]),
+
        CLKDEV_CON_ID("siof_fck", &mstp_clks[MSTP003]),
        CLKDEV_CON_ID("hspi_fck", &mstp_clks[MSTP002]),
        CLKDEV_CON_ID("hudi_fck", &mstp_clks[MSTP119]),
index 42e403b..f6c0c3d 100644 (file)
@@ -125,8 +125,6 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP102] = SH_CLK_MSTP32(NULL, MSTPCR1, 2, 0),
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("extal", &extal_clk),
@@ -141,37 +139,13 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
 
        /* MSTP32 clocks */
-       {
-               /* SCIF5 */
-               .dev_id         = "sh-sci.5",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP029],
-       }, {
-               /* SCIF4 */
-               .dev_id         = "sh-sci.4",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP028],
-       }, {
-               /* SCIF3 */
-               .dev_id         = "sh-sci.3",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP027],
-       }, {
-               /* SCIF2 */
-               .dev_id         = "sh-sci.2",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP026],
-       }, {
-               /* SCIF1 */
-               .dev_id         = "sh-sci.1",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP025],
-       }, {
-               /* SCIF0 */
-               .dev_id         = "sh-sci.0",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP024],
-       },
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP029]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP028]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP027]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP026]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP024]),
+
        CLKDEV_CON_ID("ssi3_fck", &mstp_clks[MSTP023]),
        CLKDEV_CON_ID("ssi2_fck", &mstp_clks[MSTP022]),
        CLKDEV_CON_ID("ssi1_fck", &mstp_clks[MSTP021]),
@@ -180,67 +154,20 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("hac0_fck", &mstp_clks[MSTP016]),
        CLKDEV_CON_ID("i2c1_fck", &mstp_clks[MSTP015]),
        CLKDEV_CON_ID("i2c0_fck", &mstp_clks[MSTP014]),
-       {
-               /* TMU0 */
-               .dev_id         = "sh_tmu.0",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP008],
-       }, {
-               /* TMU1 */
-               .dev_id         = "sh_tmu.1",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP008],
-       }, {
-               /* TMU2 */
-               .dev_id         = "sh_tmu.2",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP008],
-       }, {
-               /* TMU3 */
-               .dev_id         = "sh_tmu.3",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP009],
-       }, {
-               /* TMU4 */
-               .dev_id         = "sh_tmu.4",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP009],
-       }, {
-               /* TMU5 */
-               .dev_id         = "sh_tmu.5",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP009],
-       }, {
-               /* TMU6 */
-               .dev_id         = "sh_tmu.6",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP010],
-       }, {
-               /* TMU7 */
-               .dev_id         = "sh_tmu.7",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP010],
-       }, {
-               /* TMU8 */
-               .dev_id         = "sh_tmu.8",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP010],
-       }, {
-               /* TMU9 */
-               .dev_id         = "sh_tmu.9",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP011],
-       }, {
-               /* TMU10 */
-               .dev_id         = "sh_tmu.10",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP011],
-       }, {
-               /* TMU11 */
-               .dev_id         = "sh_tmu.11",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP011],
-       },
+
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.0", &mstp_clks[MSTP008]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[MSTP008]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.2", &mstp_clks[MSTP008]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.3", &mstp_clks[MSTP009]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.4", &mstp_clks[MSTP009]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.5", &mstp_clks[MSTP009]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.6", &mstp_clks[MSTP010]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.7", &mstp_clks[MSTP010]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.8", &mstp_clks[MSTP010]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.9", &mstp_clks[MSTP011]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.10", &mstp_clks[MSTP011]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.11", &mstp_clks[MSTP011]),
+
        CLKDEV_CON_ID("sdif1_fck", &mstp_clks[MSTP005]),
        CLKDEV_CON_ID("sdif0_fck", &mstp_clks[MSTP004]),
        CLKDEV_CON_ID("hspi_fck", &mstp_clks[MSTP002]),
index 1afdb93..bf2d00b 100644 (file)
@@ -100,8 +100,6 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP104] = SH_CLK_MSTP32(NULL, MSTPCR1, 4, 0),
 };
 
-#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
-
 static struct clk_lookup lookups[] = {
        /* main clocks */
        CLKDEV_CON_ID("extal", &extal_clk),
@@ -116,62 +114,23 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
 
        /* MSTP32 clocks */
-       {
-               /* SCIF3 */
-               .dev_id         = "sh-sci.3",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP027],
-       }, {
-               /* SCIF2 */
-               .dev_id         = "sh-sci.2",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP026],
-       }, {
-               /* SCIF1 */
-               .dev_id         = "sh-sci.1",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP025],
-       }, {
-               /* SCIF0 */
-               .dev_id         = "sh-sci.0",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[MSTP024],
-       },
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP027]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP026]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP024]),
+
        CLKDEV_CON_ID("h8ex_fck", &mstp_clks[MSTP003]),
        CLKDEV_CON_ID("csm_fck", &mstp_clks[MSTP002]),
        CLKDEV_CON_ID("fe1_fck", &mstp_clks[MSTP001]),
        CLKDEV_CON_ID("fe0_fck", &mstp_clks[MSTP000]),
-       {
-               /* TMU0 */
-               .dev_id         = "sh_tmu.0",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP008],
-       }, {
-               /* TMU1 */
-               .dev_id         = "sh_tmu.1",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP008],
-       }, {
-               /* TMU2 */
-               .dev_id         = "sh_tmu.2",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP008],
-       }, {
-               /* TMU3 */
-               .dev_id         = "sh_tmu.3",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP009],
-       }, {
-               /* TMU4 */
-               .dev_id         = "sh_tmu.4",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP009],
-       }, {
-               /* TMU5 */
-               .dev_id         = "sh_tmu.5",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[MSTP009],
-       },
+
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.0", &mstp_clks[MSTP008]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[MSTP008]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.2", &mstp_clks[MSTP008]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.3", &mstp_clks[MSTP009]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.4", &mstp_clks[MSTP009]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.5", &mstp_clks[MSTP009]),
+
        CLKDEV_CON_ID("hudi_fck", &mstp_clks[MSTP119]),
        CLKDEV_CON_ID("dmac_11_6_fck", &mstp_clks[MSTP105]),
        CLKDEV_CON_ID("dmac_5_0_fck", &mstp_clks[MSTP104]),
diff --git a/arch/sh/kernel/cpu/sh4a/serial-sh7722.c b/arch/sh/kernel/cpu/sh4a/serial-sh7722.c
new file mode 100644 (file)
index 0000000..59bc3a7
--- /dev/null
@@ -0,0 +1,23 @@
+#include <linux/serial_sci.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+
+#define PSCR 0xA405011E
+
+static void sh7722_sci_init_pins(struct uart_port *port, unsigned int cflag)
+{
+       unsigned short data;
+
+       if (port->mapbase == 0xffe00000) {
+               data = __raw_readw(PSCR);
+               data &= ~0x03cf;
+               if (!(cflag & CRTSCTS))
+                       data |= 0x0340;
+
+               __raw_writew(data, PSCR);
+       }
+}
+
+struct plat_sci_port_ops sh7722_sci_port_ops = {
+       .init_pins      = sh7722_sci_init_pins,
+};
index 82616af..8777386 100644 (file)
@@ -20,6 +20,7 @@
 
 static struct plat_sci_port scif0_platform_data = {
        .mapbase        = 0xffe00000,
+       .port_reg       = 0xa405013e,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
index 5813d80..278a0e5 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <cpu/dma-register.h>
 #include <cpu/sh7722.h>
+#include <cpu/serial.h>
 
 static const struct sh_dmae_slave_config sh7722_dmae_slaves[] = {
        {
@@ -185,6 +186,8 @@ static struct plat_sci_port scif0_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 80, 80, 80, 80 },
+       .ops            = &sh7722_sci_port_ops,
+       .regtype        = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -202,6 +205,8 @@ static struct plat_sci_port scif1_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 81, 81, 81, 81 },
+       .ops            = &sh7722_sci_port_ops,
+       .regtype        = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -219,6 +224,8 @@ static struct plat_sci_port scif2_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 82, 82, 82, 82 },
+       .ops            = &sh7722_sci_port_ops,
+       .regtype        = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 
 static struct platform_device scif2_device = {
index 0723822..3c2810d 100644 (file)
 /* Serial */
 static struct plat_sci_port scif0_platform_data = {
        .mapbase        = 0xffe00000,
+       .port_reg       = 0xa4050160,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 80, 80, 80, 80 },
+       .regtype        = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -40,11 +42,13 @@ static struct platform_device scif0_device = {
 
 static struct plat_sci_port scif1_platform_data = {
        .mapbase        = 0xffe10000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 81, 81, 81, 81 },
+       .regtype        = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -57,11 +61,13 @@ static struct platform_device scif1_device = {
 
 static struct plat_sci_port scif2_platform_data = {
        .mapbase        = 0xffe20000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 82, 82, 82, 82 },
+       .regtype        = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 
 static struct platform_device scif2_device = {
@@ -75,6 +81,7 @@ static struct platform_device scif2_device = {
 static struct plat_sci_port scif3_platform_data = {
        .mapbase        = 0xa4e30000,
        .flags          = UPF_BOOT_AUTOCONF,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_3,
        .type           = PORT_SCIFA,
@@ -91,6 +98,7 @@ static struct platform_device scif3_device = {
 
 static struct plat_sci_port scif4_platform_data = {
        .mapbase        = 0xa4e40000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_3,
@@ -108,6 +116,7 @@ static struct platform_device scif4_device = {
 
 static struct plat_sci_port scif5_platform_data = {
        .mapbase        = 0xa4e50000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_3,
index 134a397..a37dd72 100644 (file)
@@ -296,11 +296,13 @@ static struct platform_device dma1_device = {
 /* Serial */
 static struct plat_sci_port scif0_platform_data = {
        .mapbase        = 0xffe00000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 80, 80, 80, 80 },
+       .regtype        = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -313,11 +315,13 @@ static struct platform_device scif0_device = {
 
 static struct plat_sci_port scif1_platform_data = {
        .mapbase        = 0xffe10000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 81, 81, 81, 81 },
+       .regtype        = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -330,11 +334,13 @@ static struct platform_device scif1_device = {
 
 static struct plat_sci_port scif2_platform_data = {
        .mapbase        = 0xffe20000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 82, 82, 82, 82 },
+       .regtype        = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
 };
 
 static struct platform_device scif2_device = {
@@ -347,6 +353,7 @@ static struct platform_device scif2_device = {
 
 static struct plat_sci_port scif3_platform_data = {
        .mapbase        = 0xa4e30000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE,
        .scbrr_algo_id  = SCBRR_ALGO_3,
@@ -364,6 +371,7 @@ static struct platform_device scif3_device = {
 
 static struct plat_sci_port scif4_platform_data = {
        .mapbase        = 0xa4e40000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE,
        .scbrr_algo_id  = SCBRR_ALGO_3,
@@ -381,6 +389,7 @@ static struct platform_device scif4_device = {
 
 static struct plat_sci_port scif5_platform_data = {
        .mapbase        = 0xa4e50000,
+       .port_reg       = SCIx_NOT_SUPPORTED,
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE,
        .scbrr_algo_id  = SCBRR_ALGO_3,
index 593eca6..0011351 100644 (file)
@@ -23,6 +23,7 @@ static struct plat_sci_port scif0_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 40, 40, 40, 40 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -40,6 +41,7 @@ static struct plat_sci_port scif1_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 76, 76, 76, 76 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -57,6 +59,7 @@ static struct plat_sci_port scif2_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           = { 104, 104, 104, 104 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif2_device = {
index 08add7f..3d4d207 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/serial_sci.h>
 #include <linux/sh_dma.h>
 #include <linux/sh_timer.h>
-
 #include <cpu/dma-register.h>
 
 static struct plat_sci_port scif0_platform_data = {
@@ -24,6 +23,7 @@ static struct plat_sci_port scif0_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 40, 40, 40, 40 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -41,6 +41,7 @@ static struct plat_sci_port scif1_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 76, 76, 76, 76 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
index 18d8fc1..b29e634 100644 (file)
@@ -15,9 +15,7 @@
 #include <linux/mm.h>
 #include <linux/sh_dma.h>
 #include <linux/sh_timer.h>
-
 #include <asm/mmzone.h>
-
 #include <cpu/dma-register.h>
 
 static struct plat_sci_port scif0_platform_data = {
@@ -27,6 +25,7 @@ static struct plat_sci_port scif0_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 40, 40, 40, 40 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -44,6 +43,7 @@ static struct plat_sci_port scif1_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 44, 44, 44, 44 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -61,6 +61,7 @@ static struct plat_sci_port scif2_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 60, 60, 60, 60 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif2_device = {
@@ -78,6 +79,7 @@ static struct plat_sci_port scif3_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 61, 61, 61, 61 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif3_device = {
@@ -95,6 +97,7 @@ static struct plat_sci_port scif4_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 62, 62, 62, 62 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif4_device = {
@@ -112,6 +115,7 @@ static struct plat_sci_port scif5_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 63, 63, 63, 63 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif5_device = {
index beba32b..dd5e709 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SH7786 Setup
  *
- * Copyright (C) 2009 - 2010  Renesas Solutions Corp.
+ * Copyright (C) 2009 - 2011  Renesas Solutions Corp.
  * Kuninori Morimoto <morimoto.kuninori@renesas.com>
  * Paul Mundt <paul.mundt@renesas.com>
  *
@@ -33,6 +33,7 @@ static struct plat_sci_port scif0_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 40, 41, 43, 42 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -53,6 +54,7 @@ static struct plat_sci_port scif1_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 44, 44, 44, 44 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -70,6 +72,7 @@ static struct plat_sci_port scif2_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 50, 50, 50, 50 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif2_device = {
@@ -87,6 +90,7 @@ static struct plat_sci_port scif3_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 51, 51, 51, 51 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif3_device = {
@@ -104,6 +108,7 @@ static struct plat_sci_port scif4_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 52, 52, 52, 52 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif4_device = {
@@ -121,6 +126,7 @@ static struct plat_sci_port scif5_platform_data = {
        .scbrr_algo_id  = SCBRR_ALGO_1,
        .type           = PORT_SCIF,
        .irqs           = { 53, 53, 53, 53 },
+       .regtype        = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif5_device = {
index 6ffccd6..d0479e2 100644 (file)
@@ -65,9 +65,6 @@ static inline void dma_make_coherent(unsigned long pa, unsigned long len)
 }
 #endif
 
-static struct resource *_sparc_find_resource(struct resource *r,
-                                            unsigned long);
-
 static void __iomem *_sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz);
 static void __iomem *_sparc_alloc_io(unsigned int busno, unsigned long phys,
     unsigned long size, char *name);
@@ -143,7 +140,11 @@ void iounmap(volatile void __iomem *virtual)
        unsigned long vaddr = (unsigned long) virtual & PAGE_MASK;
        struct resource *res;
 
-       if ((res = _sparc_find_resource(&sparc_iomap, vaddr)) == NULL) {
+       /*
+        * XXX Too slow. Can have 8192 DVMA pages on sun4m in the worst case.
+        * This probably warrants some sort of hashing.
+       */
+       if ((res = lookup_resource(&sparc_iomap, vaddr)) == NULL) {
                printk("free_io/iounmap: cannot free %lx\n", vaddr);
                return;
        }
@@ -319,7 +320,7 @@ static void sbus_free_coherent(struct device *dev, size_t n, void *p,
        struct resource *res;
        struct page *pgv;
 
-       if ((res = _sparc_find_resource(&_sparc_dvma,
+       if ((res = lookup_resource(&_sparc_dvma,
            (unsigned long)p)) == NULL) {
                printk("sbus_free_consistent: cannot free %p\n", p);
                return;
@@ -492,7 +493,7 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p,
 {
        struct resource *res;
 
-       if ((res = _sparc_find_resource(&_sparc_dvma,
+       if ((res = lookup_resource(&_sparc_dvma,
            (unsigned long)p)) == NULL) {
                printk("pci_free_consistent: cannot free %p\n", p);
                return;
@@ -715,25 +716,6 @@ static const struct file_operations sparc_io_proc_fops = {
 };
 #endif /* CONFIG_PROC_FS */
 
-/*
- * This is a version of find_resource and it belongs to kernel/resource.c.
- * Until we have agreement with Linus and Martin, it lingers here.
- *
- * XXX Too slow. Can have 8192 DVMA pages on sun4m in the worst case.
- * This probably warrants some sort of hashing.
- */
-static struct resource *_sparc_find_resource(struct resource *root,
-                                            unsigned long hit)
-{
-       struct resource *tmp;
-
-       for (tmp = root->child; tmp != 0; tmp = tmp->sibling) {
-               if (tmp->start <= hit && tmp->end >= hit)
-                       return tmp;
-       }
-       return NULL;
-}
-
 static void register_proc_sparc_ioport(void)
 {
 #ifdef CONFIG_PROC_FS
index 0283300..7f49235 100644 (file)
@@ -70,12 +70,36 @@ static u32 sh_dmae_readl(struct sh_dmae_chan *sh_dc, u32 reg)
 
 static u16 dmaor_read(struct sh_dmae_device *shdev)
 {
-       return __raw_readw(shdev->chan_reg + DMAOR / sizeof(u32));
+       u32 __iomem *addr = shdev->chan_reg + DMAOR / sizeof(u32);
+
+       if (shdev->pdata->dmaor_is_32bit)
+               return __raw_readl(addr);
+       else
+               return __raw_readw(addr);
 }
 
 static void dmaor_write(struct sh_dmae_device *shdev, u16 data)
 {
-       __raw_writew(data, shdev->chan_reg + DMAOR / sizeof(u32));
+       u32 __iomem *addr = shdev->chan_reg + DMAOR / sizeof(u32);
+
+       if (shdev->pdata->dmaor_is_32bit)
+               __raw_writel(data, addr);
+       else
+               __raw_writew(data, addr);
+}
+
+static void chcr_write(struct sh_dmae_chan *sh_dc, u32 data)
+{
+       struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
+
+       __raw_writel(data, sh_dc->base + shdev->chcr_offset / sizeof(u32));
+}
+
+static u32 chcr_read(struct sh_dmae_chan *sh_dc)
+{
+       struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
+
+       return __raw_readl(sh_dc->base + shdev->chcr_offset / sizeof(u32));
 }
 
 /*
@@ -120,7 +144,7 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev)
 
 static bool dmae_is_busy(struct sh_dmae_chan *sh_chan)
 {
-       u32 chcr = sh_dmae_readl(sh_chan, CHCR);
+       u32 chcr = chcr_read(sh_chan);
 
        if ((chcr & (CHCR_DE | CHCR_TE)) == CHCR_DE)
                return true; /* working */
@@ -130,8 +154,7 @@ static bool dmae_is_busy(struct sh_dmae_chan *sh_chan)
 
 static unsigned int calc_xmit_shift(struct sh_dmae_chan *sh_chan, u32 chcr)
 {
-       struct sh_dmae_device *shdev = container_of(sh_chan->common.device,
-                                               struct sh_dmae_device, common);
+       struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
        struct sh_dmae_pdata *pdata = shdev->pdata;
        int cnt = ((chcr & pdata->ts_low_mask) >> pdata->ts_low_shift) |
                ((chcr & pdata->ts_high_mask) >> pdata->ts_high_shift);
@@ -144,8 +167,7 @@ static unsigned int calc_xmit_shift(struct sh_dmae_chan *sh_chan, u32 chcr)
 
 static u32 log2size_to_chcr(struct sh_dmae_chan *sh_chan, int l2size)
 {
-       struct sh_dmae_device *shdev = container_of(sh_chan->common.device,
-                                               struct sh_dmae_device, common);
+       struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
        struct sh_dmae_pdata *pdata = shdev->pdata;
        int i;
 
@@ -169,18 +191,23 @@ static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs *hw)
 
 static void dmae_start(struct sh_dmae_chan *sh_chan)
 {
-       u32 chcr = sh_dmae_readl(sh_chan, CHCR);
+       struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
+       u32 chcr = chcr_read(sh_chan);
+
+       if (shdev->pdata->needs_tend_set)
+               sh_dmae_writel(sh_chan, 0xFFFFFFFF, TEND);
 
-       chcr |= CHCR_DE | CHCR_IE;
-       sh_dmae_writel(sh_chan, chcr & ~CHCR_TE, CHCR);
+       chcr |= CHCR_DE | shdev->chcr_ie_bit;
+       chcr_write(sh_chan, chcr & ~CHCR_TE);
 }
 
 static void dmae_halt(struct sh_dmae_chan *sh_chan)
 {
-       u32 chcr = sh_dmae_readl(sh_chan, CHCR);
+       struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
+       u32 chcr = chcr_read(sh_chan);
 
-       chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE);
-       sh_dmae_writel(sh_chan, chcr, CHCR);
+       chcr &= ~(CHCR_DE | CHCR_TE | shdev->chcr_ie_bit);
+       chcr_write(sh_chan, chcr);
 }
 
 static void dmae_init(struct sh_dmae_chan *sh_chan)
@@ -192,7 +219,7 @@ static void dmae_init(struct sh_dmae_chan *sh_chan)
        u32 chcr = DM_INC | SM_INC | 0x400 | log2size_to_chcr(sh_chan,
                                                   LOG2_DEFAULT_XFER_SIZE);
        sh_chan->xmit_shift = calc_xmit_shift(sh_chan, chcr);
-       sh_dmae_writel(sh_chan, chcr, CHCR);
+       chcr_write(sh_chan, chcr);
 }
 
 static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val)
@@ -202,23 +229,25 @@ static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val)
                return -EBUSY;
 
        sh_chan->xmit_shift = calc_xmit_shift(sh_chan, val);
-       sh_dmae_writel(sh_chan, val, CHCR);
+       chcr_write(sh_chan, val);
 
        return 0;
 }
 
 static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
 {
-       struct sh_dmae_device *shdev = container_of(sh_chan->common.device,
-                                               struct sh_dmae_device, common);
+       struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
        struct sh_dmae_pdata *pdata = shdev->pdata;
        const struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id];
        u16 __iomem *addr = shdev->dmars;
-       int shift = chan_pdata->dmars_bit;
+       unsigned int shift = chan_pdata->dmars_bit;
 
        if (dmae_is_busy(sh_chan))
                return -EBUSY;
 
+       if (pdata->no_dmars)
+               return 0;
+
        /* in the case of a missing DMARS resource use first memory window */
        if (!addr)
                addr = (u16 __iomem *)shdev->chan_reg;
@@ -296,9 +325,7 @@ static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan)
 static const struct sh_dmae_slave_config *sh_dmae_find_slave(
        struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *param)
 {
-       struct dma_device *dma_dev = sh_chan->common.device;
-       struct sh_dmae_device *shdev = container_of(dma_dev,
-                                       struct sh_dmae_device, common);
+       struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
        struct sh_dmae_pdata *pdata = shdev->pdata;
        int i;
 
@@ -771,10 +798,8 @@ static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
 
        spin_lock_bh(&sh_chan->desc_lock);
        /* DMA work check */
-       if (dmae_is_busy(sh_chan)) {
-               spin_unlock_bh(&sh_chan->desc_lock);
-               return;
-       }
+       if (dmae_is_busy(sh_chan))
+               goto sh_chan_xfer_ld_queue_end;
 
        /* Find the first not transferred descriptor */
        list_for_each_entry(desc, &sh_chan->ld_queue, node)
@@ -788,6 +813,7 @@ static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
                        break;
                }
 
+sh_chan_xfer_ld_queue_end:
        spin_unlock_bh(&sh_chan->desc_lock);
 }
 
@@ -846,7 +872,7 @@ static irqreturn_t sh_dmae_interrupt(int irq, void *data)
 
        spin_lock(&sh_chan->desc_lock);
 
-       chcr = sh_dmae_readl(sh_chan, CHCR);
+       chcr = chcr_read(sh_chan);
 
        if (chcr & CHCR_TE) {
                /* DMA stop */
@@ -1144,6 +1170,16 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
        /* platform data */
        shdev->pdata = pdata;
 
+       if (pdata->chcr_offset)
+               shdev->chcr_offset = pdata->chcr_offset;
+       else
+               shdev->chcr_offset = CHCR;
+
+       if (pdata->chcr_ie_bit)
+               shdev->chcr_ie_bit = pdata->chcr_ie_bit;
+       else
+               shdev->chcr_ie_bit = CHCR_IE;
+
        platform_set_drvdata(pdev, shdev);
 
        pm_runtime_enable(&pdev->dev);
index 5ae9fc5..dc56576 100644 (file)
@@ -47,10 +47,14 @@ struct sh_dmae_device {
        struct list_head node;
        u32 __iomem *chan_reg;
        u16 __iomem *dmars;
+       unsigned int chcr_offset;
+       u32 chcr_ie_bit;
 };
 
 #define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, common)
 #define to_sh_desc(lh) container_of(lh, struct sh_desc, node)
 #define tx_to_sh_desc(tx) container_of(tx, struct sh_desc, async_tx)
+#define to_sh_dev(chan) container_of(chan->common.device,\
+                                    struct sh_dmae_device, common)
 
 #endif /* __DMA_SHDMA_H */
index 3634986..d539efd 100644 (file)
@@ -103,6 +103,22 @@ config GPIO_MPC5200
        def_bool y
        depends on PPC_MPC52xx
 
+config GPIO_MSM_V1
+       tristate "Qualcomm MSM GPIO v1"
+       depends on GPIOLIB && ARCH_MSM
+       help
+         Say yes here to support the GPIO interface on ARM v6 based
+         Qualcomm MSM chips.  Most of the pins on the MSM can be
+         selected for GPIO, and are controlled by this driver.
+
+config GPIO_MSM_V2
+       tristate "Qualcomm MSM GPIO v2"
+       depends on GPIOLIB && ARCH_MSM
+       help
+         Say yes here to support the GPIO interface on ARM v7 based
+         Qualcomm MSM chips.  Most of the pins on the MSM can be
+         selected for GPIO, and are controlled by this driver.
+
 config GPIO_MXC
        def_bool y
        depends on ARCH_MXC
@@ -280,6 +296,12 @@ config GPIO_TC3589X
          This enables support for the GPIOs found on the TC3589X
          I/O Expander.
 
+config GPIO_TPS65912
+       tristate "TI TPS65912 GPIO"
+       depends on (MFD_TPS65912_I2C || MFD_TPS65912_SPI)
+       help
+         This driver supports TPS65912 gpio chip
+
 config GPIO_TWL4030
        tristate "TWL4030, TWL5030, and TPS659x0 GPIOs"
        depends on TWL4030_CORE
index 7207112..9588948 100644 (file)
@@ -27,6 +27,8 @@ obj-$(CONFIG_GPIO_MC33880)    += gpio-mc33880.o
 obj-$(CONFIG_GPIO_MCP23S08)    += gpio-mcp23s08.o
 obj-$(CONFIG_GPIO_ML_IOH)      += gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MPC5200)     += gpio-mpc5200.o
+obj-$(CONFIG_GPIO_MSM_V1)      += gpio-msm-v1.o
+obj-$(CONFIG_GPIO_MSM_V2)      += gpio-msm-v2.o
 obj-$(CONFIG_GPIO_MXC)         += gpio-mxc.o
 obj-$(CONFIG_GPIO_MXS)         += gpio-mxs.o
 obj-$(CONFIG_PLAT_NOMADIK)     += gpio-nomadik.o
@@ -48,6 +50,7 @@ obj-$(CONFIG_GPIO_TC3589X)    += gpio-tc3589x.o
 obj-$(CONFIG_ARCH_TEGRA)       += gpio-tegra.o
 obj-$(CONFIG_GPIO_TIMBERDALE)  += gpio-timberdale.o
 obj-$(CONFIG_GPIO_TPS65910)    += gpio-tps65910.o
+obj-$(CONFIG_GPIO_TPS65912)    += gpio-tps65912.o
 obj-$(CONFIG_GPIO_TWL4030)     += gpio-twl4030.o
 obj-$(CONFIG_MACH_U300)                += gpio-u300.o
 obj-$(CONFIG_GPIO_UCB1400)     += gpio-ucb1400.o
index ed795e6..050c05d 100644 (file)
@@ -516,5 +516,5 @@ module_exit(ab8500_gpio_exit);
 
 MODULE_AUTHOR("BIBEK BASU <bibek.basu@stericsson.com>");
 MODULE_DESCRIPTION("Driver allows to use AB8500 unused pins to be used as GPIO");
-MODULE_ALIAS("AB8500 GPIO driver");
+MODULE_ALIAS("platform:ab8500-gpio");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/gpio-msm-v1.c b/drivers/gpio/gpio-msm-v1.c
new file mode 100644 (file)
index 0000000..52a4d42
--- /dev/null
@@ -0,0 +1,636 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <mach/cpu.h>
+#include <mach/msm_gpiomux.h>
+#include <mach/msm_iomap.h>
+
+/* see 80-VA736-2 Rev C pp 695-751
+**
+** These are actually the *shadow* gpio registers, since the
+** real ones (which allow full access) are only available to the
+** ARM9 side of the world.
+**
+** Since the _BASE need to be page-aligned when we're mapping them
+** to virtual addresses, adjust for the additional offset in these
+** macros.
+*/
+
+#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + (off))
+#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0x400 + (off))
+#define MSM_GPIO1_SHADOW_REG(off) (MSM_GPIO1_BASE + 0x800 + (off))
+#define MSM_GPIO2_SHADOW_REG(off) (MSM_GPIO2_BASE + 0xC00 + (off))
+
+/*
+ * MSM7X00 registers
+ */
+/* output value */
+#define MSM7X00_GPIO_OUT_0     MSM_GPIO1_SHADOW_REG(0x00)  /* gpio  15-0  */
+#define MSM7X00_GPIO_OUT_1     MSM_GPIO2_SHADOW_REG(0x00)  /* gpio  42-16 */
+#define MSM7X00_GPIO_OUT_2     MSM_GPIO1_SHADOW_REG(0x04)  /* gpio  67-43 */
+#define MSM7X00_GPIO_OUT_3     MSM_GPIO1_SHADOW_REG(0x08)  /* gpio  94-68 */
+#define MSM7X00_GPIO_OUT_4     MSM_GPIO1_SHADOW_REG(0x0C)  /* gpio 106-95 */
+#define MSM7X00_GPIO_OUT_5     MSM_GPIO1_SHADOW_REG(0x50)  /* gpio 107-121 */
+
+/* same pin map as above, output enable */
+#define MSM7X00_GPIO_OE_0      MSM_GPIO1_SHADOW_REG(0x10)
+#define MSM7X00_GPIO_OE_1      MSM_GPIO2_SHADOW_REG(0x08)
+#define MSM7X00_GPIO_OE_2      MSM_GPIO1_SHADOW_REG(0x14)
+#define MSM7X00_GPIO_OE_3      MSM_GPIO1_SHADOW_REG(0x18)
+#define MSM7X00_GPIO_OE_4      MSM_GPIO1_SHADOW_REG(0x1C)
+#define MSM7X00_GPIO_OE_5      MSM_GPIO1_SHADOW_REG(0x54)
+
+/* same pin map as above, input read */
+#define MSM7X00_GPIO_IN_0      MSM_GPIO1_SHADOW_REG(0x34)
+#define MSM7X00_GPIO_IN_1      MSM_GPIO2_SHADOW_REG(0x20)
+#define MSM7X00_GPIO_IN_2      MSM_GPIO1_SHADOW_REG(0x38)
+#define MSM7X00_GPIO_IN_3      MSM_GPIO1_SHADOW_REG(0x3C)
+#define MSM7X00_GPIO_IN_4      MSM_GPIO1_SHADOW_REG(0x40)
+#define MSM7X00_GPIO_IN_5      MSM_GPIO1_SHADOW_REG(0x44)
+
+/* same pin map as above, 1=edge 0=level interrup */
+#define MSM7X00_GPIO_INT_EDGE_0        MSM_GPIO1_SHADOW_REG(0x60)
+#define MSM7X00_GPIO_INT_EDGE_1        MSM_GPIO2_SHADOW_REG(0x50)
+#define MSM7X00_GPIO_INT_EDGE_2        MSM_GPIO1_SHADOW_REG(0x64)
+#define MSM7X00_GPIO_INT_EDGE_3        MSM_GPIO1_SHADOW_REG(0x68)
+#define MSM7X00_GPIO_INT_EDGE_4        MSM_GPIO1_SHADOW_REG(0x6C)
+#define MSM7X00_GPIO_INT_EDGE_5        MSM_GPIO1_SHADOW_REG(0xC0)
+
+/* same pin map as above, 1=positive 0=negative */
+#define MSM7X00_GPIO_INT_POS_0 MSM_GPIO1_SHADOW_REG(0x70)
+#define MSM7X00_GPIO_INT_POS_1 MSM_GPIO2_SHADOW_REG(0x58)
+#define MSM7X00_GPIO_INT_POS_2 MSM_GPIO1_SHADOW_REG(0x74)
+#define MSM7X00_GPIO_INT_POS_3 MSM_GPIO1_SHADOW_REG(0x78)
+#define MSM7X00_GPIO_INT_POS_4 MSM_GPIO1_SHADOW_REG(0x7C)
+#define MSM7X00_GPIO_INT_POS_5 MSM_GPIO1_SHADOW_REG(0xBC)
+
+/* same pin map as above, interrupt enable */
+#define MSM7X00_GPIO_INT_EN_0  MSM_GPIO1_SHADOW_REG(0x80)
+#define MSM7X00_GPIO_INT_EN_1  MSM_GPIO2_SHADOW_REG(0x60)
+#define MSM7X00_GPIO_INT_EN_2  MSM_GPIO1_SHADOW_REG(0x84)
+#define MSM7X00_GPIO_INT_EN_3  MSM_GPIO1_SHADOW_REG(0x88)
+#define MSM7X00_GPIO_INT_EN_4  MSM_GPIO1_SHADOW_REG(0x8C)
+#define MSM7X00_GPIO_INT_EN_5  MSM_GPIO1_SHADOW_REG(0xB8)
+
+/* same pin map as above, write 1 to clear interrupt */
+#define MSM7X00_GPIO_INT_CLEAR_0       MSM_GPIO1_SHADOW_REG(0x90)
+#define MSM7X00_GPIO_INT_CLEAR_1       MSM_GPIO2_SHADOW_REG(0x68)
+#define MSM7X00_GPIO_INT_CLEAR_2       MSM_GPIO1_SHADOW_REG(0x94)
+#define MSM7X00_GPIO_INT_CLEAR_3       MSM_GPIO1_SHADOW_REG(0x98)
+#define MSM7X00_GPIO_INT_CLEAR_4       MSM_GPIO1_SHADOW_REG(0x9C)
+#define MSM7X00_GPIO_INT_CLEAR_5       MSM_GPIO1_SHADOW_REG(0xB4)
+
+/* same pin map as above, 1=interrupt pending */
+#define MSM7X00_GPIO_INT_STATUS_0      MSM_GPIO1_SHADOW_REG(0xA0)
+#define MSM7X00_GPIO_INT_STATUS_1      MSM_GPIO2_SHADOW_REG(0x70)
+#define MSM7X00_GPIO_INT_STATUS_2      MSM_GPIO1_SHADOW_REG(0xA4)
+#define MSM7X00_GPIO_INT_STATUS_3      MSM_GPIO1_SHADOW_REG(0xA8)
+#define MSM7X00_GPIO_INT_STATUS_4      MSM_GPIO1_SHADOW_REG(0xAC)
+#define MSM7X00_GPIO_INT_STATUS_5      MSM_GPIO1_SHADOW_REG(0xB0)
+
+/*
+ * QSD8X50 registers
+ */
+/* output value */
+#define QSD8X50_GPIO_OUT_0     MSM_GPIO1_SHADOW_REG(0x00)  /* gpio  15-0   */
+#define QSD8X50_GPIO_OUT_1     MSM_GPIO2_SHADOW_REG(0x00)  /* gpio  42-16  */
+#define QSD8X50_GPIO_OUT_2     MSM_GPIO1_SHADOW_REG(0x04)  /* gpio  67-43  */
+#define QSD8X50_GPIO_OUT_3     MSM_GPIO1_SHADOW_REG(0x08)  /* gpio  94-68  */
+#define QSD8X50_GPIO_OUT_4     MSM_GPIO1_SHADOW_REG(0x0C)  /* gpio 103-95  */
+#define QSD8X50_GPIO_OUT_5     MSM_GPIO1_SHADOW_REG(0x10)  /* gpio 121-104 */
+#define QSD8X50_GPIO_OUT_6     MSM_GPIO1_SHADOW_REG(0x14)  /* gpio 152-122 */
+#define QSD8X50_GPIO_OUT_7     MSM_GPIO1_SHADOW_REG(0x18)  /* gpio 164-153 */
+
+/* same pin map as above, output enable */
+#define QSD8X50_GPIO_OE_0      MSM_GPIO1_SHADOW_REG(0x20)
+#define QSD8X50_GPIO_OE_1      MSM_GPIO2_SHADOW_REG(0x08)
+#define QSD8X50_GPIO_OE_2      MSM_GPIO1_SHADOW_REG(0x24)
+#define QSD8X50_GPIO_OE_3      MSM_GPIO1_SHADOW_REG(0x28)
+#define QSD8X50_GPIO_OE_4      MSM_GPIO1_SHADOW_REG(0x2C)
+#define QSD8X50_GPIO_OE_5      MSM_GPIO1_SHADOW_REG(0x30)
+#define QSD8X50_GPIO_OE_6      MSM_GPIO1_SHADOW_REG(0x34)
+#define QSD8X50_GPIO_OE_7      MSM_GPIO1_SHADOW_REG(0x38)
+
+/* same pin map as above, input read */
+#define QSD8X50_GPIO_IN_0      MSM_GPIO1_SHADOW_REG(0x50)
+#define QSD8X50_GPIO_IN_1      MSM_GPIO2_SHADOW_REG(0x20)
+#define QSD8X50_GPIO_IN_2      MSM_GPIO1_SHADOW_REG(0x54)
+#define QSD8X50_GPIO_IN_3      MSM_GPIO1_SHADOW_REG(0x58)
+#define QSD8X50_GPIO_IN_4      MSM_GPIO1_SHADOW_REG(0x5C)
+#define QSD8X50_GPIO_IN_5      MSM_GPIO1_SHADOW_REG(0x60)
+#define QSD8X50_GPIO_IN_6      MSM_GPIO1_SHADOW_REG(0x64)
+#define QSD8X50_GPIO_IN_7      MSM_GPIO1_SHADOW_REG(0x68)
+
+/* same pin map as above, 1=edge 0=level interrup */
+#define QSD8X50_GPIO_INT_EDGE_0        MSM_GPIO1_SHADOW_REG(0x70)
+#define QSD8X50_GPIO_INT_EDGE_1        MSM_GPIO2_SHADOW_REG(0x50)
+#define QSD8X50_GPIO_INT_EDGE_2        MSM_GPIO1_SHADOW_REG(0x74)
+#define QSD8X50_GPIO_INT_EDGE_3        MSM_GPIO1_SHADOW_REG(0x78)
+#define QSD8X50_GPIO_INT_EDGE_4        MSM_GPIO1_SHADOW_REG(0x7C)
+#define QSD8X50_GPIO_INT_EDGE_5        MSM_GPIO1_SHADOW_REG(0x80)
+#define QSD8X50_GPIO_INT_EDGE_6        MSM_GPIO1_SHADOW_REG(0x84)
+#define QSD8X50_GPIO_INT_EDGE_7        MSM_GPIO1_SHADOW_REG(0x88)
+
+/* same pin map as above, 1=positive 0=negative */
+#define QSD8X50_GPIO_INT_POS_0 MSM_GPIO1_SHADOW_REG(0x90)
+#define QSD8X50_GPIO_INT_POS_1 MSM_GPIO2_SHADOW_REG(0x58)
+#define QSD8X50_GPIO_INT_POS_2 MSM_GPIO1_SHADOW_REG(0x94)
+#define QSD8X50_GPIO_INT_POS_3 MSM_GPIO1_SHADOW_REG(0x98)
+#define QSD8X50_GPIO_INT_POS_4 MSM_GPIO1_SHADOW_REG(0x9C)
+#define QSD8X50_GPIO_INT_POS_5 MSM_GPIO1_SHADOW_REG(0xA0)
+#define QSD8X50_GPIO_INT_POS_6 MSM_GPIO1_SHADOW_REG(0xA4)
+#define QSD8X50_GPIO_INT_POS_7 MSM_GPIO1_SHADOW_REG(0xA8)
+
+/* same pin map as above, interrupt enable */
+#define QSD8X50_GPIO_INT_EN_0  MSM_GPIO1_SHADOW_REG(0xB0)
+#define QSD8X50_GPIO_INT_EN_1  MSM_GPIO2_SHADOW_REG(0x60)
+#define QSD8X50_GPIO_INT_EN_2  MSM_GPIO1_SHADOW_REG(0xB4)
+#define QSD8X50_GPIO_INT_EN_3  MSM_GPIO1_SHADOW_REG(0xB8)
+#define QSD8X50_GPIO_INT_EN_4  MSM_GPIO1_SHADOW_REG(0xBC)
+#define QSD8X50_GPIO_INT_EN_5  MSM_GPIO1_SHADOW_REG(0xC0)
+#define QSD8X50_GPIO_INT_EN_6  MSM_GPIO1_SHADOW_REG(0xC4)
+#define QSD8X50_GPIO_INT_EN_7  MSM_GPIO1_SHADOW_REG(0xC8)
+
+/* same pin map as above, write 1 to clear interrupt */
+#define QSD8X50_GPIO_INT_CLEAR_0       MSM_GPIO1_SHADOW_REG(0xD0)
+#define QSD8X50_GPIO_INT_CLEAR_1       MSM_GPIO2_SHADOW_REG(0x68)
+#define QSD8X50_GPIO_INT_CLEAR_2       MSM_GPIO1_SHADOW_REG(0xD4)
+#define QSD8X50_GPIO_INT_CLEAR_3       MSM_GPIO1_SHADOW_REG(0xD8)
+#define QSD8X50_GPIO_INT_CLEAR_4       MSM_GPIO1_SHADOW_REG(0xDC)
+#define QSD8X50_GPIO_INT_CLEAR_5       MSM_GPIO1_SHADOW_REG(0xE0)
+#define QSD8X50_GPIO_INT_CLEAR_6       MSM_GPIO1_SHADOW_REG(0xE4)
+#define QSD8X50_GPIO_INT_CLEAR_7       MSM_GPIO1_SHADOW_REG(0xE8)
+
+/* same pin map as above, 1=interrupt pending */
+#define QSD8X50_GPIO_INT_STATUS_0      MSM_GPIO1_SHADOW_REG(0xF0)
+#define QSD8X50_GPIO_INT_STATUS_1      MSM_GPIO2_SHADOW_REG(0x70)
+#define QSD8X50_GPIO_INT_STATUS_2      MSM_GPIO1_SHADOW_REG(0xF4)
+#define QSD8X50_GPIO_INT_STATUS_3      MSM_GPIO1_SHADOW_REG(0xF8)
+#define QSD8X50_GPIO_INT_STATUS_4      MSM_GPIO1_SHADOW_REG(0xFC)
+#define QSD8X50_GPIO_INT_STATUS_5      MSM_GPIO1_SHADOW_REG(0x100)
+#define QSD8X50_GPIO_INT_STATUS_6      MSM_GPIO1_SHADOW_REG(0x104)
+#define QSD8X50_GPIO_INT_STATUS_7      MSM_GPIO1_SHADOW_REG(0x108)
+
+/*
+ * MSM7X30 registers
+ */
+/* output value */
+#define MSM7X30_GPIO_OUT_0     MSM_GPIO1_REG(0x00)   /* gpio  15-0   */
+#define MSM7X30_GPIO_OUT_1     MSM_GPIO2_REG(0x00)   /* gpio  43-16  */
+#define MSM7X30_GPIO_OUT_2     MSM_GPIO1_REG(0x04)   /* gpio  67-44  */
+#define MSM7X30_GPIO_OUT_3     MSM_GPIO1_REG(0x08)   /* gpio  94-68  */
+#define MSM7X30_GPIO_OUT_4     MSM_GPIO1_REG(0x0C)   /* gpio 106-95  */
+#define MSM7X30_GPIO_OUT_5     MSM_GPIO1_REG(0x50)   /* gpio 133-107 */
+#define MSM7X30_GPIO_OUT_6     MSM_GPIO1_REG(0xC4)   /* gpio 150-134 */
+#define MSM7X30_GPIO_OUT_7     MSM_GPIO1_REG(0x214)  /* gpio 181-151 */
+
+/* same pin map as above, output enable */
+#define MSM7X30_GPIO_OE_0      MSM_GPIO1_REG(0x10)
+#define MSM7X30_GPIO_OE_1      MSM_GPIO2_REG(0x08)
+#define MSM7X30_GPIO_OE_2      MSM_GPIO1_REG(0x14)
+#define MSM7X30_GPIO_OE_3      MSM_GPIO1_REG(0x18)
+#define MSM7X30_GPIO_OE_4      MSM_GPIO1_REG(0x1C)
+#define MSM7X30_GPIO_OE_5      MSM_GPIO1_REG(0x54)
+#define MSM7X30_GPIO_OE_6      MSM_GPIO1_REG(0xC8)
+#define MSM7X30_GPIO_OE_7      MSM_GPIO1_REG(0x218)
+
+/* same pin map as above, input read */
+#define MSM7X30_GPIO_IN_0      MSM_GPIO1_REG(0x34)
+#define MSM7X30_GPIO_IN_1      MSM_GPIO2_REG(0x20)
+#define MSM7X30_GPIO_IN_2      MSM_GPIO1_REG(0x38)
+#define MSM7X30_GPIO_IN_3      MSM_GPIO1_REG(0x3C)
+#define MSM7X30_GPIO_IN_4      MSM_GPIO1_REG(0x40)
+#define MSM7X30_GPIO_IN_5      MSM_GPIO1_REG(0x44)
+#define MSM7X30_GPIO_IN_6      MSM_GPIO1_REG(0xCC)
+#define MSM7X30_GPIO_IN_7      MSM_GPIO1_REG(0x21C)
+
+/* same pin map as above, 1=edge 0=level interrup */
+#define MSM7X30_GPIO_INT_EDGE_0        MSM_GPIO1_REG(0x60)
+#define MSM7X30_GPIO_INT_EDGE_1        MSM_GPIO2_REG(0x50)
+#define MSM7X30_GPIO_INT_EDGE_2        MSM_GPIO1_REG(0x64)
+#define MSM7X30_GPIO_INT_EDGE_3        MSM_GPIO1_REG(0x68)
+#define MSM7X30_GPIO_INT_EDGE_4        MSM_GPIO1_REG(0x6C)
+#define MSM7X30_GPIO_INT_EDGE_5        MSM_GPIO1_REG(0xC0)
+#define MSM7X30_GPIO_INT_EDGE_6        MSM_GPIO1_REG(0xD0)
+#define MSM7X30_GPIO_INT_EDGE_7        MSM_GPIO1_REG(0x240)
+
+/* same pin map as above, 1=positive 0=negative */
+#define MSM7X30_GPIO_INT_POS_0 MSM_GPIO1_REG(0x70)
+#define MSM7X30_GPIO_INT_POS_1 MSM_GPIO2_REG(0x58)
+#define MSM7X30_GPIO_INT_POS_2 MSM_GPIO1_REG(0x74)
+#define MSM7X30_GPIO_INT_POS_3 MSM_GPIO1_REG(0x78)
+#define MSM7X30_GPIO_INT_POS_4 MSM_GPIO1_REG(0x7C)
+#define MSM7X30_GPIO_INT_POS_5 MSM_GPIO1_REG(0xBC)
+#define MSM7X30_GPIO_INT_POS_6 MSM_GPIO1_REG(0xD4)
+#define MSM7X30_GPIO_INT_POS_7 MSM_GPIO1_REG(0x228)
+
+/* same pin map as above, interrupt enable */
+#define MSM7X30_GPIO_INT_EN_0  MSM_GPIO1_REG(0x80)
+#define MSM7X30_GPIO_INT_EN_1  MSM_GPIO2_REG(0x60)
+#define MSM7X30_GPIO_INT_EN_2  MSM_GPIO1_REG(0x84)
+#define MSM7X30_GPIO_INT_EN_3  MSM_GPIO1_REG(0x88)
+#define MSM7X30_GPIO_INT_EN_4  MSM_GPIO1_REG(0x8C)
+#define MSM7X30_GPIO_INT_EN_5  MSM_GPIO1_REG(0xB8)
+#define MSM7X30_GPIO_INT_EN_6  MSM_GPIO1_REG(0xD8)
+#define MSM7X30_GPIO_INT_EN_7  MSM_GPIO1_REG(0x22C)
+
+/* same pin map as above, write 1 to clear interrupt */
+#define MSM7X30_GPIO_INT_CLEAR_0       MSM_GPIO1_REG(0x90)
+#define MSM7X30_GPIO_INT_CLEAR_1       MSM_GPIO2_REG(0x68)
+#define MSM7X30_GPIO_INT_CLEAR_2       MSM_GPIO1_REG(0x94)
+#define MSM7X30_GPIO_INT_CLEAR_3       MSM_GPIO1_REG(0x98)
+#define MSM7X30_GPIO_INT_CLEAR_4       MSM_GPIO1_REG(0x9C)
+#define MSM7X30_GPIO_INT_CLEAR_5       MSM_GPIO1_REG(0xB4)
+#define MSM7X30_GPIO_INT_CLEAR_6       MSM_GPIO1_REG(0xDC)
+#define MSM7X30_GPIO_INT_CLEAR_7       MSM_GPIO1_REG(0x230)
+
+/* same pin map as above, 1=interrupt pending */
+#define MSM7X30_GPIO_INT_STATUS_0      MSM_GPIO1_REG(0xA0)
+#define MSM7X30_GPIO_INT_STATUS_1      MSM_GPIO2_REG(0x70)
+#define MSM7X30_GPIO_INT_STATUS_2      MSM_GPIO1_REG(0xA4)
+#define MSM7X30_GPIO_INT_STATUS_3      MSM_GPIO1_REG(0xA8)
+#define MSM7X30_GPIO_INT_STATUS_4      MSM_GPIO1_REG(0xAC)
+#define MSM7X30_GPIO_INT_STATUS_5      MSM_GPIO1_REG(0xB0)
+#define MSM7X30_GPIO_INT_STATUS_6      MSM_GPIO1_REG(0xE0)
+#define MSM7X30_GPIO_INT_STATUS_7      MSM_GPIO1_REG(0x234)
+
+#define FIRST_GPIO_IRQ MSM_GPIO_TO_INT(0)
+
+#define MSM_GPIO_BANK(soc, bank, first, last)                          \
+       {                                                               \
+               .regs = {                                               \
+                       .out =         soc##_GPIO_OUT_##bank,           \
+                       .in =          soc##_GPIO_IN_##bank,            \
+                       .int_status =  soc##_GPIO_INT_STATUS_##bank,    \
+                       .int_clear =   soc##_GPIO_INT_CLEAR_##bank,     \
+                       .int_en =      soc##_GPIO_INT_EN_##bank,        \
+                       .int_edge =    soc##_GPIO_INT_EDGE_##bank,      \
+                       .int_pos =     soc##_GPIO_INT_POS_##bank,       \
+                       .oe =          soc##_GPIO_OE_##bank,            \
+               },                                                      \
+               .chip = {                                               \
+                       .base = (first),                                \
+                       .ngpio = (last) - (first) + 1,                  \
+                       .get = msm_gpio_get,                            \
+                       .set = msm_gpio_set,                            \
+                       .direction_input = msm_gpio_direction_input,    \
+                       .direction_output = msm_gpio_direction_output,  \
+                       .to_irq = msm_gpio_to_irq,                      \
+                       .request = msm_gpio_request,                    \
+                       .free = msm_gpio_free,                          \
+               }                                                       \
+       }
+
+#define MSM_GPIO_BROKEN_INT_CLEAR 1
+
+struct msm_gpio_regs {
+       void __iomem *out;
+       void __iomem *in;
+       void __iomem *int_status;
+       void __iomem *int_clear;
+       void __iomem *int_en;
+       void __iomem *int_edge;
+       void __iomem *int_pos;
+       void __iomem *oe;
+};
+
+struct msm_gpio_chip {
+       spinlock_t              lock;
+       struct gpio_chip        chip;
+       struct msm_gpio_regs    regs;
+#if MSM_GPIO_BROKEN_INT_CLEAR
+       unsigned                int_status_copy;
+#endif
+       unsigned int            both_edge_detect;
+       unsigned int            int_enable[2]; /* 0: awake, 1: sleep */
+};
+
+static int msm_gpio_write(struct msm_gpio_chip *msm_chip,
+                         unsigned offset, unsigned on)
+{
+       unsigned mask = BIT(offset);
+       unsigned val;
+
+       val = readl(msm_chip->regs.out);
+       if (on)
+               writel(val | mask, msm_chip->regs.out);
+       else
+               writel(val & ~mask, msm_chip->regs.out);
+       return 0;
+}
+
+static void msm_gpio_update_both_edge_detect(struct msm_gpio_chip *msm_chip)
+{
+       int loop_limit = 100;
+       unsigned pol, val, val2, intstat;
+       do {
+               val = readl(msm_chip->regs.in);
+               pol = readl(msm_chip->regs.int_pos);
+               pol = (pol & ~msm_chip->both_edge_detect) |
+                     (~val & msm_chip->both_edge_detect);
+               writel(pol, msm_chip->regs.int_pos);
+               intstat = readl(msm_chip->regs.int_status);
+               val2 = readl(msm_chip->regs.in);
+               if (((val ^ val2) & msm_chip->both_edge_detect & ~intstat) == 0)
+                       return;
+       } while (loop_limit-- > 0);
+       printk(KERN_ERR "msm_gpio_update_both_edge_detect, "
+              "failed to reach stable state %x != %x\n", val, val2);
+}
+
+static int msm_gpio_clear_detect_status(struct msm_gpio_chip *msm_chip,
+                                       unsigned offset)
+{
+       unsigned bit = BIT(offset);
+
+#if MSM_GPIO_BROKEN_INT_CLEAR
+       /* Save interrupts that already triggered before we loose them. */
+       /* Any interrupt that triggers between the read of int_status */
+       /* and the write to int_clear will still be lost though. */
+       msm_chip->int_status_copy |= readl(msm_chip->regs.int_status);
+       msm_chip->int_status_copy &= ~bit;
+#endif
+       writel(bit, msm_chip->regs.int_clear);
+       msm_gpio_update_both_edge_detect(msm_chip);
+       return 0;
+}
+
+static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       struct msm_gpio_chip *msm_chip;
+       unsigned long irq_flags;
+
+       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       writel(readl(msm_chip->regs.oe) & ~BIT(offset), msm_chip->regs.oe);
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+       return 0;
+}
+
+static int
+msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct msm_gpio_chip *msm_chip;
+       unsigned long irq_flags;
+
+       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       msm_gpio_write(msm_chip, offset, value);
+       writel(readl(msm_chip->regs.oe) | BIT(offset), msm_chip->regs.oe);
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+       return 0;
+}
+
+static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct msm_gpio_chip *msm_chip;
+
+       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+       return (readl(msm_chip->regs.in) & (1U << offset)) ? 1 : 0;
+}
+
+static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct msm_gpio_chip *msm_chip;
+       unsigned long irq_flags;
+
+       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       msm_gpio_write(msm_chip, offset, value);
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       return MSM_GPIO_TO_INT(chip->base + offset);
+}
+
+#ifdef CONFIG_MSM_GPIOMUX
+static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       return msm_gpiomux_get(chip->base + offset);
+}
+
+static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+       msm_gpiomux_put(chip->base + offset);
+}
+#else
+#define msm_gpio_request NULL
+#define msm_gpio_free NULL
+#endif
+
+static struct msm_gpio_chip *msm_gpio_chips;
+static int msm_gpio_count;
+
+static struct msm_gpio_chip msm_gpio_chips_msm7x01[] = {
+       MSM_GPIO_BANK(MSM7X00, 0,   0,  15),
+       MSM_GPIO_BANK(MSM7X00, 1,  16,  42),
+       MSM_GPIO_BANK(MSM7X00, 2,  43,  67),
+       MSM_GPIO_BANK(MSM7X00, 3,  68,  94),
+       MSM_GPIO_BANK(MSM7X00, 4,  95, 106),
+       MSM_GPIO_BANK(MSM7X00, 5, 107, 121),
+};
+
+static struct msm_gpio_chip msm_gpio_chips_msm7x30[] = {
+       MSM_GPIO_BANK(MSM7X30, 0,   0,  15),
+       MSM_GPIO_BANK(MSM7X30, 1,  16,  43),
+       MSM_GPIO_BANK(MSM7X30, 2,  44,  67),
+       MSM_GPIO_BANK(MSM7X30, 3,  68,  94),
+       MSM_GPIO_BANK(MSM7X30, 4,  95, 106),
+       MSM_GPIO_BANK(MSM7X30, 5, 107, 133),
+       MSM_GPIO_BANK(MSM7X30, 6, 134, 150),
+       MSM_GPIO_BANK(MSM7X30, 7, 151, 181),
+};
+
+static struct msm_gpio_chip msm_gpio_chips_qsd8x50[] = {
+       MSM_GPIO_BANK(QSD8X50, 0,   0,  15),
+       MSM_GPIO_BANK(QSD8X50, 1,  16,  42),
+       MSM_GPIO_BANK(QSD8X50, 2,  43,  67),
+       MSM_GPIO_BANK(QSD8X50, 3,  68,  94),
+       MSM_GPIO_BANK(QSD8X50, 4,  95, 103),
+       MSM_GPIO_BANK(QSD8X50, 5, 104, 121),
+       MSM_GPIO_BANK(QSD8X50, 6, 122, 152),
+       MSM_GPIO_BANK(QSD8X50, 7, 153, 164),
+};
+
+static void msm_gpio_irq_ack(struct irq_data *d)
+{
+       unsigned long irq_flags;
+       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       msm_gpio_clear_detect_status(msm_chip,
+                                    d->irq - gpio_to_irq(msm_chip->chip.base));
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static void msm_gpio_irq_mask(struct irq_data *d)
+{
+       unsigned long irq_flags;
+       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
+       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
+
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       /* level triggered interrupts are also latched */
+       if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
+               msm_gpio_clear_detect_status(msm_chip, offset);
+       msm_chip->int_enable[0] &= ~BIT(offset);
+       writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static void msm_gpio_irq_unmask(struct irq_data *d)
+{
+       unsigned long irq_flags;
+       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
+       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
+
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       /* level triggered interrupts are also latched */
+       if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
+               msm_gpio_clear_detect_status(msm_chip, offset);
+       msm_chip->int_enable[0] |= BIT(offset);
+       writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+       unsigned long irq_flags;
+       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
+       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
+
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+
+       if (on)
+               msm_chip->int_enable[1] |= BIT(offset);
+       else
+               msm_chip->int_enable[1] &= ~BIT(offset);
+
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+       return 0;
+}
+
+static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+       unsigned long irq_flags;
+       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
+       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
+       unsigned val, mask = BIT(offset);
+
+       spin_lock_irqsave(&msm_chip->lock, irq_flags);
+       val = readl(msm_chip->regs.int_edge);
+       if (flow_type & IRQ_TYPE_EDGE_BOTH) {
+               writel(val | mask, msm_chip->regs.int_edge);
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
+       } else {
+               writel(val & ~mask, msm_chip->regs.int_edge);
+               __irq_set_handler_locked(d->irq, handle_level_irq);
+       }
+       if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
+               msm_chip->both_edge_detect |= mask;
+               msm_gpio_update_both_edge_detect(msm_chip);
+       } else {
+               msm_chip->both_edge_detect &= ~mask;
+               val = readl(msm_chip->regs.int_pos);
+               if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH))
+                       writel(val | mask, msm_chip->regs.int_pos);
+               else
+                       writel(val & ~mask, msm_chip->regs.int_pos);
+       }
+       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+       return 0;
+}
+
+static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       int i, j, mask;
+       unsigned val;
+
+       for (i = 0; i < msm_gpio_count; i++) {
+               struct msm_gpio_chip *msm_chip = &msm_gpio_chips[i];
+               val = readl(msm_chip->regs.int_status);
+               val &= msm_chip->int_enable[0];
+               while (val) {
+                       mask = val & -val;
+                       j = fls(mask) - 1;
+                       /* printk("%s %08x %08x bit %d gpio %d irq %d\n",
+                               __func__, v, m, j, msm_chip->chip.start + j,
+                               FIRST_GPIO_IRQ + msm_chip->chip.start + j); */
+                       val &= ~mask;
+                       generic_handle_irq(FIRST_GPIO_IRQ +
+                                          msm_chip->chip.base + j);
+               }
+       }
+       desc->irq_data.chip->irq_ack(&desc->irq_data);
+}
+
+static struct irq_chip msm_gpio_irq_chip = {
+       .name          = "msmgpio",
+       .irq_ack       = msm_gpio_irq_ack,
+       .irq_mask      = msm_gpio_irq_mask,
+       .irq_unmask    = msm_gpio_irq_unmask,
+       .irq_set_wake  = msm_gpio_irq_set_wake,
+       .irq_set_type  = msm_gpio_irq_set_type,
+};
+
+static int __init msm_init_gpio(void)
+{
+       int i, j = 0;
+
+       if (cpu_is_msm7x01()) {
+               msm_gpio_chips = msm_gpio_chips_msm7x01;
+               msm_gpio_count = ARRAY_SIZE(msm_gpio_chips_msm7x01);
+       } else if (cpu_is_msm7x30()) {
+               msm_gpio_chips = msm_gpio_chips_msm7x30;
+               msm_gpio_count = ARRAY_SIZE(msm_gpio_chips_msm7x30);
+       } else if (cpu_is_qsd8x50()) {
+               msm_gpio_chips = msm_gpio_chips_qsd8x50;
+               msm_gpio_count = ARRAY_SIZE(msm_gpio_chips_qsd8x50);
+       } else {
+               return 0;
+       }
+
+       for (i = FIRST_GPIO_IRQ; i < FIRST_GPIO_IRQ + NR_GPIO_IRQS; i++) {
+               if (i - FIRST_GPIO_IRQ >=
+                       msm_gpio_chips[j].chip.base +
+                       msm_gpio_chips[j].chip.ngpio)
+                       j++;
+               irq_set_chip_data(i, &msm_gpio_chips[j]);
+               irq_set_chip_and_handler(i, &msm_gpio_irq_chip,
+                                        handle_edge_irq);
+               set_irq_flags(i, IRQF_VALID);
+       }
+
+       for (i = 0; i < msm_gpio_count; i++) {
+               spin_lock_init(&msm_gpio_chips[i].lock);
+               writel(0, msm_gpio_chips[i].regs.int_en);
+               gpiochip_add(&msm_gpio_chips[i].chip);
+       }
+
+       irq_set_chained_handler(INT_GPIO_GROUP1, msm_gpio_irq_handler);
+       irq_set_chained_handler(INT_GPIO_GROUP2, msm_gpio_irq_handler);
+       irq_set_irq_wake(INT_GPIO_GROUP1, 1);
+       irq_set_irq_wake(INT_GPIO_GROUP2, 2);
+       return 0;
+}
+
+postcore_initcall(msm_init_gpio);
similarity index 99%
rename from arch/arm/mach-msm/gpio-v2.c
rename to drivers/gpio/gpio-msm-v2.c
index cc9c4fd..5cb1227 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -30,8 +30,8 @@
 
 #include <asm/mach/irq.h>
 
+#include <mach/msm_gpiomux.h>
 #include <mach/msm_iomap.h>
-#include "gpiomux.h"
 
 /* Bits of interest in the GPIO_IN_OUT register.
  */
diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c
new file mode 100644 (file)
index 0000000..79e66c0
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2011 Texas Instruments Inc.
+ *
+ * Author: Margarita Olaya <magi@slimlogic.co.uk>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under  the terms of the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ * This driver is based on wm8350 implementation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/mfd/core.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/mfd/tps65912.h>
+
+struct tps65912_gpio_data {
+       struct tps65912 *tps65912;
+       struct gpio_chip gpio_chip;
+};
+
+static int tps65912_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+       struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio);
+       int val;
+
+       val = tps65912_reg_read(tps65912, TPS65912_GPIO1 + offset);
+
+       if (val & GPIO_STS_MASK)
+               return 1;
+
+       return 0;
+}
+
+static void tps65912_gpio_set(struct gpio_chip *gc, unsigned offset,
+                             int value)
+{
+       struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio);
+
+       if (value)
+               tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset,
+                                                       GPIO_SET_MASK);
+       else
+               tps65912_clear_bits(tps65912, TPS65912_GPIO1 + offset,
+                                                               GPIO_SET_MASK);
+}
+
+static int tps65912_gpio_output(struct gpio_chip *gc, unsigned offset,
+                               int value)
+{
+       struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio);
+
+       /* Set the initial value */
+       tps65912_gpio_set(gc, offset, value);
+
+       return tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset,
+                                                               GPIO_CFG_MASK);
+}
+
+static int tps65912_gpio_input(struct gpio_chip *gc, unsigned offset)
+{
+       struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio);
+
+       return tps65912_clear_bits(tps65912, TPS65912_GPIO1 + offset,
+                                                               GPIO_CFG_MASK);
+
+}
+
+static struct gpio_chip template_chip = {
+       .label                  = "tps65912",
+       .owner                  = THIS_MODULE,
+       .direction_input        = tps65912_gpio_input,
+       .direction_output       = tps65912_gpio_output,
+       .get                    = tps65912_gpio_get,
+       .set                    = tps65912_gpio_set,
+       .can_sleep              = 1,
+       .ngpio                  = 5,
+       .base                   = -1,
+};
+
+static int __devinit tps65912_gpio_probe(struct platform_device *pdev)
+{
+       struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
+       struct tps65912_board *pdata = tps65912->dev->platform_data;
+       struct tps65912_gpio_data *tps65912_gpio;
+       int ret;
+
+       tps65912_gpio = kzalloc(sizeof(*tps65912_gpio), GFP_KERNEL);
+       if (tps65912_gpio == NULL)
+               return -ENOMEM;
+
+       tps65912_gpio->tps65912 = tps65912;
+       tps65912_gpio->gpio_chip = template_chip;
+       tps65912_gpio->gpio_chip.dev = &pdev->dev;
+       if (pdata && pdata->gpio_base)
+               tps65912_gpio->gpio_chip.base = pdata->gpio_base;
+
+       ret = gpiochip_add(&tps65912_gpio->gpio_chip);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to register gpiochip, %d\n", ret);
+               goto err;
+       }
+
+       platform_set_drvdata(pdev, tps65912_gpio);
+
+       return ret;
+
+err:
+       kfree(tps65912_gpio);
+       return ret;
+}
+
+static int __devexit tps65912_gpio_remove(struct platform_device *pdev)
+{
+       struct tps65912_gpio_data  *tps65912_gpio = platform_get_drvdata(pdev);
+       int ret;
+
+       ret = gpiochip_remove(&tps65912_gpio->gpio_chip);
+       if (ret == 0)
+               kfree(tps65912_gpio);
+
+       return ret;
+}
+
+static struct platform_driver tps65912_gpio_driver = {
+       .driver = {
+               .name = "tps65912-gpio",
+               .owner = THIS_MODULE,
+       },
+       .probe = tps65912_gpio_probe,
+       .remove = __devexit_p(tps65912_gpio_remove),
+};
+
+static int __init tps65912_gpio_init(void)
+{
+       return platform_driver_register(&tps65912_gpio_driver);
+}
+subsys_initcall(tps65912_gpio_init);
+
+static void __exit tps65912_gpio_exit(void)
+{
+       platform_driver_unregister(&tps65912_gpio_driver);
+}
+module_exit(tps65912_gpio_exit);
+
+MODULE_AUTHOR("Margarita Olaya Cabrera <magi@slimlogic.co.uk>");
+MODULE_DESCRIPTION("GPIO interface for TPS65912 PMICs");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:tps65912-gpio");
index 37b83eb..21574bd 100644 (file)
@@ -171,6 +171,37 @@ config MFD_TPS6586X
          This driver can also be built as a module.  If so, the module
          will be called tps6586x.
 
+config MFD_TPS65910
+       bool "TPS65910 Power Management chip"
+       depends on I2C=y && GPIOLIB
+       select MFD_CORE
+       select GPIO_TPS65910
+       help
+         if you say yes here you get support for the TPS65910 series of
+         Power Management chips.
+
+config MFD_TPS65912
+       bool
+       depends on GPIOLIB
+
+config MFD_TPS65912_I2C
+       bool "TPS95612 Power Management chip with I2C"
+       select MFD_CORE
+       select MFD_TPS65912
+       depends on I2C=y && GPIOLIB
+       help
+         If you say yes here you get support for the TPS65912 series of
+         PM chips with I2C interface.
+
+config MFD_TPS65912_SPI
+       bool "TPS65912 Power Management chip with SPI"
+       select MFD_CORE
+       select MFD_TPS65912
+       depends on SPI_MASTER && GPIOLIB
+       help
+         If you say yes here you get support for the TPS65912 series of
+         PM chips with SPI interface.
+
 config MENELAUS
        bool "Texas Instruments TWL92330/Menelaus PM chip"
        depends on I2C=y && ARCH_OMAP2
@@ -662,8 +693,9 @@ config MFD_JANZ_CMODIO
          CAN and GPIO controllers.
 
 config MFD_JZ4740_ADC
-       tristate "Support for the JZ4740 SoC ADC core"
+       bool "Support for the JZ4740 SoC ADC core"
        select MFD_CORE
+       select GENERIC_IRQ_CHIP
        depends on MACH_JZ4740
        help
          Say yes here if you want support for the ADC unit in the JZ4740 SoC.
@@ -725,18 +757,19 @@ config MFD_PM8XXX_IRQ
          This is required to use certain other PM 8xxx features, such as GPIO
          and MPP.
 
-config MFD_TPS65910
-       bool "TPS65910 Power Management chip"
-       depends on I2C=y && GPIOLIB
-       select MFD_CORE
-       select GPIO_TPS65910
-       help
-         if you say yes here you get support for the TPS65910 series of
-         Power Management chips.
-
 config TPS65911_COMPARATOR
        tristate
 
+config MFD_AAT2870_CORE
+       bool "Support for the AnalogicTech AAT2870"
+       select MFD_CORE
+       depends on I2C=y && GPIOLIB
+       help
+         If you say yes here you get support for the AAT2870.
+         This driver provides common support for accessing the device,
+         additional drivers must be enabled in order to use the
+         functionality of the device.
+
 endif # MFD_SUPPORT
 
 menu "Multimedia Capabilities Port drivers"
index 22a280f..c580203 100644 (file)
@@ -23,6 +23,7 @@ obj-$(CONFIG_MFD_TC6393XB)    += tc6393xb.o tmio_core.o
 
 obj-$(CONFIG_MFD_WM8400)       += wm8400-core.o
 wm831x-objs                    := wm831x-core.o wm831x-irq.o wm831x-otp.o
+wm831x-objs                    += wm831x-auxadc.o
 obj-$(CONFIG_MFD_WM831X)       += wm831x.o
 obj-$(CONFIG_MFD_WM831X_I2C)   += wm831x-i2c.o
 obj-$(CONFIG_MFD_WM831X_SPI)   += wm831x-spi.o
@@ -35,6 +36,11 @@ obj-$(CONFIG_MFD_WM8994)     += wm8994-core.o wm8994-irq.o
 obj-$(CONFIG_TPS6105X)         += tps6105x.o
 obj-$(CONFIG_TPS65010)         += tps65010.o
 obj-$(CONFIG_TPS6507X)         += tps6507x.o
+obj-$(CONFIG_MFD_TPS65910)     += tps65910.o tps65910-irq.o
+tps65912-objs                   := tps65912-core.o tps65912-irq.o
+obj-$(CONFIG_MFD_TPS65912)     += tps65912.o
+obj-$(CONFIG_MFD_TPS65912_I2C) += tps65912-i2c.o
+obj-$(CONFIG_MFD_TPS65912_SPI)  += tps65912-spi.o
 obj-$(CONFIG_MENELAUS)         += menelaus.o
 
 obj-$(CONFIG_TWL4030_CORE)     += twl-core.o twl4030-irq.o twl6030-irq.o
@@ -94,5 +100,5 @@ obj-$(CONFIG_MFD_CS5535)     += cs5535-mfd.o
 obj-$(CONFIG_MFD_OMAP_USB_HOST)        += omap-usb-host.o
 obj-$(CONFIG_MFD_PM8921_CORE)  += pm8921-core.o
 obj-$(CONFIG_MFD_PM8XXX_IRQ)   += pm8xxx-irq.o
-obj-$(CONFIG_MFD_TPS65910)     += tps65910.o tps65910-irq.o
 obj-$(CONFIG_TPS65911_COMPARATOR)      += tps65911-comparator.o
+obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c
new file mode 100644 (file)
index 0000000..345dc65
--- /dev/null
@@ -0,0 +1,535 @@
+/*
+ * linux/drivers/mfd/aat2870-core.c
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ * Author: Jin Park <jinyoungp@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/aat2870.h>
+#include <linux/regulator/machine.h>
+
+static struct aat2870_register aat2870_regs[AAT2870_REG_NUM] = {
+       /* readable, writeable, value */
+       { 0, 1, 0x00 }, /* 0x00 AAT2870_BL_CH_EN */
+       { 0, 1, 0x16 }, /* 0x01 AAT2870_BLM */
+       { 0, 1, 0x16 }, /* 0x02 AAT2870_BLS */
+       { 0, 1, 0x56 }, /* 0x03 AAT2870_BL1 */
+       { 0, 1, 0x56 }, /* 0x04 AAT2870_BL2 */
+       { 0, 1, 0x56 }, /* 0x05 AAT2870_BL3 */
+       { 0, 1, 0x56 }, /* 0x06 AAT2870_BL4 */
+       { 0, 1, 0x56 }, /* 0x07 AAT2870_BL5 */
+       { 0, 1, 0x56 }, /* 0x08 AAT2870_BL6 */
+       { 0, 1, 0x56 }, /* 0x09 AAT2870_BL7 */
+       { 0, 1, 0x56 }, /* 0x0A AAT2870_BL8 */
+       { 0, 1, 0x00 }, /* 0x0B AAT2870_FLR */
+       { 0, 1, 0x03 }, /* 0x0C AAT2870_FM */
+       { 0, 1, 0x03 }, /* 0x0D AAT2870_FS */
+       { 0, 1, 0x10 }, /* 0x0E AAT2870_ALS_CFG0 */
+       { 0, 1, 0x06 }, /* 0x0F AAT2870_ALS_CFG1 */
+       { 0, 1, 0x00 }, /* 0x10 AAT2870_ALS_CFG2 */
+       { 1, 0, 0x00 }, /* 0x11 AAT2870_AMB */
+       { 0, 1, 0x00 }, /* 0x12 AAT2870_ALS0 */
+       { 0, 1, 0x00 }, /* 0x13 AAT2870_ALS1 */
+       { 0, 1, 0x00 }, /* 0x14 AAT2870_ALS2 */
+       { 0, 1, 0x00 }, /* 0x15 AAT2870_ALS3 */
+       { 0, 1, 0x00 }, /* 0x16 AAT2870_ALS4 */
+       { 0, 1, 0x00 }, /* 0x17 AAT2870_ALS5 */
+       { 0, 1, 0x00 }, /* 0x18 AAT2870_ALS6 */
+       { 0, 1, 0x00 }, /* 0x19 AAT2870_ALS7 */
+       { 0, 1, 0x00 }, /* 0x1A AAT2870_ALS8 */
+       { 0, 1, 0x00 }, /* 0x1B AAT2870_ALS9 */
+       { 0, 1, 0x00 }, /* 0x1C AAT2870_ALSA */
+       { 0, 1, 0x00 }, /* 0x1D AAT2870_ALSB */
+       { 0, 1, 0x00 }, /* 0x1E AAT2870_ALSC */
+       { 0, 1, 0x00 }, /* 0x1F AAT2870_ALSD */
+       { 0, 1, 0x00 }, /* 0x20 AAT2870_ALSE */
+       { 0, 1, 0x00 }, /* 0x21 AAT2870_ALSF */
+       { 0, 1, 0x00 }, /* 0x22 AAT2870_SUB_SET */
+       { 0, 1, 0x00 }, /* 0x23 AAT2870_SUB_CTRL */
+       { 0, 1, 0x00 }, /* 0x24 AAT2870_LDO_AB */
+       { 0, 1, 0x00 }, /* 0x25 AAT2870_LDO_CD */
+       { 0, 1, 0x00 }, /* 0x26 AAT2870_LDO_EN */
+};
+
+static struct mfd_cell aat2870_devs[] = {
+       {
+               .name = "aat2870-backlight",
+               .id = AAT2870_ID_BL,
+               .pdata_size = sizeof(struct aat2870_bl_platform_data),
+       },
+       {
+               .name = "aat2870-regulator",
+               .id = AAT2870_ID_LDOA,
+               .pdata_size = sizeof(struct regulator_init_data),
+       },
+       {
+               .name = "aat2870-regulator",
+               .id = AAT2870_ID_LDOB,
+               .pdata_size = sizeof(struct regulator_init_data),
+       },
+       {
+               .name = "aat2870-regulator",
+               .id = AAT2870_ID_LDOC,
+               .pdata_size = sizeof(struct regulator_init_data),
+       },
+       {
+               .name = "aat2870-regulator",
+               .id = AAT2870_ID_LDOD,
+               .pdata_size = sizeof(struct regulator_init_data),
+       },
+};
+
+static int __aat2870_read(struct aat2870_data *aat2870, u8 addr, u8 *val)
+{
+       int ret;
+
+       if (addr >= AAT2870_REG_NUM) {
+               dev_err(aat2870->dev, "Invalid address, 0x%02x\n", addr);
+               return -EINVAL;
+       }
+
+       if (!aat2870->reg_cache[addr].readable) {
+               *val = aat2870->reg_cache[addr].value;
+               goto out;
+       }
+
+       ret = i2c_master_send(aat2870->client, &addr, 1);
+       if (ret < 0)
+               return ret;
+       if (ret != 1)
+               return -EIO;
+
+       ret = i2c_master_recv(aat2870->client, val, 1);
+       if (ret < 0)
+               return ret;
+       if (ret != 1)
+               return -EIO;
+
+out:
+       dev_dbg(aat2870->dev, "read: addr=0x%02x, val=0x%02x\n", addr, *val);
+       return 0;
+}
+
+static int __aat2870_write(struct aat2870_data *aat2870, u8 addr, u8 val)
+{
+       u8 msg[2];
+       int ret;
+
+       if (addr >= AAT2870_REG_NUM) {
+               dev_err(aat2870->dev, "Invalid address, 0x%02x\n", addr);
+               return -EINVAL;
+       }
+
+       if (!aat2870->reg_cache[addr].writeable) {
+               dev_err(aat2870->dev, "Address 0x%02x is not writeable\n",
+                       addr);
+               return -EINVAL;
+       }
+
+       msg[0] = addr;
+       msg[1] = val;
+       ret = i2c_master_send(aat2870->client, msg, 2);
+       if (ret < 0)
+               return ret;
+       if (ret != 2)
+               return -EIO;
+
+       aat2870->reg_cache[addr].value = val;
+
+       dev_dbg(aat2870->dev, "write: addr=0x%02x, val=0x%02x\n", addr, val);
+       return 0;
+}
+
+static int aat2870_read(struct aat2870_data *aat2870, u8 addr, u8 *val)
+{
+       int ret;
+
+       mutex_lock(&aat2870->io_lock);
+       ret = __aat2870_read(aat2870, addr, val);
+       mutex_unlock(&aat2870->io_lock);
+
+       return ret;
+}
+
+static int aat2870_write(struct aat2870_data *aat2870, u8 addr, u8 val)
+{
+       int ret;
+
+       mutex_lock(&aat2870->io_lock);
+       ret = __aat2870_write(aat2870, addr, val);
+       mutex_unlock(&aat2870->io_lock);
+
+       return ret;
+}
+
+static int aat2870_update(struct aat2870_data *aat2870, u8 addr, u8 mask,
+                         u8 val)
+{
+       int change;
+       u8 old_val, new_val;
+       int ret;
+
+       mutex_lock(&aat2870->io_lock);
+
+       ret = __aat2870_read(aat2870, addr, &old_val);
+       if (ret)
+               goto out_unlock;
+
+       new_val = (old_val & ~mask) | (val & mask);
+       change = old_val != new_val;
+       if (change)
+               ret = __aat2870_write(aat2870, addr, new_val);
+
+out_unlock:
+       mutex_unlock(&aat2870->io_lock);
+
+       return ret;
+}
+
+static inline void aat2870_enable(struct aat2870_data *aat2870)
+{
+       if (aat2870->en_pin >= 0)
+               gpio_set_value(aat2870->en_pin, 1);
+
+       aat2870->is_enable = 1;
+}
+
+static inline void aat2870_disable(struct aat2870_data *aat2870)
+{
+       if (aat2870->en_pin >= 0)
+               gpio_set_value(aat2870->en_pin, 0);
+
+       aat2870->is_enable = 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static ssize_t aat2870_dump_reg(struct aat2870_data *aat2870, char *buf)
+{
+       u8 addr, val;
+       ssize_t count = 0;
+       int ret;
+
+       count += sprintf(buf, "aat2870 registers\n");
+       for (addr = 0; addr < AAT2870_REG_NUM; addr++) {
+               count += sprintf(buf + count, "0x%02x: ", addr);
+               if (count >= PAGE_SIZE - 1)
+                       break;
+
+               ret = aat2870->read(aat2870, addr, &val);
+               if (ret == 0)
+                       count += snprintf(buf + count, PAGE_SIZE - count,
+                                         "0x%02x", val);
+               else
+                       count += snprintf(buf + count, PAGE_SIZE - count,
+                                         "<read fail: %d>", ret);
+
+               if (count >= PAGE_SIZE - 1)
+                       break;
+
+               count += snprintf(buf + count, PAGE_SIZE - count, "\n");
+               if (count >= PAGE_SIZE - 1)
+                       break;
+       }
+
+       /* Truncate count; min() would cause a warning */
+       if (count >= PAGE_SIZE)
+               count = PAGE_SIZE - 1;
+
+       return count;
+}
+
+static int aat2870_reg_open_file(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+
+       return 0;
+}
+
+static ssize_t aat2870_reg_read_file(struct file *file, char __user *user_buf,
+                                    size_t count, loff_t *ppos)
+{
+       struct aat2870_data *aat2870 = file->private_data;
+       char *buf;
+       ssize_t ret;
+
+       buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       ret = aat2870_dump_reg(aat2870, buf);
+       if (ret >= 0)
+               ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+
+       kfree(buf);
+
+       return ret;
+}
+
+static ssize_t aat2870_reg_write_file(struct file *file,
+                                     const char __user *user_buf, size_t count,
+                                     loff_t *ppos)
+{
+       struct aat2870_data *aat2870 = file->private_data;
+       char buf[32];
+       int buf_size;
+       char *start = buf;
+       unsigned long addr, val;
+       int ret;
+
+       buf_size = min(count, (sizeof(buf)-1));
+       if (copy_from_user(buf, user_buf, buf_size)) {
+               dev_err(aat2870->dev, "Failed to copy from user\n");
+               return -EFAULT;
+       }
+       buf[buf_size] = 0;
+
+       while (*start == ' ')
+               start++;
+
+       addr = simple_strtoul(start, &start, 16);
+       if (addr >= AAT2870_REG_NUM) {
+               dev_err(aat2870->dev, "Invalid address, 0x%lx\n", addr);
+               return -EINVAL;
+       }
+
+       while (*start == ' ')
+               start++;
+
+       if (strict_strtoul(start, 16, &val))
+               return -EINVAL;
+
+       ret = aat2870->write(aat2870, (u8)addr, (u8)val);
+       if (ret)
+               return ret;
+
+       return buf_size;
+}
+
+static const struct file_operations aat2870_reg_fops = {
+       .open = aat2870_reg_open_file,
+       .read = aat2870_reg_read_file,
+       .write = aat2870_reg_write_file,
+};
+
+static void aat2870_init_debugfs(struct aat2870_data *aat2870)
+{
+       aat2870->dentry_root = debugfs_create_dir("aat2870", NULL);
+       if (!aat2870->dentry_root) {
+               dev_warn(aat2870->dev,
+                        "Failed to create debugfs root directory\n");
+               return;
+       }
+
+       aat2870->dentry_reg = debugfs_create_file("regs", 0644,
+                                                 aat2870->dentry_root,
+                                                 aat2870, &aat2870_reg_fops);
+       if (!aat2870->dentry_reg)
+               dev_warn(aat2870->dev,
+                        "Failed to create debugfs register file\n");
+}
+
+static void aat2870_uninit_debugfs(struct aat2870_data *aat2870)
+{
+       debugfs_remove_recursive(aat2870->dentry_root);
+}
+#else
+static inline void aat2870_init_debugfs(struct aat2870_data *aat2870)
+{
+}
+
+static inline void aat2870_uninit_debugfs(struct aat2870_data *aat2870)
+{
+}
+#endif /* CONFIG_DEBUG_FS */
+
+static int aat2870_i2c_probe(struct i2c_client *client,
+                            const struct i2c_device_id *id)
+{
+       struct aat2870_platform_data *pdata = client->dev.platform_data;
+       struct aat2870_data *aat2870;
+       int i, j;
+       int ret = 0;
+
+       aat2870 = kzalloc(sizeof(struct aat2870_data), GFP_KERNEL);
+       if (!aat2870) {
+               dev_err(&client->dev,
+                       "Failed to allocate memory for aat2870\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       aat2870->dev = &client->dev;
+       dev_set_drvdata(aat2870->dev, aat2870);
+
+       aat2870->client = client;
+       i2c_set_clientdata(client, aat2870);
+
+       aat2870->reg_cache = aat2870_regs;
+
+       if (pdata->en_pin < 0)
+               aat2870->en_pin = -1;
+       else
+               aat2870->en_pin = pdata->en_pin;
+
+       aat2870->init = pdata->init;
+       aat2870->uninit = pdata->uninit;
+       aat2870->read = aat2870_read;
+       aat2870->write = aat2870_write;
+       aat2870->update = aat2870_update;
+
+       mutex_init(&aat2870->io_lock);
+
+       if (aat2870->init)
+               aat2870->init(aat2870);
+
+       if (aat2870->en_pin >= 0) {
+               ret = gpio_request(aat2870->en_pin, "aat2870-en");
+               if (ret < 0) {
+                       dev_err(&client->dev,
+                               "Failed to request GPIO %d\n", aat2870->en_pin);
+                       goto out_kfree;
+               }
+               gpio_direction_output(aat2870->en_pin, 1);
+       }
+
+       aat2870_enable(aat2870);
+
+       for (i = 0; i < pdata->num_subdevs; i++) {
+               for (j = 0; j < ARRAY_SIZE(aat2870_devs); j++) {
+                       if ((pdata->subdevs[i].id == aat2870_devs[j].id) &&
+                                       !strcmp(pdata->subdevs[i].name,
+                                               aat2870_devs[j].name)) {
+                               aat2870_devs[j].platform_data =
+                                       pdata->subdevs[i].platform_data;
+                               break;
+                       }
+               }
+       }
+
+       ret = mfd_add_devices(aat2870->dev, 0, aat2870_devs,
+                             ARRAY_SIZE(aat2870_devs), NULL, 0);
+       if (ret != 0) {
+               dev_err(aat2870->dev, "Failed to add subdev: %d\n", ret);
+               goto out_disable;
+       }
+
+       aat2870_init_debugfs(aat2870);
+
+       return 0;
+
+out_disable:
+       aat2870_disable(aat2870);
+       if (aat2870->en_pin >= 0)
+               gpio_free(aat2870->en_pin);
+out_kfree:
+       kfree(aat2870);
+out:
+       return ret;
+}
+
+static int aat2870_i2c_remove(struct i2c_client *client)
+{
+       struct aat2870_data *aat2870 = i2c_get_clientdata(client);
+
+       aat2870_uninit_debugfs(aat2870);
+
+       mfd_remove_devices(aat2870->dev);
+       aat2870_disable(aat2870);
+       if (aat2870->en_pin >= 0)
+               gpio_free(aat2870->en_pin);
+       if (aat2870->uninit)
+               aat2870->uninit(aat2870);
+       kfree(aat2870);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int aat2870_i2c_suspend(struct i2c_client *client, pm_message_t state)
+{
+       struct aat2870_data *aat2870 = i2c_get_clientdata(client);
+
+       aat2870_disable(aat2870);
+
+       return 0;
+}
+
+static int aat2870_i2c_resume(struct i2c_client *client)
+{
+       struct aat2870_data *aat2870 = i2c_get_clientdata(client);
+       struct aat2870_register *reg = NULL;
+       int i;
+
+       aat2870_enable(aat2870);
+
+       /* restore registers */
+       for (i = 0; i < AAT2870_REG_NUM; i++) {
+               reg = &aat2870->reg_cache[i];
+               if (reg->writeable)
+                       aat2870->write(aat2870, i, reg->value);
+       }
+
+       return 0;
+}
+#else
+#define aat2870_i2c_suspend    NULL
+#define aat2870_i2c_resume     NULL
+#endif /* CONFIG_PM */
+
+static struct i2c_device_id aat2870_i2c_id_table[] = {
+       { "aat2870", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, aat2870_i2c_id_table);
+
+static struct i2c_driver aat2870_i2c_driver = {
+       .driver = {
+               .name   = "aat2870",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = aat2870_i2c_probe,
+       .remove         = aat2870_i2c_remove,
+       .suspend        = aat2870_i2c_suspend,
+       .resume         = aat2870_i2c_resume,
+       .id_table       = aat2870_i2c_id_table,
+};
+
+static int __init aat2870_init(void)
+{
+       return i2c_add_driver(&aat2870_i2c_driver);
+}
+subsys_initcall(aat2870_init);
+
+static void __exit aat2870_exit(void)
+{
+       i2c_del_driver(&aat2870_i2c_driver);
+}
+module_exit(aat2870_exit);
+
+MODULE_DESCRIPTION("Core support for the AnalogicTech AAT2870");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jin Park <jinyoungp@nvidia.com>");
index 3d7dce6..56ba194 100644 (file)
@@ -879,20 +879,13 @@ static ssize_t ab3550_bank_write(struct file *file,
        size_t count, loff_t *ppos)
 {
        struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private;
-       char buf[32];
-       int buf_size;
        unsigned long user_bank;
        int err;
 
        /* Get userspace string and assure termination */
-       buf_size = min(count, (sizeof(buf) - 1));
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       buf[buf_size] = 0;
-
-       err = strict_strtoul(buf, 0, &user_bank);
+       err = kstrtoul_from_user(user_buf, count, 0, &user_bank);
        if (err)
-               return -EINVAL;
+               return err;
 
        if (user_bank >= AB3550_NUM_BANKS) {
                dev_err(&ab->i2c_client[0]->dev,
@@ -902,7 +895,7 @@ static ssize_t ab3550_bank_write(struct file *file,
 
        ab->debug_bank = user_bank;
 
-       return buf_size;
+       return count;
 }
 
 static int ab3550_address_print(struct seq_file *s, void *p)
@@ -923,27 +916,21 @@ static ssize_t ab3550_address_write(struct file *file,
        size_t count, loff_t *ppos)
 {
        struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private;
-       char buf[32];
-       int buf_size;
        unsigned long user_address;
        int err;
 
        /* Get userspace string and assure termination */
-       buf_size = min(count, (sizeof(buf) - 1));
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       buf[buf_size] = 0;
-
-       err = strict_strtoul(buf, 0, &user_address);
+       err = kstrtoul_from_user(user_buf, count, 0, &user_address);
        if (err)
-               return -EINVAL;
+               return err;
+
        if (user_address > 0xff) {
                dev_err(&ab->i2c_client[0]->dev,
                        "debugfs error input > 0xff\n");
                return -EINVAL;
        }
        ab->debug_address = user_address;
-       return buf_size;
+       return count;
 }
 
 static int ab3550_val_print(struct seq_file *s, void *p)
@@ -971,21 +958,15 @@ static ssize_t ab3550_val_write(struct file *file,
        size_t count, loff_t *ppos)
 {
        struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private;
-       char buf[32];
-       int buf_size;
        unsigned long user_val;
        int err;
        u8 regvalue;
 
        /* Get userspace string and assure termination */
-       buf_size = min(count, (sizeof(buf)-1));
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       buf[buf_size] = 0;
-
-       err = strict_strtoul(buf, 0, &user_val);
+       err = kstrtoul_from_user(user_buf, count, 0, &user_val);
        if (err)
-               return -EINVAL;
+               return err;
+
        if (user_val > 0xff) {
                dev_err(&ab->i2c_client[0]->dev,
                        "debugfs error input > 0xff\n");
@@ -1002,7 +983,7 @@ static ssize_t ab3550_val_write(struct file *file,
        if (err)
                return -EINVAL;
 
-       return buf_size;
+       return count;
 }
 
 static const struct file_operations ab3550_bank_fops = {
index fc0c1af..387705e 100644 (file)
@@ -363,7 +363,7 @@ static void ab8500_irq_remove(struct ab8500 *ab8500)
        }
 }
 
-static struct resource ab8500_gpio_resources[] = {
+static struct resource __devinitdata ab8500_gpio_resources[] = {
        {
                .name   = "GPIO_INT6",
                .start  = AB8500_INT_GPIO6R,
@@ -372,7 +372,7 @@ static struct resource ab8500_gpio_resources[] = {
        }
 };
 
-static struct resource ab8500_gpadc_resources[] = {
+static struct resource __devinitdata ab8500_gpadc_resources[] = {
        {
                .name   = "HW_CONV_END",
                .start  = AB8500_INT_GP_HW_ADC_CONV_END,
@@ -387,7 +387,7 @@ static struct resource ab8500_gpadc_resources[] = {
        },
 };
 
-static struct resource ab8500_rtc_resources[] = {
+static struct resource __devinitdata ab8500_rtc_resources[] = {
        {
                .name   = "60S",
                .start  = AB8500_INT_RTC_60S,
@@ -402,7 +402,7 @@ static struct resource ab8500_rtc_resources[] = {
        },
 };
 
-static struct resource ab8500_poweronkey_db_resources[] = {
+static struct resource __devinitdata ab8500_poweronkey_db_resources[] = {
        {
                .name   = "ONKEY_DBF",
                .start  = AB8500_INT_PON_KEY1DB_F,
@@ -417,19 +417,46 @@ static struct resource ab8500_poweronkey_db_resources[] = {
        },
 };
 
-static struct resource ab8500_bm_resources[] = {
+static struct resource __devinitdata ab8500_av_acc_detect_resources[] = {
        {
-               .name = "MAIN_EXT_CH_NOT_OK",
-               .start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
-               .end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
-               .flags = IORESOURCE_IRQ,
+              .name = "ACC_DETECT_1DB_F",
+              .start = AB8500_INT_ACC_DETECT_1DB_F,
+              .end = AB8500_INT_ACC_DETECT_1DB_F,
+              .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "BATT_OVV",
-               .start = AB8500_INT_BATT_OVV,
-               .end = AB8500_INT_BATT_OVV,
-               .flags = IORESOURCE_IRQ,
+              .name = "ACC_DETECT_1DB_R",
+              .start = AB8500_INT_ACC_DETECT_1DB_R,
+              .end = AB8500_INT_ACC_DETECT_1DB_R,
+              .flags = IORESOURCE_IRQ,
+       },
+       {
+              .name = "ACC_DETECT_21DB_F",
+              .start = AB8500_INT_ACC_DETECT_21DB_F,
+              .end = AB8500_INT_ACC_DETECT_21DB_F,
+              .flags = IORESOURCE_IRQ,
+       },
+       {
+              .name = "ACC_DETECT_21DB_R",
+              .start = AB8500_INT_ACC_DETECT_21DB_R,
+              .end = AB8500_INT_ACC_DETECT_21DB_R,
+              .flags = IORESOURCE_IRQ,
+       },
+       {
+              .name = "ACC_DETECT_22DB_F",
+              .start = AB8500_INT_ACC_DETECT_22DB_F,
+              .end = AB8500_INT_ACC_DETECT_22DB_F,
+              .flags = IORESOURCE_IRQ,
        },
+       {
+              .name = "ACC_DETECT_22DB_R",
+              .start = AB8500_INT_ACC_DETECT_22DB_R,
+              .end = AB8500_INT_ACC_DETECT_22DB_R,
+              .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource __devinitdata ab8500_charger_resources[] = {
        {
                .name = "MAIN_CH_UNPLUG_DET",
                .start = AB8500_INT_MAIN_CH_UNPLUG_DET,
@@ -442,12 +469,6 @@ static struct resource ab8500_bm_resources[] = {
                .end = AB8500_INT_MAIN_CH_PLUG_DET,
                .flags = IORESOURCE_IRQ,
        },
-       {
-               .name = "VBUS_DET_F",
-               .start = AB8500_INT_VBUS_DET_F,
-               .end = AB8500_INT_VBUS_DET_F,
-               .flags = IORESOURCE_IRQ,
-       },
        {
                .name = "VBUS_DET_R",
                .start = AB8500_INT_VBUS_DET_R,
@@ -455,15 +476,21 @@ static struct resource ab8500_bm_resources[] = {
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "BAT_CTRL_INDB",
-               .start = AB8500_INT_BAT_CTRL_INDB,
-               .end = AB8500_INT_BAT_CTRL_INDB,
+               .name = "VBUS_DET_F",
+               .start = AB8500_INT_VBUS_DET_F,
+               .end = AB8500_INT_VBUS_DET_F,
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "CH_WD_EXP",
-               .start = AB8500_INT_CH_WD_EXP,
-               .end = AB8500_INT_CH_WD_EXP,
+               .name = "USB_LINK_STATUS",
+               .start = AB8500_INT_USB_LINK_STATUS,
+               .end = AB8500_INT_USB_LINK_STATUS,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "USB_CHARGE_DET_DONE",
+               .start = AB8500_INT_USB_CHG_DET_DONE,
+               .end = AB8500_INT_USB_CHG_DET_DONE,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -473,21 +500,60 @@ static struct resource ab8500_bm_resources[] = {
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "NCONV_ACCU",
-               .start = AB8500_INT_CCN_CONV_ACC,
-               .end = AB8500_INT_CCN_CONV_ACC,
+               .name = "USB_CH_TH_PROT_R",
+               .start = AB8500_INT_USB_CH_TH_PROT_R,
+               .end = AB8500_INT_USB_CH_TH_PROT_R,
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "LOW_BAT_F",
-               .start = AB8500_INT_LOW_BAT_F,
-               .end = AB8500_INT_LOW_BAT_F,
+               .name = "USB_CH_TH_PROT_F",
+               .start = AB8500_INT_USB_CH_TH_PROT_F,
+               .end = AB8500_INT_USB_CH_TH_PROT_F,
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "LOW_BAT_R",
-               .start = AB8500_INT_LOW_BAT_R,
-               .end = AB8500_INT_LOW_BAT_R,
+               .name = "MAIN_EXT_CH_NOT_OK",
+               .start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
+               .end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "MAIN_CH_TH_PROT_R",
+               .start = AB8500_INT_MAIN_CH_TH_PROT_R,
+               .end = AB8500_INT_MAIN_CH_TH_PROT_R,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "MAIN_CH_TH_PROT_F",
+               .start = AB8500_INT_MAIN_CH_TH_PROT_F,
+               .end = AB8500_INT_MAIN_CH_TH_PROT_F,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "USB_CHARGER_NOT_OKR",
+               .start = AB8500_INT_USB_CHARGER_NOT_OK,
+               .end = AB8500_INT_USB_CHARGER_NOT_OK,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "USB_CHARGER_NOT_OKF",
+               .start = AB8500_INT_USB_CHARGER_NOT_OKF,
+               .end = AB8500_INT_USB_CHARGER_NOT_OKF,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "CH_WD_EXP",
+               .start = AB8500_INT_CH_WD_EXP,
+               .end = AB8500_INT_CH_WD_EXP,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource __devinitdata ab8500_btemp_resources[] = {
+       {
+               .name = "BAT_CTRL_INDB",
+               .start = AB8500_INT_BAT_CTRL_INDB,
+               .end = AB8500_INT_BAT_CTRL_INDB,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -503,38 +569,55 @@ static struct resource ab8500_bm_resources[] = {
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "USB_CHARGER_NOT_OKR",
-               .start = AB8500_INT_USB_CHARGER_NOT_OK,
-               .end = AB8500_INT_USB_CHARGER_NOT_OK,
+               .name = "BTEMP_LOW_MEDIUM",
+               .start = AB8500_INT_BTEMP_LOW_MEDIUM,
+               .end = AB8500_INT_BTEMP_LOW_MEDIUM,
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "USB_CHARGE_DET_DONE",
-               .start = AB8500_INT_USB_CHG_DET_DONE,
-               .end = AB8500_INT_USB_CHG_DET_DONE,
+               .name = "BTEMP_MEDIUM_HIGH",
+               .start = AB8500_INT_BTEMP_MEDIUM_HIGH,
+               .end = AB8500_INT_BTEMP_MEDIUM_HIGH,
                .flags = IORESOURCE_IRQ,
        },
+};
+
+static struct resource __devinitdata ab8500_fg_resources[] = {
        {
-               .name = "USB_CH_TH_PROT_R",
-               .start = AB8500_INT_USB_CH_TH_PROT_R,
-               .end = AB8500_INT_USB_CH_TH_PROT_R,
+               .name = "NCONV_ACCU",
+               .start = AB8500_INT_CCN_CONV_ACC,
+               .end = AB8500_INT_CCN_CONV_ACC,
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "MAIN_CH_TH_PROT_R",
-               .start = AB8500_INT_MAIN_CH_TH_PROT_R,
-               .end = AB8500_INT_MAIN_CH_TH_PROT_R,
+               .name = "BATT_OVV",
+               .start = AB8500_INT_BATT_OVV,
+               .end = AB8500_INT_BATT_OVV,
                .flags = IORESOURCE_IRQ,
        },
        {
-               .name = "USB_CHARGER_NOT_OKF",
-               .start = AB8500_INT_USB_CHARGER_NOT_OKF,
-               .end = AB8500_INT_USB_CHARGER_NOT_OKF,
+               .name = "LOW_BAT_F",
+               .start = AB8500_INT_LOW_BAT_F,
+               .end = AB8500_INT_LOW_BAT_F,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "LOW_BAT_R",
+               .start = AB8500_INT_LOW_BAT_R,
+               .end = AB8500_INT_LOW_BAT_R,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "CC_INT_CALIB",
+               .start = AB8500_INT_CC_INT_CALIB,
+               .end = AB8500_INT_CC_INT_CALIB,
                .flags = IORESOURCE_IRQ,
        },
 };
 
-static struct resource ab8500_debug_resources[] = {
+static struct resource __devinitdata ab8500_chargalg_resources[] = {};
+
+static struct resource __devinitdata ab8500_debug_resources[] = {
        {
                .name   = "IRQ_FIRST",
                .start  = AB8500_INT_MAIN_EXT_CH_NOT_OK,
@@ -549,7 +632,7 @@ static struct resource ab8500_debug_resources[] = {
        },
 };
 
-static struct resource ab8500_usb_resources[] = {
+static struct resource __devinitdata ab8500_usb_resources[] = {
        {
                .name = "ID_WAKEUP_R",
                .start = AB8500_INT_ID_WAKEUP_R,
@@ -580,9 +663,21 @@ static struct resource ab8500_usb_resources[] = {
                .end = AB8500_INT_USB_LINK_STATUS,
                .flags = IORESOURCE_IRQ,
        },
+       {
+               .name = "USB_ADP_PROBE_PLUG",
+               .start = AB8500_INT_ADP_PROBE_PLUG,
+               .end = AB8500_INT_ADP_PROBE_PLUG,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .name = "USB_ADP_PROBE_UNPLUG",
+               .start = AB8500_INT_ADP_PROBE_UNPLUG,
+               .end = AB8500_INT_ADP_PROBE_UNPLUG,
+               .flags = IORESOURCE_IRQ,
+       },
 };
 
-static struct resource ab8500_temp_resources[] = {
+static struct resource __devinitdata ab8500_temp_resources[] = {
        {
                .name  = "AB8500_TEMP_WARM",
                .start = AB8500_INT_TEMP_WARM,
@@ -591,7 +686,7 @@ static struct resource ab8500_temp_resources[] = {
        },
 };
 
-static struct mfd_cell ab8500_devs[] = {
+static struct mfd_cell __devinitdata ab8500_devs[] = {
 #ifdef CONFIG_DEBUG_FS
        {
                .name = "ab8500-debug",
@@ -621,11 +716,33 @@ static struct mfd_cell ab8500_devs[] = {
                .resources = ab8500_rtc_resources,
        },
        {
-               .name = "ab8500-bm",
-               .num_resources = ARRAY_SIZE(ab8500_bm_resources),
-               .resources = ab8500_bm_resources,
+               .name = "ab8500-charger",
+               .num_resources = ARRAY_SIZE(ab8500_charger_resources),
+               .resources = ab8500_charger_resources,
+       },
+       {
+               .name = "ab8500-btemp",
+               .num_resources = ARRAY_SIZE(ab8500_btemp_resources),
+               .resources = ab8500_btemp_resources,
+       },
+       {
+               .name = "ab8500-fg",
+               .num_resources = ARRAY_SIZE(ab8500_fg_resources),
+               .resources = ab8500_fg_resources,
+       },
+       {
+               .name = "ab8500-chargalg",
+               .num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
+               .resources = ab8500_chargalg_resources,
+       },
+       {
+               .name = "ab8500-acc-det",
+               .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
+               .resources = ab8500_av_acc_detect_resources,
+       },
+       {
+               .name = "ab8500-codec",
        },
-       { .name = "ab8500-codec", },
        {
                .name = "ab8500-usb",
                .num_resources = ARRAY_SIZE(ab8500_usb_resources),
index 64748e4..64bdeeb 100644 (file)
@@ -419,20 +419,13 @@ static ssize_t ab8500_bank_write(struct file *file,
        size_t count, loff_t *ppos)
 {
        struct device *dev = ((struct seq_file *)(file->private_data))->private;
-       char buf[32];
-       int buf_size;
        unsigned long user_bank;
        int err;
 
        /* Get userspace string and assure termination */
-       buf_size = min(count, (sizeof(buf) - 1));
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       buf[buf_size] = 0;
-
-       err = strict_strtoul(buf, 0, &user_bank);
+       err = kstrtoul_from_user(user_buf, count, 0, &user_bank);
        if (err)
-               return -EINVAL;
+               return err;
 
        if (user_bank >= AB8500_NUM_BANKS) {
                dev_err(dev, "debugfs error input > number of banks\n");
@@ -441,7 +434,7 @@ static ssize_t ab8500_bank_write(struct file *file,
 
        debug_bank = user_bank;
 
-       return buf_size;
+       return count;
 }
 
 static int ab8500_address_print(struct seq_file *s, void *p)
@@ -459,26 +452,20 @@ static ssize_t ab8500_address_write(struct file *file,
        size_t count, loff_t *ppos)
 {
        struct device *dev = ((struct seq_file *)(file->private_data))->private;
-       char buf[32];
-       int buf_size;
        unsigned long user_address;
        int err;
 
        /* Get userspace string and assure termination */
-       buf_size = min(count, (sizeof(buf) - 1));
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       buf[buf_size] = 0;
-
-       err = strict_strtoul(buf, 0, &user_address);
+       err = kstrtoul_from_user(user_buf, count, 0, &user_address);
        if (err)
-               return -EINVAL;
+               return err;
+
        if (user_address > 0xff) {
                dev_err(dev, "debugfs error input > 0xff\n");
                return -EINVAL;
        }
        debug_address = user_address;
-       return buf_size;
+       return count;
 }
 
 static int ab8500_val_print(struct seq_file *s, void *p)
@@ -509,20 +496,14 @@ static ssize_t ab8500_val_write(struct file *file,
        size_t count, loff_t *ppos)
 {
        struct device *dev = ((struct seq_file *)(file->private_data))->private;
-       char buf[32];
-       int buf_size;
        unsigned long user_val;
        int err;
 
        /* Get userspace string and assure termination */
-       buf_size = min(count, (sizeof(buf)-1));
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       buf[buf_size] = 0;
-
-       err = strict_strtoul(buf, 0, &user_val);
+       err = kstrtoul_from_user(user_buf, count, 0, &user_val);
        if (err)
-               return -EINVAL;
+               return err;
+
        if (user_val > 0xff) {
                dev_err(dev, "debugfs error input > 0xff\n");
                return -EINVAL;
@@ -534,7 +515,7 @@ static ssize_t ab8500_val_write(struct file *file,
                return -EINVAL;
        }
 
-       return buf_size;
+       return count;
 }
 
 static const struct file_operations ab8500_bank_fops = {
index a0bd0cf..21131c7 100644 (file)
@@ -56,7 +56,7 @@ struct jz4740_adc {
        void __iomem *base;
 
        int irq;
-       int irq_base;
+       struct irq_chip_generic *gc;
 
        struct clk *clk;
        atomic_t clk_ref;
@@ -64,63 +64,17 @@ struct jz4740_adc {
        spinlock_t lock;
 };
 
-static inline void jz4740_adc_irq_set_masked(struct jz4740_adc *adc, int irq,
-       bool masked)
-{
-       unsigned long flags;
-       uint8_t val;
-
-       irq -= adc->irq_base;
-
-       spin_lock_irqsave(&adc->lock, flags);
-
-       val = readb(adc->base + JZ_REG_ADC_CTRL);
-       if (masked)
-               val |= BIT(irq);
-       else
-               val &= ~BIT(irq);
-       writeb(val, adc->base + JZ_REG_ADC_CTRL);
-
-       spin_unlock_irqrestore(&adc->lock, flags);
-}
-
-static void jz4740_adc_irq_mask(struct irq_data *data)
-{
-       struct jz4740_adc *adc = irq_data_get_irq_chip_data(data);
-       jz4740_adc_irq_set_masked(adc, data->irq, true);
-}
-
-static void jz4740_adc_irq_unmask(struct irq_data *data)
-{
-       struct jz4740_adc *adc = irq_data_get_irq_chip_data(data);
-       jz4740_adc_irq_set_masked(adc, data->irq, false);
-}
-
-static void jz4740_adc_irq_ack(struct irq_data *data)
-{
-       struct jz4740_adc *adc = irq_data_get_irq_chip_data(data);
-       unsigned int irq = data->irq - adc->irq_base;
-       writeb(BIT(irq), adc->base + JZ_REG_ADC_STATUS);
-}
-
-static struct irq_chip jz4740_adc_irq_chip = {
-       .name = "jz4740-adc",
-       .irq_mask = jz4740_adc_irq_mask,
-       .irq_unmask = jz4740_adc_irq_unmask,
-       .irq_ack = jz4740_adc_irq_ack,
-};
-
 static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-       struct jz4740_adc *adc = irq_desc_get_handler_data(desc);
+       struct irq_chip_generic *gc = irq_desc_get_handler_data(desc);
        uint8_t status;
        unsigned int i;
 
-       status = readb(adc->base + JZ_REG_ADC_STATUS);
+       status = readb(gc->reg_base + JZ_REG_ADC_STATUS);
 
        for (i = 0; i < 5; ++i) {
                if (status & BIT(i))
-                       generic_handle_irq(adc->irq_base + i);
+                       generic_handle_irq(gc->irq_base + i);
        }
 }
 
@@ -249,10 +203,12 @@ const struct mfd_cell jz4740_adc_cells[] = {
 
 static int __devinit jz4740_adc_probe(struct platform_device *pdev)
 {
-       int ret;
+       struct irq_chip_generic *gc;
+       struct irq_chip_type *ct;
        struct jz4740_adc *adc;
        struct resource *mem_base;
-       int irq;
+       int ret;
+       int irq_base;
 
        adc = kmalloc(sizeof(*adc), GFP_KERNEL);
        if (!adc) {
@@ -267,9 +223,9 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev)
                goto err_free;
        }
 
-       adc->irq_base = platform_get_irq(pdev, 1);
-       if (adc->irq_base < 0) {
-               ret = adc->irq_base;
+       irq_base = platform_get_irq(pdev, 1);
+       if (irq_base < 0) {
+               ret = irq_base;
                dev_err(&pdev->dev, "Failed to get irq base: %d\n", ret);
                goto err_free;
        }
@@ -309,20 +265,28 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, adc);
 
-       for (irq = adc->irq_base; irq < adc->irq_base + 5; ++irq) {
-               irq_set_chip_data(irq, adc);
-               irq_set_chip_and_handler(irq, &jz4740_adc_irq_chip,
-                                        handle_level_irq);
-       }
+       gc = irq_alloc_generic_chip("INTC", 1, irq_base, adc->base,
+               handle_level_irq);
+
+       ct = gc->chip_types;
+       ct->regs.mask = JZ_REG_ADC_CTRL;
+       ct->regs.ack = JZ_REG_ADC_STATUS;
+       ct->chip.irq_mask = irq_gc_mask_set_bit;
+       ct->chip.irq_unmask = irq_gc_mask_clr_bit;
+       ct->chip.irq_ack = irq_gc_ack;
+
+       irq_setup_generic_chip(gc, IRQ_MSK(5), 0, 0, IRQ_NOPROBE | IRQ_LEVEL);
+
+       adc->gc = gc;
 
-       irq_set_handler_data(adc->irq, adc);
+       irq_set_handler_data(adc->irq, gc);
        irq_set_chained_handler(adc->irq, jz4740_adc_irq_demux);
 
        writeb(0x00, adc->base + JZ_REG_ADC_ENABLE);
        writeb(0xff, adc->base + JZ_REG_ADC_CTRL);
 
        ret = mfd_add_devices(&pdev->dev, 0, jz4740_adc_cells,
-               ARRAY_SIZE(jz4740_adc_cells), mem_base, adc->irq_base);
+               ARRAY_SIZE(jz4740_adc_cells), mem_base, irq_base);
        if (ret < 0)
                goto err_clk_put;
 
@@ -347,6 +311,8 @@ static int __devexit jz4740_adc_remove(struct platform_device *pdev)
 
        mfd_remove_devices(&pdev->dev);
 
+       irq_remove_generic_chip(adc->gc, IRQ_MSK(5), IRQ_NOPROBE | IRQ_LEVEL, 0);
+       kfree(adc->gc);
        irq_set_handler_data(adc->irq, NULL);
        irq_set_chained_handler(adc->irq, NULL);
 
index ea3f52c..ea1169b 100644 (file)
@@ -37,6 +37,9 @@
 #define GPIOBASE       0x44
 #define GPIO_IO_SIZE   64
 
+#define WDTBASE                0x84
+#define WDT_IO_SIZE    64
+
 static struct resource smbus_sch_resource = {
                .flags = IORESOURCE_IO,
 };
@@ -59,6 +62,18 @@ static struct mfd_cell lpc_sch_cells[] = {
        },
 };
 
+static struct resource wdt_sch_resource = {
+               .flags = IORESOURCE_IO,
+};
+
+static struct mfd_cell tunnelcreek_cells[] = {
+       {
+               .name = "tunnelcreek_wdt",
+               .num_resources = 1,
+               .resources = &wdt_sch_resource,
+       },
+};
+
 static struct pci_device_id lpc_sch_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC) },
@@ -72,6 +87,7 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev,
        unsigned int base_addr_cfg;
        unsigned short base_addr;
        int i;
+       int ret;
 
        pci_read_config_dword(dev, SMBASE, &base_addr_cfg);
        if (!(base_addr_cfg & (1 << 31))) {
@@ -104,8 +120,39 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev,
        for (i=0; i < ARRAY_SIZE(lpc_sch_cells); i++)
                lpc_sch_cells[i].id = id->device;
 
-       return mfd_add_devices(&dev->dev, 0,
+       ret = mfd_add_devices(&dev->dev, 0,
                        lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0);
+       if (ret)
+               goto out_dev;
+
+       if (id->device == PCI_DEVICE_ID_INTEL_ITC_LPC) {
+               pci_read_config_dword(dev, WDTBASE, &base_addr_cfg);
+               if (!(base_addr_cfg & (1 << 31))) {
+                       dev_err(&dev->dev, "Decode of the WDT I/O range disabled\n");
+                       ret = -ENODEV;
+                       goto out_dev;
+               }
+               base_addr = (unsigned short)base_addr_cfg;
+               if (base_addr == 0) {
+                       dev_err(&dev->dev, "I/O space for WDT uninitialized\n");
+                       ret = -ENODEV;
+                       goto out_dev;
+               }
+
+               wdt_sch_resource.start = base_addr;
+               wdt_sch_resource.end = base_addr + WDT_IO_SIZE - 1;
+
+               for (i = 0; i < ARRAY_SIZE(tunnelcreek_cells); i++)
+                       tunnelcreek_cells[i].id = id->device;
+
+               ret = mfd_add_devices(&dev->dev, 0, tunnelcreek_cells,
+                       ARRAY_SIZE(tunnelcreek_cells), NULL, 0);
+       }
+
+       return ret;
+out_dev:
+       mfd_remove_devices(&dev->dev);
+       return ret;
 }
 
 static void __devexit lpc_sch_remove(struct pci_dev *dev)
index 638bf7e..09274cf 100644 (file)
@@ -58,8 +58,6 @@ static struct i2c_client *get_i2c(struct max8997_dev *max8997,
        default:
                return ERR_PTR(-EINVAL);
        }
-
-       return ERR_PTR(-EINVAL);
 }
 
 struct max8997_irq_data {
index 1717144..29601e7 100644 (file)
@@ -998,9 +998,9 @@ static void usbhs_disable(struct device *dev)
 
        if (is_omap_usbhs_rev2(omap)) {
                if (is_ehci_tll_mode(pdata->port_mode[0]))
-                       clk_enable(omap->usbtll_p1_fck);
+                       clk_disable(omap->usbtll_p1_fck);
                if (is_ehci_tll_mode(pdata->port_mode[1]))
-                       clk_enable(omap->usbtll_p2_fck);
+                       clk_disable(omap->usbtll_p2_fck);
                clk_disable(omap->utmi_p2_fck);
                clk_disable(omap->utmi_p1_fck);
        }
index 7ab7746..2963689 100644 (file)
@@ -228,7 +228,7 @@ int stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length,
 EXPORT_SYMBOL_GPL(stmpe_block_write);
 
 /**
- * stmpe_set_altfunc: set the alternate function for STMPE pins
+ * stmpe_set_altfunc()- set the alternate function for STMPE pins
  * @stmpe:     Device to configure
  * @pins:      Bitmask of pins to affect
  * @block:     block to enable alternate functions for
index 0dbdc4e..e4ee389 100644 (file)
@@ -42,6 +42,7 @@ struct stmpe_variant_block {
  * @id_mask:   bits valid in CHIPID register for comparison with id_val
  * @num_gpios: number of GPIOS
  * @af_bits:   number of bits used to specify the alternate function
+ * @regs: variant specific registers.
  * @blocks:    list of blocks present on this device
  * @num_blocks:        number of blocks present on this device
  * @num_irqs:  number of internal IRQs available on this device
index 2229e66..6f5b8cf 100644 (file)
@@ -147,12 +147,11 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
        if (init_data == NULL)
                return -ENOMEM;
 
-       init_data->irq = pmic_plat_data->irq;
-       init_data->irq_base = pmic_plat_data->irq;
-
        tps65910 = kzalloc(sizeof(struct tps65910), GFP_KERNEL);
-       if (tps65910 == NULL)
+       if (tps65910 == NULL) {
+               kfree(init_data);
                return -ENOMEM;
+       }
 
        i2c_set_clientdata(i2c, tps65910);
        tps65910->dev = &i2c->dev;
@@ -168,17 +167,22 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
        if (ret < 0)
                goto err;
 
+       init_data->irq = pmic_plat_data->irq;
+       init_data->irq_base = pmic_plat_data->irq;
+
        tps65910_gpio_init(tps65910, pmic_plat_data->gpio_base);
 
        ret = tps65910_irq_init(tps65910, init_data->irq, init_data);
        if (ret < 0)
                goto err;
 
+       kfree(init_data);
        return ret;
 
 err:
        mfd_remove_devices(tps65910->dev);
        kfree(tps65910);
+       kfree(init_data);
        return ret;
 }
 
@@ -187,6 +191,7 @@ static int tps65910_i2c_remove(struct i2c_client *i2c)
        struct tps65910 *tps65910 = i2c_get_clientdata(i2c);
 
        mfd_remove_devices(tps65910->dev);
+       tps65910_irq_exit(tps65910);
        kfree(tps65910);
 
        return 0;
index 283ac67..e7ff783 100644 (file)
@@ -157,6 +157,8 @@ static __devexit int tps65911_comparator_remove(struct platform_device *pdev)
        struct tps65910 *tps65910;
 
        tps65910 = dev_get_drvdata(pdev->dev.parent);
+       device_remove_file(&pdev->dev, &dev_attr_comp2_threshold);
+       device_remove_file(&pdev->dev, &dev_attr_comp1_threshold);
 
        return 0;
 }
diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c
new file mode 100644 (file)
index 0000000..955bc00
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * tps65912-core.c  --  TI TPS65912x
+ *
+ * Copyright 2011 Texas Instruments Inc.
+ *
+ * Author: Margarita Olaya Cabrera <magi@slimlogic.co.uk>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under  the terms of the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  This driver is based on wm8350 implementation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps65912.h>
+
+static struct mfd_cell tps65912s[] = {
+       {
+               .name = "tps65912-pmic",
+       },
+};
+
+int tps65912_set_bits(struct tps65912 *tps65912, u8 reg, u8 mask)
+{
+       u8 data;
+       int err;
+
+       mutex_lock(&tps65912->io_mutex);
+
+       err = tps65912->read(tps65912, reg, 1, &data);
+       if (err) {
+               dev_err(tps65912->dev, "Read from reg 0x%x failed\n", reg);
+               goto out;
+       }
+
+       data |= mask;
+       err = tps65912->write(tps65912, reg, 1, &data);
+       if (err)
+               dev_err(tps65912->dev, "Write to reg 0x%x failed\n", reg);
+
+out:
+       mutex_unlock(&tps65912->io_mutex);
+       return err;
+}
+EXPORT_SYMBOL_GPL(tps65912_set_bits);
+
+int tps65912_clear_bits(struct tps65912 *tps65912, u8 reg, u8 mask)
+{
+       u8 data;
+       int err;
+
+       mutex_lock(&tps65912->io_mutex);
+       err = tps65912->read(tps65912, reg, 1, &data);
+       if (err) {
+               dev_err(tps65912->dev, "Read from reg 0x%x failed\n", reg);
+               goto out;
+       }
+
+       data &= ~mask;
+       err = tps65912->write(tps65912, reg, 1, &data);
+       if (err)
+               dev_err(tps65912->dev, "Write to reg 0x%x failed\n", reg);
+
+out:
+       mutex_unlock(&tps65912->io_mutex);
+       return err;
+}
+EXPORT_SYMBOL_GPL(tps65912_clear_bits);
+
+static inline int tps65912_read(struct tps65912 *tps65912, u8 reg)
+{
+       u8 val;
+       int err;
+
+       err = tps65912->read(tps65912, reg, 1, &val);
+       if (err < 0)
+               return err;
+
+       return val;
+}
+
+static inline int tps65912_write(struct tps65912 *tps65912, u8 reg, u8 val)
+{
+       return tps65912->write(tps65912, reg, 1, &val);
+}
+
+int tps65912_reg_read(struct tps65912 *tps65912, u8 reg)
+{
+       int data;
+
+       mutex_lock(&tps65912->io_mutex);
+
+       data = tps65912_read(tps65912, reg);
+       if (data < 0)
+               dev_err(tps65912->dev, "Read from reg 0x%x failed\n", reg);
+
+       mutex_unlock(&tps65912->io_mutex);
+       return data;
+}
+EXPORT_SYMBOL_GPL(tps65912_reg_read);
+
+int tps65912_reg_write(struct tps65912 *tps65912, u8 reg, u8 val)
+{
+       int err;
+
+       mutex_lock(&tps65912->io_mutex);
+
+       err = tps65912_write(tps65912, reg, val);
+       if (err < 0)
+               dev_err(tps65912->dev, "Write for reg 0x%x failed\n", reg);
+
+       mutex_unlock(&tps65912->io_mutex);
+       return err;
+}
+EXPORT_SYMBOL_GPL(tps65912_reg_write);
+
+int tps65912_device_init(struct tps65912 *tps65912)
+{
+       struct tps65912_board *pmic_plat_data = tps65912->dev->platform_data;
+       struct tps65912_platform_data *init_data;
+       int ret, dcdc_avs, value;
+
+       init_data = kzalloc(sizeof(struct tps65912_platform_data), GFP_KERNEL);
+       if (init_data == NULL)
+               return -ENOMEM;
+
+       init_data->irq = pmic_plat_data->irq;
+       init_data->irq_base = pmic_plat_data->irq;
+
+       mutex_init(&tps65912->io_mutex);
+       dev_set_drvdata(tps65912->dev, tps65912);
+
+       dcdc_avs = (pmic_plat_data->is_dcdc1_avs << 0 |
+                       pmic_plat_data->is_dcdc2_avs  << 1 |
+                               pmic_plat_data->is_dcdc3_avs << 2 |
+                                       pmic_plat_data->is_dcdc4_avs << 3);
+       if (dcdc_avs) {
+               tps65912->read(tps65912, TPS65912_I2C_SPI_CFG, 1, &value);
+               dcdc_avs |= value;
+               tps65912->write(tps65912, TPS65912_I2C_SPI_CFG, 1, &dcdc_avs);
+       }
+
+       ret = mfd_add_devices(tps65912->dev, -1,
+                             tps65912s, ARRAY_SIZE(tps65912s),
+                             NULL, 0);
+       if (ret < 0)
+               goto err;
+
+       ret = tps65912_irq_init(tps65912, init_data->irq, init_data);
+       if (ret < 0)
+               goto err;
+
+       return ret;
+
+err:
+       kfree(init_data);
+       mfd_remove_devices(tps65912->dev);
+       kfree(tps65912);
+       return ret;
+}
+
+void tps65912_device_exit(struct tps65912 *tps65912)
+{
+       mfd_remove_devices(tps65912->dev);
+       kfree(tps65912);
+}
+
+MODULE_AUTHOR("Margarita Olaya <magi@slimlogic.co.uk>");
+MODULE_DESCRIPTION("TPS65912x chip family multi-function driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/tps65912-i2c.c b/drivers/mfd/tps65912-i2c.c
new file mode 100644 (file)
index 0000000..c041f2c
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * tps65912-i2c.c  --  I2C access for TI TPS65912x PMIC
+ *
+ * Copyright 2011 Texas Instruments Inc.
+ *
+ * Author: Margarita Olaya Cabrera <magi@slimlogic.co.uk>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under  the terms of the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  This driver is based on wm8350 implementation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps65912.h>
+
+static int tps65912_i2c_read(struct tps65912 *tps65912, u8 reg,
+                                 int bytes, void *dest)
+{
+       struct i2c_client *i2c = tps65912->control_data;
+       struct i2c_msg xfer[2];
+       int ret;
+
+       /* Write register */
+       xfer[0].addr = i2c->addr;
+       xfer[0].flags = 0;
+       xfer[0].len = 1;
+       xfer[0].buf = &reg;
+
+       /* Read data */
+       xfer[1].addr = i2c->addr;
+       xfer[1].flags = I2C_M_RD;
+       xfer[1].len = bytes;
+       xfer[1].buf = dest;
+
+       ret = i2c_transfer(i2c->adapter, xfer, 2);
+       if (ret == 2)
+               ret = 0;
+       else if (ret >= 0)
+               ret = -EIO;
+       return ret;
+}
+
+static int tps65912_i2c_write(struct tps65912 *tps65912, u8 reg,
+                                  int bytes, void *src)
+{
+       struct i2c_client *i2c = tps65912->control_data;
+       /* we add 1 byte for device register */
+       u8 msg[TPS6591X_MAX_REGISTER + 1];
+       int ret;
+
+       if (bytes > TPS6591X_MAX_REGISTER)
+               return -EINVAL;
+
+       msg[0] = reg;
+       memcpy(&msg[1], src, bytes);
+
+       ret = i2c_master_send(i2c, msg, bytes + 1);
+       if (ret < 0)
+               return ret;
+       if (ret != bytes + 1)
+               return -EIO;
+
+       return 0;
+}
+
+static int tps65912_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
+{
+       struct tps65912 *tps65912;
+
+       tps65912 = kzalloc(sizeof(struct tps65912), GFP_KERNEL);
+       if (tps65912 == NULL)
+               return -ENOMEM;
+
+       i2c_set_clientdata(i2c, tps65912);
+       tps65912->dev = &i2c->dev;
+       tps65912->control_data = i2c;
+       tps65912->read = tps65912_i2c_read;
+       tps65912->write = tps65912_i2c_write;
+
+       return tps65912_device_init(tps65912);
+}
+
+static int tps65912_i2c_remove(struct i2c_client *i2c)
+{
+       struct tps65912 *tps65912 = i2c_get_clientdata(i2c);
+
+       tps65912_device_exit(tps65912);
+
+       return 0;
+}
+
+static const struct i2c_device_id tps65912_i2c_id[] = {
+       {"tps65912", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, tps65912_i2c_id);
+
+static struct i2c_driver tps65912_i2c_driver = {
+       .driver = {
+                  .name = "tps65912",
+                  .owner = THIS_MODULE,
+       },
+       .probe = tps65912_i2c_probe,
+       .remove = tps65912_i2c_remove,
+       .id_table = tps65912_i2c_id,
+};
+
+static int __init tps65912_i2c_init(void)
+{
+       int ret;
+
+       ret = i2c_add_driver(&tps65912_i2c_driver);
+       if (ret != 0)
+               pr_err("Failed to register TPS65912 I2C driver: %d\n", ret);
+
+       return ret;
+}
+/* init early so consumer devices can complete system boot */
+subsys_initcall(tps65912_i2c_init);
+
+static void __exit tps65912_i2c_exit(void)
+{
+       i2c_del_driver(&tps65912_i2c_driver);
+}
+module_exit(tps65912_i2c_exit);
+
+MODULE_AUTHOR("Margarita Olaya <magi@slimlogic.co.uk>");
+MODULE_DESCRIPTION("TPS6591x chip family multi-function driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/tps65912-irq.c b/drivers/mfd/tps65912-irq.c
new file mode 100644 (file)
index 0000000..d360a83
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * tps65912-irq.c  --  TI TPS6591x
+ *
+ * Copyright 2011 Texas Instruments Inc.
+ *
+ * Author: Margarita Olaya <magi@slimlogic.co.uk>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under  the terms of the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ * This driver is based on wm8350 implementation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/bug.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/mfd/tps65912.h>
+
+static inline int irq_to_tps65912_irq(struct tps65912 *tps65912,
+                                                       int irq)
+{
+       return irq - tps65912->irq_base;
+}
+
+/*
+ * This is a threaded IRQ handler so can access I2C/SPI.  Since the
+ * IRQ handler explicitly clears the IRQ it handles the IRQ line
+ * will be reasserted and the physical IRQ will be handled again if
+ * another interrupt is asserted while we run - in the normal course
+ * of events this is a rare occurrence so we save I2C/SPI reads. We're
+ * also assuming that it's rare to get lots of interrupts firing
+ * simultaneously so try to minimise I/O.
+ */
+static irqreturn_t tps65912_irq(int irq, void *irq_data)
+{
+       struct tps65912 *tps65912 = irq_data;
+       u32 irq_sts;
+       u32 irq_mask;
+       u8 reg;
+       int i;
+
+
+       tps65912->read(tps65912, TPS65912_INT_STS, 1, &reg);
+       irq_sts = reg;
+       tps65912->read(tps65912, TPS65912_INT_STS2, 1, &reg);
+       irq_sts |= reg << 8;
+       tps65912->read(tps65912, TPS65912_INT_STS3, 1, &reg);
+       irq_sts |= reg << 16;
+       tps65912->read(tps65912, TPS65912_INT_STS4, 1, &reg);
+       irq_sts |= reg << 24;
+
+       tps65912->read(tps65912, TPS65912_INT_MSK, 1, &reg);
+       irq_mask = reg;
+       tps65912->read(tps65912, TPS65912_INT_MSK2, 1, &reg);
+       irq_mask |= reg << 8;
+       tps65912->read(tps65912, TPS65912_INT_MSK3, 1, &reg);
+       irq_mask |= reg << 16;
+       tps65912->read(tps65912, TPS65912_INT_MSK4, 1, &reg);
+       irq_mask |= reg << 24;
+
+       irq_sts &= ~irq_mask;
+       if (!irq_sts)
+               return IRQ_NONE;
+
+       for (i = 0; i < tps65912->irq_num; i++) {
+               if (!(irq_sts & (1 << i)))
+                       continue;
+
+               handle_nested_irq(tps65912->irq_base + i);
+       }
+
+       /* Write the STS register back to clear IRQs we handled */
+       reg = irq_sts & 0xFF;
+       irq_sts >>= 8;
+       if (reg)
+               tps65912->write(tps65912, TPS65912_INT_STS, 1, &reg);
+       reg = irq_sts & 0xFF;
+       irq_sts >>= 8;
+       if (reg)
+               tps65912->write(tps65912, TPS65912_INT_STS2, 1, &reg);
+       reg = irq_sts & 0xFF;
+       irq_sts >>= 8;
+       if (reg)
+               tps65912->write(tps65912, TPS65912_INT_STS3, 1, &reg);
+       reg = irq_sts & 0xFF;
+       if (reg)
+               tps65912->write(tps65912, TPS65912_INT_STS4, 1, &reg);
+
+       return IRQ_HANDLED;
+}
+
+static void tps65912_irq_lock(struct irq_data *data)
+{
+       struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data);
+
+       mutex_lock(&tps65912->irq_lock);
+}
+
+static void tps65912_irq_sync_unlock(struct irq_data *data)
+{
+       struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data);
+       u32 reg_mask;
+       u8 reg;
+
+       tps65912->read(tps65912, TPS65912_INT_MSK, 1, &reg);
+       reg_mask = reg;
+       tps65912->read(tps65912, TPS65912_INT_MSK2, 1, &reg);
+       reg_mask |= reg << 8;
+       tps65912->read(tps65912, TPS65912_INT_MSK3, 1, &reg);
+       reg_mask |= reg << 16;
+       tps65912->read(tps65912, TPS65912_INT_MSK4, 1, &reg);
+       reg_mask |= reg << 24;
+
+       if (tps65912->irq_mask != reg_mask) {
+               reg = tps65912->irq_mask & 0xFF;
+               tps65912->write(tps65912, TPS65912_INT_MSK, 1, &reg);
+               reg = tps65912->irq_mask >> 8 & 0xFF;
+               tps65912->write(tps65912, TPS65912_INT_MSK2, 1, &reg);
+               reg = tps65912->irq_mask >> 16 & 0xFF;
+               tps65912->write(tps65912, TPS65912_INT_MSK3, 1, &reg);
+               reg = tps65912->irq_mask >> 24 & 0xFF;
+               tps65912->write(tps65912, TPS65912_INT_MSK4, 1, &reg);
+       }
+
+       mutex_unlock(&tps65912->irq_lock);
+}
+
+static void tps65912_irq_enable(struct irq_data *data)
+{
+       struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data);
+
+       tps65912->irq_mask &= ~(1 << irq_to_tps65912_irq(tps65912, data->irq));
+}
+
+static void tps65912_irq_disable(struct irq_data *data)
+{
+       struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data);
+
+       tps65912->irq_mask |= (1 << irq_to_tps65912_irq(tps65912, data->irq));
+}
+
+static struct irq_chip tps65912_irq_chip = {
+       .name = "tps65912",
+       .irq_bus_lock = tps65912_irq_lock,
+       .irq_bus_sync_unlock = tps65912_irq_sync_unlock,
+       .irq_disable = tps65912_irq_disable,
+       .irq_enable = tps65912_irq_enable,
+};
+
+int tps65912_irq_init(struct tps65912 *tps65912, int irq,
+                           struct tps65912_platform_data *pdata)
+{
+       int ret, cur_irq;
+       int flags = IRQF_ONESHOT;
+       u8 reg;
+
+       if (!irq) {
+               dev_warn(tps65912->dev, "No interrupt support, no core IRQ\n");
+               return 0;
+       }
+
+       if (!pdata || !pdata->irq_base) {
+               dev_warn(tps65912->dev, "No interrupt support, no IRQ base\n");
+               return 0;
+       }
+
+       /* Clear unattended interrupts */
+       tps65912->read(tps65912, TPS65912_INT_STS, 1, &reg);
+       tps65912->write(tps65912, TPS65912_INT_STS, 1, &reg);
+       tps65912->read(tps65912, TPS65912_INT_STS2, 1, &reg);
+       tps65912->write(tps65912, TPS65912_INT_STS2, 1, &reg);
+       tps65912->read(tps65912, TPS65912_INT_STS3, 1, &reg);
+       tps65912->write(tps65912, TPS65912_INT_STS3, 1, &reg);
+       tps65912->read(tps65912, TPS65912_INT_STS4, 1, &reg);
+       tps65912->write(tps65912, TPS65912_INT_STS4, 1, &reg);
+
+       /* Mask top level interrupts */
+       tps65912->irq_mask = 0xFFFFFFFF;
+
+       mutex_init(&tps65912->irq_lock);
+       tps65912->chip_irq = irq;
+       tps65912->irq_base = pdata->irq_base;
+
+       tps65912->irq_num = TPS65912_NUM_IRQ;
+
+       /* Register with genirq */
+       for (cur_irq = tps65912->irq_base;
+            cur_irq < tps65912->irq_num + tps65912->irq_base;
+            cur_irq++) {
+               irq_set_chip_data(cur_irq, tps65912);
+               irq_set_chip_and_handler(cur_irq, &tps65912_irq_chip,
+                                        handle_edge_irq);
+               irq_set_nested_thread(cur_irq, 1);
+               /* ARM needs us to explicitly flag the IRQ as valid
+                * and will set them noprobe when we do so. */
+#ifdef CONFIG_ARM
+               set_irq_flags(cur_irq, IRQF_VALID);
+#else
+               irq_set_noprobe(cur_irq);
+#endif
+       }
+
+       ret = request_threaded_irq(irq, NULL, tps65912_irq, flags,
+                                  "tps65912", tps65912);
+
+       irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);
+       if (ret != 0)
+               dev_err(tps65912->dev, "Failed to request IRQ: %d\n", ret);
+
+       return ret;
+}
+
+int tps65912_irq_exit(struct tps65912 *tps65912)
+{
+       free_irq(tps65912->chip_irq, tps65912);
+       return 0;
+}
diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c
new file mode 100644 (file)
index 0000000..6d71e0d
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * tps65912-spi.c  --  SPI access for TI TPS65912x PMIC
+ *
+ * Copyright 2011 Texas Instruments Inc.
+ *
+ * Author: Margarita Olaya Cabrera <magi@slimlogic.co.uk>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under  the terms of the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  This driver is based on wm8350 implementation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps65912.h>
+
+static int tps65912_spi_write(struct tps65912 *tps65912, u8 addr,
+                                                       int bytes, void *src)
+{
+       struct spi_device *spi = tps65912->control_data;
+       u8 *data = (u8 *) src;
+       int ret;
+       /* bit 23 is the read/write bit */
+       unsigned long spi_data = 1 << 23 | addr << 15 | *data;
+       struct spi_transfer xfer;
+       struct spi_message msg;
+       u32 tx_buf, rx_buf;
+
+       tx_buf = spi_data;
+       rx_buf = 0;
+
+       xfer.tx_buf     = &tx_buf;
+       xfer.rx_buf     = NULL;
+       xfer.len        = sizeof(unsigned long);
+       xfer.bits_per_word = 24;
+
+       spi_message_init(&msg);
+       spi_message_add_tail(&xfer, &msg);
+
+       ret = spi_sync(spi, &msg);
+       return ret;
+}
+
+static int tps65912_spi_read(struct tps65912 *tps65912, u8 addr,
+                                                       int bytes, void *dest)
+{
+       struct spi_device *spi = tps65912->control_data;
+       /* bit 23 is the read/write bit */
+       unsigned long spi_data = 0 << 23 | addr << 15;
+       struct spi_transfer xfer;
+       struct spi_message msg;
+       int ret;
+       u8 *data = (u8 *) dest;
+       u32 tx_buf, rx_buf;
+
+       tx_buf = spi_data;
+       rx_buf = 0;
+
+       xfer.tx_buf     = &tx_buf;
+       xfer.rx_buf     = &rx_buf;
+       xfer.len        = sizeof(unsigned long);
+       xfer.bits_per_word = 24;
+
+       spi_message_init(&msg);
+       spi_message_add_tail(&xfer, &msg);
+
+       if (spi == NULL)
+               return 0;
+
+       ret = spi_sync(spi, &msg);
+       if (ret == 0)
+               *data = (u8) (rx_buf & 0xFF);
+       return ret;
+}
+
+static int __devinit tps65912_spi_probe(struct spi_device *spi)
+{
+       struct tps65912 *tps65912;
+
+       tps65912 = kzalloc(sizeof(struct tps65912), GFP_KERNEL);
+       if (tps65912 == NULL)
+               return -ENOMEM;
+
+       tps65912->dev = &spi->dev;
+       tps65912->control_data = spi;
+       tps65912->read = tps65912_spi_read;
+       tps65912->write = tps65912_spi_write;
+
+       spi_set_drvdata(spi, tps65912);
+
+       return tps65912_device_init(tps65912);
+}
+
+static int __devexit tps65912_spi_remove(struct spi_device *spi)
+{
+       struct tps65912 *tps65912 = spi_get_drvdata(spi);
+
+       tps65912_device_exit(tps65912);
+
+       return 0;
+}
+
+static struct spi_driver tps65912_spi_driver = {
+       .driver = {
+               .name = "tps65912",
+               .bus = &spi_bus_type,
+               .owner = THIS_MODULE,
+       },
+       .probe  = tps65912_spi_probe,
+       .remove = __devexit_p(tps65912_spi_remove),
+};
+
+static int __init tps65912_spi_init(void)
+{
+       int ret;
+
+       ret = spi_register_driver(&tps65912_spi_driver);
+       if (ret != 0)
+               pr_err("Failed to register TPS65912 SPI driver: %d\n", ret);
+
+       return 0;
+}
+/* init early so consumer devices can complete system boot */
+subsys_initcall(tps65912_spi_init);
+
+static void __exit tps65912_spi_exit(void)
+{
+       spi_unregister_driver(&tps65912_spi_driver);
+}
+module_exit(tps65912_spi_exit);
+
+MODULE_AUTHOR("Margarita Olaya <magi@slimlogic.co.uk>");
+MODULE_DESCRIPTION("SPI support for TPS65912 chip family mfd");
+MODULE_LICENSE("GPL");
index a2eddc7..01ecfee 100644 (file)
@@ -1283,6 +1283,8 @@ static const struct i2c_device_id twl_ids[] = {
        { "tps65950", 0 },              /* catalog version of twl5030 */
        { "tps65930", TPS_SUBSET },     /* fewer LDOs and DACs; no charger */
        { "tps65920", TPS_SUBSET },     /* fewer LDOs; no codec or charger */
+       { "tps65921", TPS_SUBSET },     /* fewer LDOs; no codec, no LED
+                                          and vibrator. Charger in USB module*/
        { "twl6030", TWL6030_CLASS },   /* "Phoenix power chip" */
        { "twl6025", TWL6030_CLASS | TWL6025_SUBCLASS }, /* "Phoenix lite" */
        { /* end of list */ },
index 3941ddc..b5d598c 100644 (file)
@@ -530,13 +530,13 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req)
        if (ret) {
                dev_err(twl4030_madc->dev,
                        "unable to write sel register 0x%X\n", method->sel + 1);
-               return ret;
+               goto out;
        }
        ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_lsb, method->sel);
        if (ret) {
                dev_err(twl4030_madc->dev,
                        "unable to write sel register 0x%X\n", method->sel + 1);
-               return ret;
+               goto out;
        }
        /* Select averaging for all channels if do_avg is set */
        if (req->do_avg) {
@@ -546,7 +546,7 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req)
                        dev_err(twl4030_madc->dev,
                                "unable to write avg register 0x%X\n",
                                method->avg + 1);
-                       return ret;
+                       goto out;
                }
                ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
                                       ch_lsb, method->avg);
@@ -554,7 +554,7 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req)
                        dev_err(twl4030_madc->dev,
                                "unable to write sel reg 0x%X\n",
                                method->sel + 1);
-                       return ret;
+                       goto out;
                }
        }
        if (req->type == TWL4030_MADC_IRQ_ONESHOT && req->func_cb != NULL) {
index 5d25bdc..e8fee14 100644 (file)
@@ -161,3 +161,5 @@ void pwm_free(struct pwm_device *pwm)
        kfree(pwm);
 }
 EXPORT_SYMBOL(pwm_free);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/wm831x-auxadc.c b/drivers/mfd/wm831x-auxadc.c
new file mode 100644 (file)
index 0000000..8721095
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * wm831x-auxadc.c  --  AUXADC for Wolfson WM831x PMICs
+ *
+ * Copyright 2009-2011 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/mfd/core.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+
+#include <linux/mfd/wm831x/core.h>
+#include <linux/mfd/wm831x/pdata.h>
+#include <linux/mfd/wm831x/irq.h>
+#include <linux/mfd/wm831x/auxadc.h>
+#include <linux/mfd/wm831x/otp.h>
+#include <linux/mfd/wm831x/regulator.h>
+
+struct wm831x_auxadc_req {
+       struct list_head list;
+       enum wm831x_auxadc input;
+       int val;
+       struct completion done;
+};
+
+static int wm831x_auxadc_read_irq(struct wm831x *wm831x,
+                                 enum wm831x_auxadc input)
+{
+       struct wm831x_auxadc_req *req;
+       int ret;
+       bool ena = false;
+
+       req = kzalloc(sizeof(*req), GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
+
+       init_completion(&req->done);
+       req->input = input;
+       req->val = -ETIMEDOUT;
+
+       mutex_lock(&wm831x->auxadc_lock);
+
+       /* Enqueue the request */
+       list_add(&req->list, &wm831x->auxadc_pending);
+
+       ena = !wm831x->auxadc_active;
+
+       if (ena) {
+               ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
+                                     WM831X_AUX_ENA, WM831X_AUX_ENA);
+               if (ret != 0) {
+                       dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n",
+                               ret);
+                       goto out;
+               }
+       }
+
+       /* Enable the conversion if not already running */
+       if (!(wm831x->auxadc_active & (1 << input))) {
+               ret = wm831x_set_bits(wm831x, WM831X_AUXADC_SOURCE,
+                                     1 << input, 1 << input);
+               if (ret != 0) {
+                       dev_err(wm831x->dev,
+                               "Failed to set AUXADC source: %d\n", ret);
+                       goto out;
+               }
+
+               wm831x->auxadc_active |= 1 << input;
+       }
+
+       /* We convert at the fastest rate possible */
+       if (ena) {
+               ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
+                                     WM831X_AUX_CVT_ENA |
+                                     WM831X_AUX_RATE_MASK,
+                                     WM831X_AUX_CVT_ENA |
+                                     WM831X_AUX_RATE_MASK);
+               if (ret != 0) {
+                       dev_err(wm831x->dev, "Failed to start AUXADC: %d\n",
+                               ret);
+                       goto out;
+               }
+       }
+
+       mutex_unlock(&wm831x->auxadc_lock);
+
+       /* Wait for an interrupt */
+       wait_for_completion_timeout(&req->done, msecs_to_jiffies(500));
+
+       mutex_lock(&wm831x->auxadc_lock);
+
+       list_del(&req->list);
+       ret = req->val;
+
+out:
+       mutex_unlock(&wm831x->auxadc_lock);
+
+       kfree(req);
+
+       return ret;
+}
+
+static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data)
+{
+       struct wm831x *wm831x = irq_data;
+       struct wm831x_auxadc_req *req;
+       int ret, input, val;
+
+       ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);
+       if (ret < 0) {
+               dev_err(wm831x->dev,
+                       "Failed to read AUXADC data: %d\n", ret);
+               return IRQ_NONE;
+       }
+
+       input = ((ret & WM831X_AUX_DATA_SRC_MASK)
+                >> WM831X_AUX_DATA_SRC_SHIFT) - 1;
+
+       if (input == 14)
+               input = WM831X_AUX_CAL;
+
+       val = ret & WM831X_AUX_DATA_MASK;
+
+       mutex_lock(&wm831x->auxadc_lock);
+
+       /* Disable this conversion, we're about to complete all users */
+       wm831x_set_bits(wm831x, WM831X_AUXADC_SOURCE,
+                       1 << input, 0);
+       wm831x->auxadc_active &= ~(1 << input);
+
+       /* Turn off the entire convertor if idle */
+       if (!wm831x->auxadc_active)
+               wm831x_reg_write(wm831x, WM831X_AUXADC_CONTROL, 0);
+
+       /* Wake up any threads waiting for this request */
+       list_for_each_entry(req, &wm831x->auxadc_pending, list) {
+               if (req->input == input) {
+                       req->val = val;
+                       complete(&req->done);
+               }
+       }
+
+       mutex_unlock(&wm831x->auxadc_lock);
+
+       return IRQ_HANDLED;
+}
+
+static int wm831x_auxadc_read_polled(struct wm831x *wm831x,
+                                    enum wm831x_auxadc input)
+{
+       int ret, src, timeout;
+
+       mutex_lock(&wm831x->auxadc_lock);
+
+       ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
+                             WM831X_AUX_ENA, WM831X_AUX_ENA);
+       if (ret < 0) {
+               dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n", ret);
+               goto out;
+       }
+
+       /* We force a single source at present */
+       src = input;
+       ret = wm831x_reg_write(wm831x, WM831X_AUXADC_SOURCE,
+                              1 << src);
+       if (ret < 0) {
+               dev_err(wm831x->dev, "Failed to set AUXADC source: %d\n", ret);
+               goto out;
+       }
+
+       ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
+                             WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA);
+       if (ret < 0) {
+               dev_err(wm831x->dev, "Failed to start AUXADC: %d\n", ret);
+               goto disable;
+       }
+
+       /* If we're not using interrupts then poll the
+        * interrupt status register */
+       timeout = 5;
+       while (timeout) {
+               msleep(1);
+
+               ret = wm831x_reg_read(wm831x,
+                                     WM831X_INTERRUPT_STATUS_1);
+               if (ret < 0) {
+                       dev_err(wm831x->dev,
+                               "ISR 1 read failed: %d\n", ret);
+                       goto disable;
+               }
+
+               /* Did it complete? */
+               if (ret & WM831X_AUXADC_DATA_EINT) {
+                       wm831x_reg_write(wm831x,
+                                        WM831X_INTERRUPT_STATUS_1,
+                                        WM831X_AUXADC_DATA_EINT);
+                       break;
+               } else {
+                       dev_err(wm831x->dev,
+                               "AUXADC conversion timeout\n");
+                       ret = -EBUSY;
+                       goto disable;
+               }
+       }
+
+       ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);
+       if (ret < 0) {
+               dev_err(wm831x->dev,
+                       "Failed to read AUXADC data: %d\n", ret);
+               goto disable;
+       }
+
+       src = ((ret & WM831X_AUX_DATA_SRC_MASK)
+              >> WM831X_AUX_DATA_SRC_SHIFT) - 1;
+
+       if (src == 14)
+               src = WM831X_AUX_CAL;
+
+       if (src != input) {
+               dev_err(wm831x->dev, "Data from source %d not %d\n",
+                       src, input);
+               ret = -EINVAL;
+       } else {
+               ret &= WM831X_AUX_DATA_MASK;
+       }
+
+disable:
+       wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, WM831X_AUX_ENA, 0);
+out:
+       mutex_unlock(&wm831x->auxadc_lock);
+       return ret;
+}
+
+/**
+ * wm831x_auxadc_read: Read a value from the WM831x AUXADC
+ *
+ * @wm831x: Device to read from.
+ * @input: AUXADC input to read.
+ */
+int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
+{
+       return wm831x->auxadc_read(wm831x, input);
+}
+EXPORT_SYMBOL_GPL(wm831x_auxadc_read);
+
+/**
+ * wm831x_auxadc_read_uv: Read a voltage from the WM831x AUXADC
+ *
+ * @wm831x: Device to read from.
+ * @input: AUXADC input to read.
+ */
+int wm831x_auxadc_read_uv(struct wm831x *wm831x, enum wm831x_auxadc input)
+{
+       int ret;
+
+       ret = wm831x_auxadc_read(wm831x, input);
+       if (ret < 0)
+               return ret;
+
+       ret *= 1465;
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wm831x_auxadc_read_uv);
+
+void wm831x_auxadc_init(struct wm831x *wm831x)
+{
+       int ret;
+
+       mutex_init(&wm831x->auxadc_lock);
+       INIT_LIST_HEAD(&wm831x->auxadc_pending);
+
+       if (wm831x->irq && wm831x->irq_base) {
+               wm831x->auxadc_read = wm831x_auxadc_read_irq;
+
+               ret = request_threaded_irq(wm831x->irq_base +
+                                          WM831X_IRQ_AUXADC_DATA,
+                                          NULL, wm831x_auxadc_irq, 0,
+                                          "auxadc", wm831x);
+               if (ret < 0) {
+                       dev_err(wm831x->dev, "AUXADC IRQ request failed: %d\n",
+                               ret);
+                       wm831x->auxadc_read = NULL;
+               }
+       }
+
+       if (!wm831x->auxadc_read)
+               wm831x->auxadc_read = wm831x_auxadc_read_polled;
+}
index 265f75f..282e76a 100644 (file)
@@ -295,7 +295,7 @@ int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg,
                goto out;
 
        r &= ~mask;
-       r |= val;
+       r |= val & mask;
 
        ret = wm831x_write(wm831x, reg, 2, &r);
 
@@ -306,146 +306,6 @@ out:
 }
 EXPORT_SYMBOL_GPL(wm831x_set_bits);
 
-/**
- * wm831x_auxadc_read: Read a value from the WM831x AUXADC
- *
- * @wm831x: Device to read from.
- * @input: AUXADC input to read.
- */
-int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
-{
-       int ret, src, irq_masked, timeout;
-
-       /* Are we using the interrupt? */
-       irq_masked = wm831x_reg_read(wm831x, WM831X_INTERRUPT_STATUS_1_MASK);
-       irq_masked &= WM831X_AUXADC_DATA_EINT;
-
-       mutex_lock(&wm831x->auxadc_lock);
-
-       ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
-                             WM831X_AUX_ENA, WM831X_AUX_ENA);
-       if (ret < 0) {
-               dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n", ret);
-               goto out;
-       }
-
-       /* We force a single source at present */
-       src = input;
-       ret = wm831x_reg_write(wm831x, WM831X_AUXADC_SOURCE,
-                              1 << src);
-       if (ret < 0) {
-               dev_err(wm831x->dev, "Failed to set AUXADC source: %d\n", ret);
-               goto out;
-       }
-
-       /* Clear any notification from a very late arriving interrupt */
-       try_wait_for_completion(&wm831x->auxadc_done);
-
-       ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL,
-                             WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA);
-       if (ret < 0) {
-               dev_err(wm831x->dev, "Failed to start AUXADC: %d\n", ret);
-               goto disable;
-       }
-
-       if (irq_masked) {
-               /* If we're not using interrupts then poll the
-                * interrupt status register */
-               timeout = 5;
-               while (timeout) {
-                       msleep(1);
-
-                       ret = wm831x_reg_read(wm831x,
-                                             WM831X_INTERRUPT_STATUS_1);
-                       if (ret < 0) {
-                               dev_err(wm831x->dev,
-                                       "ISR 1 read failed: %d\n", ret);
-                               goto disable;
-                       }
-
-                       /* Did it complete? */
-                       if (ret & WM831X_AUXADC_DATA_EINT) {
-                               wm831x_reg_write(wm831x,
-                                                WM831X_INTERRUPT_STATUS_1,
-                                                WM831X_AUXADC_DATA_EINT);
-                               break;
-                       } else {
-                               dev_err(wm831x->dev,
-                                       "AUXADC conversion timeout\n");
-                               ret = -EBUSY;
-                               goto disable;
-                       }
-               }
-       } else {
-               /* If we are using interrupts then wait for the
-                * interrupt to complete.  Use an extremely long
-                * timeout to handle situations with heavy load where
-                * the notification of the interrupt may be delayed by
-                * threaded IRQ handling. */
-               if (!wait_for_completion_timeout(&wm831x->auxadc_done,
-                                                msecs_to_jiffies(500))) {
-                       dev_err(wm831x->dev, "Timed out waiting for AUXADC\n");
-                       ret = -EBUSY;
-                       goto disable;
-               }
-       }
-
-       ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA);
-       if (ret < 0) {
-               dev_err(wm831x->dev, "Failed to read AUXADC data: %d\n", ret);
-       } else {
-               src = ((ret & WM831X_AUX_DATA_SRC_MASK)
-                      >> WM831X_AUX_DATA_SRC_SHIFT) - 1;
-
-               if (src == 14)
-                       src = WM831X_AUX_CAL;
-
-               if (src != input) {
-                       dev_err(wm831x->dev, "Data from source %d not %d\n",
-                               src, input);
-                       ret = -EINVAL;
-               } else {
-                       ret &= WM831X_AUX_DATA_MASK;
-               }
-       }
-
-disable:
-       wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, WM831X_AUX_ENA, 0);
-out:
-       mutex_unlock(&wm831x->auxadc_lock);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(wm831x_auxadc_read);
-
-static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data)
-{
-       struct wm831x *wm831x = irq_data;
-
-       complete(&wm831x->auxadc_done);
-
-       return IRQ_HANDLED;
-}
-
-/**
- * wm831x_auxadc_read_uv: Read a voltage from the WM831x AUXADC
- *
- * @wm831x: Device to read from.
- * @input: AUXADC input to read.
- */
-int wm831x_auxadc_read_uv(struct wm831x *wm831x, enum wm831x_auxadc input)
-{
-       int ret;
-
-       ret = wm831x_auxadc_read(wm831x, input);
-       if (ret < 0)
-               return ret;
-
-       ret *= 1465;
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(wm831x_auxadc_read_uv);
-
 static struct resource wm831x_dcdc1_resources[] = {
        {
                .start = WM831X_DC1_CONTROL_1,
@@ -871,6 +731,9 @@ static struct mfd_cell wm8310_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_dcdc4_resources),
                .resources = wm831x_dcdc4_resources,
        },
+       {
+               .name = "wm831x-clk",
+       },
        {
                .name = "wm831x-epe",
                .id = 1,
@@ -975,11 +838,6 @@ static struct mfd_cell wm8310_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_power_resources),
                .resources = wm831x_power_resources,
        },
-       {
-               .name = "wm831x-rtc",
-               .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
-               .resources = wm831x_rtc_resources,
-       },
        {
                .name = "wm831x-status",
                .id = 1,
@@ -1027,6 +885,9 @@ static struct mfd_cell wm8311_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_dcdc4_resources),
                .resources = wm831x_dcdc4_resources,
        },
+       {
+               .name = "wm831x-clk",
+       },
        {
                .name = "wm831x-epe",
                .id = 1,
@@ -1107,11 +968,6 @@ static struct mfd_cell wm8311_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_power_resources),
                .resources = wm831x_power_resources,
        },
-       {
-               .name = "wm831x-rtc",
-               .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
-               .resources = wm831x_rtc_resources,
-       },
        {
                .name = "wm831x-status",
                .id = 1,
@@ -1124,11 +980,6 @@ static struct mfd_cell wm8311_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_status2_resources),
                .resources = wm831x_status2_resources,
        },
-       {
-               .name = "wm831x-touch",
-               .num_resources = ARRAY_SIZE(wm831x_touch_resources),
-               .resources = wm831x_touch_resources,
-       },
        {
                .name = "wm831x-watchdog",
                .num_resources = ARRAY_SIZE(wm831x_wdt_resources),
@@ -1164,6 +1015,9 @@ static struct mfd_cell wm8312_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_dcdc4_resources),
                .resources = wm831x_dcdc4_resources,
        },
+       {
+               .name = "wm831x-clk",
+       },
        {
                .name = "wm831x-epe",
                .id = 1,
@@ -1268,11 +1122,6 @@ static struct mfd_cell wm8312_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_power_resources),
                .resources = wm831x_power_resources,
        },
-       {
-               .name = "wm831x-rtc",
-               .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
-               .resources = wm831x_rtc_resources,
-       },
        {
                .name = "wm831x-status",
                .id = 1,
@@ -1285,11 +1134,6 @@ static struct mfd_cell wm8312_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_status2_resources),
                .resources = wm831x_status2_resources,
        },
-       {
-               .name = "wm831x-touch",
-               .num_resources = ARRAY_SIZE(wm831x_touch_resources),
-               .resources = wm831x_touch_resources,
-       },
        {
                .name = "wm831x-watchdog",
                .num_resources = ARRAY_SIZE(wm831x_wdt_resources),
@@ -1325,6 +1169,9 @@ static struct mfd_cell wm8320_devs[] = {
                .num_resources = ARRAY_SIZE(wm8320_dcdc4_buck_resources),
                .resources = wm8320_dcdc4_buck_resources,
        },
+       {
+               .name = "wm831x-clk",
+       },
        {
                .name = "wm831x-gpio",
                .num_resources = ARRAY_SIZE(wm831x_gpio_resources),
@@ -1404,11 +1251,6 @@ static struct mfd_cell wm8320_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_on_resources),
                .resources = wm831x_on_resources,
        },
-       {
-               .name = "wm831x-rtc",
-               .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
-               .resources = wm831x_rtc_resources,
-       },
        {
                .name = "wm831x-status",
                .id = 1,
@@ -1428,6 +1270,22 @@ static struct mfd_cell wm8320_devs[] = {
        },
 };
 
+static struct mfd_cell touch_devs[] = {
+       {
+               .name = "wm831x-touch",
+               .num_resources = ARRAY_SIZE(wm831x_touch_resources),
+               .resources = wm831x_touch_resources,
+       },
+};
+
+static struct mfd_cell rtc_devs[] = {
+       {
+               .name = "wm831x-rtc",
+               .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
+               .resources = wm831x_rtc_resources,
+       },
+};
+
 static struct mfd_cell backlight_devs[] = {
        {
                .name = "wm831x-backlight",
@@ -1440,14 +1298,12 @@ static struct mfd_cell backlight_devs[] = {
 int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
 {
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
-       int rev;
+       int rev, wm831x_num;
        enum wm831x_parent parent;
        int ret, i;
 
        mutex_init(&wm831x->io_lock);
        mutex_init(&wm831x->key_lock);
-       mutex_init(&wm831x->auxadc_lock);
-       init_completion(&wm831x->auxadc_done);
        dev_set_drvdata(wm831x->dev, wm831x);
 
        ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
@@ -1592,45 +1448,51 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
                }
        }
 
+       /* Multiply by 10 as we have many subdevices of the same type */
+       if (pdata && pdata->wm831x_num)
+               wm831x_num = pdata->wm831x_num * 10;
+       else
+               wm831x_num = -1;
+
        ret = wm831x_irq_init(wm831x, irq);
        if (ret != 0)
                goto err;
 
-       if (wm831x->irq_base) {
-               ret = request_threaded_irq(wm831x->irq_base +
-                                          WM831X_IRQ_AUXADC_DATA,
-                                          NULL, wm831x_auxadc_irq, 0,
-                                          "auxadc", wm831x);
-               if (ret < 0)
-                       dev_err(wm831x->dev, "AUXADC IRQ request failed: %d\n",
-                               ret);
-       }
+       wm831x_auxadc_init(wm831x);
 
        /* The core device is up, instantiate the subdevices. */
        switch (parent) {
        case WM8310:
-               ret = mfd_add_devices(wm831x->dev, -1,
+               ret = mfd_add_devices(wm831x->dev, wm831x_num,
                                      wm8310_devs, ARRAY_SIZE(wm8310_devs),
                                      NULL, wm831x->irq_base);
                break;
 
        case WM8311:
-               ret = mfd_add_devices(wm831x->dev, -1,
+               ret = mfd_add_devices(wm831x->dev, wm831x_num,
                                      wm8311_devs, ARRAY_SIZE(wm8311_devs),
                                      NULL, wm831x->irq_base);
+               if (!pdata || !pdata->disable_touch)
+                       mfd_add_devices(wm831x->dev, wm831x_num,
+                                       touch_devs, ARRAY_SIZE(touch_devs),
+                                       NULL, wm831x->irq_base);
                break;
 
        case WM8312:
-               ret = mfd_add_devices(wm831x->dev, -1,
+               ret = mfd_add_devices(wm831x->dev, wm831x_num,
                                      wm8312_devs, ARRAY_SIZE(wm8312_devs),
                                      NULL, wm831x->irq_base);
+               if (!pdata || !pdata->disable_touch)
+                       mfd_add_devices(wm831x->dev, wm831x_num,
+                                       touch_devs, ARRAY_SIZE(touch_devs),
+                                       NULL, wm831x->irq_base);
                break;
 
        case WM8320:
        case WM8321:
        case WM8325:
        case WM8326:
-               ret = mfd_add_devices(wm831x->dev, -1,
+               ret = mfd_add_devices(wm831x->dev, wm831x_num,
                                      wm8320_devs, ARRAY_SIZE(wm8320_devs),
                                      NULL, wm831x->irq_base);
                break;
@@ -1645,9 +1507,30 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
                goto err_irq;
        }
 
+       /* The RTC can only be used if the 32.768kHz crystal is
+        * enabled; this can't be controlled by software at runtime.
+        */
+       ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
+       if (ret < 0) {
+               dev_err(wm831x->dev, "Failed to read clock status: %d\n", ret);
+               goto err_irq;
+       }
+
+       if (ret & WM831X_XTAL_ENA) {
+               ret = mfd_add_devices(wm831x->dev, wm831x_num,
+                                     rtc_devs, ARRAY_SIZE(rtc_devs),
+                                     NULL, wm831x->irq_base);
+               if (ret != 0) {
+                       dev_err(wm831x->dev, "Failed to add RTC: %d\n", ret);
+                       goto err_irq;
+               }
+       } else {
+               dev_info(wm831x->dev, "32.768kHz clock disabled, no RTC\n");
+       }
+
        if (pdata && pdata->backlight) {
                /* Treat errors as non-critical */
-               ret = mfd_add_devices(wm831x->dev, -1, backlight_devs,
+               ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs,
                                      ARRAY_SIZE(backlight_devs), NULL,
                                      wm831x->irq_base);
                if (ret < 0)
index 42b928e..ada1835 100644 (file)
@@ -348,6 +348,15 @@ static void wm831x_irq_sync_unlock(struct irq_data *data)
        struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
        int i;
 
+       for (i = 0; i < ARRAY_SIZE(wm831x->gpio_update); i++) {
+               if (wm831x->gpio_update[i]) {
+                       wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + i,
+                                       WM831X_GPN_INT_MODE | WM831X_GPN_POL,
+                                       wm831x->gpio_update[i]);
+                       wm831x->gpio_update[i] = 0;
+               }
+       }
+
        for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) {
                /* If there's been a change in the mask write it back
                 * to the hardware. */
@@ -387,7 +396,7 @@ static void wm831x_irq_disable(struct irq_data *data)
 static int wm831x_irq_set_type(struct irq_data *data, unsigned int type)
 {
        struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
-       int val, irq;
+       int irq;
 
        irq = data->irq - wm831x->irq_base;
 
@@ -399,22 +408,30 @@ static int wm831x_irq_set_type(struct irq_data *data, unsigned int type)
                        return -EINVAL;
        }
 
+       /* Rebase the IRQ into the GPIO range so we've got a sensible array
+        * index.
+        */
+       irq -= WM831X_IRQ_GPIO_1;
+
+       /* We set the high bit to flag that we need an update; don't
+        * do the update here as we can be called with the bus lock
+        * held.
+        */
        switch (type) {
        case IRQ_TYPE_EDGE_BOTH:
-               val = WM831X_GPN_INT_MODE;
+               wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_INT_MODE;
                break;
        case IRQ_TYPE_EDGE_RISING:
-               val = WM831X_GPN_POL;
+               wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL;
                break;
        case IRQ_TYPE_EDGE_FALLING:
-               val = 0;
+               wm831x->gpio_update[irq] = 0x10000;
                break;
        default:
                return -EINVAL;
        }
 
-       return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + irq,
-                              WM831X_GPN_INT_MODE | WM831X_GPN_POL, val);
+       return 0;
 }
 
 static struct irq_chip wm831x_irq_chip = {
@@ -432,7 +449,7 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
 {
        struct wm831x *wm831x = data;
        unsigned int i;
-       int primary;
+       int primary, status_addr;
        int status_regs[WM831X_NUM_IRQ_REGS] = { 0 };
        int read[WM831X_NUM_IRQ_REGS] = { 0 };
        int *status;
@@ -467,8 +484,9 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
                /* Hopefully there should only be one register to read
                 * each time otherwise we ought to do a block read. */
                if (!read[offset]) {
-                       *status = wm831x_reg_read(wm831x,
-                                    irq_data_to_status_reg(&wm831x_irqs[i]));
+                       status_addr = irq_data_to_status_reg(&wm831x_irqs[i]);
+
+                       *status = wm831x_reg_read(wm831x, status_addr);
                        if (*status < 0) {
                                dev_err(wm831x->dev,
                                        "Failed to read IRQ status: %d\n",
@@ -477,26 +495,21 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
                        }
 
                        read[offset] = 1;
+
+                       /* Ignore any bits that we don't think are masked */
+                       *status &= ~wm831x->irq_masks_cur[offset];
+
+                       /* Acknowledge now so we don't miss
+                        * notifications while we handle.
+                        */
+                       wm831x_reg_write(wm831x, status_addr, *status);
                }
 
-               /* Report it if it isn't masked, or forget the status. */
-               if ((*status & ~wm831x->irq_masks_cur[offset])
-                   & wm831x_irqs[i].mask)
+               if (*status & wm831x_irqs[i].mask)
                        handle_nested_irq(wm831x->irq_base + i);
-               else
-                       *status &= ~wm831x_irqs[i].mask;
        }
 
 out:
-       /* Touchscreen interrupts are handled specially in the driver */
-       status_regs[0] &= ~(WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT);
-
-       for (i = 0; i < ARRAY_SIZE(status_regs); i++) {
-               if (status_regs[i])
-                       wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1 + i,
-                                        status_regs[i]);
-       }
-
        return IRQ_HANDLED;
 }
 
@@ -515,13 +528,22 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
                                 0xffff);
        }
 
-       if (!pdata || !pdata->irq_base) {
-               dev_err(wm831x->dev,
-                       "No interrupt base specified, no interrupts\n");
+       /* Try to dynamically allocate IRQs if no base is specified */
+       if (!pdata || !pdata->irq_base)
+               wm831x->irq_base = -1;
+       else
+               wm831x->irq_base = pdata->irq_base;
+
+       wm831x->irq_base = irq_alloc_descs(wm831x->irq_base, 0,
+                                          WM831X_NUM_IRQS, 0);
+       if (wm831x->irq_base < 0) {
+               dev_warn(wm831x->dev, "Failed to allocate IRQs: %d\n",
+                        wm831x->irq_base);
+               wm831x->irq_base = 0;
                return 0;
        }
 
-       if (pdata->irq_cmos)
+       if (pdata && pdata->irq_cmos)
                i = 0;
        else
                i = WM831X_IRQ_OD;
@@ -541,7 +563,6 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
        }
 
        wm831x->irq = irq;
-       wm831x->irq_base = pdata->irq_base;
 
        /* Register them with genirq */
        for (cur_irq = wm831x->irq_base;
index ed4b22a..8a1fafd 100644 (file)
@@ -473,17 +473,13 @@ int wm8350_irq_init(struct wm8350 *wm8350, int irq,
 {
        int ret, cur_irq, i;
        int flags = IRQF_ONESHOT;
+       int irq_base = -1;
 
        if (!irq) {
                dev_warn(wm8350->dev, "No interrupt support, no core IRQ\n");
                return 0;
        }
 
-       if (!pdata || !pdata->irq_base) {
-               dev_warn(wm8350->dev, "No interrupt support, no IRQ base\n");
-               return 0;
-       }
-
        /* Mask top level interrupts */
        wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0xFFFF);
 
@@ -502,7 +498,17 @@ int wm8350_irq_init(struct wm8350 *wm8350, int irq,
        wm8350->chip_irq = irq;
        wm8350->irq_base = pdata->irq_base;
 
-       if (pdata->irq_high) {
+       if (pdata && pdata->irq_base > 0)
+               irq_base = pdata->irq_base;
+
+       wm8350->irq_base = irq_alloc_descs(irq_base, 0, ARRAY_SIZE(wm8350_irqs), 0);
+       if (wm8350->irq_base < 0) {
+               dev_warn(wm8350->dev, "Allocating irqs failed with %d\n",
+                       wm8350->irq_base);
+               return 0;
+       }
+
+       if (pdata && pdata->irq_high) {
                flags |= IRQF_TRIGGER_HIGH;
 
                wm8350_set_bits(wm8350, WM8350_SYSTEM_CONTROL_1,
index e198d40..96479c9 100644 (file)
@@ -316,7 +316,7 @@ static int wm8994_suspend(struct device *dev)
 static int wm8994_resume(struct device *dev)
 {
        struct wm8994 *wm8994 = dev_get_drvdata(dev);
-       int ret;
+       int ret, i;
 
        /* We may have lied to the PM core about suspending */
        if (!wm8994->suspended)
@@ -329,10 +329,16 @@ static int wm8994_resume(struct device *dev)
                return ret;
        }
 
-       ret = wm8994_write(wm8994, WM8994_INTERRUPT_STATUS_1_MASK,
-                          WM8994_NUM_IRQ_REGS * 2, &wm8994->irq_masks_cur);
-       if (ret < 0)
-               dev_err(dev, "Failed to restore interrupt masks: %d\n", ret);
+       /* Write register at a time as we use the cache on the CPU so store
+        * it in native endian.
+        */
+       for (i = 0; i < ARRAY_SIZE(wm8994->irq_masks_cur); i++) {
+               ret = wm8994_reg_write(wm8994, WM8994_INTERRUPT_STATUS_1_MASK
+                                      + i, wm8994->irq_masks_cur[i]);
+               if (ret < 0)
+                       dev_err(dev, "Failed to restore interrupt masks: %d\n",
+                               ret);
+       }
 
        ret = wm8994_write(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
                           &wm8994->ldo_regs);
@@ -403,7 +409,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
                break;
        default:
                BUG();
-               return -EINVAL;
+               goto err;
        }
 
        wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
@@ -425,7 +431,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
                break;
        default:
                BUG();
-               return -EINVAL;
+               goto err;
        }
                
        ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies,
@@ -476,13 +482,18 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
                goto err_enable;
        }
 
-       switch (ret) {
-       case 0:
-       case 1:
-               if (wm8994->type == WM8994)
+       switch (wm8994->type) {
+       case WM8994:
+               switch (ret) {
+               case 0:
+               case 1:
                        dev_warn(wm8994->dev,
                                 "revision %c not fully supported\n",
                                 'A' + ret);
+                       break;
+               default:
+                       break;
+               }
                break;
        default:
                break;
index 71c6e8f..d682f7b 100644 (file)
@@ -231,12 +231,6 @@ static irqreturn_t wm8994_irq_thread(int irq, void *data)
                status[i] &= ~wm8994->irq_masks_cur[i];
        }
 
-       /* Report */
-       for (i = 0; i < ARRAY_SIZE(wm8994_irqs); i++) {
-               if (status[wm8994_irqs[i].reg - 1] & wm8994_irqs[i].mask)
-                       handle_nested_irq(wm8994->irq_base + i);
-       }
-
        /* Ack any unmasked IRQs */
        for (i = 0; i < ARRAY_SIZE(status); i++) {
                if (status[i])
@@ -244,6 +238,12 @@ static irqreturn_t wm8994_irq_thread(int irq, void *data)
                                         status[i]);
        }
 
+       /* Report */
+       for (i = 0; i < ARRAY_SIZE(wm8994_irqs); i++) {
+               if (status[wm8994_irqs[i].reg - 1] & wm8994_irqs[i].mask)
+                       handle_nested_irq(wm8994->irq_base + i);
+       }
+
        return IRQ_HANDLED;
 }
 
index 3007662..ef0105f 100644 (file)
@@ -127,8 +127,8 @@ EXPORT_SYMBOL(of_gpio_count);
  * gpio chips. This function performs only one sanity check: whether gpio
  * is less than ngpios (that is specified in the gpio_chip).
  */
-static int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
-                               const void *gpio_spec, u32 *flags)
+int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
+                        const void *gpio_spec, u32 *flags)
 {
        const __be32 *gpio = gpio_spec;
        const u32 n = be32_to_cpup(gpio);
@@ -152,6 +152,7 @@ static int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
 
        return n;
 }
+EXPORT_SYMBOL(of_gpio_simple_xlate);
 
 /**
  * of_mm_gpiochip_add - Add memory mapped GPIO chip (bank)
index 118eb21..c7fd2c0 100644 (file)
@@ -249,6 +249,12 @@ config REGULATOR_TPS6507X
          three step-down converters and two general-purpose LDO voltage regulators.
          It supports TI's software based Class-2 SmartReflex implementation.
 
+config REGULATOR_TPS65912
+       tristate "TI TPS65912 Power regulator"
+       depends on (MFD_TPS65912_I2C || MFD_TPS65912_SPI)
+       help
+           This driver supports TPS65912 voltage regulator chip.
+
 config REGULATOR_88PM8607
        bool "Marvell 88PM8607 Power regulators"
        depends on MFD_88PM860X=y
@@ -304,5 +310,12 @@ config REGULATOR_TPS65910
        help
          This driver supports TPS65910 voltage regulator chips.
 
+config REGULATOR_AAT2870
+       tristate "AnalogicTech AAT2870 Regulators"
+       depends on MFD_AAT2870_CORE
+       help
+         If you have a AnalogicTech AAT2870 say Y to enable the
+         regulator driver.
+
 endif
 
index 3932d2e..040d5aa 100644 (file)
@@ -38,10 +38,12 @@ obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
+obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
 obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
 obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
 obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
 obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
 obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
+obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
 
 ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c
new file mode 100644 (file)
index 0000000..cd41045
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * linux/drivers/regulator/aat2870-regulator.c
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ * Author: Jin Park <jinyoungp@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/aat2870.h>
+
+struct aat2870_regulator {
+       struct platform_device *pdev;
+       struct regulator_desc desc;
+
+       const int *voltages; /* uV */
+
+       int min_uV;
+       int max_uV;
+
+       u8 enable_addr;
+       u8 enable_shift;
+       u8 enable_mask;
+
+       u8 voltage_addr;
+       u8 voltage_shift;
+       u8 voltage_mask;
+};
+
+static int aat2870_ldo_list_voltage(struct regulator_dev *rdev,
+                                   unsigned selector)
+{
+       struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
+
+       return ri->voltages[selector];
+}
+
+static int aat2870_ldo_set_voltage_sel(struct regulator_dev *rdev,
+                                      unsigned selector)
+{
+       struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
+       struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent);
+
+       return aat2870->update(aat2870, ri->voltage_addr, ri->voltage_mask,
+                       (selector << ri->voltage_shift) & ri->voltage_mask);
+}
+
+static int aat2870_ldo_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
+       struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent);
+       u8 val;
+       int ret;
+
+       ret = aat2870->read(aat2870, ri->voltage_addr, &val);
+       if (ret)
+               return ret;
+
+       return (val & ri->voltage_mask) >> ri->voltage_shift;
+}
+
+static int aat2870_ldo_enable(struct regulator_dev *rdev)
+{
+       struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
+       struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent);
+
+       return aat2870->update(aat2870, ri->enable_addr, ri->enable_mask,
+                              ri->enable_mask);
+}
+
+static int aat2870_ldo_disable(struct regulator_dev *rdev)
+{
+       struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
+       struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent);
+
+       return aat2870->update(aat2870, ri->enable_addr, ri->enable_mask, 0);
+}
+
+static int aat2870_ldo_is_enabled(struct regulator_dev *rdev)
+{
+       struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
+       struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent);
+       u8 val;
+       int ret;
+
+       ret = aat2870->read(aat2870, ri->enable_addr, &val);
+       if (ret)
+               return ret;
+
+       return val & ri->enable_mask ? 1 : 0;
+}
+
+static struct regulator_ops aat2870_ldo_ops = {
+       .list_voltage = aat2870_ldo_list_voltage,
+       .set_voltage_sel = aat2870_ldo_set_voltage_sel,
+       .get_voltage_sel = aat2870_ldo_get_voltage_sel,
+       .enable = aat2870_ldo_enable,
+       .disable = aat2870_ldo_disable,
+       .is_enabled = aat2870_ldo_is_enabled,
+};
+
+static const int aat2870_ldo_voltages[] = {
+       1200000, 1300000, 1500000, 1600000,
+       1800000, 2000000, 2200000, 2500000,
+       2600000, 2700000, 2800000, 2900000,
+       3000000, 3100000, 3200000, 3300000,
+};
+
+#define AAT2870_LDO(ids)                               \
+       {                                               \
+               .desc = {                               \
+                       .name = #ids,                   \
+                       .id = AAT2870_ID_##ids,         \
+                       .n_voltages = ARRAY_SIZE(aat2870_ldo_voltages), \
+                       .ops = &aat2870_ldo_ops,        \
+                       .type = REGULATOR_VOLTAGE,      \
+                       .owner = THIS_MODULE,           \
+               },                                      \
+               .voltages = aat2870_ldo_voltages,       \
+               .min_uV = 1200000,                      \
+               .max_uV = 3300000,                      \
+       }
+
+static struct aat2870_regulator aat2870_regulators[] = {
+       AAT2870_LDO(LDOA),
+       AAT2870_LDO(LDOB),
+       AAT2870_LDO(LDOC),
+       AAT2870_LDO(LDOD),
+};
+
+static struct aat2870_regulator *aat2870_get_regulator(int id)
+{
+       struct aat2870_regulator *ri = NULL;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(aat2870_regulators); i++) {
+               ri = &aat2870_regulators[i];
+               if (ri->desc.id == id)
+                       break;
+       }
+
+       if (!ri)
+               return NULL;
+
+       ri->enable_addr = AAT2870_LDO_EN;
+       ri->enable_shift = id - AAT2870_ID_LDOA;
+       ri->enable_mask = 0x1 << ri->enable_shift;
+
+       ri->voltage_addr = (id - AAT2870_ID_LDOA) / 2 ?
+                          AAT2870_LDO_CD : AAT2870_LDO_AB;
+       ri->voltage_shift = (id - AAT2870_ID_LDOA) % 2 ? 0 : 4;
+       ri->voltage_mask = 0xF << ri->voltage_shift;
+
+       return ri;
+}
+
+static int aat2870_regulator_probe(struct platform_device *pdev)
+{
+       struct aat2870_regulator *ri;
+       struct regulator_dev *rdev;
+
+       ri = aat2870_get_regulator(pdev->id);
+       if (!ri) {
+               dev_err(&pdev->dev, "Invalid device ID, %d\n", pdev->id);
+               return -EINVAL;
+       }
+       ri->pdev = pdev;
+
+       rdev = regulator_register(&ri->desc, &pdev->dev,
+                                 pdev->dev.platform_data, ri);
+       if (IS_ERR(rdev)) {
+               dev_err(&pdev->dev, "Failed to register regulator %s\n",
+                       ri->desc.name);
+               return PTR_ERR(rdev);
+       }
+       platform_set_drvdata(pdev, rdev);
+
+       return 0;
+}
+
+static int __devexit aat2870_regulator_remove(struct platform_device *pdev)
+{
+       struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+       regulator_unregister(rdev);
+       return 0;
+}
+
+static struct platform_driver aat2870_regulator_driver = {
+       .driver = {
+               .name   = "aat2870-regulator",
+               .owner  = THIS_MODULE,
+       },
+       .probe  = aat2870_regulator_probe,
+       .remove = __devexit_p(aat2870_regulator_remove),
+};
+
+static int __init aat2870_regulator_init(void)
+{
+       return platform_driver_register(&aat2870_regulator_driver);
+}
+subsys_initcall(aat2870_regulator_init);
+
+static void __exit aat2870_regulator_exit(void)
+{
+       platform_driver_unregister(&aat2870_regulator_driver);
+}
+module_exit(aat2870_regulator_exit);
+
+MODULE_DESCRIPTION("AnalogicTech AAT2870 Regulator");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jin Park <jinyoungp@nvidia.com>");
diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c
new file mode 100644 (file)
index 0000000..3a9313e
--- /dev/null
@@ -0,0 +1,800 @@
+/*
+ * tps65912.c  --  TI tps65912
+ *
+ * Copyright 2011 Texas Instruments Inc.
+ *
+ * Author: Margarita Olaya Cabrera <magi@slimlogic.co.uk>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under  the terms of the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ * This driver is based on wm8350 implementation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/mfd/tps65912.h>
+
+/* DCDC's */
+#define TPS65912_REG_DCDC1     0
+#define TPS65912_REG_DCDC2     1
+#define TPS65912_REG_DCDC3     2
+#define TPS65912_REG_DCDC4     3
+
+/* LDOs */
+#define TPS65912_REG_LDO1      4
+#define TPS65912_REG_LDO2      5
+#define TPS65912_REG_LDO3      6
+#define TPS65912_REG_LDO4      7
+#define TPS65912_REG_LDO5      8
+#define TPS65912_REG_LDO6      9
+#define TPS65912_REG_LDO7      10
+#define TPS65912_REG_LDO8      11
+#define TPS65912_REG_LDO9      12
+#define TPS65912_REG_LDO10     13
+
+#define TPS65912_MAX_REG_ID    TPS65912_REG_LDO_10
+
+/* Number of step-down converters available */
+#define TPS65912_NUM_DCDC      4
+
+/* Number of LDO voltage regulators  available */
+#define TPS65912_NUM_LDO       10
+
+/* Number of total regulators available */
+#define TPS65912_NUM_REGULATOR         (TPS65912_NUM_DCDC + TPS65912_NUM_LDO)
+
+#define TPS65912_REG_ENABLED   0x80
+#define OP_SELREG_MASK         0x40
+#define OP_SELREG_SHIFT                6
+
+struct tps_info {
+       const char *name;
+};
+
+static struct tps_info tps65912_regs[] = {
+       {
+               .name = "DCDC1",
+       },
+       {
+               .name = "DCDC2",
+       },
+       {
+               .name = "DCDC3",
+       },
+       {
+               .name = "DCDC4",
+       },
+       {
+               .name = "LDO1",
+       },
+       {
+               .name = "LDO2",
+       },
+       {
+               .name = "LDO3",
+       },
+       {
+               .name = "LDO4",
+       },
+       {
+               .name = "LDO5",
+       },
+       {
+               .name = "LDO6",
+       },
+       {
+               .name = "LDO7",
+       },
+       {
+               .name = "LDO8",
+       },
+       {
+               .name = "LDO9",
+       },
+       {
+               .name = "LDO10",
+       },
+};
+
+struct tps65912_reg {
+       struct regulator_desc desc[TPS65912_NUM_REGULATOR];
+       struct tps65912 *mfd;
+       struct regulator_dev *rdev[TPS65912_NUM_REGULATOR];
+       struct tps_info *info[TPS65912_NUM_REGULATOR];
+       /* for read/write access */
+       struct mutex io_lock;
+       int mode;
+       int (*get_ctrl_reg)(int);
+       int dcdc1_range;
+       int dcdc2_range;
+       int dcdc3_range;
+       int dcdc4_range;
+       int pwm_mode_reg;
+       int eco_reg;
+};
+
+static int tps65912_get_range(struct tps65912_reg *pmic, int id)
+{
+       struct tps65912 *mfd = pmic->mfd;
+
+       if (id > TPS65912_REG_DCDC4)
+               return 0;
+
+       switch (id) {
+       case TPS65912_REG_DCDC1:
+               pmic->dcdc1_range = tps65912_reg_read(mfd,
+                                                       TPS65912_DCDC1_LIMIT);
+               if (pmic->dcdc1_range < 0)
+                       return pmic->dcdc1_range;
+               pmic->dcdc1_range = (pmic->dcdc1_range &
+                       DCDC_LIMIT_RANGE_MASK) >> DCDC_LIMIT_RANGE_SHIFT;
+               return pmic->dcdc1_range;
+       case TPS65912_REG_DCDC2:
+               pmic->dcdc2_range = tps65912_reg_read(mfd,
+                                                       TPS65912_DCDC2_LIMIT);
+               if (pmic->dcdc2_range < 0)
+                       return pmic->dcdc2_range;
+               pmic->dcdc2_range = (pmic->dcdc2_range &
+                       DCDC_LIMIT_RANGE_MASK) >> DCDC_LIMIT_RANGE_SHIFT;
+               return pmic->dcdc2_range;
+       case TPS65912_REG_DCDC3:
+               pmic->dcdc3_range = tps65912_reg_read(mfd,
+                                                       TPS65912_DCDC3_LIMIT);
+               if (pmic->dcdc3_range < 0)
+                       return pmic->dcdc3_range;
+               pmic->dcdc3_range = (pmic->dcdc3_range &
+                       DCDC_LIMIT_RANGE_MASK) >> DCDC_LIMIT_RANGE_SHIFT;
+               return pmic->dcdc3_range;
+       case TPS65912_REG_DCDC4:
+               pmic->dcdc4_range = tps65912_reg_read(mfd,
+                                                       TPS65912_DCDC4_LIMIT);
+               if (pmic->dcdc4_range < 0)
+                       return pmic->dcdc4_range;
+               pmic->dcdc4_range = (pmic->dcdc4_range &
+                       DCDC_LIMIT_RANGE_MASK) >> DCDC_LIMIT_RANGE_SHIFT;
+               return pmic->dcdc4_range;
+       default:
+               return 0;
+       }
+}
+
+static unsigned long tps65912_vsel_to_uv_range0(u8 vsel)
+{
+       unsigned long uv;
+
+       uv = ((vsel * 12500) + 500000);
+       return uv;
+}
+
+static unsigned long tps65912_vsel_to_uv_range1(u8 vsel)
+{
+       unsigned long uv;
+
+        uv = ((vsel * 12500) + 700000);
+       return uv;
+}
+
+static unsigned long tps65912_vsel_to_uv_range2(u8 vsel)
+{
+       unsigned long uv;
+
+       uv = ((vsel * 25000) + 500000);
+       return uv;
+}
+
+static unsigned long tps65912_vsel_to_uv_range3(u8 vsel)
+{
+       unsigned long uv;
+
+       if (vsel == 0x3f)
+               uv = 3800000;
+       else
+               uv = ((vsel * 50000) + 500000);
+
+       return uv;
+}
+
+static unsigned long tps65912_vsel_to_uv_ldo(u8 vsel)
+{
+       unsigned long uv = 0;
+
+       if (vsel <= 32)
+               uv = ((vsel * 25000) + 800000);
+       else if (vsel > 32 && vsel <= 60)
+               uv = (((vsel - 32) * 50000) + 1600000);
+       else if (vsel > 60)
+               uv = (((vsel - 60) * 100000) + 3000000);
+
+       return uv;
+}
+
+static int tps65912_get_ctrl_register(int id)
+{
+       switch (id) {
+       case TPS65912_REG_DCDC1:
+               return TPS65912_DCDC1_AVS;
+       case TPS65912_REG_DCDC2:
+               return TPS65912_DCDC2_AVS;
+       case TPS65912_REG_DCDC3:
+               return TPS65912_DCDC3_AVS;
+       case TPS65912_REG_DCDC4:
+               return TPS65912_DCDC4_AVS;
+       case TPS65912_REG_LDO1:
+               return TPS65912_LDO1_AVS;
+       case TPS65912_REG_LDO2:
+               return TPS65912_LDO2_AVS;
+       case TPS65912_REG_LDO3:
+               return TPS65912_LDO3_AVS;
+       case TPS65912_REG_LDO4:
+               return TPS65912_LDO4_AVS;
+       case TPS65912_REG_LDO5:
+               return TPS65912_LDO5;
+       case TPS65912_REG_LDO6:
+               return TPS65912_LDO6;
+       case TPS65912_REG_LDO7:
+               return TPS65912_LDO7;
+       case TPS65912_REG_LDO8:
+               return TPS65912_LDO8;
+       case TPS65912_REG_LDO9:
+               return TPS65912_LDO9;
+       case TPS65912_REG_LDO10:
+               return TPS65912_LDO10;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int tps65912_get_dcdc_sel_register(struct tps65912_reg *pmic, int id)
+{
+       struct tps65912 *mfd = pmic->mfd;
+       int opvsel = 0, sr = 0;
+       u8 reg = 0;
+
+       if (id < TPS65912_REG_DCDC1 || id > TPS65912_REG_DCDC4)
+               return -EINVAL;
+
+       switch (id) {
+       case TPS65912_REG_DCDC1:
+               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC1_OP);
+               sr = ((opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT);
+               if (sr)
+                       reg = TPS65912_DCDC1_AVS;
+               else
+                       reg = TPS65912_DCDC1_OP;
+               break;
+       case TPS65912_REG_DCDC2:
+               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC2_OP);
+               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
+               if (sr)
+                       reg = TPS65912_DCDC2_AVS;
+               else
+                       reg = TPS65912_DCDC2_OP;
+               break;
+       case TPS65912_REG_DCDC3:
+               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC3_OP);
+               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
+               if (sr)
+                       reg = TPS65912_DCDC3_AVS;
+               else
+                       reg = TPS65912_DCDC3_OP;
+               break;
+       case TPS65912_REG_DCDC4:
+               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC4_OP);
+               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
+               if (sr)
+                       reg = TPS65912_DCDC4_AVS;
+               else
+                       reg = TPS65912_DCDC4_OP;
+               break;
+       }
+       return reg;
+}
+
+static int tps65912_get_ldo_sel_register(struct tps65912_reg *pmic, int id)
+{
+       struct tps65912 *mfd = pmic->mfd;
+       int opvsel = 0, sr = 0;
+       u8 reg = 0;
+
+       if (id < TPS65912_REG_LDO1 || id > TPS65912_REG_LDO10)
+               return -EINVAL;
+
+       switch (id) {
+       case TPS65912_REG_LDO1:
+               opvsel = tps65912_reg_read(mfd, TPS65912_LDO1_OP);
+               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
+               if (sr)
+                       reg = TPS65912_LDO1_AVS;
+               else
+                       reg = TPS65912_LDO1_OP;
+               break;
+       case TPS65912_REG_LDO2:
+               opvsel = tps65912_reg_read(mfd, TPS65912_LDO2_OP);
+               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
+               if (sr)
+                       reg = TPS65912_LDO2_AVS;
+               else
+                       reg = TPS65912_LDO2_OP;
+               break;
+       case TPS65912_REG_LDO3:
+               opvsel = tps65912_reg_read(mfd, TPS65912_LDO3_OP);
+               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
+               if (sr)
+                       reg = TPS65912_LDO3_AVS;
+               else
+                       reg = TPS65912_LDO3_OP;
+               break;
+       case TPS65912_REG_LDO4:
+               opvsel = tps65912_reg_read(mfd, TPS65912_LDO4_OP);
+               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
+               if (sr)
+                       reg = TPS65912_LDO4_AVS;
+               else
+                       reg = TPS65912_LDO4_OP;
+               break;
+       case TPS65912_REG_LDO5:
+               reg = TPS65912_LDO5;
+               break;
+       case TPS65912_REG_LDO6:
+               reg = TPS65912_LDO6;
+               break;
+       case TPS65912_REG_LDO7:
+               reg = TPS65912_LDO7;
+               break;
+       case TPS65912_REG_LDO8:
+               reg = TPS65912_LDO8;
+               break;
+       case TPS65912_REG_LDO9:
+               reg = TPS65912_LDO9;
+               break;
+       case TPS65912_REG_LDO10:
+               reg = TPS65912_LDO10;
+               break;
+       }
+
+       return reg;
+}
+
+static int tps65912_get_mode_regiters(struct tps65912_reg *pmic, int id)
+{
+       switch (id) {
+       case TPS65912_REG_DCDC1:
+               pmic->pwm_mode_reg = TPS65912_DCDC1_CTRL;
+               pmic->eco_reg = TPS65912_DCDC1_AVS;
+               break;
+       case TPS65912_REG_DCDC2:
+               pmic->pwm_mode_reg = TPS65912_DCDC2_CTRL;
+               pmic->eco_reg = TPS65912_DCDC2_AVS;
+               break;
+       case TPS65912_REG_DCDC3:
+               pmic->pwm_mode_reg = TPS65912_DCDC3_CTRL;
+               pmic->eco_reg = TPS65912_DCDC3_AVS;
+               break;
+       case TPS65912_REG_DCDC4:
+               pmic->pwm_mode_reg = TPS65912_DCDC4_CTRL;
+               pmic->eco_reg = TPS65912_DCDC4_AVS;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int tps65912_reg_is_enabled(struct regulator_dev *dev)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int reg, value, id = rdev_get_id(dev);
+
+       if (id < TPS65912_REG_DCDC1 || id > TPS65912_REG_LDO10)
+               return -EINVAL;
+
+       reg = pmic->get_ctrl_reg(id);
+       if (reg < 0)
+               return reg;
+
+       value = tps65912_reg_read(mfd, reg);
+       if (value < 0)
+               return value;
+
+       return value & TPS65912_REG_ENABLED;
+}
+
+static int tps65912_reg_enable(struct regulator_dev *dev)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int id = rdev_get_id(dev);
+       int reg;
+
+       if (id < TPS65912_REG_DCDC1 || id > TPS65912_REG_LDO10)
+               return -EINVAL;
+
+       reg = pmic->get_ctrl_reg(id);
+       if (reg < 0)
+               return reg;
+
+       return tps65912_set_bits(mfd, reg, TPS65912_REG_ENABLED);
+}
+
+static int tps65912_reg_disable(struct regulator_dev *dev)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int id = rdev_get_id(dev), reg;
+
+       reg = pmic->get_ctrl_reg(id);
+       if (reg < 0)
+               return reg;
+
+       return tps65912_clear_bits(mfd, reg, TPS65912_REG_ENABLED);
+}
+
+static int tps65912_set_mode(struct regulator_dev *dev, unsigned int mode)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int pwm_mode, eco, id = rdev_get_id(dev);
+
+       tps65912_get_mode_regiters(pmic, id);
+
+       pwm_mode = tps65912_reg_read(mfd, pmic->pwm_mode_reg);
+       eco = tps65912_reg_read(mfd, pmic->eco_reg);
+
+       pwm_mode &= DCDCCTRL_DCDC_MODE_MASK;
+       eco &= DCDC_AVS_ECO_MASK;
+
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               /* Verify if mode alredy set */
+               if (pwm_mode && !eco)
+                       break;
+               tps65912_set_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK);
+               tps65912_clear_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK);
+               break;
+       case REGULATOR_MODE_NORMAL:
+       case REGULATOR_MODE_IDLE:
+               if (!pwm_mode && !eco)
+                       break;
+               tps65912_clear_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK);
+               tps65912_clear_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK);
+               break;
+       case REGULATOR_MODE_STANDBY:
+               if (!pwm_mode && eco)
+                       break;
+               tps65912_clear_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK);
+               tps65912_set_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static unsigned int tps65912_get_mode(struct regulator_dev *dev)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int pwm_mode, eco, mode = 0, id = rdev_get_id(dev);
+
+       tps65912_get_mode_regiters(pmic, id);
+
+       pwm_mode = tps65912_reg_read(mfd, pmic->pwm_mode_reg);
+       eco = tps65912_reg_read(mfd, pmic->eco_reg);
+
+       pwm_mode &= DCDCCTRL_DCDC_MODE_MASK;
+       eco &= DCDC_AVS_ECO_MASK;
+
+       if (pwm_mode && !eco)
+               mode = REGULATOR_MODE_FAST;
+       else if (!pwm_mode && !eco)
+               mode = REGULATOR_MODE_NORMAL;
+       else if (!pwm_mode && eco)
+               mode = REGULATOR_MODE_STANDBY;
+
+       return mode;
+}
+
+static int tps65912_get_voltage_dcdc(struct regulator_dev *dev)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int id = rdev_get_id(dev), voltage = 0, range;
+       int opvsel = 0, avsel = 0, sr, vsel;
+
+       switch (id) {
+       case TPS65912_REG_DCDC1:
+               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC1_OP);
+               avsel = tps65912_reg_read(mfd, TPS65912_DCDC1_AVS);
+               range = pmic->dcdc1_range;
+               break;
+       case TPS65912_REG_DCDC2:
+               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC2_OP);
+               avsel = tps65912_reg_read(mfd, TPS65912_DCDC2_AVS);
+               range = pmic->dcdc2_range;
+               break;
+       case TPS65912_REG_DCDC3:
+               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC3_OP);
+               avsel = tps65912_reg_read(mfd, TPS65912_DCDC3_AVS);
+               range = pmic->dcdc3_range;
+               break;
+       case TPS65912_REG_DCDC4:
+               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC4_OP);
+               avsel = tps65912_reg_read(mfd, TPS65912_DCDC4_AVS);
+               range = pmic->dcdc4_range;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
+       if (sr)
+               vsel = avsel;
+       else
+               vsel = opvsel;
+       vsel &= 0x3F;
+
+       switch (range) {
+       case 0:
+               /* 0.5 - 1.2875V in 12.5mV steps */
+               voltage = tps65912_vsel_to_uv_range0(vsel);
+               break;
+       case 1:
+               /* 0.7 - 1.4875V in 12.5mV steps */
+               voltage = tps65912_vsel_to_uv_range1(vsel);
+               break;
+       case 2:
+               /* 0.5 - 2.075V in 25mV steps */
+               voltage = tps65912_vsel_to_uv_range2(vsel);
+               break;
+       case 3:
+               /* 0.5 - 3.8V in 50mV steps */
+               voltage = tps65912_vsel_to_uv_range3(vsel);
+               break;
+       }
+       return voltage;
+}
+
+static int tps65912_set_voltage_dcdc(struct regulator_dev *dev,
+                                               unsigned selector)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int id = rdev_get_id(dev);
+       int value;
+       u8 reg;
+
+       reg = tps65912_get_dcdc_sel_register(pmic, id);
+       value = tps65912_reg_read(mfd, reg);
+       value &= 0xC0;
+       return tps65912_reg_write(mfd, reg, selector | value);
+}
+
+static int tps65912_get_voltage_ldo(struct regulator_dev *dev)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int id = rdev_get_id(dev);
+       int vsel = 0;
+       u8 reg;
+
+       reg = tps65912_get_ldo_sel_register(pmic, id);
+       vsel = tps65912_reg_read(mfd, reg);
+       vsel &= 0x3F;
+
+       return tps65912_vsel_to_uv_ldo(vsel);
+}
+
+static int tps65912_set_voltage_ldo(struct regulator_dev *dev,
+                                               unsigned selector)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int id = rdev_get_id(dev), reg, value;
+
+       reg = tps65912_get_ldo_sel_register(pmic, id);
+       value = tps65912_reg_read(mfd, reg);
+       value &= 0xC0;
+       return tps65912_reg_write(mfd, reg, selector | value);
+}
+
+static int tps65912_list_voltage_dcdc(struct regulator_dev *dev,
+                                       unsigned selector)
+{
+       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
+       int range, voltage = 0, id = rdev_get_id(dev);
+
+       switch (id) {
+       case TPS65912_REG_DCDC1:
+               range = pmic->dcdc1_range;
+               break;
+       case TPS65912_REG_DCDC2:
+               range = pmic->dcdc2_range;
+               break;
+       case TPS65912_REG_DCDC3:
+               range = pmic->dcdc3_range;
+               break;
+       case TPS65912_REG_DCDC4:
+               range = pmic->dcdc4_range;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (range) {
+       case 0:
+               /* 0.5 - 1.2875V in 12.5mV steps */
+               voltage = tps65912_vsel_to_uv_range0(selector);
+               break;
+       case 1:
+               /* 0.7 - 1.4875V in 12.5mV steps */
+               voltage = tps65912_vsel_to_uv_range1(selector);
+               break;
+       case 2:
+               /* 0.5 - 2.075V in 25mV steps */
+               voltage = tps65912_vsel_to_uv_range2(selector);
+               break;
+       case 3:
+               /* 0.5 - 3.8V in 50mV steps */
+               voltage = tps65912_vsel_to_uv_range3(selector);
+               break;
+       }
+       return voltage;
+}
+
+static int tps65912_list_voltage_ldo(struct regulator_dev *dev,
+                                       unsigned selector)
+{
+       int ldo = rdev_get_id(dev);
+
+       if (ldo < TPS65912_REG_LDO1 || ldo > TPS65912_REG_LDO10)
+               return -EINVAL;
+
+       return tps65912_vsel_to_uv_ldo(selector);
+}
+
+/* Operations permitted on DCDCx */
+static struct regulator_ops tps65912_ops_dcdc = {
+       .is_enabled = tps65912_reg_is_enabled,
+       .enable = tps65912_reg_enable,
+       .disable = tps65912_reg_disable,
+       .set_mode = tps65912_set_mode,
+       .get_mode = tps65912_get_mode,
+       .get_voltage = tps65912_get_voltage_dcdc,
+       .set_voltage_sel = tps65912_set_voltage_dcdc,
+       .list_voltage = tps65912_list_voltage_dcdc,
+};
+
+/* Operations permitted on LDOx */
+static struct regulator_ops tps65912_ops_ldo = {
+       .is_enabled = tps65912_reg_is_enabled,
+       .enable = tps65912_reg_enable,
+       .disable = tps65912_reg_disable,
+       .get_voltage = tps65912_get_voltage_ldo,
+       .set_voltage_sel = tps65912_set_voltage_ldo,
+       .list_voltage = tps65912_list_voltage_ldo,
+};
+
+static __devinit int tps65912_probe(struct platform_device *pdev)
+{
+       struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
+       struct tps_info *info;
+       struct regulator_init_data *reg_data;
+       struct regulator_dev *rdev;
+       struct tps65912_reg *pmic;
+       struct tps65912_board *pmic_plat_data;
+       int i, err;
+
+       pmic_plat_data = dev_get_platdata(tps65912->dev);
+       if (!pmic_plat_data)
+               return -EINVAL;
+
+       reg_data = pmic_plat_data->tps65912_pmic_init_data;
+
+       pmic = kzalloc(sizeof(*pmic), GFP_KERNEL);
+       if (!pmic)
+               return -ENOMEM;
+
+       mutex_init(&pmic->io_lock);
+       pmic->mfd = tps65912;
+       platform_set_drvdata(pdev, pmic);
+
+       pmic->get_ctrl_reg = &tps65912_get_ctrl_register;
+       info = tps65912_regs;
+
+       for (i = 0; i < TPS65912_NUM_REGULATOR; i++, info++, reg_data++) {
+               int range = 0;
+               /* Register the regulators */
+               pmic->info[i] = info;
+
+               pmic->desc[i].name = info->name;
+               pmic->desc[i].id = i;
+               pmic->desc[i].n_voltages = 64;
+               pmic->desc[i].ops = (i > TPS65912_REG_DCDC4 ?
+                       &tps65912_ops_ldo : &tps65912_ops_dcdc);
+               pmic->desc[i].type = REGULATOR_VOLTAGE;
+               pmic->desc[i].owner = THIS_MODULE;
+               range = tps65912_get_range(pmic, i);
+               rdev = regulator_register(&pmic->desc[i],
+                                       tps65912->dev, reg_data, pmic);
+               if (IS_ERR(rdev)) {
+                       dev_err(tps65912->dev,
+                               "failed to register %s regulator\n",
+                               pdev->name);
+                       err = PTR_ERR(rdev);
+                       goto err;
+               }
+
+               /* Save regulator for cleanup */
+               pmic->rdev[i] = rdev;
+       }
+       return 0;
+
+err:
+       while (--i >= 0)
+               regulator_unregister(pmic->rdev[i]);
+
+       kfree(pmic);
+       return err;
+}
+
+static int __devexit tps65912_remove(struct platform_device *pdev)
+{
+       struct tps65912_reg *tps65912_reg = platform_get_drvdata(pdev);
+       int i;
+
+       for (i = 0; i < TPS65912_NUM_REGULATOR; i++)
+               regulator_unregister(tps65912_reg->rdev[i]);
+
+       kfree(tps65912_reg);
+       return 0;
+}
+
+static struct platform_driver tps65912_driver = {
+       .driver = {
+               .name = "tps65912-pmic",
+               .owner = THIS_MODULE,
+       },
+       .probe = tps65912_probe,
+       .remove = __devexit_p(tps65912_remove),
+};
+
+/**
+ * tps65912_init
+ *
+ * Module init function
+ */
+static int __init tps65912_init(void)
+{
+       return platform_driver_register(&tps65912_driver);
+}
+subsys_initcall(tps65912_init);
+
+/**
+ * tps65912_cleanup
+ *
+ * Module exit function
+ */
+static void __exit tps65912_cleanup(void)
+{
+       platform_driver_unregister(&tps65912_driver);
+}
+module_exit(tps65912_cleanup);
+
+MODULE_AUTHOR("Margarita Olaya Cabrera <magi@slimlogic.co.uk>");
+MODULE_DESCRIPTION("TPS65912 voltage regulator driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:tps65912-pmic");
index d6702e5..dc8d022 100644 (file)
@@ -34,6 +34,9 @@ static LIST_HEAD(clock_list);
 static DEFINE_SPINLOCK(clock_lock);
 static DEFINE_MUTEX(clock_list_sem);
 
+/* clock disable operations are not passed on to hardware during boot */
+static int allow_disable;
+
 void clk_rate_table_build(struct clk *clk,
                          struct cpufreq_frequency_table *freq_table,
                          int nr_freqs,
@@ -228,7 +231,7 @@ static void __clk_disable(struct clk *clk)
                return;
 
        if (!(--clk->usecount)) {
-               if (likely(clk->ops && clk->ops->disable))
+               if (likely(allow_disable && clk->ops && clk->ops->disable))
                        clk->ops->disable(clk);
                if (likely(clk->parent))
                        __clk_disable(clk->parent);
@@ -393,7 +396,7 @@ int clk_register(struct clk *clk)
 {
        int ret;
 
-       if (clk == NULL || IS_ERR(clk))
+       if (IS_ERR_OR_NULL(clk))
                return -EINVAL;
 
        /*
@@ -744,3 +747,25 @@ err_out:
        return err;
 }
 late_initcall(clk_debugfs_init);
+
+static int __init clk_late_init(void)
+{
+       unsigned long flags;
+       struct clk *clk;
+
+       /* disable all clocks with zero use count */
+       mutex_lock(&clock_list_sem);
+       spin_lock_irqsave(&clock_lock, flags);
+
+       list_for_each_entry(clk, &clock_list, node)
+               if (!clk->usecount && clk->ops && clk->ops->disable)
+                       clk->ops->disable(clk);
+
+       /* from now on allow clock disable operations */
+       allow_disable = 1;
+
+       spin_unlock_irqrestore(&clock_lock, flags);
+       mutex_unlock(&clock_list_sem);
+       return 0;
+}
+late_initcall(clk_late_init);
index cb40b82..4dcb37b 100644 (file)
@@ -959,7 +959,7 @@ config SERIAL_IP22_ZILOG_CONSOLE
 
 config SERIAL_SH_SCI
        tristate "SuperH SCI(F) serial port support"
-       depends on HAVE_CLK && (SUPERH || H8300 || ARCH_SHMOBILE)
+       depends on HAVE_CLK && (SUPERH || ARCH_SHMOBILE)
        select SERIAL_CORE
 
 config SERIAL_SH_SCI_NR_UARTS
index ebd8629..d0a5623 100644 (file)
 #include <asm/sh_bios.h>
 #endif
 
-#ifdef CONFIG_H8300
-#include <asm/gpio.h>
-#endif
-
 #include "sh-sci.h"
 
 struct sci_port {
@@ -66,12 +62,6 @@ struct sci_port {
        /* Platform configuration */
        struct plat_sci_port    *cfg;
 
-       /* Port enable callback */
-       void                    (*enable)(struct uart_port *port);
-
-       /* Port disable callback */
-       void                    (*disable)(struct uart_port *port);
-
        /* Break timer */
        struct timer_list       break_timer;
        int                     break_flag;
@@ -81,6 +71,8 @@ struct sci_port {
        /* Function clock */
        struct clk              *fclk;
 
+       char                    *irqstr[SCIx_NR_IRQS];
+
        struct dma_chan                 *chan_tx;
        struct dma_chan                 *chan_rx;
 
@@ -121,6 +113,278 @@ to_sci_port(struct uart_port *uart)
        return container_of(uart, struct sci_port, port);
 }
 
+struct plat_sci_reg {
+       u8 offset, size;
+};
+
+/* Helper for invalidating specific entries of an inherited map. */
+#define sci_reg_invalid        { .offset = 0, .size = 0 }
+
+static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
+       [SCIx_PROBE_REGTYPE] = {
+               [0 ... SCIx_NR_REGS - 1] = sci_reg_invalid,
+       },
+
+       /*
+        * Common SCI definitions, dependent on the port's regshift
+        * value.
+        */
+       [SCIx_SCI_REGTYPE] = {
+               [SCSMR]         = { 0x00,  8 },
+               [SCBRR]         = { 0x01,  8 },
+               [SCSCR]         = { 0x02,  8 },
+               [SCxTDR]        = { 0x03,  8 },
+               [SCxSR]         = { 0x04,  8 },
+               [SCxRDR]        = { 0x05,  8 },
+               [SCFCR]         = sci_reg_invalid,
+               [SCFDR]         = sci_reg_invalid,
+               [SCTFDR]        = sci_reg_invalid,
+               [SCRFDR]        = sci_reg_invalid,
+               [SCSPTR]        = sci_reg_invalid,
+               [SCLSR]         = sci_reg_invalid,
+       },
+
+       /*
+        * Common definitions for legacy IrDA ports, dependent on
+        * regshift value.
+        */
+       [SCIx_IRDA_REGTYPE] = {
+               [SCSMR]         = { 0x00,  8 },
+               [SCBRR]         = { 0x01,  8 },
+               [SCSCR]         = { 0x02,  8 },
+               [SCxTDR]        = { 0x03,  8 },
+               [SCxSR]         = { 0x04,  8 },
+               [SCxRDR]        = { 0x05,  8 },
+               [SCFCR]         = { 0x06,  8 },
+               [SCFDR]         = { 0x07, 16 },
+               [SCTFDR]        = sci_reg_invalid,
+               [SCRFDR]        = sci_reg_invalid,
+               [SCSPTR]        = sci_reg_invalid,
+               [SCLSR]         = sci_reg_invalid,
+       },
+
+       /*
+        * Common SCIFA definitions.
+        */
+       [SCIx_SCIFA_REGTYPE] = {
+               [SCSMR]         = { 0x00, 16 },
+               [SCBRR]         = { 0x04,  8 },
+               [SCSCR]         = { 0x08, 16 },
+               [SCxTDR]        = { 0x20,  8 },
+               [SCxSR]         = { 0x14, 16 },
+               [SCxRDR]        = { 0x24,  8 },
+               [SCFCR]         = { 0x18, 16 },
+               [SCFDR]         = { 0x1c, 16 },
+               [SCTFDR]        = sci_reg_invalid,
+               [SCRFDR]        = sci_reg_invalid,
+               [SCSPTR]        = sci_reg_invalid,
+               [SCLSR]         = sci_reg_invalid,
+       },
+
+       /*
+        * Common SCIFB definitions.
+        */
+       [SCIx_SCIFB_REGTYPE] = {
+               [SCSMR]         = { 0x00, 16 },
+               [SCBRR]         = { 0x04,  8 },
+               [SCSCR]         = { 0x08, 16 },
+               [SCxTDR]        = { 0x40,  8 },
+               [SCxSR]         = { 0x14, 16 },
+               [SCxRDR]        = { 0x60,  8 },
+               [SCFCR]         = { 0x18, 16 },
+               [SCFDR]         = { 0x1c, 16 },
+               [SCTFDR]        = sci_reg_invalid,
+               [SCRFDR]        = sci_reg_invalid,
+               [SCSPTR]        = sci_reg_invalid,
+               [SCLSR]         = sci_reg_invalid,
+       },
+
+       /*
+        * Common SH-3 SCIF definitions.
+        */
+       [SCIx_SH3_SCIF_REGTYPE] = {
+               [SCSMR]         = { 0x00,  8 },
+               [SCBRR]         = { 0x02,  8 },
+               [SCSCR]         = { 0x04,  8 },
+               [SCxTDR]        = { 0x06,  8 },
+               [SCxSR]         = { 0x08, 16 },
+               [SCxRDR]        = { 0x0a,  8 },
+               [SCFCR]         = { 0x0c,  8 },
+               [SCFDR]         = { 0x0e, 16 },
+               [SCTFDR]        = sci_reg_invalid,
+               [SCRFDR]        = sci_reg_invalid,
+               [SCSPTR]        = sci_reg_invalid,
+               [SCLSR]         = sci_reg_invalid,
+       },
+
+       /*
+        * Common SH-4(A) SCIF(B) definitions.
+        */
+       [SCIx_SH4_SCIF_REGTYPE] = {
+               [SCSMR]         = { 0x00, 16 },
+               [SCBRR]         = { 0x04,  8 },
+               [SCSCR]         = { 0x08, 16 },
+               [SCxTDR]        = { 0x0c,  8 },
+               [SCxSR]         = { 0x10, 16 },
+               [SCxRDR]        = { 0x14,  8 },
+               [SCFCR]         = { 0x18, 16 },
+               [SCFDR]         = { 0x1c, 16 },
+               [SCTFDR]        = sci_reg_invalid,
+               [SCRFDR]        = sci_reg_invalid,
+               [SCSPTR]        = { 0x20, 16 },
+               [SCLSR]         = { 0x24, 16 },
+       },
+
+       /*
+        * Common SH-4(A) SCIF(B) definitions for ports without an SCSPTR
+        * register.
+        */
+       [SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE] = {
+               [SCSMR]         = { 0x00, 16 },
+               [SCBRR]         = { 0x04,  8 },
+               [SCSCR]         = { 0x08, 16 },
+               [SCxTDR]        = { 0x0c,  8 },
+               [SCxSR]         = { 0x10, 16 },
+               [SCxRDR]        = { 0x14,  8 },
+               [SCFCR]         = { 0x18, 16 },
+               [SCFDR]         = { 0x1c, 16 },
+               [SCTFDR]        = sci_reg_invalid,
+               [SCRFDR]        = sci_reg_invalid,
+               [SCSPTR]        = sci_reg_invalid,
+               [SCLSR]         = { 0x24, 16 },
+       },
+
+       /*
+        * Common SH-4(A) SCIF(B) definitions for ports with FIFO data
+        * count registers.
+        */
+       [SCIx_SH4_SCIF_FIFODATA_REGTYPE] = {
+               [SCSMR]         = { 0x00, 16 },
+               [SCBRR]         = { 0x04,  8 },
+               [SCSCR]         = { 0x08, 16 },
+               [SCxTDR]        = { 0x0c,  8 },
+               [SCxSR]         = { 0x10, 16 },
+               [SCxRDR]        = { 0x14,  8 },
+               [SCFCR]         = { 0x18, 16 },
+               [SCFDR]         = { 0x1c, 16 },
+               [SCTFDR]        = { 0x1c, 16 }, /* aliased to SCFDR */
+               [SCRFDR]        = { 0x20, 16 },
+               [SCSPTR]        = { 0x24, 16 },
+               [SCLSR]         = { 0x28, 16 },
+       },
+
+       /*
+        * SH7705-style SCIF(B) ports, lacking both SCSPTR and SCLSR
+        * registers.
+        */
+       [SCIx_SH7705_SCIF_REGTYPE] = {
+               [SCSMR]         = { 0x00, 16 },
+               [SCBRR]         = { 0x04,  8 },
+               [SCSCR]         = { 0x08, 16 },
+               [SCxTDR]        = { 0x20,  8 },
+               [SCxSR]         = { 0x14, 16 },
+               [SCxRDR]        = { 0x24,  8 },
+               [SCFCR]         = { 0x18, 16 },
+               [SCFDR]         = { 0x1c, 16 },
+               [SCTFDR]        = sci_reg_invalid,
+               [SCRFDR]        = sci_reg_invalid,
+               [SCSPTR]        = sci_reg_invalid,
+               [SCLSR]         = sci_reg_invalid,
+       },
+};
+
+#define sci_getreg(up, offset)         (sci_regmap[to_sci_port(up)->cfg->regtype] + offset)
+
+/*
+ * The "offset" here is rather misleading, in that it refers to an enum
+ * value relative to the port mapping rather than the fixed offset
+ * itself, which needs to be manually retrieved from the platform's
+ * register map for the given port.
+ */
+static unsigned int sci_serial_in(struct uart_port *p, int offset)
+{
+       struct plat_sci_reg *reg = sci_getreg(p, offset);
+
+       if (reg->size == 8)
+               return ioread8(p->membase + (reg->offset << p->regshift));
+       else if (reg->size == 16)
+               return ioread16(p->membase + (reg->offset << p->regshift));
+       else
+               WARN(1, "Invalid register access\n");
+
+       return 0;
+}
+
+static void sci_serial_out(struct uart_port *p, int offset, int value)
+{
+       struct plat_sci_reg *reg = sci_getreg(p, offset);
+
+       if (reg->size == 8)
+               iowrite8(value, p->membase + (reg->offset << p->regshift));
+       else if (reg->size == 16)
+               iowrite16(value, p->membase + (reg->offset << p->regshift));
+       else
+               WARN(1, "Invalid register access\n");
+}
+
+#define sci_in(up, offset)             (up->serial_in(up, offset))
+#define sci_out(up, offset, value)     (up->serial_out(up, offset, value))
+
+static int sci_probe_regmap(struct plat_sci_port *cfg)
+{
+       switch (cfg->type) {
+       case PORT_SCI:
+               cfg->regtype = SCIx_SCI_REGTYPE;
+               break;
+       case PORT_IRDA:
+               cfg->regtype = SCIx_IRDA_REGTYPE;
+               break;
+       case PORT_SCIFA:
+               cfg->regtype = SCIx_SCIFA_REGTYPE;
+               break;
+       case PORT_SCIFB:
+               cfg->regtype = SCIx_SCIFB_REGTYPE;
+               break;
+       case PORT_SCIF:
+               /*
+                * The SH-4 is a bit of a misnomer here, although that's
+                * where this particular port layout originated. This
+                * configuration (or some slight variation thereof)
+                * remains the dominant model for all SCIFs.
+                */
+               cfg->regtype = SCIx_SH4_SCIF_REGTYPE;
+               break;
+       default:
+               printk(KERN_ERR "Can't probe register map for given port\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void sci_port_enable(struct sci_port *sci_port)
+{
+       if (!sci_port->port.dev)
+               return;
+
+       pm_runtime_get_sync(sci_port->port.dev);
+
+       clk_enable(sci_port->iclk);
+       sci_port->port.uartclk = clk_get_rate(sci_port->iclk);
+       clk_enable(sci_port->fclk);
+}
+
+static void sci_port_disable(struct sci_port *sci_port)
+{
+       if (!sci_port->port.dev)
+               return;
+
+       clk_disable(sci_port->fclk);
+       clk_disable(sci_port->iclk);
+
+       pm_runtime_put_sync(sci_port->port.dev);
+}
+
 #if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
 
 #ifdef CONFIG_CONSOLE_POLL
@@ -164,223 +428,76 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c)
 }
 #endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */
 
-#if defined(__H8300H__) || defined(__H8300S__)
 static void sci_init_pins(struct uart_port *port, unsigned int cflag)
 {
-       int ch = (port->mapbase - SMR0) >> 3;
-
-       /* set DDR regs */
-       H8300_GPIO_DDR(h8300_sci_pins[ch].port,
-                      h8300_sci_pins[ch].rx,
-                      H8300_GPIO_INPUT);
-       H8300_GPIO_DDR(h8300_sci_pins[ch].port,
-                      h8300_sci_pins[ch].tx,
-                      H8300_GPIO_OUTPUT);
-
-       /* tx mark output*/
-       H8300_SCI_DR(ch) |= h8300_sci_pins[ch].tx;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
-       if (port->mapbase == 0xA4400000) {
-               __raw_writew(__raw_readw(PACR) & 0xffc0, PACR);
-               __raw_writew(__raw_readw(PBCR) & 0x0fff, PBCR);
-       } else if (port->mapbase == 0xA4410000)
-               __raw_writew(__raw_readw(PBCR) & 0xf003, PBCR);
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7720) || defined(CONFIG_CPU_SUBTYPE_SH7721)
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
-       unsigned short data;
-
-       if (cflag & CRTSCTS) {
-               /* enable RTS/CTS */
-               if (port->mapbase == 0xa4430000) { /* SCIF0 */
-                       /* Clear PTCR bit 9-2; enable all scif pins but sck */
-                       data = __raw_readw(PORT_PTCR);
-                       __raw_writew((data & 0xfc03), PORT_PTCR);
-               } else if (port->mapbase == 0xa4438000) { /* SCIF1 */
-                       /* Clear PVCR bit 9-2 */
-                       data = __raw_readw(PORT_PVCR);
-                       __raw_writew((data & 0xfc03), PORT_PVCR);
-               }
-       } else {
-               if (port->mapbase == 0xa4430000) { /* SCIF0 */
-                       /* Clear PTCR bit 5-2; enable only tx and rx  */
-                       data = __raw_readw(PORT_PTCR);
-                       __raw_writew((data & 0xffc3), PORT_PTCR);
-               } else if (port->mapbase == 0xa4438000) { /* SCIF1 */
-                       /* Clear PVCR bit 5-2 */
-                       data = __raw_readw(PORT_PVCR);
-                       __raw_writew((data & 0xffc3), PORT_PVCR);
-               }
-       }
-}
-#elif defined(CONFIG_CPU_SH3)
-/* For SH7705, SH7706, SH7707, SH7709, SH7709A, SH7729 */
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
-       unsigned short data;
-
-       /* We need to set SCPCR to enable RTS/CTS */
-       data = __raw_readw(SCPCR);
-       /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/
-       __raw_writew(data & 0x0fcf, SCPCR);
-
-       if (!(cflag & CRTSCTS)) {
-               /* We need to set SCPCR to enable RTS/CTS */
-               data = __raw_readw(SCPCR);
-               /* Clear out SCP7MD1,0, SCP4MD1,0,
-                  Set SCP6MD1,0 = {01} (output)  */
-               __raw_writew((data & 0x0fcf) | 0x1000, SCPCR);
+       struct sci_port *s = to_sci_port(port);
+       struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR;
 
-               data = __raw_readb(SCPDR);
-               /* Set /RTS2 (bit6) = 0 */
-               __raw_writeb(data & 0xbf, SCPDR);
+       /*
+        * Use port-specific handler if provided.
+        */
+       if (s->cfg->ops && s->cfg->ops->init_pins) {
+               s->cfg->ops->init_pins(port, cflag);
+               return;
        }
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
-       unsigned short data;
 
-       if (port->mapbase == 0xffe00000) {
-               data = __raw_readw(PSCR);
-               data &= ~0x03cf;
-               if (!(cflag & CRTSCTS))
-                       data |= 0x0340;
+       /*
+        * For the generic path SCSPTR is necessary. Bail out if that's
+        * unavailable, too.
+        */
+       if (!reg->size)
+               return;
 
-               __raw_writew(data, PSCR);
-       }
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7757) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7763) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7780) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7785) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7786) || \
-      defined(CONFIG_CPU_SUBTYPE_SHX3)
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
-       if (!(cflag & CRTSCTS))
-               __raw_writew(0x0080, SCSPTR0); /* Set RTS = 1 */
-}
-#elif defined(CONFIG_CPU_SH4) && !defined(CONFIG_CPU_SH4A)
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
        if (!(cflag & CRTSCTS))
-               __raw_writew(0x0080, SCSPTR2); /* Set RTS = 1 */
+               sci_out(port, SCSPTR, 0x0080); /* Set RTS = 1 */
 }
-#else
-static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
-{
-       /* Nothing to do */
-}
-#endif
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7760) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7780) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7785) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7786)
-static int scif_txfill(struct uart_port *port)
+static int sci_txfill(struct uart_port *port)
 {
-       return sci_in(port, SCTFDR) & 0xff;
-}
+       struct plat_sci_reg *reg;
 
-static int scif_txroom(struct uart_port *port)
-{
-       return SCIF_TXROOM_MAX - scif_txfill(port);
-}
-
-static int scif_rxfill(struct uart_port *port)
-{
-       return sci_in(port, SCRFDR) & 0xff;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
-static int scif_txfill(struct uart_port *port)
-{
-       if (port->mapbase == 0xffe00000 ||
-           port->mapbase == 0xffe08000)
-               /* SCIF0/1*/
+       reg = sci_getreg(port, SCTFDR);
+       if (reg->size)
                return sci_in(port, SCTFDR) & 0xff;
-       else
-               /* SCIF2 */
+
+       reg = sci_getreg(port, SCFDR);
+       if (reg->size)
                return sci_in(port, SCFDR) >> 8;
-}
 
-static int scif_txroom(struct uart_port *port)
-{
-       if (port->mapbase == 0xffe00000 ||
-           port->mapbase == 0xffe08000)
-               /* SCIF0/1*/
-               return SCIF_TXROOM_MAX - scif_txfill(port);
-       else
-               /* SCIF2 */
-               return SCIF2_TXROOM_MAX - scif_txfill(port);
+       return !(sci_in(port, SCxSR) & SCI_TDRE);
 }
 
-static int scif_rxfill(struct uart_port *port)
-{
-       if ((port->mapbase == 0xffe00000) ||
-           (port->mapbase == 0xffe08000)) {
-               /* SCIF0/1*/
-               return sci_in(port, SCRFDR) & 0xff;
-       } else {
-               /* SCIF2 */
-               return sci_in(port, SCFDR) & SCIF2_RFDC_MASK;
-       }
-}
-#elif defined(CONFIG_ARCH_SH7372)
-static int scif_txfill(struct uart_port *port)
+static int sci_txroom(struct uart_port *port)
 {
-       if (port->type == PORT_SCIFA)
-               return sci_in(port, SCFDR) >> 8;
-       else
-               return sci_in(port, SCTFDR);
+       return port->fifosize - sci_txfill(port);
 }
 
-static int scif_txroom(struct uart_port *port)
+static int sci_rxfill(struct uart_port *port)
 {
-       return port->fifosize - scif_txfill(port);
-}
+       struct plat_sci_reg *reg;
 
-static int scif_rxfill(struct uart_port *port)
-{
-       if (port->type == PORT_SCIFA)
-               return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
-       else
-               return sci_in(port, SCRFDR);
-}
-#else
-static int scif_txfill(struct uart_port *port)
-{
-       return sci_in(port, SCFDR) >> 8;
-}
+       reg = sci_getreg(port, SCRFDR);
+       if (reg->size)
+               return sci_in(port, SCRFDR) & 0xff;
 
-static int scif_txroom(struct uart_port *port)
-{
-       return SCIF_TXROOM_MAX - scif_txfill(port);
-}
+       reg = sci_getreg(port, SCFDR);
+       if (reg->size)
+               return sci_in(port, SCFDR) & ((port->fifosize << 1) - 1);
 
-static int scif_rxfill(struct uart_port *port)
-{
-       return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
+       return (sci_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
 }
-#endif
 
-static int sci_txfill(struct uart_port *port)
+/*
+ * SCI helper for checking the state of the muxed port/RXD pins.
+ */
+static inline int sci_rxd_in(struct uart_port *port)
 {
-       return !(sci_in(port, SCxSR) & SCI_TDRE);
-}
+       struct sci_port *s = to_sci_port(port);
 
-static int sci_txroom(struct uart_port *port)
-{
-       return !sci_txfill(port);
-}
+       if (s->cfg->port_reg <= 0)
+               return 1;
 
-static int sci_rxfill(struct uart_port *port)
-{
-       return (sci_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
+       return !!__raw_readb(s->cfg->port_reg);
 }
 
 /* ********************************************************************** *
@@ -406,10 +523,7 @@ static void sci_transmit_chars(struct uart_port *port)
                return;
        }
 
-       if (port->type == PORT_SCI)
-               count = sci_txroom(port);
-       else
-               count = scif_txroom(port);
+       count = sci_txroom(port);
 
        do {
                unsigned char c;
@@ -464,13 +578,8 @@ static void sci_receive_chars(struct uart_port *port)
                return;
 
        while (1) {
-               if (port->type == PORT_SCI)
-                       count = sci_rxfill(port);
-               else
-                       count = scif_rxfill(port);
-
                /* Don't copy more bytes than there is room for in the buffer */
-               count = tty_buffer_request_room(tty, count);
+               count = tty_buffer_request_room(tty, sci_rxfill(port));
 
                /* If for any reason we can't copy more data, we're done! */
                if (count == 0)
@@ -561,8 +670,7 @@ static void sci_break_timer(unsigned long data)
 {
        struct sci_port *port = (struct sci_port *)data;
 
-       if (port->enable)
-               port->enable(&port->port);
+       sci_port_enable(port);
 
        if (sci_rxd_in(&port->port) == 0) {
                port->break_flag = 1;
@@ -574,8 +682,7 @@ static void sci_break_timer(unsigned long data)
        } else
                port->break_flag = 0;
 
-       if (port->disable)
-               port->disable(&port->port);
+       sci_port_disable(port);
 }
 
 static int sci_handle_errors(struct uart_port *port)
@@ -583,13 +690,19 @@ static int sci_handle_errors(struct uart_port *port)
        int copied = 0;
        unsigned short status = sci_in(port, SCxSR);
        struct tty_struct *tty = port->state->port.tty;
+       struct sci_port *s = to_sci_port(port);
 
-       if (status & SCxSR_ORER(port)) {
-               /* overrun error */
-               if (tty_insert_flip_char(tty, 0, TTY_OVERRUN))
-                       copied++;
+       /*
+        * Handle overruns, if supported.
+        */
+       if (s->cfg->overrun_bit != SCIx_NOT_SUPPORTED) {
+               if (status & (1 << s->cfg->overrun_bit)) {
+                       /* overrun error */
+                       if (tty_insert_flip_char(tty, 0, TTY_OVERRUN))
+                               copied++;
 
-               dev_notice(port->dev, "overrun error");
+                       dev_notice(port->dev, "overrun error");
+               }
        }
 
        if (status & SCxSR_FER(port)) {
@@ -637,12 +750,15 @@ static int sci_handle_errors(struct uart_port *port)
 static int sci_handle_fifo_overrun(struct uart_port *port)
 {
        struct tty_struct *tty = port->state->port.tty;
+       struct sci_port *s = to_sci_port(port);
+       struct plat_sci_reg *reg;
        int copied = 0;
 
-       if (port->type != PORT_SCIF)
+       reg = sci_getreg(port, SCLSR);
+       if (!reg->size)
                return 0;
 
-       if ((sci_in(port, SCLSR) & SCIF_ORER) != 0) {
+       if ((sci_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) {
                sci_out(port, SCLSR, 0);
 
                tty_insert_flip_char(tty, 0, TTY_OVERRUN);
@@ -840,74 +956,102 @@ static int sci_notifier(struct notifier_block *self,
        return NOTIFY_OK;
 }
 
-static void sci_clk_enable(struct uart_port *port)
-{
-       struct sci_port *sci_port = to_sci_port(port);
-
-       pm_runtime_get_sync(port->dev);
+static struct sci_irq_desc {
+       const char      *desc;
+       irq_handler_t   handler;
+} sci_irq_desc[] = {
+       /*
+        * Split out handlers, the default case.
+        */
+       [SCIx_ERI_IRQ] = {
+               .desc = "rx err",
+               .handler = sci_er_interrupt,
+       },
 
-       clk_enable(sci_port->iclk);
-       sci_port->port.uartclk = clk_get_rate(sci_port->iclk);
-       clk_enable(sci_port->fclk);
-}
+       [SCIx_RXI_IRQ] = {
+               .desc = "rx full",
+               .handler = sci_rx_interrupt,
+       },
 
-static void sci_clk_disable(struct uart_port *port)
-{
-       struct sci_port *sci_port = to_sci_port(port);
+       [SCIx_TXI_IRQ] = {
+               .desc = "tx empty",
+               .handler = sci_tx_interrupt,
+       },
 
-       clk_disable(sci_port->fclk);
-       clk_disable(sci_port->iclk);
+       [SCIx_BRI_IRQ] = {
+               .desc = "break",
+               .handler = sci_br_interrupt,
+       },
 
-       pm_runtime_put_sync(port->dev);
-}
+       /*
+        * Special muxed handler.
+        */
+       [SCIx_MUX_IRQ] = {
+               .desc = "mux",
+               .handler = sci_mpxed_interrupt,
+       },
+};
 
 static int sci_request_irq(struct sci_port *port)
 {
-       int i;
-       irqreturn_t (*handlers[4])(int irq, void *ptr) = {
-               sci_er_interrupt, sci_rx_interrupt, sci_tx_interrupt,
-               sci_br_interrupt,
-       };
-       const char *desc[] = { "SCI Receive Error", "SCI Receive Data Full",
-                              "SCI Transmit Data Empty", "SCI Break" };
-
-       if (port->cfg->irqs[0] == port->cfg->irqs[1]) {
-               if (unlikely(!port->cfg->irqs[0]))
-                       return -ENODEV;
-
-               if (request_irq(port->cfg->irqs[0], sci_mpxed_interrupt,
-                               IRQF_DISABLED, "sci", port)) {
-                       dev_err(port->port.dev, "Can't allocate IRQ\n");
-                       return -ENODEV;
+       struct uart_port *up = &port->port;
+       int i, j, ret = 0;
+
+       for (i = j = 0; i < SCIx_NR_IRQS; i++, j++) {
+               struct sci_irq_desc *desc;
+               unsigned int irq;
+
+               if (SCIx_IRQ_IS_MUXED(port)) {
+                       i = SCIx_MUX_IRQ;
+                       irq = up->irq;
+               } else
+                       irq = port->cfg->irqs[i];
+
+               desc = sci_irq_desc + i;
+               port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s",
+                                           dev_name(up->dev), desc->desc);
+               if (!port->irqstr[j]) {
+                       dev_err(up->dev, "Failed to allocate %s IRQ string\n",
+                               desc->desc);
+                       goto out_nomem;
                }
-       } else {
-               for (i = 0; i < ARRAY_SIZE(handlers); i++) {
-                       if (unlikely(!port->cfg->irqs[i]))
-                               continue;
-
-                       if (request_irq(port->cfg->irqs[i], handlers[i],
-                                       IRQF_DISABLED, desc[i], port)) {
-                               dev_err(port->port.dev, "Can't allocate IRQ\n");
-                               return -ENODEV;
-                       }
+
+               ret = request_irq(irq, desc->handler, up->irqflags,
+                                 port->irqstr[j], port);
+               if (unlikely(ret)) {
+                       dev_err(up->dev, "Can't allocate %s IRQ\n", desc->desc);
+                       goto out_noirq;
                }
        }
 
        return 0;
+
+out_noirq:
+       while (--i >= 0)
+               free_irq(port->cfg->irqs[i], port);
+
+out_nomem:
+       while (--j >= 0)
+               kfree(port->irqstr[j]);
+
+       return ret;
 }
 
 static void sci_free_irq(struct sci_port *port)
 {
        int i;
 
-       if (port->cfg->irqs[0] == port->cfg->irqs[1])
-               free_irq(port->cfg->irqs[0], port);
-       else {
-               for (i = 0; i < ARRAY_SIZE(port->cfg->irqs); i++) {
-                       if (!port->cfg->irqs[i])
-                               continue;
+       /*
+        * Intentionally in reverse order so we iterate over the muxed
+        * IRQ first.
+        */
+       for (i = 0; i < SCIx_NR_IRQS; i++) {
+               free_irq(port->cfg->irqs[i], port);
+               kfree(port->irqstr[i]);
 
-                       free_irq(port->cfg->irqs[i], port);
+               if (SCIx_IRQ_IS_MUXED(port)) {
+                       /* If there's only one IRQ, we're done. */
+                       return;
                }
        }
 }
@@ -915,7 +1059,7 @@ static void sci_free_irq(struct sci_port *port)
 static unsigned int sci_tx_empty(struct uart_port *port)
 {
        unsigned short status = sci_in(port, SCxSR);
-       unsigned short in_tx_fifo = scif_txfill(port);
+       unsigned short in_tx_fifo = sci_txfill(port);
 
        return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
 }
@@ -1438,8 +1582,7 @@ static int sci_startup(struct uart_port *port)
 
        dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
 
-       if (s->enable)
-               s->enable(port);
+       sci_port_enable(s);
 
        ret = sci_request_irq(s);
        if (unlikely(ret < 0))
@@ -1465,8 +1608,7 @@ static void sci_shutdown(struct uart_port *port)
        sci_free_dma(port);
        sci_free_irq(s);
 
-       if (s->disable)
-               s->disable(port);
+       sci_port_disable(s);
 }
 
 static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
@@ -1513,8 +1655,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
        if (likely(baud && port->uartclk))
                t = sci_scbrr_calc(s->cfg->scbrr_algo_id, baud, port->uartclk);
 
-       if (s->enable)
-               s->enable(port);
+       sci_port_enable(s);
 
        do {
                status = sci_in(port, SCxSR);
@@ -1584,8 +1725,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
        if ((termios->c_cflag & CREAD) != 0)
                sci_start_rx(port);
 
-       if (s->disable)
-               s->disable(port);
+       sci_port_disable(s);
 }
 
 static const char *sci_type(struct uart_port *port)
@@ -1726,6 +1866,7 @@ static int __devinit sci_init_single(struct platform_device *dev,
                                     struct plat_sci_port *p)
 {
        struct uart_port *port = &sci_port->port;
+       int ret;
 
        port->ops       = &sci_uart_ops;
        port->iotype    = UPIO_MEM;
@@ -1746,6 +1887,12 @@ static int __devinit sci_init_single(struct platform_device *dev,
                break;
        }
 
+       if (p->regtype == SCIx_PROBE_REGTYPE) {
+               ret = sci_probe_regmap(p);
+               if (unlikely(!ret))
+                       return ret;
+       }
+
        if (dev) {
                sci_port->iclk = clk_get(&dev->dev, "sci_ick");
                if (IS_ERR(sci_port->iclk)) {
@@ -1764,8 +1911,6 @@ static int __devinit sci_init_single(struct platform_device *dev,
                if (IS_ERR(sci_port->fclk))
                        sci_port->fclk = NULL;
 
-               sci_port->enable = sci_clk_enable;
-               sci_port->disable = sci_clk_disable;
                port->dev = &dev->dev;
 
                pm_runtime_enable(&dev->dev);
@@ -1775,20 +1920,51 @@ static int __devinit sci_init_single(struct platform_device *dev,
        sci_port->break_timer.function = sci_break_timer;
        init_timer(&sci_port->break_timer);
 
+       /*
+        * Establish some sensible defaults for the error detection.
+        */
+       if (!p->error_mask)
+               p->error_mask = (p->type == PORT_SCI) ?
+                       SCI_DEFAULT_ERROR_MASK : SCIF_DEFAULT_ERROR_MASK;
+
+       /*
+        * Establish sensible defaults for the overrun detection, unless
+        * the part has explicitly disabled support for it.
+        */
+       if (p->overrun_bit != SCIx_NOT_SUPPORTED) {
+               if (p->type == PORT_SCI)
+                       p->overrun_bit = 5;
+               else if (p->scbrr_algo_id == SCBRR_ALGO_4)
+                       p->overrun_bit = 9;
+               else
+                       p->overrun_bit = 0;
+
+               /*
+                * Make the error mask inclusive of overrun detection, if
+                * supported.
+                */
+               p->error_mask |= (1 << p->overrun_bit);
+       }
+
        sci_port->cfg           = p;
 
        port->mapbase           = p->mapbase;
        port->type              = p->type;
        port->flags             = p->flags;
+       port->regshift          = p->regshift;
 
        /*
-        * The UART port needs an IRQ value, so we peg this to the TX IRQ
+        * The UART port needs an IRQ value, so we peg this to the RX IRQ
         * for the multi-IRQ ports, which is where we are primarily
         * concerned with the shutdown path synchronization.
         *
         * For the muxed case there's nothing more to do.
         */
        port->irq               = p->irqs[SCIx_RXI_IRQ];
+       port->irqflags          = IRQF_DISABLED;
+
+       port->serial_in         = sci_serial_in;
+       port->serial_out        = sci_serial_out;
 
        if (p->dma_dev)
                dev_dbg(port->dev, "DMA device %p, tx %d, rx %d\n",
@@ -1814,8 +1990,7 @@ static void serial_console_write(struct console *co, const char *s,
        struct uart_port *port = &sci_port->port;
        unsigned short bits;
 
-       if (sci_port->enable)
-               sci_port->enable(port);
+       sci_port_enable(sci_port);
 
        uart_console_write(port, s, count, serial_console_putchar);
 
@@ -1824,8 +1999,7 @@ static void serial_console_write(struct console *co, const char *s,
        while ((sci_in(port, SCxSR) & bits) != bits)
                cpu_relax();
 
-       if (sci_port->disable)
-               sci_port->disable(port);
+       sci_port_disable(sci_port);
 }
 
 static int __devinit serial_console_setup(struct console *co, char *options)
@@ -1857,20 +2031,13 @@ static int __devinit serial_console_setup(struct console *co, char *options)
        if (unlikely(ret != 0))
                return ret;
 
-       if (sci_port->enable)
-               sci_port->enable(port);
+       sci_port_enable(sci_port);
 
        if (options)
                uart_parse_options(options, &baud, &parity, &bits, &flow);
 
-       ret = uart_set_options(port, co, baud, parity, bits, flow);
-#if defined(__H8300H__) || defined(__H8300S__)
-       /* disable rx interrupt */
-       if (ret == 0)
-               sci_stop_rx(port);
-#endif
        /* TODO: disable clock */
-       return ret;
+       return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
 static struct console serial_console = {
@@ -2081,3 +2248,5 @@ module_exit(sci_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:sh-sci");
+MODULE_AUTHOR("Paul Mundt");
+MODULE_DESCRIPTION("SuperH SCI(F) serial driver");
index b04d937..e9bed03 100644 (file)
 #include <linux/io.h>
 #include <linux/gpio.h>
 
-#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
-#include <asm/regs306x.h>
-#endif
-#if defined(CONFIG_H8S2678)
-#include <asm/regs267x.h>
-#endif
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7707) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7708) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7709)
-# define SCPCR  0xA4000116 /* 16 bit SCI and SCIF */
-# define SCPDR  0xA4000136 /* 8  bit SCI and SCIF */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
-# define SCIF0         0xA4400000
-# define SCIF2         0xA4410000
-# define SCPCR 0xA4000116
-# define SCPDR 0xA4000136
-#elif defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-      defined(CONFIG_ARCH_SH73A0) || \
-      defined(CONFIG_ARCH_SH7367) || \
-      defined(CONFIG_ARCH_SH7377) || \
-      defined(CONFIG_ARCH_SH7372)
-# define PORT_PTCR        0xA405011EUL
-# define PORT_PVCR        0xA4050122UL
-# define SCIF_ORER        0x0200   /* overrun error bit */
-#elif defined(CONFIG_SH_RTS7751R2D)
-# define SCSPTR1 0xFFE0001C /* 8 bit SCIF */
-# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001   /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750)  || \
-      defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7091)  || \
-      defined(CONFIG_CPU_SUBTYPE_SH7751)  || \
-      defined(CONFIG_CPU_SUBTYPE_SH7751R)
-# define SCSPTR1 0xffe0001c /* 8  bit SCI */
-# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001   /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
-# define SCSPTR0 0xfe600024 /* 16 bit SCIF */
-# define SCSPTR1 0xfe610024 /* 16 bit SCIF */
-# define SCSPTR2 0xfe620024 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001  /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
-# define SCSPTR0 0xA4400000      /* 16 bit SCIF */
-# define SCIF_ORER 0x0001   /* overrun error bit */
-# define PACR 0xa4050100
-# define PBCR 0xa4050102
-#elif defined(CONFIG_CPU_SUBTYPE_SH7343)
-# define SCSPTR0 0xffe00010    /* 16 bit SCIF */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
-# define PADR                  0xA4050120
-# define PSDR                  0xA405013e
-# define PWDR                  0xA4050166
-# define PSCR                  0xA405011E
-# define SCIF_ORER             0x0001  /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7366)
-# define SCPDR0                        0xA405013E      /* 16 bit SCIF0 PSDR */
-# define SCSPTR0               SCPDR0
-# define SCIF_ORER             0x0001  /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
-# define SCSPTR0                0xa4050160
-# define SCIF_ORER              0x0001  /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
-# define SCIF_ORER              0x0001  /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
-# define SCSPTR2 0xffe80020 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001   /* overrun error bit */
-#elif defined(CONFIG_H83007) || defined(CONFIG_H83068)
-# define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port)
-#elif defined(CONFIG_H8S2678)
-# define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7757)
-# define SCSPTR0 0xfe4b0020
-# define SCIF_ORER 0x0001
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
-# define SCSPTR0 0xffe00024 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001  /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
-# define SCSPTR0 0xff923020 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001  /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
-# define SCSPTR0       0xffe00024      /* 16 bit SCIF */
-# define SCIF_ORER     0x0001          /* Overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7786)
-# define SCSPTR0       0xffea0024      /* 16 bit SCIF */
-# define SCIF_ORER     0x0001          /* Overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7203) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7206) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7263)
-# define SCSPTR0 0xfffe8020 /* 16 bit SCIF */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
-# define SCSPTR0 0xf8400020 /* 16 bit SCIF */
-# define SCIF_ORER 0x0001  /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
-# define SCSPTR0 0xffc30020            /* 16 bit SCIF */
-# define SCIF_ORER 0x0001              /* Overrun error bit */
-#else
-# error CPU subtype not defined
-#endif
-
-/* SCxSR SCI */
-#define SCI_TDRE  0x80 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_RDRF  0x40 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_ORER  0x20 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_FER   0x10 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_PER   0x08 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-#define SCI_TEND  0x04 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-/*      SCI_MPB   0x02  * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-/*      SCI_MPBT  0x01  * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
-
-#define SCI_ERRORS ( SCI_PER | SCI_FER | SCI_ORER)
-
-/* SCxSR SCIF */
-#define SCIF_ER    0x0080 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_TEND  0x0040 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_TDFE  0x0020 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_BRK   0x0010 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_FER   0x0008 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_PER   0x0004 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_RDF   0x0002 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-#define SCIF_DR    0x0001 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-    defined(CONFIG_ARCH_SH73A0) || \
-    defined(CONFIG_ARCH_SH7367) || \
-    defined(CONFIG_ARCH_SH7377) || \
-    defined(CONFIG_ARCH_SH7372)
-# define SCIF_ORER    0x0200
-# define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK | SCIF_ORER)
-# define SCIF_RFDC_MASK 0x007f
-# define SCIF_TXROOM_MAX 64
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
-# define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK )
-# define SCIF_RFDC_MASK 0x007f
-# define SCIF_TXROOM_MAX 64
-/* SH7763 SCIF2 support */
-# define SCIF2_RFDC_MASK 0x001f
-# define SCIF2_TXROOM_MAX 16
-#else
-# define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
-# define SCIF_RFDC_MASK 0x001f
-# define SCIF_TXROOM_MAX 16
-#endif
-
-#ifndef SCIF_ORER
-#define SCIF_ORER      0x0000
-#endif
-
 #define SCxSR_TEND(port)       (((port)->type == PORT_SCI) ? SCI_TEND   : SCIF_TEND)
-#define SCxSR_ERRORS(port)     (((port)->type == PORT_SCI) ? SCI_ERRORS : SCIF_ERRORS)
 #define SCxSR_RDxF(port)       (((port)->type == PORT_SCI) ? SCI_RDRF   : SCIF_RDF)
 #define SCxSR_TDxE(port)       (((port)->type == PORT_SCI) ? SCI_TDRE   : SCIF_TDFE)
 #define SCxSR_FER(port)                (((port)->type == PORT_SCI) ? SCI_FER    : SCIF_FER)
 #define SCxSR_PER(port)                (((port)->type == PORT_SCI) ? SCI_PER    : SCIF_PER)
 #define SCxSR_BRK(port)                (((port)->type == PORT_SCI) ? 0x00       : SCIF_BRK)
-#define SCxSR_ORER(port)       (((port)->type == PORT_SCI) ? SCI_ORER   : SCIF_ORER)
+
+#define SCxSR_ERRORS(port)     (to_sci_port(port)->cfg->error_mask)
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
     defined(CONFIG_CPU_SUBTYPE_SH7720) || \
 
 #define SCI_MAJOR              204
 #define SCI_MINOR_START                8
-
-#define SCI_IN(size, offset)                                   \
-  if ((size) == 8) {                                           \
-    return ioread8(port->membase + (offset));                  \
-  } else {                                                     \
-    return ioread16(port->membase + (offset));                 \
-  }
-#define SCI_OUT(size, offset, value)                           \
-  if ((size) == 8) {                                           \
-    iowrite8(value, port->membase + (offset));                 \
-  } else if ((size) == 16) {                                   \
-    iowrite16(value, port->membase + (offset));                        \
-  }
-
-#define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\
-  static inline unsigned int sci_##name##_in(struct uart_port *port)   \
-  {                                                                    \
-    if (port->type == PORT_SCIF || port->type == PORT_SCIFB) {         \
-      SCI_IN(scif_size, scif_offset)                                   \
-    } else {   /* PORT_SCI or PORT_SCIFA */                            \
-      SCI_IN(sci_size, sci_offset);                                    \
-    }                                                                  \
-  }                                                                    \
-  static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
-  {                                                                    \
-    if (port->type == PORT_SCIF || port->type == PORT_SCIFB) {         \
-      SCI_OUT(scif_size, scif_offset, value)                           \
-    } else {   /* PORT_SCI or PORT_SCIFA */                            \
-      SCI_OUT(sci_size, sci_offset, value);                            \
-    }                                                                  \
-  }
-
-#ifdef CONFIG_H8300
-/* h8300 don't have SCIF */
-#define CPU_SCIF_FNS(name)                                             \
-  static inline unsigned int sci_##name##_in(struct uart_port *port)   \
-  {                                                                    \
-    return 0;                                                          \
-  }                                                                    \
-  static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
-  {                                                                    \
-  }
-#else
-#define CPU_SCIF_FNS(name, scif_offset, scif_size)                     \
-  static inline unsigned int sci_##name##_in(struct uart_port *port)   \
-  {                                                                    \
-    SCI_IN(scif_size, scif_offset);                                    \
-  }                                                                    \
-  static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
-  {                                                                    \
-    SCI_OUT(scif_size, scif_offset, value);                            \
-  }
-#endif
-
-#define CPU_SCI_FNS(name, sci_offset, sci_size)                                \
-  static inline unsigned int sci_##name##_in(struct uart_port* port)   \
-  {                                                                    \
-    SCI_IN(sci_size, sci_offset);                                      \
-  }                                                                    \
-  static inline void sci_##name##_out(struct uart_port* port, unsigned int value) \
-  {                                                                    \
-    SCI_OUT(sci_size, sci_offset, value);                              \
-  }
-
-#if defined(CONFIG_CPU_SH3) || \
-    defined(CONFIG_ARCH_SH73A0) || \
-    defined(CONFIG_ARCH_SH7367) || \
-    defined(CONFIG_ARCH_SH7377) || \
-    defined(CONFIG_ARCH_SH7372)
-#if defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
-#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
-                               sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
-                                h8_sci_offset, h8_sci_size) \
-  CPU_SCIx_FNS(name, sh4_sci_offset, sh4_sci_size, sh4_scif_offset, sh4_scif_size)
-#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \
-         CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-      defined(CONFIG_ARCH_SH7367)
-#define SCIF_FNS(name, scif_offset, scif_size) \
-  CPU_SCIF_FNS(name, scif_offset, scif_size)
-#elif defined(CONFIG_ARCH_SH7377) || \
-      defined(CONFIG_ARCH_SH7372) || \
-      defined(CONFIG_ARCH_SH73A0)
-#define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) \
-  CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size)
-#define SCIF_FNS(name, scif_offset, scif_size) \
-  CPU_SCIF_FNS(name, scif_offset, scif_size)
-#else
-#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
-                sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
-                 h8_sci_offset, h8_sci_size) \
-  CPU_SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh3_scif_offset, sh3_scif_size)
-#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \
-  CPU_SCIF_FNS(name, sh3_scif_offset, sh3_scif_size)
-#endif
-#elif defined(__H8300H__) || defined(__H8300S__)
-#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
-                sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
-                 h8_sci_offset, h8_sci_size) \
-  CPU_SCI_FNS(name, h8_sci_offset, h8_sci_size)
-#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \
-  CPU_SCIF_FNS(name)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\
-      defined(CONFIG_CPU_SUBTYPE_SH7724)
-        #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) \
-                CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size)
-        #define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \
-                CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
-#else
-#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
-                sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
-                h8_sci_offset, h8_sci_size) \
-  CPU_SCIx_FNS(name, sh4_sci_offset, sh4_sci_size, sh4_scif_offset, sh4_scif_size)
-#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \
-  CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
-#endif
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-    defined(CONFIG_ARCH_SH7367)
-
-SCIF_FNS(SCSMR,  0x00, 16)
-SCIF_FNS(SCBRR,  0x04,  8)
-SCIF_FNS(SCSCR,  0x08, 16)
-SCIF_FNS(SCxSR,  0x14, 16)
-SCIF_FNS(SCFCR,  0x18, 16)
-SCIF_FNS(SCFDR,  0x1c, 16)
-SCIF_FNS(SCxTDR, 0x20,  8)
-SCIF_FNS(SCxRDR, 0x24,  8)
-SCIF_FNS(SCLSR,  0x00,  0)
-#elif defined(CONFIG_ARCH_SH7377) || \
-      defined(CONFIG_ARCH_SH7372) || \
-      defined(CONFIG_ARCH_SH73A0)
-SCIF_FNS(SCSMR,  0x00, 16)
-SCIF_FNS(SCBRR,  0x04,  8)
-SCIF_FNS(SCSCR,  0x08, 16)
-SCIF_FNS(SCTDSR, 0x0c, 16)
-SCIF_FNS(SCFER,  0x10, 16)
-SCIF_FNS(SCxSR,  0x14, 16)
-SCIF_FNS(SCFCR,  0x18, 16)
-SCIF_FNS(SCFDR,  0x1c, 16)
-SCIF_FNS(SCTFDR, 0x38, 16)
-SCIF_FNS(SCRFDR, 0x3c, 16)
-SCIx_FNS(SCxTDR, 0x20,  8, 0x40,  8)
-SCIx_FNS(SCxRDR, 0x24,  8, 0x60,  8)
-SCIF_FNS(SCLSR,  0x00,  0)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\
-      defined(CONFIG_CPU_SUBTYPE_SH7724)
-SCIx_FNS(SCSMR,  0x00, 16, 0x00, 16)
-SCIx_FNS(SCBRR,  0x04,  8, 0x04,  8)
-SCIx_FNS(SCSCR,  0x08, 16, 0x08, 16)
-SCIx_FNS(SCxTDR, 0x20,  8, 0x0c,  8)
-SCIx_FNS(SCxSR,  0x14, 16, 0x10, 16)
-SCIx_FNS(SCxRDR, 0x24,  8, 0x14,  8)
-SCIx_FNS(SCSPTR, 0,     0,    0,  0)
-SCIF_FNS(SCFCR,  0x18, 16)
-SCIF_FNS(SCFDR,  0x1c, 16)
-SCIF_FNS(SCLSR,  0x24, 16)
-#else
-/*      reg      SCI/SH3   SCI/SH4  SCIF/SH3   SCIF/SH4  SCI/H8*/
-/*      name     off  sz   off  sz   off  sz   off  sz   off  sz*/
-SCIx_FNS(SCSMR,  0x00,  8, 0x00,  8, 0x00,  8, 0x00, 16, 0x00,  8)
-SCIx_FNS(SCBRR,  0x02,  8, 0x04,  8, 0x02,  8, 0x04,  8, 0x01,  8)
-SCIx_FNS(SCSCR,  0x04,  8, 0x08,  8, 0x04,  8, 0x08, 16, 0x02,  8)
-SCIx_FNS(SCxTDR, 0x06,  8, 0x0c,  8, 0x06,  8, 0x0C,  8, 0x03,  8)
-SCIx_FNS(SCxSR,  0x08,  8, 0x10,  8, 0x08, 16, 0x10, 16, 0x04,  8)
-SCIx_FNS(SCxRDR, 0x0a,  8, 0x14,  8, 0x0A,  8, 0x14,  8, 0x05,  8)
-SCIF_FNS(SCFCR,                      0x0c,  8, 0x18, 16)
-#if defined(CONFIG_CPU_SUBTYPE_SH7760) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7780) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7785) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7786)
-SCIF_FNS(SCFDR,                             0x0e, 16, 0x1C, 16)
-SCIF_FNS(SCTFDR,                    0x0e, 16, 0x1C, 16)
-SCIF_FNS(SCRFDR,                    0x0e, 16, 0x20, 16)
-SCIF_FNS(SCSPTR,                       0,  0, 0x24, 16)
-SCIF_FNS(SCLSR,                                0,  0, 0x28, 16)
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
-SCIF_FNS(SCFDR,                                0,  0, 0x1C, 16)
-SCIF_FNS(SCTFDR,                    0x0e, 16, 0x1C, 16)
-SCIF_FNS(SCRFDR,                    0x0e, 16, 0x20, 16)
-SCIF_FNS(SCSPTR,                       0,  0, 0x24, 16)
-SCIF_FNS(SCLSR,                                0,  0, 0x28, 16)
-#else
-SCIF_FNS(SCFDR,                      0x0e, 16, 0x1C, 16)
-#if defined(CONFIG_CPU_SUBTYPE_SH7722)
-SCIF_FNS(SCSPTR,                        0,  0, 0, 0)
-#else
-SCIF_FNS(SCSPTR,                        0,  0, 0x20, 16)
-#endif
-SCIF_FNS(SCLSR,                         0,  0, 0x24, 16)
-#endif
-#endif
-#define sci_in(port, reg) sci_##reg##_in(port)
-#define sci_out(port, reg, value) sci_##reg##_out(port, value)
-
-/* H8/300 series SCI pins assignment */
-#if defined(__H8300H__) || defined(__H8300S__)
-static const struct __attribute__((packed)) {
-       int port;             /* GPIO port no */
-       unsigned short rx,tx; /* GPIO bit no */
-} h8300_sci_pins[] = {
-#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
-       {    /* SCI0 */
-               .port = H8300_GPIO_P9,
-               .rx   = H8300_GPIO_B2,
-               .tx   = H8300_GPIO_B0,
-       },
-       {    /* SCI1 */
-               .port = H8300_GPIO_P9,
-               .rx   = H8300_GPIO_B3,
-               .tx   = H8300_GPIO_B1,
-       },
-       {    /* SCI2 */
-               .port = H8300_GPIO_PB,
-               .rx   = H8300_GPIO_B7,
-               .tx   = H8300_GPIO_B6,
-       }
-#elif defined(CONFIG_H8S2678)
-       {    /* SCI0 */
-               .port = H8300_GPIO_P3,
-               .rx   = H8300_GPIO_B2,
-               .tx   = H8300_GPIO_B0,
-       },
-       {    /* SCI1 */
-               .port = H8300_GPIO_P3,
-               .rx   = H8300_GPIO_B3,
-               .tx   = H8300_GPIO_B1,
-       },
-       {    /* SCI2 */
-               .port = H8300_GPIO_P5,
-               .rx   = H8300_GPIO_B1,
-               .tx   = H8300_GPIO_B0,
-       }
-#endif
-};
-#endif
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7707) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7708) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7709)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-       if (port->mapbase == 0xfffffe80)
-               return __raw_readb(SCPDR)&0x01 ? 1 : 0; /* SCI */
-       return 1;
-}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750)  || \
-      defined(CONFIG_CPU_SUBTYPE_SH7751)  || \
-      defined(CONFIG_CPU_SUBTYPE_SH7751R) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7091)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-       if (port->mapbase == 0xffe00000)
-               return __raw_readb(SCSPTR1)&0x01 ? 1 : 0; /* SCI */
-       return 1;
-}
-#elif defined(__H8300H__) || defined(__H8300S__)
-static inline int sci_rxd_in(struct uart_port *port)
-{
-       int ch = (port->mapbase - SMR0) >> 3;
-       return (H8300_SCI_DR(ch) & h8300_sci_pins[ch].rx) ? 1 : 0;
-}
-#else /* default case for non-SCI processors */
-static inline int sci_rxd_in(struct uart_port *port)
-{
-       return 1;
-}
-#endif
index 1e54b8b..69407e7 100644 (file)
@@ -335,6 +335,13 @@ config BACKLIGHT_PCF50633
          If you have a backlight driven by a NXP PCF50633 MFD, say Y here to
          enable its driver.
 
+config BACKLIGHT_AAT2870
+       bool "AnalogicTech AAT2870 Backlight"
+       depends on BACKLIGHT_CLASS_DEVICE && MFD_AAT2870_CORE
+       help
+         If you have a AnalogicTech AAT2870 say Y to enable the
+         backlight driver.
+
 endif # BACKLIGHT_CLASS_DEVICE
 
 endif # BACKLIGHT_LCD_SUPPORT
index bf1dd92..fdd1fc4 100644 (file)
@@ -38,4 +38,5 @@ obj-$(CONFIG_BACKLIGHT_ADP8860)       += adp8860_bl.o
 obj-$(CONFIG_BACKLIGHT_ADP8870)        += adp8870_bl.o
 obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o
 obj-$(CONFIG_BACKLIGHT_PCF50633)       += pcf50633-backlight.o
+obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o
 
diff --git a/drivers/video/backlight/aat2870_bl.c b/drivers/video/backlight/aat2870_bl.c
new file mode 100644 (file)
index 0000000..4952a61
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * linux/drivers/video/backlight/aat2870_bl.c
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ * Author: Jin Park <jinyoungp@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/mfd/aat2870.h>
+
+struct aat2870_bl_driver_data {
+       struct platform_device *pdev;
+       struct backlight_device *bd;
+
+       int channels;
+       int max_current;
+       int brightness; /* current brightness */
+};
+
+static inline int aat2870_brightness(struct aat2870_bl_driver_data *aat2870_bl,
+                                    int brightness)
+{
+       struct backlight_device *bd = aat2870_bl->bd;
+       int val;
+
+       val = brightness * aat2870_bl->max_current;
+       val /= bd->props.max_brightness;
+
+       return val;
+}
+
+static inline int aat2870_bl_enable(struct aat2870_bl_driver_data *aat2870_bl)
+{
+       struct aat2870_data *aat2870
+                       = dev_get_drvdata(aat2870_bl->pdev->dev.parent);
+
+       return aat2870->write(aat2870, AAT2870_BL_CH_EN,
+                             (u8)aat2870_bl->channels);
+}
+
+static inline int aat2870_bl_disable(struct aat2870_bl_driver_data *aat2870_bl)
+{
+       struct aat2870_data *aat2870
+                       = dev_get_drvdata(aat2870_bl->pdev->dev.parent);
+
+       return aat2870->write(aat2870, AAT2870_BL_CH_EN, 0x0);
+}
+
+static int aat2870_bl_get_brightness(struct backlight_device *bd)
+{
+       return bd->props.brightness;
+}
+
+static int aat2870_bl_update_status(struct backlight_device *bd)
+{
+       struct aat2870_bl_driver_data *aat2870_bl = dev_get_drvdata(&bd->dev);
+       struct aat2870_data *aat2870 =
+                       dev_get_drvdata(aat2870_bl->pdev->dev.parent);
+       int brightness = bd->props.brightness;
+       int ret;
+
+       if ((brightness < 0) || (bd->props.max_brightness < brightness)) {
+               dev_err(&bd->dev, "invalid brightness, %d\n", brightness);
+               return -EINVAL;
+       }
+
+       dev_dbg(&bd->dev, "brightness=%d, power=%d, state=%d\n",
+                bd->props.brightness, bd->props.power, bd->props.state);
+
+       if ((bd->props.power != FB_BLANK_UNBLANK) ||
+                       (bd->props.state & BL_CORE_FBBLANK) ||
+                       (bd->props.state & BL_CORE_SUSPENDED))
+               brightness = 0;
+
+       ret = aat2870->write(aat2870, AAT2870_BLM,
+                            (u8)aat2870_brightness(aat2870_bl, brightness));
+       if (ret < 0)
+               return ret;
+
+       if (brightness == 0) {
+               ret = aat2870_bl_disable(aat2870_bl);
+               if (ret < 0)
+                       return ret;
+       } else if (aat2870_bl->brightness == 0) {
+               ret = aat2870_bl_enable(aat2870_bl);
+               if (ret < 0)
+                       return ret;
+       }
+
+       aat2870_bl->brightness = brightness;
+
+       return 0;
+}
+
+static int aat2870_bl_check_fb(struct backlight_device *bd, struct fb_info *fi)
+{
+       return 1;
+}
+
+static const struct backlight_ops aat2870_bl_ops = {
+       .options = BL_CORE_SUSPENDRESUME,
+       .get_brightness = aat2870_bl_get_brightness,
+       .update_status = aat2870_bl_update_status,
+       .check_fb = aat2870_bl_check_fb,
+};
+
+static int aat2870_bl_probe(struct platform_device *pdev)
+{
+       struct aat2870_bl_platform_data *pdata = pdev->dev.platform_data;
+       struct aat2870_bl_driver_data *aat2870_bl;
+       struct backlight_device *bd;
+       struct backlight_properties props;
+       int ret = 0;
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "No platform data\n");
+               ret = -ENXIO;
+               goto out;
+       }
+
+       if (pdev->id != AAT2870_ID_BL) {
+               dev_err(&pdev->dev, "Invalid device ID, %d\n", pdev->id);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       aat2870_bl = kzalloc(sizeof(struct aat2870_bl_driver_data), GFP_KERNEL);
+       if (!aat2870_bl) {
+               dev_err(&pdev->dev,
+                       "Failed to allocate memory for aat2870 backlight\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       memset(&props, 0, sizeof(struct backlight_properties));
+
+       props.type = BACKLIGHT_RAW;
+       bd = backlight_device_register("aat2870-backlight", &pdev->dev,
+                                      aat2870_bl, &aat2870_bl_ops, &props);
+       if (!bd) {
+               dev_err(&pdev->dev,
+                       "Failed allocate memory for backlight device\n");
+               ret = -ENOMEM;
+               goto out_kfree;
+       }
+
+       aat2870_bl->pdev = pdev;
+       platform_set_drvdata(pdev, aat2870_bl);
+
+       aat2870_bl->bd = bd;
+
+       if (pdata->channels > 0)
+               aat2870_bl->channels = pdata->channels;
+       else
+               aat2870_bl->channels = AAT2870_BL_CH_ALL;
+
+       if (pdata->max_brightness > 0)
+               aat2870_bl->max_current = pdata->max_current;
+       else
+               aat2870_bl->max_current = AAT2870_CURRENT_27_9;
+
+       if (pdata->max_brightness > 0)
+               bd->props.max_brightness = pdata->max_brightness;
+       else
+               bd->props.max_brightness = 255;
+
+       aat2870_bl->brightness = 0;
+       bd->props.power = FB_BLANK_UNBLANK;
+       bd->props.brightness = bd->props.max_brightness;
+
+       ret = aat2870_bl_update_status(bd);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to initialize\n");
+               goto out_bl_dev_unregister;
+       }
+
+       return 0;
+
+out_bl_dev_unregister:
+       backlight_device_unregister(bd);
+out_kfree:
+       kfree(aat2870_bl);
+out:
+       return ret;
+}
+
+static int aat2870_bl_remove(struct platform_device *pdev)
+{
+       struct aat2870_bl_driver_data *aat2870_bl = platform_get_drvdata(pdev);
+       struct backlight_device *bd = aat2870_bl->bd;
+
+       bd->props.power = FB_BLANK_POWERDOWN;
+       bd->props.brightness = 0;
+       backlight_update_status(bd);
+
+       backlight_device_unregister(bd);
+       kfree(aat2870_bl);
+
+       return 0;
+}
+
+static struct platform_driver aat2870_bl_driver = {
+       .driver = {
+               .name   = "aat2870-backlight",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = aat2870_bl_probe,
+       .remove         = aat2870_bl_remove,
+};
+
+static int __init aat2870_bl_init(void)
+{
+       return platform_driver_register(&aat2870_bl_driver);
+}
+subsys_initcall(aat2870_bl_init);
+
+static void __exit aat2870_bl_exit(void)
+{
+       platform_driver_unregister(&aat2870_bl_driver);
+}
+module_exit(aat2870_bl_exit);
+
+MODULE_DESCRIPTION("AnalogicTech AAT2870 Backlight");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jin Park <jinyoungp@nvidia.com>");
index fdd5d4a..4e888ac 100644 (file)
@@ -504,14 +504,18 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
                return 0;
 
        r = omapdss_dsi_display_enable(dssdev);
-       if (r)
-               goto err;
+       if (r) {
+               dev_err(&dssdev->dev, "failed to enable DSI\n");
+               goto err1;
+       }
 
        omapdss_dsi_vc_enable_hs(dssdev, td->channel, true);
 
        r = _taal_enable_te(dssdev, true);
-       if (r)
-               goto err;
+       if (r) {
+               dev_err(&dssdev->dev, "failed to re-enable TE");
+               goto err2;
+       }
 
        enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
 
@@ -521,13 +525,15 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
 
        return 0;
 
-err:
-       dev_err(&dssdev->dev, "exit ULPS failed");
-       r = taal_panel_reset(dssdev);
-
-       enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
-       td->ulps_enabled = false;
+err2:
+       dev_err(&dssdev->dev, "failed to exit ULPS");
 
+       r = taal_panel_reset(dssdev);
+       if (!r) {
+               enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
+               td->ulps_enabled = false;
+       }
+err1:
        taal_queue_ulps_work(dssdev);
 
        return r;
@@ -1241,11 +1247,8 @@ static void taal_power_off(struct omap_dss_device *dssdev)
        int r;
 
        r = taal_dcs_write_0(td, DCS_DISPLAY_OFF);
-       if (!r) {
+       if (!r)
                r = taal_sleep_in(td);
-               /* HACK: wait a bit so that the message goes through */
-               msleep(10);
-       }
 
        if (r) {
                dev_err(&dssdev->dev,
@@ -1317,8 +1320,11 @@ static void taal_disable(struct omap_dss_device *dssdev)
        dsi_bus_lock(dssdev);
 
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
-               taal_wake_up(dssdev);
-               taal_power_off(dssdev);
+               int r;
+
+               r = taal_wake_up(dssdev);
+               if (!r)
+                       taal_power_off(dssdev);
        }
 
        dsi_bus_unlock(dssdev);
@@ -1897,20 +1903,6 @@ err:
        mutex_unlock(&td->lock);
 }
 
-static int taal_set_update_mode(struct omap_dss_device *dssdev,
-               enum omap_dss_update_mode mode)
-{
-       if (mode != OMAP_DSS_UPDATE_MANUAL)
-               return -EINVAL;
-       return 0;
-}
-
-static enum omap_dss_update_mode taal_get_update_mode(
-               struct omap_dss_device *dssdev)
-{
-       return OMAP_DSS_UPDATE_MANUAL;
-}
-
 static struct omap_dss_driver taal_driver = {
        .probe          = taal_probe,
        .remove         = __exit_p(taal_remove),
@@ -1920,9 +1912,6 @@ static struct omap_dss_driver taal_driver = {
        .suspend        = taal_suspend,
        .resume         = taal_resume,
 
-       .set_update_mode = taal_set_update_mode,
-       .get_update_mode = taal_get_update_mode,
-
        .update         = taal_update,
        .sync           = taal_sync,
 
index 6b3e2da..0d12524 100644 (file)
@@ -117,18 +117,6 @@ config OMAP2_DSS_MIN_FCK_PER_PCK
          Max FCK is 173MHz, so this doesn't work if your PCK
          is very high.
 
-config OMAP2_DSS_SLEEP_BEFORE_RESET
-       bool "Sleep 50ms before DSS reset"
-       default y
-       help
-         For some unknown reason we may get SYNC_LOST errors from the display
-         subsystem at initialization time if we don't sleep before resetting
-         the DSS. See the source (dss.c) for more comments.
-
-         However, 50ms is quite long time to sleep, and with some
-         configurations the SYNC_LOST may never happen, so the sleep can
-         be disabled here.
-
 config OMAP2_DSS_SLEEP_AFTER_VENC_RESET
        bool "Sleep 20ms after VENC reset"
        default y
index 3da4267..76821fe 100644 (file)
@@ -183,8 +183,11 @@ static int omap_dss_probe(struct platform_device *pdev)
                goto err_dss;
        }
 
-       /* keep clocks enabled to prevent context saves/restores during init */
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+       r = dispc_init_platform_driver();
+       if (r) {
+               DSSERR("Failed to initialize dispc platform driver\n");
+               goto err_dispc;
+       }
 
        r = rfbi_init_platform_driver();
        if (r) {
@@ -192,12 +195,6 @@ static int omap_dss_probe(struct platform_device *pdev)
                goto err_rfbi;
        }
 
-       r = dispc_init_platform_driver();
-       if (r) {
-               DSSERR("Failed to initialize dispc platform driver\n");
-               goto err_dispc;
-       }
-
        r = venc_init_platform_driver();
        if (r) {
                DSSERR("Failed to initialize venc platform driver\n");
@@ -238,8 +235,6 @@ static int omap_dss_probe(struct platform_device *pdev)
                        pdata->default_device = dssdev;
        }
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
-
        return 0;
 
 err_register:
@@ -268,11 +263,11 @@ static int omap_dss_remove(struct platform_device *pdev)
 
        dss_uninitialize_debugfs();
 
+       hdmi_uninit_platform_driver();
+       dsi_uninit_platform_driver();
        venc_uninit_platform_driver();
-       dispc_uninit_platform_driver();
        rfbi_uninit_platform_driver();
-       dsi_uninit_platform_driver();
-       hdmi_uninit_platform_driver();
+       dispc_uninit_platform_driver();
        dss_uninit_platform_driver();
 
        dss_uninit_overlays(pdev);
index 7a9a2e7..0f3961a 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/workqueue.h>
 #include <linux/hardirq.h>
 #include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 
 #include <plat/sram.h>
 #include <plat/clock.h>
@@ -77,6 +79,12 @@ struct dispc_v_coef {
        s8 vc00;
 };
 
+enum omap_burst_size {
+       BURST_SIZE_X2 = 0,
+       BURST_SIZE_X4 = 1,
+       BURST_SIZE_X8 = 2,
+};
+
 #define REG_GET(idx, start, end) \
        FLD_GET(dispc_read_reg(idx), start, end)
 
@@ -92,7 +100,11 @@ struct dispc_irq_stats {
 static struct {
        struct platform_device *pdev;
        void __iomem    *base;
+
+       int             ctx_loss_cnt;
+
        int irq;
+       struct clk *dss_clk;
 
        u32     fifo_size[3];
 
@@ -102,6 +114,7 @@ static struct {
        u32 error_irqs;
        struct work_struct error_work;
 
+       bool            ctx_valid;
        u32             ctx[DISPC_SZ_REGS / sizeof(u32)];
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -134,18 +147,34 @@ static inline u32 dispc_read_reg(const u16 idx)
        return __raw_readl(dispc.base + idx);
 }
 
+static int dispc_get_ctx_loss_count(void)
+{
+       struct device *dev = &dispc.pdev->dev;
+       struct omap_display_platform_data *pdata = dev->platform_data;
+       struct omap_dss_board_info *board_data = pdata->board_data;
+       int cnt;
+
+       if (!board_data->get_context_loss_count)
+               return -ENOENT;
+
+       cnt = board_data->get_context_loss_count(dev);
+
+       WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
+
+       return cnt;
+}
+
 #define SR(reg) \
        dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
 #define RR(reg) \
        dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)])
 
-void dispc_save_context(void)
+static void dispc_save_context(void)
 {
        int i;
-       if (cpu_is_omap24xx())
-               return;
 
-       SR(SYSCONFIG);
+       DSSDBG("dispc_save_context\n");
+
        SR(IRQENABLE);
        SR(CONTROL);
        SR(CONFIG);
@@ -158,7 +187,8 @@ void dispc_save_context(void)
        SR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
        SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
        SR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
-       SR(GLOBAL_ALPHA);
+       if (dss_has_feature(FEAT_GLOBAL_ALPHA))
+               SR(GLOBAL_ALPHA);
        SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
        SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
        if (dss_has_feature(FEAT_MGR_LCD2)) {
@@ -188,20 +218,25 @@ void dispc_save_context(void)
        SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
        SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
 
-       SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
-       SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
-       SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+       if (dss_has_feature(FEAT_CPR)) {
+               SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
+               SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
+               SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+       }
        if (dss_has_feature(FEAT_MGR_LCD2)) {
-               SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
-               SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
-               SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+               if (dss_has_feature(FEAT_CPR)) {
+                       SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+                       SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
+                       SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+               }
 
                SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
                SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
                SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
        }
 
-       SR(OVL_PRELOAD(OMAP_DSS_GFX));
+       if (dss_has_feature(FEAT_PRELOAD))
+               SR(OVL_PRELOAD(OMAP_DSS_GFX));
 
        /* VID1 */
        SR(OVL_BA0(OMAP_DSS_VIDEO1));
@@ -226,8 +261,10 @@ void dispc_save_context(void)
        for (i = 0; i < 5; i++)
                SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
 
-       for (i = 0; i < 8; i++)
-               SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
+       if (dss_has_feature(FEAT_FIR_COEF_V)) {
+               for (i = 0; i < 8; i++)
+                       SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
+       }
 
        if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
                SR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
@@ -248,7 +285,8 @@ void dispc_save_context(void)
        if (dss_has_feature(FEAT_ATTR2))
                SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
 
-       SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
+       if (dss_has_feature(FEAT_PRELOAD))
+               SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
 
        /* VID2 */
        SR(OVL_BA0(OMAP_DSS_VIDEO2));
@@ -273,8 +311,10 @@ void dispc_save_context(void)
        for (i = 0; i < 5; i++)
                SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
 
-       for (i = 0; i < 8; i++)
-               SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
+       if (dss_has_feature(FEAT_FIR_COEF_V)) {
+               for (i = 0; i < 8; i++)
+                       SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
+       }
 
        if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
                SR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
@@ -295,16 +335,35 @@ void dispc_save_context(void)
        if (dss_has_feature(FEAT_ATTR2))
                SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
 
-       SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
+       if (dss_has_feature(FEAT_PRELOAD))
+               SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
 
        if (dss_has_feature(FEAT_CORE_CLK_DIV))
                SR(DIVISOR);
+
+       dispc.ctx_loss_cnt = dispc_get_ctx_loss_count();
+       dispc.ctx_valid = true;
+
+       DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
 }
 
-void dispc_restore_context(void)
+static void dispc_restore_context(void)
 {
-       int i;
-       RR(SYSCONFIG);
+       int i, ctx;
+
+       DSSDBG("dispc_restore_context\n");
+
+       if (!dispc.ctx_valid)
+               return;
+
+       ctx = dispc_get_ctx_loss_count();
+
+       if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
+               return;
+
+       DSSDBG("ctx_loss_count: saved %d, current %d\n",
+                       dispc.ctx_loss_cnt, ctx);
+
        /*RR(IRQENABLE);*/
        /*RR(CONTROL);*/
        RR(CONFIG);
@@ -317,7 +376,8 @@ void dispc_restore_context(void)
        RR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
        RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
        RR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
-       RR(GLOBAL_ALPHA);
+       if (dss_has_feature(FEAT_GLOBAL_ALPHA))
+               RR(GLOBAL_ALPHA);
        RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
        RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
        if (dss_has_feature(FEAT_MGR_LCD2)) {
@@ -347,20 +407,25 @@ void dispc_restore_context(void)
        RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
        RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
 
-       RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
-       RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
-       RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+       if (dss_has_feature(FEAT_CPR)) {
+               RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
+               RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
+               RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+       }
        if (dss_has_feature(FEAT_MGR_LCD2)) {
                RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
                RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
                RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
 
-               RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
-               RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
-               RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+               if (dss_has_feature(FEAT_CPR)) {
+                       RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+                       RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
+                       RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+               }
        }
 
-       RR(OVL_PRELOAD(OMAP_DSS_GFX));
+       if (dss_has_feature(FEAT_PRELOAD))
+               RR(OVL_PRELOAD(OMAP_DSS_GFX));
 
        /* VID1 */
        RR(OVL_BA0(OMAP_DSS_VIDEO1));
@@ -385,8 +450,10 @@ void dispc_restore_context(void)
        for (i = 0; i < 5; i++)
                RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
 
-       for (i = 0; i < 8; i++)
-               RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
+       if (dss_has_feature(FEAT_FIR_COEF_V)) {
+               for (i = 0; i < 8; i++)
+                       RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
+       }
 
        if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
                RR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
@@ -407,7 +474,8 @@ void dispc_restore_context(void)
        if (dss_has_feature(FEAT_ATTR2))
                RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
 
-       RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
+       if (dss_has_feature(FEAT_PRELOAD))
+               RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
 
        /* VID2 */
        RR(OVL_BA0(OMAP_DSS_VIDEO2));
@@ -432,8 +500,10 @@ void dispc_restore_context(void)
        for (i = 0; i < 5; i++)
                RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
 
-       for (i = 0; i < 8; i++)
-               RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
+       if (dss_has_feature(FEAT_FIR_COEF_V)) {
+               for (i = 0; i < 8; i++)
+                       RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
+       }
 
        if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
                RR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
@@ -454,7 +524,8 @@ void dispc_restore_context(void)
        if (dss_has_feature(FEAT_ATTR2))
                RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
 
-       RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
+       if (dss_has_feature(FEAT_PRELOAD))
+               RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
 
        if (dss_has_feature(FEAT_CORE_CLK_DIV))
                RR(DIVISOR);
@@ -471,19 +542,35 @@ void dispc_restore_context(void)
         * the context is fully restored
         */
        RR(IRQENABLE);
+
+       DSSDBG("context restored\n");
 }
 
 #undef SR
 #undef RR
 
-static inline void enable_clocks(bool enable)
+int dispc_runtime_get(void)
 {
-       if (enable)
-               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
-       else
-               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       int r;
+
+       DSSDBG("dispc_runtime_get\n");
+
+       r = pm_runtime_get_sync(&dispc.pdev->dev);
+       WARN_ON(r < 0);
+       return r < 0 ? r : 0;
 }
 
+void dispc_runtime_put(void)
+{
+       int r;
+
+       DSSDBG("dispc_runtime_put\n");
+
+       r = pm_runtime_put(&dispc.pdev->dev);
+       WARN_ON(r < 0);
+}
+
+
 bool dispc_go_busy(enum omap_channel channel)
 {
        int bit;
@@ -505,8 +592,6 @@ void dispc_go(enum omap_channel channel)
        int bit;
        bool enable_bit, go_bit;
 
-       enable_clocks(1);
-
        if (channel == OMAP_DSS_CHANNEL_LCD ||
                        channel == OMAP_DSS_CHANNEL_LCD2)
                bit = 0; /* LCDENABLE */
@@ -520,7 +605,7 @@ void dispc_go(enum omap_channel channel)
                enable_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1;
 
        if (!enable_bit)
-               goto end;
+               return;
 
        if (channel == OMAP_DSS_CHANNEL_LCD ||
                        channel == OMAP_DSS_CHANNEL_LCD2)
@@ -535,7 +620,7 @@ void dispc_go(enum omap_channel channel)
 
        if (go_bit) {
                DSSERR("GO bit not down for channel %d\n", channel);
-               goto end;
+               return;
        }
 
        DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" :
@@ -545,8 +630,6 @@ void dispc_go(enum omap_channel channel)
                REG_FLD_MOD(DISPC_CONTROL2, 1, bit, bit);
        else
                REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
-end:
-       enable_clocks(0);
 }
 
 static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
@@ -920,7 +1003,7 @@ static void _dispc_set_color_mode(enum omap_plane plane,
        REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
 }
 
-static void _dispc_set_channel_out(enum omap_plane plane,
+void dispc_set_channel_out(enum omap_plane plane,
                enum omap_channel channel)
 {
        int shift;
@@ -967,13 +1050,10 @@ static void _dispc_set_channel_out(enum omap_plane plane,
        dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
 }
 
-void dispc_set_burst_size(enum omap_plane plane,
+static void dispc_set_burst_size(enum omap_plane plane,
                enum omap_burst_size burst_size)
 {
        int shift;
-       u32 val;
-
-       enable_clocks(1);
 
        switch (plane) {
        case OMAP_DSS_GFX:
@@ -988,11 +1068,24 @@ void dispc_set_burst_size(enum omap_plane plane,
                return;
        }
 
-       val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
-       val = FLD_MOD(val, burst_size, shift+1, shift);
-       dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
+       REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift);
+}
 
-       enable_clocks(0);
+static void dispc_configure_burst_sizes(void)
+{
+       int i;
+       const int burst_size = BURST_SIZE_X8;
+
+       /* Configure burst size always to maximum size */
+       for (i = 0; i < omap_dss_get_num_overlays(); ++i)
+               dispc_set_burst_size(i, burst_size);
+}
+
+u32 dispc_get_burst_size(enum omap_plane plane)
+{
+       unsigned unit = dss_feat_get_burst_size_unit();
+       /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */
+       return unit * 8;
 }
 
 void dispc_enable_gamma_table(bool enable)
@@ -1009,6 +1102,40 @@ void dispc_enable_gamma_table(bool enable)
        REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
 }
 
+void dispc_enable_cpr(enum omap_channel channel, bool enable)
+{
+       u16 reg;
+
+       if (channel == OMAP_DSS_CHANNEL_LCD)
+               reg = DISPC_CONFIG;
+       else if (channel == OMAP_DSS_CHANNEL_LCD2)
+               reg = DISPC_CONFIG2;
+       else
+               return;
+
+       REG_FLD_MOD(reg, enable, 15, 15);
+}
+
+void dispc_set_cpr_coef(enum omap_channel channel,
+               struct omap_dss_cpr_coefs *coefs)
+{
+       u32 coef_r, coef_g, coef_b;
+
+       if (channel != OMAP_DSS_CHANNEL_LCD && channel != OMAP_DSS_CHANNEL_LCD2)
+               return;
+
+       coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) |
+               FLD_VAL(coefs->rb, 9, 0);
+       coef_g = FLD_VAL(coefs->gr, 31, 22) | FLD_VAL(coefs->gg, 20, 11) |
+               FLD_VAL(coefs->gb, 9, 0);
+       coef_b = FLD_VAL(coefs->br, 31, 22) | FLD_VAL(coefs->bg, 20, 11) |
+               FLD_VAL(coefs->bb, 9, 0);
+
+       dispc_write_reg(DISPC_CPR_COEF_R(channel), coef_r);
+       dispc_write_reg(DISPC_CPR_COEF_G(channel), coef_g);
+       dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b);
+}
+
 static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
 {
        u32 val;
@@ -1029,9 +1156,7 @@ void dispc_enable_replication(enum omap_plane plane, bool enable)
        else
                bit = 10;
 
-       enable_clocks(1);
        REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
-       enable_clocks(0);
 }
 
 void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
@@ -1039,9 +1164,7 @@ void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
        u32 val;
        BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
        val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
-       enable_clocks(1);
        dispc_write_reg(DISPC_SIZE_MGR(channel), val);
-       enable_clocks(0);
 }
 
 void dispc_set_digit_size(u16 width, u16 height)
@@ -1049,9 +1172,7 @@ void dispc_set_digit_size(u16 width, u16 height)
        u32 val;
        BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
        val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
-       enable_clocks(1);
        dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val);
-       enable_clocks(0);
 }
 
 static void dispc_read_plane_fifo_sizes(void)
@@ -1059,18 +1180,17 @@ static void dispc_read_plane_fifo_sizes(void)
        u32 size;
        int plane;
        u8 start, end;
+       u32 unit;
 
-       enable_clocks(1);
+       unit = dss_feat_get_buffer_size_unit();
 
        dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
 
        for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
-               size = FLD_GET(dispc_read_reg(DISPC_OVL_FIFO_SIZE_STATUS(plane)),
-                       start, end);
+               size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end);
+               size *= unit;
                dispc.fifo_size[plane] = size;
        }
-
-       enable_clocks(0);
 }
 
 u32 dispc_get_plane_fifo_size(enum omap_plane plane)
@@ -1078,15 +1198,22 @@ u32 dispc_get_plane_fifo_size(enum omap_plane plane)
        return dispc.fifo_size[plane];
 }
 
-void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
+void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
 {
        u8 hi_start, hi_end, lo_start, lo_end;
+       u32 unit;
+
+       unit = dss_feat_get_buffer_size_unit();
+
+       WARN_ON(low % unit != 0);
+       WARN_ON(high % unit != 0);
+
+       low /= unit;
+       high /= unit;
 
        dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
        dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
 
-       enable_clocks(1);
-
        DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
                        plane,
                        REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
@@ -1098,18 +1225,12 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
        dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane),
                        FLD_VAL(high, hi_start, hi_end) |
                        FLD_VAL(low, lo_start, lo_end));
-
-       enable_clocks(0);
 }
 
 void dispc_enable_fifomerge(bool enable)
 {
-       enable_clocks(1);
-
        DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
        REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
-
-       enable_clocks(0);
 }
 
 static void _dispc_set_fir(enum omap_plane plane,
@@ -1729,14 +1850,7 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
        return dispc_pclk_rate(channel) * vf * hf;
 }
 
-void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
-{
-       enable_clocks(1);
-       _dispc_set_channel_out(plane, channel_out);
-       enable_clocks(0);
-}
-
-static int _dispc_setup_plane(enum omap_plane plane,
+int dispc_setup_plane(enum omap_plane plane,
                u32 paddr, u16 screen_width,
                u16 pos_x, u16 pos_y,
                u16 width, u16 height,
@@ -1744,7 +1858,7 @@ static int _dispc_setup_plane(enum omap_plane plane,
                enum omap_color_mode color_mode,
                bool ilace,
                enum omap_dss_rotation_type rotation_type,
-               u8 rotation, int mirror,
+               u8 rotation, bool mirror,
                u8 global_alpha, u8 pre_mult_alpha,
                enum omap_channel channel, u32 puv_addr)
 {
@@ -1758,6 +1872,14 @@ static int _dispc_setup_plane(enum omap_plane plane,
        u16 frame_height = height;
        unsigned int field_offset = 0;
 
+       DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
+              "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
+              plane, paddr, screen_width, pos_x, pos_y,
+              width, height,
+              out_width, out_height,
+              ilace, color_mode,
+              rotation, mirror, channel);
+
        if (paddr == 0)
                return -EINVAL;
 
@@ -1903,9 +2025,13 @@ static int _dispc_setup_plane(enum omap_plane plane,
        return 0;
 }
 
-static void _dispc_enable_plane(enum omap_plane plane, bool enable)
+int dispc_enable_plane(enum omap_plane plane, bool enable)
 {
+       DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
+
        REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
+
+       return 0;
 }
 
 static void dispc_disable_isr(void *data, u32 mask)
@@ -1929,8 +2055,6 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
        int r;
        u32 irq;
 
-       enable_clocks(1);
-
        /* When we disable LCD output, we need to wait until frame is done.
         * Otherwise the DSS is still working, and turning off the clocks
         * prevents DSS from going to OFF mode */
@@ -1964,8 +2088,6 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
                if (r)
                        DSSERR("failed to unregister FRAMEDONE isr\n");
        }
-
-       enable_clocks(0);
 }
 
 static void _enable_digit_out(bool enable)
@@ -1978,12 +2100,8 @@ static void dispc_enable_digit_out(bool enable)
        struct completion frame_done_completion;
        int r;
 
-       enable_clocks(1);
-
-       if (REG_GET(DISPC_CONTROL, 1, 1) == enable) {
-               enable_clocks(0);
+       if (REG_GET(DISPC_CONTROL, 1, 1) == enable)
                return;
-       }
 
        if (enable) {
                unsigned long flags;
@@ -2035,8 +2153,6 @@ static void dispc_enable_digit_out(bool enable)
                _omap_dispc_set_irqs();
                spin_unlock_irqrestore(&dispc.irq_lock, flags);
        }
-
-       enable_clocks(0);
 }
 
 bool dispc_is_channel_enabled(enum omap_channel channel)
@@ -2067,9 +2183,7 @@ void dispc_lcd_enable_signal_polarity(bool act_high)
        if (!dss_has_feature(FEAT_LCDENABLEPOL))
                return;
 
-       enable_clocks(1);
        REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
-       enable_clocks(0);
 }
 
 void dispc_lcd_enable_signal(bool enable)
@@ -2077,9 +2191,7 @@ void dispc_lcd_enable_signal(bool enable)
        if (!dss_has_feature(FEAT_LCDENABLESIGNAL))
                return;
 
-       enable_clocks(1);
        REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
-       enable_clocks(0);
 }
 
 void dispc_pck_free_enable(bool enable)
@@ -2087,19 +2199,15 @@ void dispc_pck_free_enable(bool enable)
        if (!dss_has_feature(FEAT_PCKFREEENABLE))
                return;
 
-       enable_clocks(1);
        REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
-       enable_clocks(0);
 }
 
 void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)
 {
-       enable_clocks(1);
        if (channel == OMAP_DSS_CHANNEL_LCD2)
                REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16);
        else
                REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
-       enable_clocks(0);
 }
 
 
@@ -2122,27 +2230,21 @@ void dispc_set_lcd_display_type(enum omap_channel channel,
                return;
        }
 
-       enable_clocks(1);
        if (channel == OMAP_DSS_CHANNEL_LCD2)
                REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3);
        else
                REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
-       enable_clocks(0);
 }
 
 void dispc_set_loadmode(enum omap_dss_load_mode mode)
 {
-       enable_clocks(1);
        REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
-       enable_clocks(0);
 }
 
 
 void dispc_set_default_color(enum omap_channel channel, u32 color)
 {
-       enable_clocks(1);
        dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
-       enable_clocks(0);
 }
 
 u32 dispc_get_default_color(enum omap_channel channel)
@@ -2153,9 +2255,7 @@ u32 dispc_get_default_color(enum omap_channel channel)
                channel != OMAP_DSS_CHANNEL_LCD &&
                channel != OMAP_DSS_CHANNEL_LCD2);
 
-       enable_clocks(1);
        l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel));
-       enable_clocks(0);
 
        return l;
 }
@@ -2164,7 +2264,6 @@ void dispc_set_trans_key(enum omap_channel ch,
                enum omap_dss_trans_key_type type,
                u32 trans_key)
 {
-       enable_clocks(1);
        if (ch == OMAP_DSS_CHANNEL_LCD)
                REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
        else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2173,14 +2272,12 @@ void dispc_set_trans_key(enum omap_channel ch,
                REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11);
 
        dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
-       enable_clocks(0);
 }
 
 void dispc_get_trans_key(enum omap_channel ch,
                enum omap_dss_trans_key_type *type,
                u32 *trans_key)
 {
-       enable_clocks(1);
        if (type) {
                if (ch == OMAP_DSS_CHANNEL_LCD)
                        *type = REG_GET(DISPC_CONFIG, 11, 11);
@@ -2194,33 +2291,28 @@ void dispc_get_trans_key(enum omap_channel ch,
 
        if (trans_key)
                *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
-       enable_clocks(0);
 }
 
 void dispc_enable_trans_key(enum omap_channel ch, bool enable)
 {
-       enable_clocks(1);
        if (ch == OMAP_DSS_CHANNEL_LCD)
                REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
        else if (ch == OMAP_DSS_CHANNEL_DIGIT)
                REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
        else /* OMAP_DSS_CHANNEL_LCD2 */
                REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
-       enable_clocks(0);
 }
 void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
 {
        if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
                return;
 
-       enable_clocks(1);
        if (ch == OMAP_DSS_CHANNEL_LCD)
                REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
        else if (ch == OMAP_DSS_CHANNEL_DIGIT)
                REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
        else /* OMAP_DSS_CHANNEL_LCD2 */
                REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18);
-       enable_clocks(0);
 }
 bool dispc_alpha_blending_enabled(enum omap_channel ch)
 {
@@ -2229,7 +2321,6 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
        if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
                return false;
 
-       enable_clocks(1);
        if (ch == OMAP_DSS_CHANNEL_LCD)
                enabled = REG_GET(DISPC_CONFIG, 18, 18);
        else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2238,7 +2329,6 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
                enabled = REG_GET(DISPC_CONFIG2, 18, 18);
        else
                BUG();
-       enable_clocks(0);
 
        return enabled;
 }
@@ -2248,7 +2338,6 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
 {
        bool enabled;
 
-       enable_clocks(1);
        if (ch == OMAP_DSS_CHANNEL_LCD)
                enabled = REG_GET(DISPC_CONFIG, 10, 10);
        else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2257,7 +2346,6 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
                enabled = REG_GET(DISPC_CONFIG2, 10, 10);
        else
                BUG();
-       enable_clocks(0);
 
        return enabled;
 }
@@ -2285,12 +2373,10 @@ void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
                return;
        }
 
-       enable_clocks(1);
        if (channel == OMAP_DSS_CHANNEL_LCD2)
                REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8);
        else
                REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
-       enable_clocks(0);
 }
 
 void dispc_set_parallel_interface_mode(enum omap_channel channel,
@@ -2322,8 +2408,6 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel,
                return;
        }
 
-       enable_clocks(1);
-
        if (channel == OMAP_DSS_CHANNEL_LCD2) {
                l = dispc_read_reg(DISPC_CONTROL2);
                l = FLD_MOD(l, stallmode, 11, 11);
@@ -2335,8 +2419,6 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel,
                l = FLD_MOD(l, gpout1, 16, 16);
                dispc_write_reg(DISPC_CONTROL, l);
        }
-
-       enable_clocks(0);
 }
 
 static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
@@ -2389,10 +2471,8 @@ static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
                        FLD_VAL(vbp, 31, 20);
        }
 
-       enable_clocks(1);
        dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
        dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
-       enable_clocks(0);
 }
 
 /* change name to mode? */
@@ -2435,10 +2515,8 @@ static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
        BUG_ON(lck_div < 1);
        BUG_ON(pck_div < 2);
 
-       enable_clocks(1);
        dispc_write_reg(DISPC_DIVISORo(channel),
                        FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
-       enable_clocks(0);
 }
 
 static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div,
@@ -2457,7 +2535,7 @@ unsigned long dispc_fclk_rate(void)
 
        switch (dss_get_dispc_clk_source()) {
        case OMAP_DSS_CLK_SRC_FCK:
-               r = dss_clk_get_rate(DSS_CLK_FCK);
+               r = clk_get_rate(dispc.dss_clk);
                break;
        case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
                dsidev = dsi_get_dsidev_from_id(0);
@@ -2487,7 +2565,7 @@ unsigned long dispc_lclk_rate(enum omap_channel channel)
 
        switch (dss_get_lcd_clk_source(channel)) {
        case OMAP_DSS_CLK_SRC_FCK:
-               r = dss_clk_get_rate(DSS_CLK_FCK);
+               r = clk_get_rate(dispc.dss_clk);
                break;
        case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
                dsidev = dsi_get_dsidev_from_id(0);
@@ -2526,7 +2604,8 @@ void dispc_dump_clocks(struct seq_file *s)
        enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
        enum omap_dss_clk_source lcd_clk_src;
 
-       enable_clocks(1);
+       if (dispc_runtime_get())
+               return;
 
        seq_printf(s, "- DISPC -\n");
 
@@ -2574,7 +2653,8 @@ void dispc_dump_clocks(struct seq_file *s)
                seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
                                dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd);
        }
-       enable_clocks(0);
+
+       dispc_runtime_put();
 }
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -2629,7 +2709,8 @@ void dispc_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r))
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+       if (dispc_runtime_get())
+               return;
 
        DUMPREG(DISPC_REVISION);
        DUMPREG(DISPC_SYSCONFIG);
@@ -2649,7 +2730,8 @@ void dispc_dump_regs(struct seq_file *s)
        DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD));
        DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD));
        DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD));
-       DUMPREG(DISPC_GLOBAL_ALPHA);
+       if (dss_has_feature(FEAT_GLOBAL_ALPHA))
+               DUMPREG(DISPC_GLOBAL_ALPHA);
        DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
        DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
        if (dss_has_feature(FEAT_MGR_LCD2)) {
@@ -2680,20 +2762,25 @@ void dispc_dump_regs(struct seq_file *s)
        DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
        DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
 
-       DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
-       DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
-       DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+       if (dss_has_feature(FEAT_CPR)) {
+               DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
+               DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
+               DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
+       }
        if (dss_has_feature(FEAT_MGR_LCD2)) {
                DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
                DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
                DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
 
-               DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
-               DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
-               DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+               if (dss_has_feature(FEAT_CPR)) {
+                       DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+                       DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
+                       DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+               }
        }
 
-       DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX));
+       if (dss_has_feature(FEAT_PRELOAD))
+               DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX));
 
        DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1));
        DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1));
@@ -2744,14 +2831,16 @@ void dispc_dump_regs(struct seq_file *s)
        DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2));
        DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3));
        DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
+       if (dss_has_feature(FEAT_FIR_COEF_V)) {
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
+       }
 
        if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
                DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO1));
@@ -2812,14 +2901,17 @@ void dispc_dump_regs(struct seq_file *s)
        DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2));
        DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3));
        DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
-       DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
+
+       if (dss_has_feature(FEAT_FIR_COEF_V)) {
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
+               DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
+       }
 
        if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
                DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO2));
@@ -2858,10 +2950,12 @@ void dispc_dump_regs(struct seq_file *s)
        if (dss_has_feature(FEAT_ATTR2))
                DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
 
-       DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1));
-       DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
+       if (dss_has_feature(FEAT_PRELOAD)) {
+               DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1));
+               DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
+       }
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       dispc_runtime_put();
 #undef DUMPREG
 }
 
@@ -2882,9 +2976,7 @@ static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,
        l |= FLD_VAL(acbi, 11, 8);
        l |= FLD_VAL(acb, 7, 0);
 
-       enable_clocks(1);
        dispc_write_reg(DISPC_POL_FREQ(channel), l);
-       enable_clocks(0);
 }
 
 void dispc_set_pol_freq(enum omap_channel channel,
@@ -3005,15 +3097,11 @@ static void _omap_dispc_set_irqs(void)
                mask |= isr_data->mask;
        }
 
-       enable_clocks(1);
-
        old_mask = dispc_read_reg(DISPC_IRQENABLE);
        /* clear the irqstatus for newly enabled irqs */
        dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
 
        dispc_write_reg(DISPC_IRQENABLE, mask);
-
-       enable_clocks(0);
 }
 
 int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
@@ -3522,13 +3610,6 @@ static void _omap_dispc_initial_config(void)
 {
        u32 l;
 
-       l = dispc_read_reg(DISPC_SYSCONFIG);
-       l = FLD_MOD(l, 2, 13, 12);      /* MIDLEMODE: smart standby */
-       l = FLD_MOD(l, 2, 4, 3);        /* SIDLEMODE: smart idle */
-       l = FLD_MOD(l, 1, 2, 2);        /* ENWAKEUP */
-       l = FLD_MOD(l, 1, 0, 0);        /* AUTOIDLE */
-       dispc_write_reg(DISPC_SYSCONFIG, l);
-
        /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */
        if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
                l = dispc_read_reg(DISPC_DIVISOR);
@@ -3552,58 +3633,8 @@ static void _omap_dispc_initial_config(void)
        dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
 
        dispc_read_plane_fifo_sizes();
-}
 
-int dispc_enable_plane(enum omap_plane plane, bool enable)
-{
-       DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
-
-       enable_clocks(1);
-       _dispc_enable_plane(plane, enable);
-       enable_clocks(0);
-
-       return 0;
-}
-
-int dispc_setup_plane(enum omap_plane plane,
-                      u32 paddr, u16 screen_width,
-                      u16 pos_x, u16 pos_y,
-                      u16 width, u16 height,
-                      u16 out_width, u16 out_height,
-                      enum omap_color_mode color_mode,
-                      bool ilace,
-                      enum omap_dss_rotation_type rotation_type,
-                      u8 rotation, bool mirror, u8 global_alpha,
-                      u8 pre_mult_alpha, enum omap_channel channel,
-                      u32 puv_addr)
-{
-       int r = 0;
-
-       DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d, %d, %dx%d -> "
-              "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
-              plane, paddr, screen_width, pos_x, pos_y,
-              width, height,
-              out_width, out_height,
-              ilace, color_mode,
-              rotation, mirror, channel);
-
-       enable_clocks(1);
-
-       r = _dispc_setup_plane(plane,
-                          paddr, screen_width,
-                          pos_x, pos_y,
-                          width, height,
-                          out_width, out_height,
-                          color_mode, ilace,
-                          rotation_type,
-                          rotation, mirror,
-                          global_alpha,
-                          pre_mult_alpha,
-                          channel, puv_addr);
-
-       enable_clocks(0);
-
-       return r;
+       dispc_configure_burst_sizes();
 }
 
 /* DISPC HW IP initialisation */
@@ -3612,9 +3643,19 @@ static int omap_dispchw_probe(struct platform_device *pdev)
        u32 rev;
        int r = 0;
        struct resource *dispc_mem;
+       struct clk *clk;
 
        dispc.pdev = pdev;
 
+       clk = clk_get(&pdev->dev, "fck");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get fck\n");
+               r = PTR_ERR(clk);
+               goto err_get_clk;
+       }
+
+       dispc.dss_clk = clk;
+
        spin_lock_init(&dispc.irq_lock);
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -3628,62 +3669,103 @@ static int omap_dispchw_probe(struct platform_device *pdev)
        if (!dispc_mem) {
                DSSERR("can't get IORESOURCE_MEM DISPC\n");
                r = -EINVAL;
-               goto fail0;
+               goto err_ioremap;
        }
        dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem));
        if (!dispc.base) {
                DSSERR("can't ioremap DISPC\n");
                r = -ENOMEM;
-               goto fail0;
+               goto err_ioremap;
        }
        dispc.irq = platform_get_irq(dispc.pdev, 0);
        if (dispc.irq < 0) {
                DSSERR("platform_get_irq failed\n");
                r = -ENODEV;
-               goto fail1;
+               goto err_irq;
        }
 
        r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED,
                "OMAP DISPC", dispc.pdev);
        if (r < 0) {
                DSSERR("request_irq failed\n");
-               goto fail1;
+               goto err_irq;
        }
 
-       enable_clocks(1);
+       pm_runtime_enable(&pdev->dev);
+
+       r = dispc_runtime_get();
+       if (r)
+               goto err_runtime_get;
 
        _omap_dispc_initial_config();
 
        _omap_dispc_initialize_irq();
 
-       dispc_save_context();
-
        rev = dispc_read_reg(DISPC_REVISION);
        dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
               FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
 
-       enable_clocks(0);
+       dispc_runtime_put();
 
        return 0;
-fail1:
+
+err_runtime_get:
+       pm_runtime_disable(&pdev->dev);
+       free_irq(dispc.irq, dispc.pdev);
+err_irq:
        iounmap(dispc.base);
-fail0:
+err_ioremap:
+       clk_put(dispc.dss_clk);
+err_get_clk:
        return r;
 }
 
 static int omap_dispchw_remove(struct platform_device *pdev)
 {
+       pm_runtime_disable(&pdev->dev);
+
+       clk_put(dispc.dss_clk);
+
        free_irq(dispc.irq, dispc.pdev);
        iounmap(dispc.base);
        return 0;
 }
 
+static int dispc_runtime_suspend(struct device *dev)
+{
+       dispc_save_context();
+       clk_disable(dispc.dss_clk);
+       dss_runtime_put();
+
+       return 0;
+}
+
+static int dispc_runtime_resume(struct device *dev)
+{
+       int r;
+
+       r = dss_runtime_get();
+       if (r < 0)
+               return r;
+
+       clk_enable(dispc.dss_clk);
+       dispc_restore_context();
+
+       return 0;
+}
+
+static const struct dev_pm_ops dispc_pm_ops = {
+       .runtime_suspend = dispc_runtime_suspend,
+       .runtime_resume = dispc_runtime_resume,
+};
+
 static struct platform_driver omap_dispchw_driver = {
        .probe          = omap_dispchw_probe,
        .remove         = omap_dispchw_remove,
        .driver         = {
                .name   = "omapdss_dispc",
                .owner  = THIS_MODULE,
+               .pm     = &dispc_pm_ops,
        },
 };
 
index c2dfc8c..94495e4 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <video/omapdss.h>
 #include "dss.h"
+#include "dss_features.h"
 
 static ssize_t display_enabled_show(struct device *dev,
                struct device_attribute *attr, char *buf)
@@ -65,48 +66,6 @@ static ssize_t display_enabled_store(struct device *dev,
        return size;
 }
 
-static ssize_t display_upd_mode_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO;
-       if (dssdev->driver->get_update_mode)
-               mode = dssdev->driver->get_update_mode(dssdev);
-       return snprintf(buf, PAGE_SIZE, "%d\n", mode);
-}
-
-static ssize_t display_upd_mode_store(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf, size_t size)
-{
-       struct omap_dss_device *dssdev = to_dss_device(dev);
-       int val, r;
-       enum omap_dss_update_mode mode;
-
-       if (!dssdev->driver->set_update_mode)
-               return -EINVAL;
-
-       r = kstrtoint(buf, 0, &val);
-       if (r)
-               return r;
-
-       switch (val) {
-       case OMAP_DSS_UPDATE_DISABLED:
-       case OMAP_DSS_UPDATE_AUTO:
-       case OMAP_DSS_UPDATE_MANUAL:
-               mode = (enum omap_dss_update_mode)val;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       r = dssdev->driver->set_update_mode(dssdev, mode);
-       if (r)
-               return r;
-
-       return size;
-}
-
 static ssize_t display_tear_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
@@ -294,8 +253,6 @@ static ssize_t display_wss_store(struct device *dev,
 
 static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
                display_enabled_show, display_enabled_store);
-static DEVICE_ATTR(update_mode, S_IRUGO|S_IWUSR,
-               display_upd_mode_show, display_upd_mode_store);
 static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
                display_tear_show, display_tear_store);
 static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
@@ -309,7 +266,6 @@ static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
 
 static struct device_attribute *display_sysfs_attrs[] = {
        &dev_attr_enabled,
-       &dev_attr_update_mode,
        &dev_attr_tear_elim,
        &dev_attr_timings,
        &dev_attr_rotate,
@@ -327,16 +283,13 @@ void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
 EXPORT_SYMBOL(omapdss_default_get_resolution);
 
 void default_get_overlay_fifo_thresholds(enum omap_plane plane,
-               u32 fifo_size, enum omap_burst_size *burst_size,
+               u32 fifo_size, u32 burst_size,
                u32 *fifo_low, u32 *fifo_high)
 {
-       unsigned burst_size_bytes;
-
-       *burst_size = OMAP_DSS_BURST_16x32;
-       burst_size_bytes = 16 * 32 / 8;
+       unsigned buf_unit = dss_feat_get_buffer_size_unit();
 
-       *fifo_high = fifo_size - 1;
-       *fifo_low = fifo_size - burst_size_bytes;
+       *fifo_high = fifo_size - buf_unit;
+       *fifo_low = fifo_size - burst_size;
 }
 
 int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
index ff6bd30..f053b18 100644 (file)
@@ -23,7 +23,6 @@
 #define DSS_SUBSYS_NAME "DPI"
 
 #include <linux/kernel.h>
-#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/errno.h>
@@ -130,8 +129,6 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
        bool is_tft;
        int r = 0;
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
-
        dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
                        dssdev->panel.acbi, dssdev->panel.acb);
 
@@ -144,7 +141,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
                r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000,
                                &fck, &lck_div, &pck_div);
        if (r)
-               goto err0;
+               return r;
 
        pck = fck / lck_div / pck_div / 1000;
 
@@ -158,12 +155,10 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
 
        dispc_set_lcd_timings(dssdev->manager->id, t);
 
-err0:
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
-       return r;
+       return 0;
 }
 
-static int dpi_basic_init(struct omap_dss_device *dssdev)
+static void dpi_basic_init(struct omap_dss_device *dssdev)
 {
        bool is_tft;
 
@@ -175,8 +170,6 @@ static int dpi_basic_init(struct omap_dss_device *dssdev)
                        OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN);
        dispc_set_tft_data_lines(dssdev->manager->id,
                        dssdev->phy.dpi.data_lines);
-
-       return 0;
 }
 
 int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
@@ -186,31 +179,38 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
        r = omap_dss_start_device(dssdev);
        if (r) {
                DSSERR("failed to start device\n");
-               goto err0;
+               goto err_start_dev;
        }
 
        if (cpu_is_omap34xx()) {
                r = regulator_enable(dpi.vdds_dsi_reg);
                if (r)
-                       goto err1;
+                       goto err_reg_enable;
        }
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+       r = dss_runtime_get();
+       if (r)
+               goto err_get_dss;
 
-       r = dpi_basic_init(dssdev);
+       r = dispc_runtime_get();
        if (r)
-               goto err2;
+               goto err_get_dispc;
+
+       dpi_basic_init(dssdev);
 
        if (dpi_use_dsi_pll(dssdev)) {
-               dss_clk_enable(DSS_CLK_SYSCK);
+               r = dsi_runtime_get(dpi.dsidev);
+               if (r)
+                       goto err_get_dsi;
+
                r = dsi_pll_init(dpi.dsidev, 0, 1);
                if (r)
-                       goto err3;
+                       goto err_dsi_pll_init;
        }
 
        r = dpi_set_mode(dssdev);
        if (r)
-               goto err4;
+               goto err_set_mode;
 
        mdelay(2);
 
@@ -218,19 +218,22 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 
        return 0;
 
-err4:
+err_set_mode:
        if (dpi_use_dsi_pll(dssdev))
                dsi_pll_uninit(dpi.dsidev, true);
-err3:
+err_dsi_pll_init:
        if (dpi_use_dsi_pll(dssdev))
-               dss_clk_disable(DSS_CLK_SYSCK);
-err2:
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+               dsi_runtime_put(dpi.dsidev);
+err_get_dsi:
+       dispc_runtime_put();
+err_get_dispc:
+       dss_runtime_put();
+err_get_dss:
        if (cpu_is_omap34xx())
                regulator_disable(dpi.vdds_dsi_reg);
-err1:
+err_reg_enable:
        omap_dss_stop_device(dssdev);
-err0:
+err_start_dev:
        return r;
 }
 EXPORT_SYMBOL(omapdss_dpi_display_enable);
@@ -242,10 +245,11 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
        if (dpi_use_dsi_pll(dssdev)) {
                dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
                dsi_pll_uninit(dpi.dsidev, true);
-               dss_clk_disable(DSS_CLK_SYSCK);
+               dsi_runtime_put(dpi.dsidev);
        }
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       dispc_runtime_put();
+       dss_runtime_put();
 
        if (cpu_is_omap34xx())
                regulator_disable(dpi.vdds_dsi_reg);
@@ -257,11 +261,26 @@ EXPORT_SYMBOL(omapdss_dpi_display_disable);
 void dpi_set_timings(struct omap_dss_device *dssdev,
                        struct omap_video_timings *timings)
 {
+       int r;
+
        DSSDBG("dpi_set_timings\n");
        dssdev->panel.timings = *timings;
        if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+               r = dss_runtime_get();
+               if (r)
+                       return;
+
+               r = dispc_runtime_get();
+               if (r) {
+                       dss_runtime_put();
+                       return;
+               }
+
                dpi_set_mode(dssdev);
                dispc_go(dssdev->manager->id);
+
+               dispc_runtime_put();
+               dss_runtime_put();
        }
 }
 EXPORT_SYMBOL(dpi_set_timings);
index 345757c..7adbbeb 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/debugfs.h>
+#include <linux/pm_runtime.h>
 
 #include <video/omapdss.h>
 #include <plat/clock.h>
@@ -267,8 +268,12 @@ struct dsi_isr_tables {
 struct dsi_data {
        struct platform_device *pdev;
        void __iomem    *base;
+
        int irq;
 
+       struct clk *dss_clk;
+       struct clk *sys_clk;
+
        void (*dsi_mux_pads)(bool enable);
 
        struct dsi_clock_info current_cinfo;
@@ -389,15 +394,6 @@ static inline u32 dsi_read_reg(struct platform_device *dsidev,
        return __raw_readl(dsi->base + idx.idx);
 }
 
-
-void dsi_save_context(void)
-{
-}
-
-void dsi_restore_context(void)
-{
-}
-
 void dsi_bus_lock(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -493,9 +489,18 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name)
                        total_bytes * 1000 / total_us);
 }
 #else
-#define dsi_perf_mark_setup(x)
-#define dsi_perf_mark_start(x)
-#define dsi_perf_show(x, y)
+static inline void dsi_perf_mark_setup(struct platform_device *dsidev)
+{
+}
+
+static inline void dsi_perf_mark_start(struct platform_device *dsidev)
+{
+}
+
+static inline void dsi_perf_show(struct platform_device *dsidev,
+               const char *name)
+{
+}
 #endif
 
 static void print_irq_status(u32 status)
@@ -1039,13 +1044,27 @@ static u32 dsi_get_errors(struct platform_device *dsidev)
        return e;
 }
 
-/* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */
-static inline void enable_clocks(bool enable)
+int dsi_runtime_get(struct platform_device *dsidev)
 {
-       if (enable)
-               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
-       else
-               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       int r;
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+       DSSDBG("dsi_runtime_get\n");
+
+       r = pm_runtime_get_sync(&dsi->pdev->dev);
+       WARN_ON(r < 0);
+       return r < 0 ? r : 0;
+}
+
+void dsi_runtime_put(struct platform_device *dsidev)
+{
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       int r;
+
+       DSSDBG("dsi_runtime_put\n");
+
+       r = pm_runtime_put(&dsi->pdev->dev);
+       WARN_ON(r < 0);
 }
 
 /* source clock for DSI PLL. this could also be PCLKFREE */
@@ -1055,9 +1074,9 @@ static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
        if (enable)
-               dss_clk_enable(DSS_CLK_SYSCK);
+               clk_enable(dsi->sys_clk);
        else
-               dss_clk_disable(DSS_CLK_SYSCK);
+               clk_disable(dsi->sys_clk);
 
        if (enable && dsi->pll_locked) {
                if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1)
@@ -1150,10 +1169,11 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
 {
        unsigned long r;
        int dsi_module = dsi_get_dsidev_id(dsidev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
        if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) {
                /* DSI FCLK source is DSS_CLK_FCK */
-               r = dss_clk_get_rate(DSS_CLK_FCK);
+               r = clk_get_rate(dsi->dss_clk);
        } else {
                /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */
                r = dsi_get_pll_hsdiv_dsi_rate(dsidev);
@@ -1262,7 +1282,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
                return -EINVAL;
 
        if (cinfo->use_sys_clk) {
-               cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK);
+               cinfo->clkin = clk_get_rate(dsi->sys_clk);
                /* XXX it is unclear if highfreq should be used
                 * with DSS_SYS_CLK source also */
                cinfo->highfreq = 0;
@@ -1311,7 +1331,7 @@ int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft,
        int match = 0;
        unsigned long dss_sys_clk, max_dss_fck;
 
-       dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK);
+       dss_sys_clk = clk_get_rate(dsi->sys_clk);
 
        max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
 
@@ -1601,7 +1621,6 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
                dsi->vdds_dsi_reg = vdds_dsi;
        }
 
-       enable_clocks(1);
        dsi_enable_pll_clock(dsidev, 1);
        /*
         * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4.
@@ -1653,7 +1672,6 @@ err1:
        }
 err0:
        dsi_disable_scp_clk(dsidev);
-       enable_clocks(0);
        dsi_enable_pll_clock(dsidev, 0);
        return r;
 }
@@ -1671,7 +1689,6 @@ void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes)
        }
 
        dsi_disable_scp_clk(dsidev);
-       enable_clocks(0);
        dsi_enable_pll_clock(dsidev, 0);
 
        DSSDBG("PLL uninit done\n");
@@ -1688,7 +1705,8 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
        dispc_clk_src = dss_get_dispc_clk_source();
        dsi_clk_src = dss_get_dsi_clk_source(dsi_module);
 
-       enable_clocks(1);
+       if (dsi_runtime_get(dsidev))
+               return;
 
        seq_printf(s,   "- DSI%d PLL -\n", dsi_module + 1);
 
@@ -1731,7 +1749,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
 
        seq_printf(s,   "LP_CLK\t\t%lu\n", cinfo->lp_clk);
 
-       enable_clocks(0);
+       dsi_runtime_put(dsidev);
 }
 
 void dsi_dump_clocks(struct seq_file *s)
@@ -1873,7 +1891,8 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsidev, r))
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+       if (dsi_runtime_get(dsidev))
+               return;
        dsi_enable_scp_clk(dsidev);
 
        DUMPREG(DSI_REVISION);
@@ -1947,7 +1966,7 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
        DUMPREG(DSI_PLL_CONFIGURATION2);
 
        dsi_disable_scp_clk(dsidev);
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       dsi_runtime_put(dsidev);
 #undef DUMPREG
 }
 
@@ -2463,28 +2482,6 @@ static void dsi_cio_uninit(struct platform_device *dsidev)
                dsi->dsi_mux_pads(false);
 }
 
-static int _dsi_wait_reset(struct platform_device *dsidev)
-{
-       int t = 0;
-
-       while (REG_GET(dsidev, DSI_SYSSTATUS, 0, 0) == 0) {
-               if (++t > 5) {
-                       DSSERR("soft reset failed\n");
-                       return -ENODEV;
-               }
-               udelay(1);
-       }
-
-       return 0;
-}
-
-static int _dsi_reset(struct platform_device *dsidev)
-{
-       /* Soft reset */
-       REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 1, 1);
-       return _dsi_wait_reset(dsidev);
-}
-
 static void dsi_config_tx_fifo(struct platform_device *dsidev,
                enum fifo_size size1, enum fifo_size size2,
                enum fifo_size size3, enum fifo_size size4)
@@ -3386,6 +3383,10 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
        dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion,
                        DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
 
+       /* Reset LANEx_ULPS_SIG2 */
+       REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0 << 0) | (0 << 1) | (0 << 2),
+               7, 5);
+
        dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS);
 
        dsi_if_enable(dsidev, false);
@@ -4198,22 +4199,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
        dsi_pll_uninit(dsidev, disconnect_lanes);
 }
 
-static int dsi_core_init(struct platform_device *dsidev)
-{
-       /* Autoidle */
-       REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 0, 0);
-
-       /* ENWAKEUP */
-       REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 2, 2);
-
-       /* SIDLEMODE smart-idle */
-       REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 2, 4, 3);
-
-       _dsi_initialize_irq(dsidev);
-
-       return 0;
-}
-
 int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
 {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -4229,37 +4214,37 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
        r = omap_dss_start_device(dssdev);
        if (r) {
                DSSERR("failed to start device\n");
-               goto err0;
+               goto err_start_dev;
        }
 
-       enable_clocks(1);
-       dsi_enable_pll_clock(dsidev, 1);
-
-       r = _dsi_reset(dsidev);
+       r = dsi_runtime_get(dsidev);
        if (r)
-               goto err1;
+               goto err_get_dsi;
 
-       dsi_core_init(dsidev);
+       dsi_enable_pll_clock(dsidev, 1);
+
+       _dsi_initialize_irq(dsidev);
 
        r = dsi_display_init_dispc(dssdev);
        if (r)
-               goto err1;
+               goto err_init_dispc;
 
        r = dsi_display_init_dsi(dssdev);
        if (r)
-               goto err2;
+               goto err_init_dsi;
 
        mutex_unlock(&dsi->lock);
 
        return 0;
 
-err2:
+err_init_dsi:
        dsi_display_uninit_dispc(dssdev);
-err1:
-       enable_clocks(0);
+err_init_dispc:
        dsi_enable_pll_clock(dsidev, 0);
+       dsi_runtime_put(dsidev);
+err_get_dsi:
        omap_dss_stop_device(dssdev);
-err0:
+err_start_dev:
        mutex_unlock(&dsi->lock);
        DSSDBG("dsi_display_enable FAILED\n");
        return r;
@@ -4278,11 +4263,16 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
 
        mutex_lock(&dsi->lock);
 
+       dsi_sync_vc(dsidev, 0);
+       dsi_sync_vc(dsidev, 1);
+       dsi_sync_vc(dsidev, 2);
+       dsi_sync_vc(dsidev, 3);
+
        dsi_display_uninit_dispc(dssdev);
 
        dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps);
 
-       enable_clocks(0);
+       dsi_runtime_put(dsidev);
        dsi_enable_pll_clock(dsidev, 0);
 
        omap_dss_stop_device(dssdev);
@@ -4302,16 +4292,11 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
 EXPORT_SYMBOL(omapdss_dsi_enable_te);
 
 void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
-               u32 fifo_size, enum omap_burst_size *burst_size,
+               u32 fifo_size, u32 burst_size,
                u32 *fifo_low, u32 *fifo_high)
 {
-       unsigned burst_size_bytes;
-
-       *burst_size = OMAP_DSS_BURST_16x32;
-       burst_size_bytes = 16 * 32 / 8;
-
-       *fifo_high = fifo_size - burst_size_bytes;
-       *fifo_low = fifo_size - burst_size_bytes * 2;
+       *fifo_high = fifo_size - burst_size;
+       *fifo_low = fifo_size - burst_size * 2;
 }
 
 int dsi_init_display(struct omap_dss_device *dssdev)
@@ -4437,7 +4422,47 @@ static void dsi_calc_clock_param_ranges(struct platform_device *dsidev)
        dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
 }
 
-static int dsi_init(struct platform_device *dsidev)
+static int dsi_get_clocks(struct platform_device *dsidev)
+{
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       struct clk *clk;
+
+       clk = clk_get(&dsidev->dev, "fck");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get fck\n");
+               return PTR_ERR(clk);
+       }
+
+       dsi->dss_clk = clk;
+
+       if (cpu_is_omap34xx() || cpu_is_omap3630())
+               clk = clk_get(&dsidev->dev, "dss2_alwon_fck");
+       else
+               clk = clk_get(&dsidev->dev, "sys_clk");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get sys_clk\n");
+               clk_put(dsi->dss_clk);
+               dsi->dss_clk = NULL;
+               return PTR_ERR(clk);
+       }
+
+       dsi->sys_clk = clk;
+
+       return 0;
+}
+
+static void dsi_put_clocks(struct platform_device *dsidev)
+{
+       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+       if (dsi->dss_clk)
+               clk_put(dsi->dss_clk);
+       if (dsi->sys_clk)
+               clk_put(dsi->sys_clk);
+}
+
+/* DSI1 HW IP initialisation */
+static int omap_dsi1hw_probe(struct platform_device *dsidev)
 {
        struct omap_display_platform_data *dss_plat_data;
        struct omap_dss_board_info *board_info;
@@ -4449,7 +4474,7 @@ static int dsi_init(struct platform_device *dsidev)
        dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
        if (!dsi) {
                r = -ENOMEM;
-               goto err0;
+               goto err_alloc;
        }
 
        dsi->pdev = dsidev;
@@ -4472,6 +4497,12 @@ static int dsi_init(struct platform_device *dsidev)
        mutex_init(&dsi->lock);
        sema_init(&dsi->bus_lock, 1);
 
+       r = dsi_get_clocks(dsidev);
+       if (r)
+               goto err_get_clk;
+
+       pm_runtime_enable(&dsidev->dev);
+
        INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work,
                        dsi_framedone_timeout_work_callback);
 
@@ -4484,26 +4515,26 @@ static int dsi_init(struct platform_device *dsidev)
        if (!dsi_mem) {
                DSSERR("can't get IORESOURCE_MEM DSI\n");
                r = -EINVAL;
-               goto err1;
+               goto err_ioremap;
        }
        dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem));
        if (!dsi->base) {
                DSSERR("can't ioremap DSI\n");
                r = -ENOMEM;
-               goto err1;
+               goto err_ioremap;
        }
        dsi->irq = platform_get_irq(dsi->pdev, 0);
        if (dsi->irq < 0) {
                DSSERR("platform_get_irq failed\n");
                r = -ENODEV;
-               goto err2;
+               goto err_get_irq;
        }
 
        r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED,
                dev_name(&dsidev->dev), dsi->pdev);
        if (r < 0) {
                DSSERR("request_irq failed\n");
-               goto err2;
+               goto err_get_irq;
        }
 
        /* DSI VCs initialization */
@@ -4515,7 +4546,9 @@ static int dsi_init(struct platform_device *dsidev)
 
        dsi_calc_clock_param_ranges(dsidev);
 
-       enable_clocks(1);
+       r = dsi_runtime_get(dsidev);
+       if (r)
+               goto err_get_dsi;
 
        rev = dsi_read_reg(dsidev, DSI_REVISION);
        dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n",
@@ -4523,21 +4556,32 @@ static int dsi_init(struct platform_device *dsidev)
 
        dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev);
 
-       enable_clocks(0);
+       dsi_runtime_put(dsidev);
 
        return 0;
-err2:
+
+err_get_dsi:
+       free_irq(dsi->irq, dsi->pdev);
+err_get_irq:
        iounmap(dsi->base);
-err1:
+err_ioremap:
+       pm_runtime_disable(&dsidev->dev);
+err_get_clk:
        kfree(dsi);
-err0:
+err_alloc:
        return r;
 }
 
-static void dsi_exit(struct platform_device *dsidev)
+static int omap_dsi1hw_remove(struct platform_device *dsidev)
 {
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 
+       WARN_ON(dsi->scp_clk_refcount > 0);
+
+       pm_runtime_disable(&dsidev->dev);
+
+       dsi_put_clocks(dsidev);
+
        if (dsi->vdds_dsi_reg != NULL) {
                if (dsi->vdds_dsi_enabled) {
                        regulator_disable(dsi->vdds_dsi_reg);
@@ -4553,38 +4597,56 @@ static void dsi_exit(struct platform_device *dsidev)
 
        kfree(dsi);
 
-       DSSDBG("omap_dsi_exit\n");
+       return 0;
 }
 
-/* DSI1 HW IP initialisation */
-static int omap_dsi1hw_probe(struct platform_device *dsidev)
+static int dsi_runtime_suspend(struct device *dev)
 {
-       int r;
+       struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
 
-       r = dsi_init(dsidev);
-       if (r) {
-               DSSERR("Failed to initialize DSI\n");
-               goto err_dsi;
-       }
-err_dsi:
-       return r;
+       clk_disable(dsi->dss_clk);
+
+       dispc_runtime_put();
+       dss_runtime_put();
+
+       return 0;
 }
 
-static int omap_dsi1hw_remove(struct platform_device *dsidev)
+static int dsi_runtime_resume(struct device *dev)
 {
-       struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+       struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
+       int r;
+
+       r = dss_runtime_get();
+       if (r)
+               goto err_get_dss;
+
+       r = dispc_runtime_get();
+       if (r)
+               goto err_get_dispc;
+
+       clk_enable(dsi->dss_clk);
 
-       dsi_exit(dsidev);
-       WARN_ON(dsi->scp_clk_refcount > 0);
        return 0;
+
+err_get_dispc:
+       dss_runtime_put();
+err_get_dss:
+       return r;
 }
 
+static const struct dev_pm_ops dsi_pm_ops = {
+       .runtime_suspend = dsi_runtime_suspend,
+       .runtime_resume = dsi_runtime_resume,
+};
+
 static struct platform_driver omap_dsi1hw_driver = {
        .probe          = omap_dsi1hw_probe,
        .remove         = omap_dsi1hw_remove,
        .driver         = {
                .name   = "omapdss_dsi1",
                .owner  = THIS_MODULE,
+               .pm     = &dsi_pm_ops,
        },
 };
 
index d9489d5..0f9c3a6 100644 (file)
@@ -28,6 +28,8 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 
 #include <video/omapdss.h>
 #include <plat/clock.h>
@@ -59,15 +61,9 @@ struct dss_reg {
 static struct {
        struct platform_device *pdev;
        void __iomem    *base;
-       int             ctx_id;
 
        struct clk      *dpll4_m4_ck;
-       struct clk      *dss_ick;
-       struct clk      *dss_fck;
-       struct clk      *dss_sys_clk;
-       struct clk      *dss_tv_fck;
-       struct clk      *dss_video_fck;
-       unsigned        num_clks_enabled;
+       struct clk      *dss_clk;
 
        unsigned long   cache_req_pck;
        unsigned long   cache_prate;
@@ -78,6 +74,7 @@ static struct {
        enum omap_dss_clk_source dispc_clk_source;
        enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
 
+       bool            ctx_valid;
        u32             ctx[DSS_SZ_REGS / sizeof(u32)];
 } dss;
 
@@ -87,13 +84,6 @@ static const char * const dss_generic_clk_source_names[] = {
        [OMAP_DSS_CLK_SRC_FCK]                  = "DSS_FCK",
 };
 
-static void dss_clk_enable_all_no_ctx(void);
-static void dss_clk_disable_all_no_ctx(void);
-static void dss_clk_enable_no_ctx(enum dss_clock clks);
-static void dss_clk_disable_no_ctx(enum dss_clock clks);
-
-static int _omap_dss_wait_reset(void);
-
 static inline void dss_write_reg(const struct dss_reg idx, u32 val)
 {
        __raw_writel(val, dss.base + idx.idx);
@@ -109,12 +99,10 @@ static inline u32 dss_read_reg(const struct dss_reg idx)
 #define RR(reg) \
        dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
 
-void dss_save_context(void)
+static void dss_save_context(void)
 {
-       if (cpu_is_omap24xx())
-               return;
+       DSSDBG("dss_save_context\n");
 
-       SR(SYSCONFIG);
        SR(CONTROL);
 
        if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -122,14 +110,19 @@ void dss_save_context(void)
                SR(SDI_CONTROL);
                SR(PLL_CONTROL);
        }
+
+       dss.ctx_valid = true;
+
+       DSSDBG("context saved\n");
 }
 
-void dss_restore_context(void)
+static void dss_restore_context(void)
 {
-       if (_omap_dss_wait_reset())
-               DSSERR("DSS not coming out of reset after sleep\n");
+       DSSDBG("dss_restore_context\n");
+
+       if (!dss.ctx_valid)
+               return;
 
-       RR(SYSCONFIG);
        RR(CONTROL);
 
        if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -137,6 +130,8 @@ void dss_restore_context(void)
                RR(SDI_CONTROL);
                RR(PLL_CONTROL);
        }
+
+       DSSDBG("context restored\n");
 }
 
 #undef SR
@@ -234,6 +229,7 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
        return dss_generic_clk_source_names[clk_src];
 }
 
+
 void dss_dump_clocks(struct seq_file *s)
 {
        unsigned long dpll4_ck_rate;
@@ -241,13 +237,14 @@ void dss_dump_clocks(struct seq_file *s)
        const char *fclk_name, *fclk_real_name;
        unsigned long fclk_rate;
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+       if (dss_runtime_get())
+               return;
 
        seq_printf(s, "- DSS -\n");
 
        fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
        fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
-       fclk_rate = dss_clk_get_rate(DSS_CLK_FCK);
+       fclk_rate = clk_get_rate(dss.dss_clk);
 
        if (dss.dpll4_m4_ck) {
                dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
@@ -273,14 +270,15 @@ void dss_dump_clocks(struct seq_file *s)
                                fclk_rate);
        }
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       dss_runtime_put();
 }
 
 void dss_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+       if (dss_runtime_get())
+               return;
 
        DUMPREG(DSS_REVISION);
        DUMPREG(DSS_SYSCONFIG);
@@ -294,7 +292,7 @@ void dss_dump_regs(struct seq_file *s)
                DUMPREG(DSS_SDI_STATUS);
        }
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       dss_runtime_put();
 #undef DUMPREG
 }
 
@@ -437,7 +435,7 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
        } else {
                if (cinfo->fck_div != 0)
                        return -EINVAL;
-               cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
+               cinfo->fck = clk_get_rate(dss.dss_clk);
        }
 
        return 0;
@@ -467,7 +465,7 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
 
 int dss_get_clock_div(struct dss_clock_info *cinfo)
 {
-       cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
+       cinfo->fck = clk_get_rate(dss.dss_clk);
 
        if (dss.dpll4_m4_ck) {
                unsigned long prate;
@@ -512,7 +510,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
 
        max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
 
-       fck = dss_clk_get_rate(DSS_CLK_FCK);
+       fck = clk_get_rate(dss.dss_clk);
        if (req_pck == dss.cache_req_pck &&
                        ((cpu_is_omap34xx() && prate == dss.cache_prate) ||
                         dss.cache_dss_cinfo.fck == fck)) {
@@ -539,7 +537,7 @@ retry:
        if (dss.dpll4_m4_ck == NULL) {
                struct dispc_clock_info cur_dispc;
                /* XXX can we change the clock on omap2? */
-               fck = dss_clk_get_rate(DSS_CLK_FCK);
+               fck = clk_get_rate(dss.dss_clk);
                fck_div = 1;
 
                dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
@@ -616,28 +614,6 @@ found:
        return 0;
 }
 
-static int _omap_dss_wait_reset(void)
-{
-       int t = 0;
-
-       while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
-               if (++t > 1000) {
-                       DSSERR("soft reset failed\n");
-                       return -ENODEV;
-               }
-               udelay(1);
-       }
-
-       return 0;
-}
-
-static int _omap_dss_reset(void)
-{
-       /* Soft reset */
-       REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
-       return _omap_dss_wait_reset();
-}
-
 void dss_set_venc_output(enum omap_dss_venc_type type)
 {
        int l = 0;
@@ -663,424 +639,88 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
        REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */
 }
 
-static int dss_init(void)
+static int dss_get_clocks(void)
 {
+       struct clk *clk;
        int r;
-       u32 rev;
-       struct resource *dss_mem;
-       struct clk *dpll4_m4_ck;
 
-       dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
-       if (!dss_mem) {
-               DSSERR("can't get IORESOURCE_MEM DSS\n");
-               r = -EINVAL;
-               goto fail0;
-       }
-       dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
-       if (!dss.base) {
-               DSSERR("can't ioremap DSS\n");
-               r = -ENOMEM;
-               goto fail0;
+       clk = clk_get(&dss.pdev->dev, "fck");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get clock fck\n");
+               r = PTR_ERR(clk);
+               goto err;
        }
 
-       /* disable LCD and DIGIT output. This seems to fix the synclost
-        * problem that we get, if the bootloader starts the DSS and
-        * the kernel resets it */
-       omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
-
-#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
-       /* We need to wait here a bit, otherwise we sometimes start to
-        * get synclost errors, and after that only power cycle will
-        * restore DSS functionality. I have no idea why this happens.
-        * And we have to wait _before_ resetting the DSS, but after
-        * enabling clocks.
-        *
-        * This bug was at least present on OMAP3430. It's unknown
-        * if it happens on OMAP2 or OMAP3630.
-        */
-       msleep(50);
-#endif
-
-       _omap_dss_reset();
+       dss.dss_clk = clk;
 
-       /* autoidle */
-       REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
-
-       /* Select DPLL */
-       REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
-
-#ifdef CONFIG_OMAP2_DSS_VENC
-       REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);      /* venc dac demen */
-       REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);      /* venc clock 4x enable */
-       REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);      /* venc clock mode = normal */
-#endif
        if (cpu_is_omap34xx()) {
-               dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
-               if (IS_ERR(dpll4_m4_ck)) {
+               clk = clk_get(NULL, "dpll4_m4_ck");
+               if (IS_ERR(clk)) {
                        DSSERR("Failed to get dpll4_m4_ck\n");
-                       r = PTR_ERR(dpll4_m4_ck);
-                       goto fail1;
+                       r = PTR_ERR(clk);
+                       goto err;
                }
        } else if (cpu_is_omap44xx()) {
-               dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck");
-               if (IS_ERR(dpll4_m4_ck)) {
-                       DSSERR("Failed to get dpll4_m4_ck\n");
-                       r = PTR_ERR(dpll4_m4_ck);
-                       goto fail1;
+               clk = clk_get(NULL, "dpll_per_m5x2_ck");
+               if (IS_ERR(clk)) {
+                       DSSERR("Failed to get dpll_per_m5x2_ck\n");
+                       r = PTR_ERR(clk);
+                       goto err;
                }
        } else { /* omap24xx */
-               dpll4_m4_ck = NULL;
+               clk = NULL;
        }
 
-       dss.dpll4_m4_ck = dpll4_m4_ck;
-
-       dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
-       dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
-       dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
-       dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
-       dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
-
-       dss_save_context();
-
-       rev = dss_read_reg(DSS_REVISION);
-       printk(KERN_INFO "OMAP DSS rev %d.%d\n",
-                       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+       dss.dpll4_m4_ck = clk;
 
        return 0;
 
-fail1:
-       iounmap(dss.base);
-fail0:
-       return r;
-}
-
-static void dss_exit(void)
-{
+err:
+       if (dss.dss_clk)
+               clk_put(dss.dss_clk);
        if (dss.dpll4_m4_ck)
                clk_put(dss.dpll4_m4_ck);
 
-       iounmap(dss.base);
-}
-
-/* CONTEXT */
-static int dss_get_ctx_id(void)
-{
-       struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
-       int r;
-
-       if (!pdata->board_data->get_last_off_on_transaction_id)
-               return 0;
-       r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev);
-       if (r < 0) {
-               dev_err(&dss.pdev->dev, "getting transaction ID failed, "
-                               "will force context restore\n");
-               r = -1;
-       }
-       return r;
-}
-
-int dss_need_ctx_restore(void)
-{
-       int id = dss_get_ctx_id();
-
-       if (id < 0 || id != dss.ctx_id) {
-               DSSDBG("ctx id %d -> id %d\n",
-                               dss.ctx_id, id);
-               dss.ctx_id = id;
-               return 1;
-       } else {
-               return 0;
-       }
-}
-
-static void save_all_ctx(void)
-{
-       DSSDBG("save context\n");
-
-       dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
-
-       dss_save_context();
-       dispc_save_context();
-#ifdef CONFIG_OMAP2_DSS_DSI
-       dsi_save_context();
-#endif
-
-       dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
-}
-
-static void restore_all_ctx(void)
-{
-       DSSDBG("restore context\n");
-
-       dss_clk_enable_all_no_ctx();
-
-       dss_restore_context();
-       dispc_restore_context();
-#ifdef CONFIG_OMAP2_DSS_DSI
-       dsi_restore_context();
-#endif
-
-       dss_clk_disable_all_no_ctx();
-}
-
-static int dss_get_clock(struct clk **clock, const char *clk_name)
-{
-       struct clk *clk;
-
-       clk = clk_get(&dss.pdev->dev, clk_name);
-
-       if (IS_ERR(clk)) {
-               DSSERR("can't get clock %s", clk_name);
-               return PTR_ERR(clk);
-       }
-
-       *clock = clk;
-
-       DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
-
-       return 0;
-}
-
-static int dss_get_clocks(void)
-{
-       int r;
-       struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
-
-       dss.dss_ick = NULL;
-       dss.dss_fck = NULL;
-       dss.dss_sys_clk = NULL;
-       dss.dss_tv_fck = NULL;
-       dss.dss_video_fck = NULL;
-
-       r = dss_get_clock(&dss.dss_ick, "ick");
-       if (r)
-               goto err;
-
-       r = dss_get_clock(&dss.dss_fck, "fck");
-       if (r)
-               goto err;
-
-       if (!pdata->opt_clock_available) {
-               r = -ENODEV;
-               goto err;
-       }
-
-       if (pdata->opt_clock_available("sys_clk")) {
-               r = dss_get_clock(&dss.dss_sys_clk, "sys_clk");
-               if (r)
-                       goto err;
-       }
-
-       if (pdata->opt_clock_available("tv_clk")) {
-               r = dss_get_clock(&dss.dss_tv_fck, "tv_clk");
-               if (r)
-                       goto err;
-       }
-
-       if (pdata->opt_clock_available("video_clk")) {
-               r = dss_get_clock(&dss.dss_video_fck, "video_clk");
-               if (r)
-                       goto err;
-       }
-
-       return 0;
-
-err:
-       if (dss.dss_ick)
-               clk_put(dss.dss_ick);
-       if (dss.dss_fck)
-               clk_put(dss.dss_fck);
-       if (dss.dss_sys_clk)
-               clk_put(dss.dss_sys_clk);
-       if (dss.dss_tv_fck)
-               clk_put(dss.dss_tv_fck);
-       if (dss.dss_video_fck)
-               clk_put(dss.dss_video_fck);
-
        return r;
 }
 
 static void dss_put_clocks(void)
 {
-       if (dss.dss_video_fck)
-               clk_put(dss.dss_video_fck);
-       if (dss.dss_tv_fck)
-               clk_put(dss.dss_tv_fck);
-       if (dss.dss_sys_clk)
-               clk_put(dss.dss_sys_clk);
-       clk_put(dss.dss_fck);
-       clk_put(dss.dss_ick);
-}
-
-unsigned long dss_clk_get_rate(enum dss_clock clk)
-{
-       switch (clk) {
-       case DSS_CLK_ICK:
-               return clk_get_rate(dss.dss_ick);
-       case DSS_CLK_FCK:
-               return clk_get_rate(dss.dss_fck);
-       case DSS_CLK_SYSCK:
-               return clk_get_rate(dss.dss_sys_clk);
-       case DSS_CLK_TVFCK:
-               return clk_get_rate(dss.dss_tv_fck);
-       case DSS_CLK_VIDFCK:
-               return clk_get_rate(dss.dss_video_fck);
-       }
-
-       BUG();
-       return 0;
-}
-
-static unsigned count_clk_bits(enum dss_clock clks)
-{
-       unsigned num_clks = 0;
-
-       if (clks & DSS_CLK_ICK)
-               ++num_clks;
-       if (clks & DSS_CLK_FCK)
-               ++num_clks;
-       if (clks & DSS_CLK_SYSCK)
-               ++num_clks;
-       if (clks & DSS_CLK_TVFCK)
-               ++num_clks;
-       if (clks & DSS_CLK_VIDFCK)
-               ++num_clks;
-
-       return num_clks;
-}
-
-static void dss_clk_enable_no_ctx(enum dss_clock clks)
-{
-       unsigned num_clks = count_clk_bits(clks);
-
-       if (clks & DSS_CLK_ICK)
-               clk_enable(dss.dss_ick);
-       if (clks & DSS_CLK_FCK)
-               clk_enable(dss.dss_fck);
-       if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
-               clk_enable(dss.dss_sys_clk);
-       if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
-               clk_enable(dss.dss_tv_fck);
-       if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
-               clk_enable(dss.dss_video_fck);
-
-       dss.num_clks_enabled += num_clks;
-}
-
-void dss_clk_enable(enum dss_clock clks)
-{
-       bool check_ctx = dss.num_clks_enabled == 0;
-
-       dss_clk_enable_no_ctx(clks);
-
-       /*
-        * HACK: On omap4 the registers may not be accessible right after
-        * enabling the clocks. At some point this will be handled by
-        * pm_runtime, but for the time begin this should make things work.
-        */
-       if (cpu_is_omap44xx() && check_ctx)
-               udelay(10);
-
-       if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
-               restore_all_ctx();
+       if (dss.dpll4_m4_ck)
+               clk_put(dss.dpll4_m4_ck);
+       clk_put(dss.dss_clk);
 }
 
-static void dss_clk_disable_no_ctx(enum dss_clock clks)
+struct clk *dss_get_ick(void)
 {
-       unsigned num_clks = count_clk_bits(clks);
-
-       if (clks & DSS_CLK_ICK)
-               clk_disable(dss.dss_ick);
-       if (clks & DSS_CLK_FCK)
-               clk_disable(dss.dss_fck);
-       if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
-               clk_disable(dss.dss_sys_clk);
-       if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
-               clk_disable(dss.dss_tv_fck);
-       if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
-               clk_disable(dss.dss_video_fck);
-
-       dss.num_clks_enabled -= num_clks;
+       return clk_get(&dss.pdev->dev, "ick");
 }
 
-void dss_clk_disable(enum dss_clock clks)
+int dss_runtime_get(void)
 {
-       if (cpu_is_omap34xx()) {
-               unsigned num_clks = count_clk_bits(clks);
-
-               BUG_ON(dss.num_clks_enabled < num_clks);
+       int r;
 
-               if (dss.num_clks_enabled == num_clks)
-                       save_all_ctx();
-       }
+       DSSDBG("dss_runtime_get\n");
 
-       dss_clk_disable_no_ctx(clks);
+       r = pm_runtime_get_sync(&dss.pdev->dev);
+       WARN_ON(r < 0);
+       return r < 0 ? r : 0;
 }
 
-static void dss_clk_enable_all_no_ctx(void)
+void dss_runtime_put(void)
 {
-       enum dss_clock clks;
-
-       clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
-       if (cpu_is_omap34xx())
-               clks |= DSS_CLK_VIDFCK;
-       dss_clk_enable_no_ctx(clks);
-}
-
-static void dss_clk_disable_all_no_ctx(void)
-{
-       enum dss_clock clks;
+       int r;
 
-       clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
-       if (cpu_is_omap34xx())
-               clks |= DSS_CLK_VIDFCK;
-       dss_clk_disable_no_ctx(clks);
-}
+       DSSDBG("dss_runtime_put\n");
 
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
-/* CLOCKS */
-static void core_dump_clocks(struct seq_file *s)
-{
-       int i;
-       struct clk *clocks[5] = {
-               dss.dss_ick,
-               dss.dss_fck,
-               dss.dss_sys_clk,
-               dss.dss_tv_fck,
-               dss.dss_video_fck
-       };
-
-       const char *names[5] = {
-               "ick",
-               "fck",
-               "sys_clk",
-               "tv_fck",
-               "video_fck"
-       };
-
-       seq_printf(s, "- CORE -\n");
-
-       seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled);
-
-       for (i = 0; i < 5; i++) {
-               if (!clocks[i])
-                       continue;
-               seq_printf(s, "%s (%s)%*s\t%lu\t%d\n",
-                               names[i],
-                               clocks[i]->name,
-                               24 - strlen(names[i]) - strlen(clocks[i]->name),
-                               "",
-                               clk_get_rate(clocks[i]),
-                               clocks[i]->usecount);
-       }
+       r = pm_runtime_put(&dss.pdev->dev);
+       WARN_ON(r < 0);
 }
-#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */
 
 /* DEBUGFS */
 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
 void dss_debug_dump_clocks(struct seq_file *s)
 {
-       core_dump_clocks(s);
        dss_dump_clocks(s);
        dispc_dump_clocks(s);
 #ifdef CONFIG_OMAP2_DSS_DSI
@@ -1089,28 +729,51 @@ void dss_debug_dump_clocks(struct seq_file *s)
 }
 #endif
 
-
 /* DSS HW IP initialisation */
 static int omap_dsshw_probe(struct platform_device *pdev)
 {
+       struct resource *dss_mem;
+       u32 rev;
        int r;
 
        dss.pdev = pdev;
 
+       dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
+       if (!dss_mem) {
+               DSSERR("can't get IORESOURCE_MEM DSS\n");
+               r = -EINVAL;
+               goto err_ioremap;
+       }
+       dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
+       if (!dss.base) {
+               DSSERR("can't ioremap DSS\n");
+               r = -ENOMEM;
+               goto err_ioremap;
+       }
+
        r = dss_get_clocks();
        if (r)
                goto err_clocks;
 
-       dss_clk_enable_all_no_ctx();
+       pm_runtime_enable(&pdev->dev);
 
-       dss.ctx_id = dss_get_ctx_id();
-       DSSDBG("initial ctx id %u\n", dss.ctx_id);
+       r = dss_runtime_get();
+       if (r)
+               goto err_runtime_get;
 
-       r = dss_init();
-       if (r) {
-               DSSERR("Failed to initialize DSS\n");
-               goto err_dss;
-       }
+       /* Select DPLL */
+       REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
+
+#ifdef CONFIG_OMAP2_DSS_VENC
+       REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);      /* venc dac demen */
+       REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);      /* venc clock 4x enable */
+       REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);      /* venc clock mode = normal */
+#endif
+       dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
+       dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
+       dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
+       dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
+       dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
 
        r = dpi_init();
        if (r) {
@@ -1124,42 +787,66 @@ static int omap_dsshw_probe(struct platform_device *pdev)
                goto err_sdi;
        }
 
-       dss_clk_disable_all_no_ctx();
+       rev = dss_read_reg(DSS_REVISION);
+       printk(KERN_INFO "OMAP DSS rev %d.%d\n",
+                       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+       dss_runtime_put();
+
        return 0;
 err_sdi:
        dpi_exit();
 err_dpi:
-       dss_exit();
-err_dss:
-       dss_clk_disable_all_no_ctx();
+       dss_runtime_put();
+err_runtime_get:
+       pm_runtime_disable(&pdev->dev);
        dss_put_clocks();
 err_clocks:
+       iounmap(dss.base);
+err_ioremap:
        return r;
 }
 
 static int omap_dsshw_remove(struct platform_device *pdev)
 {
+       dpi_exit();
+       sdi_exit();
 
-       dss_exit();
+       iounmap(dss.base);
 
-       /*
-        * As part of hwmod changes, DSS is not the only controller of dss
-        * clocks; hwmod framework itself will also enable clocks during hwmod
-        * init for dss, and autoidle is set in h/w for DSS. Hence, there's no
-        * need to disable clocks if their usecounts > 1.
-        */
-       WARN_ON(dss.num_clks_enabled > 0);
+       pm_runtime_disable(&pdev->dev);
 
        dss_put_clocks();
+
+       return 0;
+}
+
+static int dss_runtime_suspend(struct device *dev)
+{
+       dss_save_context();
+       clk_disable(dss.dss_clk);
        return 0;
 }
 
+static int dss_runtime_resume(struct device *dev)
+{
+       clk_enable(dss.dss_clk);
+       dss_restore_context();
+       return 0;
+}
+
+static const struct dev_pm_ops dss_pm_ops = {
+       .runtime_suspend = dss_runtime_suspend,
+       .runtime_resume = dss_runtime_resume,
+};
+
 static struct platform_driver omap_dsshw_driver = {
        .probe          = omap_dsshw_probe,
        .remove         = omap_dsshw_remove,
        .driver         = {
                .name   = "omapdss_dss",
                .owner  = THIS_MODULE,
+               .pm     = &dss_pm_ops,
        },
 };
 
index 8ab6d43..9c94b11 100644 (file)
@@ -97,26 +97,12 @@ extern unsigned int dss_debug;
 #define FLD_MOD(orig, val, start, end) \
        (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
 
-enum omap_burst_size {
-       OMAP_DSS_BURST_4x32 = 0,
-       OMAP_DSS_BURST_8x32 = 1,
-       OMAP_DSS_BURST_16x32 = 2,
-};
-
 enum omap_parallel_interface_mode {
        OMAP_DSS_PARALLELMODE_BYPASS,           /* MIPI DPI */
        OMAP_DSS_PARALLELMODE_RFBI,             /* MIPI DBI */
        OMAP_DSS_PARALLELMODE_DSI,
 };
 
-enum dss_clock {
-       DSS_CLK_ICK     = 1 << 0,       /* DSS_L3_ICLK and DSS_L4_ICLK */
-       DSS_CLK_FCK     = 1 << 1,       /* DSS1_ALWON_FCLK */
-       DSS_CLK_SYSCK   = 1 << 2,       /* DSS2_ALWON_FCLK */
-       DSS_CLK_TVFCK   = 1 << 3,       /* DSS_TV_FCLK */
-       DSS_CLK_VIDFCK  = 1 << 4,       /* DSS_96M_FCLK*/
-};
-
 enum dss_hdmi_venc_clk_source_select {
        DSS_VENC_TV_CLK = 0,
        DSS_HDMI_M_PCLK = 1,
@@ -194,7 +180,7 @@ void dss_uninit_device(struct platform_device *pdev,
 bool dss_use_replication(struct omap_dss_device *dssdev,
                enum omap_color_mode mode);
 void default_get_overlay_fifo_thresholds(enum omap_plane plane,
-               u32 fifo_size, enum omap_burst_size *burst_size,
+               u32 fifo_size, u32 burst_size,
                u32 *fifo_low, u32 *fifo_high);
 
 /* manager */
@@ -220,13 +206,12 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
 int dss_init_platform_driver(void);
 void dss_uninit_platform_driver(void);
 
+int dss_runtime_get(void);
+void dss_runtime_put(void);
+
+struct clk *dss_get_ick(void);
+
 void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
-void dss_save_context(void);
-void dss_restore_context(void);
-void dss_clk_enable(enum dss_clock clks);
-void dss_clk_disable(enum dss_clock clks);
-unsigned long dss_clk_get_rate(enum dss_clock clk);
-int dss_need_ctx_restore(void);
 const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
 void dss_dump_clocks(struct seq_file *s);
 
@@ -283,15 +268,15 @@ struct file_operations;
 int dsi_init_platform_driver(void);
 void dsi_uninit_platform_driver(void);
 
+int dsi_runtime_get(struct platform_device *dsidev);
+void dsi_runtime_put(struct platform_device *dsidev);
+
 void dsi_dump_clocks(struct seq_file *s);
 void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir,
                const struct file_operations *debug_fops);
 void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
                const struct file_operations *debug_fops);
 
-void dsi_save_context(void);
-void dsi_restore_context(void);
-
 int dsi_init_display(struct omap_dss_device *display);
 void dsi_irq_handler(void);
 unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
@@ -304,7 +289,7 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
                bool enable_hsdiv);
 void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
 void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
-               u32 fifo_size, enum omap_burst_size *burst_size,
+               u32 fifo_size, u32 burst_size,
                u32 *fifo_low, u32 *fifo_high);
 void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev);
 void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev);
@@ -317,6 +302,13 @@ static inline int dsi_init_platform_driver(void)
 static inline void dsi_uninit_platform_driver(void)
 {
 }
+static inline int dsi_runtime_get(struct platform_device *dsidev)
+{
+       return 0;
+}
+static inline void dsi_runtime_put(struct platform_device *dsidev)
+{
+}
 static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
 {
        WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
@@ -384,8 +376,8 @@ void dispc_dump_regs(struct seq_file *s);
 void dispc_irq_handler(void);
 void dispc_fake_vsync_irq(void);
 
-void dispc_save_context(void);
-void dispc_restore_context(void);
+int dispc_runtime_get(void);
+void dispc_runtime_put(void);
 
 void dispc_enable_sidle(void);
 void dispc_disable_sidle(void);
@@ -398,10 +390,12 @@ void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable);
 void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
 void dispc_set_digit_size(u16 width, u16 height);
 u32 dispc_get_plane_fifo_size(enum omap_plane plane);
-void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high);
+void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
 void dispc_enable_fifomerge(bool enable);
-void dispc_set_burst_size(enum omap_plane plane,
-               enum omap_burst_size burst_size);
+u32 dispc_get_burst_size(enum omap_plane plane);
+void dispc_enable_cpr(enum omap_channel channel, bool enable);
+void dispc_set_cpr_coef(enum omap_channel channel,
+               struct omap_dss_cpr_coefs *coefs);
 
 void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
 void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
index 1c18888..b415c4e 100644 (file)
@@ -49,6 +49,9 @@ struct omap_dss_features {
        const enum omap_color_mode *supported_color_modes;
        const char * const *clksrc_names;
        const struct dss_param_range *dss_params;
+
+       const u32 buffer_size_unit;
+       const u32 burst_size_unit;
 };
 
 /* This struct is assigned to one of the below during initialization */
@@ -274,6 +277,8 @@ static const struct omap_dss_features omap2_dss_features = {
        .supported_color_modes = omap2_dss_supported_color_modes,
        .clksrc_names = omap2_dss_clk_source_names,
        .dss_params = omap2_dss_param_range,
+       .buffer_size_unit = 1,
+       .burst_size_unit = 8,
 };
 
 /* OMAP3 DSS Features */
@@ -286,7 +291,9 @@ static const struct omap_dss_features omap3430_dss_features = {
                FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
                FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
                FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
-               FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC,
+               FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC |
+               FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD |
+               FEAT_FIR_COEF_V,
 
        .num_mgrs = 2,
        .num_ovls = 3,
@@ -294,6 +301,8 @@ static const struct omap_dss_features omap3430_dss_features = {
        .supported_color_modes = omap3_dss_supported_color_modes,
        .clksrc_names = omap3_dss_clk_source_names,
        .dss_params = omap3_dss_param_range,
+       .buffer_size_unit = 1,
+       .burst_size_unit = 8,
 };
 
 static const struct omap_dss_features omap3630_dss_features = {
@@ -306,7 +315,8 @@ static const struct omap_dss_features omap3630_dss_features = {
                FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
                FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
                FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG |
-               FEAT_DSI_PLL_FREQSEL,
+               FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD |
+               FEAT_FIR_COEF_V,
 
        .num_mgrs = 2,
        .num_ovls = 3,
@@ -314,6 +324,8 @@ static const struct omap_dss_features omap3630_dss_features = {
        .supported_color_modes = omap3_dss_supported_color_modes,
        .clksrc_names = omap3_dss_clk_source_names,
        .dss_params = omap3_dss_param_range,
+       .buffer_size_unit = 1,
+       .burst_size_unit = 8,
 };
 
 /* OMAP4 DSS Features */
@@ -327,7 +339,8 @@ static const struct omap_dss_features omap4430_es1_0_dss_features  = {
                FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
                FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
                FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
-               FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2,
+               FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 |
+               FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V,
 
        .num_mgrs = 3,
        .num_ovls = 3,
@@ -335,6 +348,8 @@ static const struct omap_dss_features omap4430_es1_0_dss_features  = {
        .supported_color_modes = omap4_dss_supported_color_modes,
        .clksrc_names = omap4_dss_clk_source_names,
        .dss_params = omap4_dss_param_range,
+       .buffer_size_unit = 16,
+       .burst_size_unit = 16,
 };
 
 /* For all the other OMAP4 versions */
@@ -348,7 +363,8 @@ static const struct omap_dss_features omap4_dss_features = {
                FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
                FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
                FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE |
-               FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2,
+               FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR |
+               FEAT_PRELOAD | FEAT_FIR_COEF_V,
 
        .num_mgrs = 3,
        .num_ovls = 3,
@@ -356,6 +372,8 @@ static const struct omap_dss_features omap4_dss_features = {
        .supported_color_modes = omap4_dss_supported_color_modes,
        .clksrc_names = omap4_dss_clk_source_names,
        .dss_params = omap4_dss_param_range,
+       .buffer_size_unit = 16,
+       .burst_size_unit = 16,
 };
 
 /* Functions returning values related to a DSS feature */
@@ -401,6 +419,16 @@ const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id)
        return omap_current_dss_features->clksrc_names[id];
 }
 
+u32 dss_feat_get_buffer_size_unit(void)
+{
+       return omap_current_dss_features->buffer_size_unit;
+}
+
+u32 dss_feat_get_burst_size_unit(void)
+{
+       return omap_current_dss_features->burst_size_unit;
+}
+
 /* DSS has_feature check */
 bool dss_has_feature(enum dss_feat_id id)
 {
index 07b346f..b7398cb 100644 (file)
@@ -51,6 +51,10 @@ enum dss_feat_id {
        FEAT_HDMI_CTS_SWMODE            = 1 << 19,
        FEAT_HANDLE_UV_SEPARATE         = 1 << 20,
        FEAT_ATTR2                      = 1 << 21,
+       FEAT_VENC_REQUIRES_TV_DAC_CLK   = 1 << 22,
+       FEAT_CPR                        = 1 << 23,
+       FEAT_PRELOAD                    = 1 << 24,
+       FEAT_FIR_COEF_V                 = 1 << 25,
 };
 
 /* DSS register field id */
@@ -90,6 +94,9 @@ bool dss_feat_color_mode_supported(enum omap_plane plane,
                enum omap_color_mode color_mode);
 const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id);
 
+u32 dss_feat_get_buffer_size_unit(void);       /* in bytes */
+u32 dss_feat_get_burst_size_unit(void);                /* in bytes */
+
 bool dss_has_feature(enum dss_feat_id id);
 void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
 void dss_features_init(void);
index b0555f4..256f27a 100644 (file)
@@ -29,6 +29,9 @@
 #include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
 #include <video/omapdss.h>
 #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
        defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
@@ -51,6 +54,9 @@ static struct {
        u8 edid_set;
        bool custom_set;
        struct hdmi_config cfg;
+
+       struct clk *sys_clk;
+       struct clk *hdmi_clk;
 } hdmi;
 
 /*
@@ -162,6 +168,27 @@ static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx,
        return val;
 }
 
+static int hdmi_runtime_get(void)
+{
+       int r;
+
+       DSSDBG("hdmi_runtime_get\n");
+
+       r = pm_runtime_get_sync(&hdmi.pdev->dev);
+       WARN_ON(r < 0);
+       return r < 0 ? r : 0;
+}
+
+static void hdmi_runtime_put(void)
+{
+       int r;
+
+       DSSDBG("hdmi_runtime_put\n");
+
+       r = pm_runtime_put(&hdmi.pdev->dev);
+       WARN_ON(r < 0);
+}
+
 int hdmi_init_display(struct omap_dss_device *dssdev)
 {
        DSSDBG("init_display\n");
@@ -311,30 +338,11 @@ static int hdmi_phy_init(void)
        return 0;
 }
 
-static int hdmi_wait_softreset(void)
-{
-       /* reset W1 */
-       REG_FLD_MOD(HDMI_WP_SYSCONFIG, 0x1, 0, 0);
-
-       /* wait till SOFTRESET == 0 */
-       if (hdmi_wait_for_bit_change(HDMI_WP_SYSCONFIG, 0, 0, 0) != 0) {
-               DSSERR("sysconfig reset failed\n");
-               return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
 static int hdmi_pll_program(struct hdmi_pll_info *fmt)
 {
        u16 r = 0;
        enum hdmi_clk_refsel refsel;
 
-       /* wait for wrapper reset */
-       r = hdmi_wait_softreset();
-       if (r)
-               return r;
-
        r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
        if (r)
                return r;
@@ -1064,7 +1072,7 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
        unsigned long clkin, refclk;
        u32 mf;
 
-       clkin = dss_clk_get_rate(DSS_CLK_SYSCK) / 10000;
+       clkin = clk_get_rate(hdmi.sys_clk) / 10000;
        /*
         * Input clock is predivided by N + 1
         * out put of which is reference clk
@@ -1098,16 +1106,6 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
        DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
 }
 
-static void hdmi_enable_clocks(int enable)
-{
-       if (enable)
-               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK |
-                               DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
-       else
-               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK |
-                               DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
-}
-
 static int hdmi_power_on(struct omap_dss_device *dssdev)
 {
        int r, code = 0;
@@ -1115,7 +1113,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
        struct omap_video_timings *p;
        unsigned long phy;
 
-       hdmi_enable_clocks(1);
+       r = hdmi_runtime_get();
+       if (r)
+               return r;
 
        dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
 
@@ -1180,7 +1180,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 
        return 0;
 err:
-       hdmi_enable_clocks(0);
+       hdmi_runtime_put();
        return -EIO;
 }
 
@@ -1191,7 +1191,7 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
        hdmi_wp_video_start(0);
        hdmi_phy_off();
        hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
-       hdmi_enable_clocks(0);
+       hdmi_runtime_put();
 
        hdmi.edid_set = 0;
 }
@@ -1686,14 +1686,43 @@ static struct snd_soc_dai_driver hdmi_codec_dai_drv = {
 };
 #endif
 
+static int hdmi_get_clocks(struct platform_device *pdev)
+{
+       struct clk *clk;
+
+       clk = clk_get(&pdev->dev, "sys_clk");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get sys_clk\n");
+               return PTR_ERR(clk);
+       }
+
+       hdmi.sys_clk = clk;
+
+       clk = clk_get(&pdev->dev, "dss_48mhz_clk");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get hdmi_clk\n");
+               clk_put(hdmi.sys_clk);
+               return PTR_ERR(clk);
+       }
+
+       hdmi.hdmi_clk = clk;
+
+       return 0;
+}
+
+static void hdmi_put_clocks(void)
+{
+       if (hdmi.sys_clk)
+               clk_put(hdmi.sys_clk);
+       if (hdmi.hdmi_clk)
+               clk_put(hdmi.hdmi_clk);
+}
+
 /* HDMI HW IP initialisation */
 static int omapdss_hdmihw_probe(struct platform_device *pdev)
 {
        struct resource *hdmi_mem;
-#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
-       defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
-       int ret;
-#endif
+       int r;
 
        hdmi.pdata = pdev->dev.platform_data;
        hdmi.pdev = pdev;
@@ -1713,17 +1742,25 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
+       r = hdmi_get_clocks(pdev);
+       if (r) {
+               iounmap(hdmi.base_wp);
+               return r;
+       }
+
+       pm_runtime_enable(&pdev->dev);
+
        hdmi_panel_init();
 
 #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
        defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
 
        /* Register ASoC codec DAI */
-       ret = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
+       r = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
                                        &hdmi_codec_dai_drv, 1);
-       if (ret) {
+       if (r) {
                DSSERR("can't register ASoC HDMI audio codec\n");
-               return ret;
+               return r;
        }
 #endif
        return 0;
@@ -1738,17 +1775,62 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev)
        snd_soc_unregister_codec(&pdev->dev);
 #endif
 
+       pm_runtime_disable(&pdev->dev);
+
+       hdmi_put_clocks();
+
        iounmap(hdmi.base_wp);
 
        return 0;
 }
 
+static int hdmi_runtime_suspend(struct device *dev)
+{
+       clk_disable(hdmi.hdmi_clk);
+       clk_disable(hdmi.sys_clk);
+
+       dispc_runtime_put();
+       dss_runtime_put();
+
+       return 0;
+}
+
+static int hdmi_runtime_resume(struct device *dev)
+{
+       int r;
+
+       r = dss_runtime_get();
+       if (r < 0)
+               goto err_get_dss;
+
+       r = dispc_runtime_get();
+       if (r < 0)
+               goto err_get_dispc;
+
+
+       clk_enable(hdmi.sys_clk);
+       clk_enable(hdmi.hdmi_clk);
+
+       return 0;
+
+err_get_dispc:
+       dss_runtime_put();
+err_get_dss:
+       return r;
+}
+
+static const struct dev_pm_ops hdmi_pm_ops = {
+       .runtime_suspend = hdmi_runtime_suspend,
+       .runtime_resume = hdmi_runtime_resume,
+};
+
 static struct platform_driver omapdss_hdmihw_driver = {
        .probe          = omapdss_hdmihw_probe,
        .remove         = omapdss_hdmihw_remove,
        .driver         = {
                .name   = "omapdss_hdmi",
                .owner  = THIS_MODULE,
+               .pm     = &hdmi_pm_ops,
        },
 };
 
index 9aeea50..13d72d5 100644 (file)
@@ -275,6 +275,108 @@ static ssize_t manager_alpha_blending_enabled_store(
        return size;
 }
 
+static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
+               char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.cpr_enable);
+}
+
+static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
+               const char *buf, size_t size)
+{
+       struct omap_overlay_manager_info info;
+       int v;
+       int r;
+       bool enable;
+
+       if (!dss_has_feature(FEAT_CPR))
+               return -ENODEV;
+
+       r = kstrtoint(buf, 0, &v);
+       if (r)
+               return r;
+
+       enable = !!v;
+
+       mgr->get_manager_info(mgr, &info);
+
+       if (info.cpr_enable == enable)
+               return size;
+
+       info.cpr_enable = enable;
+
+       r = mgr->set_manager_info(mgr, &info);
+       if (r)
+               return r;
+
+       r = mgr->apply(mgr);
+       if (r)
+               return r;
+
+       return size;
+}
+
+static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
+               char *buf)
+{
+       struct omap_overlay_manager_info info;
+
+       mgr->get_manager_info(mgr, &info);
+
+       return snprintf(buf, PAGE_SIZE,
+                       "%d %d %d %d %d %d %d %d %d\n",
+                       info.cpr_coefs.rr,
+                       info.cpr_coefs.rg,
+                       info.cpr_coefs.rb,
+                       info.cpr_coefs.gr,
+                       info.cpr_coefs.gg,
+                       info.cpr_coefs.gb,
+                       info.cpr_coefs.br,
+                       info.cpr_coefs.bg,
+                       info.cpr_coefs.bb);
+}
+
+static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
+               const char *buf, size_t size)
+{
+       struct omap_overlay_manager_info info;
+       struct omap_dss_cpr_coefs coefs;
+       int r, i;
+       s16 *arr;
+
+       if (!dss_has_feature(FEAT_CPR))
+               return -ENODEV;
+
+       if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
+                               &coefs.rr, &coefs.rg, &coefs.rb,
+                               &coefs.gr, &coefs.gg, &coefs.gb,
+                               &coefs.br, &coefs.bg, &coefs.bb) != 9)
+               return -EINVAL;
+
+       arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
+               coefs.gr, coefs.gg, coefs.gb,
+               coefs.br, coefs.bg, coefs.bb };
+
+       for (i = 0; i < 9; ++i) {
+               if (arr[i] < -512 || arr[i] > 511)
+                       return -EINVAL;
+       }
+
+       mgr->get_manager_info(mgr, &info);
+
+       info.cpr_coefs = coefs;
+
+       r = mgr->set_manager_info(mgr, &info);
+       if (r)
+               return r;
+
+       r = mgr->apply(mgr);
+       if (r)
+               return r;
+
+       return size;
+}
+
 struct manager_attribute {
        struct attribute attr;
        ssize_t (*show)(struct omap_overlay_manager *, char *);
@@ -300,6 +402,12 @@ static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
 static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
                manager_alpha_blending_enabled_show,
                manager_alpha_blending_enabled_store);
+static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
+               manager_cpr_enable_show,
+               manager_cpr_enable_store);
+static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
+               manager_cpr_coef_show,
+               manager_cpr_coef_store);
 
 
 static struct attribute *manager_sysfs_attrs[] = {
@@ -310,6 +418,8 @@ static struct attribute *manager_sysfs_attrs[] = {
        &manager_attr_trans_key_value.attr,
        &manager_attr_trans_key_enabled.attr,
        &manager_attr_alpha_blending_enabled.attr,
+       &manager_attr_cpr_enable.attr,
+       &manager_attr_cpr_coef.attr,
        NULL
 };
 
@@ -391,33 +501,14 @@ struct overlay_cache_data {
 
        bool enabled;
 
-       u32 paddr;
-       void __iomem *vaddr;
-       u32 p_uv_addr; /* relevant for NV12 format only */
-       u16 screen_width;
-       u16 width;
-       u16 height;
-       enum omap_color_mode color_mode;
-       u8 rotation;
-       enum omap_dss_rotation_type rotation_type;
-       bool mirror;
-
-       u16 pos_x;
-       u16 pos_y;
-       u16 out_width;  /* if 0, out_width == width */
-       u16 out_height; /* if 0, out_height == height */
-       u8 global_alpha;
-       u8 pre_mult_alpha;
+       struct omap_overlay_info info;
 
        enum omap_channel channel;
        bool replication;
        bool ilace;
 
-       enum omap_burst_size burst_size;
        u32 fifo_low;
        u32 fifo_high;
-
-       bool manual_update;
 };
 
 struct manager_cache_data {
@@ -429,15 +520,8 @@ struct manager_cache_data {
         * VSYNC/EVSYNC */
        bool shadow_dirty;
 
-       u32 default_color;
-
-       enum omap_dss_trans_key_type trans_key_type;
-       u32 trans_key;
-       bool trans_enabled;
-
-       bool alpha_enabled;
+       struct omap_overlay_manager_info info;
 
-       bool manual_upd_display;
        bool manual_update;
        bool do_manual_update;
 
@@ -539,24 +623,15 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
        if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
                return 0;
 
+       if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
+               return 0;
+
        if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
                        || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
                irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
        } else {
-               if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
-                       enum omap_dss_update_mode mode;
-                       mode = dssdev->driver->get_update_mode(dssdev);
-                       if (mode != OMAP_DSS_UPDATE_AUTO)
-                               return 0;
-
-                       irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
-                               DISPC_IRQ_FRAMEDONE
-                               : DISPC_IRQ_FRAMEDONE2;
-               } else {
-                       irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
-                               DISPC_IRQ_VSYNC
-                               : DISPC_IRQ_VSYNC2;
-               }
+               irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
+                       DISPC_IRQ_VSYNC : DISPC_IRQ_VSYNC2;
        }
 
        mc = &dss_cache.manager_cache[mgr->id];
@@ -617,24 +692,15 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
        if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
                return 0;
 
+       if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
+               return 0;
+
        if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
                        || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
                irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
        } else {
-               if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
-                       enum omap_dss_update_mode mode;
-                       mode = dssdev->driver->get_update_mode(dssdev);
-                       if (mode != OMAP_DSS_UPDATE_AUTO)
-                               return 0;
-
-                       irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
-                               DISPC_IRQ_FRAMEDONE
-                               : DISPC_IRQ_FRAMEDONE2;
-               } else {
-                       irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
-                               DISPC_IRQ_VSYNC
-                               : DISPC_IRQ_VSYNC2;
-               }
+               irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
+                       DISPC_IRQ_VSYNC : DISPC_IRQ_VSYNC2;
        }
 
        oc = &dss_cache.overlay_cache[ovl->id];
@@ -720,10 +786,12 @@ static bool rectangle_intersects(int x1, int y1, int w1, int h1,
 
 static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc)
 {
-       if (oc->out_width != 0 && oc->width != oc->out_width)
+       struct omap_overlay_info *oi = &oc->info;
+
+       if (oi->out_width != 0 && oi->width != oi->out_width)
                return true;
 
-       if (oc->out_height != 0 && oc->height != oc->out_height)
+       if (oi->out_height != 0 && oi->height != oi->out_height)
                return true;
 
        return false;
@@ -733,6 +801,8 @@ static int configure_overlay(enum omap_plane plane)
 {
        struct overlay_cache_data *c;
        struct manager_cache_data *mc;
+       struct omap_overlay_info *oi;
+       struct omap_overlay_manager_info *mi;
        u16 outw, outh;
        u16 x, y, w, h;
        u32 paddr;
@@ -742,6 +812,7 @@ static int configure_overlay(enum omap_plane plane)
        DSSDBGF("%d", plane);
 
        c = &dss_cache.overlay_cache[plane];
+       oi = &c->info;
 
        if (!c->enabled) {
                dispc_enable_plane(plane, 0);
@@ -749,21 +820,22 @@ static int configure_overlay(enum omap_plane plane)
        }
 
        mc = &dss_cache.manager_cache[c->channel];
+       mi = &mc->info;
 
-       x = c->pos_x;
-       y = c->pos_y;
-       w = c->width;
-       h = c->height;
-       outw = c->out_width == 0 ? c->width : c->out_width;
-       outh = c->out_height == 0 ? c->height : c->out_height;
-       paddr = c->paddr;
+       x = oi->pos_x;
+       y = oi->pos_y;
+       w = oi->width;
+       h = oi->height;
+       outw = oi->out_width == 0 ? oi->width : oi->out_width;
+       outh = oi->out_height == 0 ? oi->height : oi->out_height;
+       paddr = oi->paddr;
 
        orig_w = w;
        orig_h = h;
        orig_outw = outw;
        orig_outh = outh;
 
-       if (c->manual_update && mc->do_manual_update) {
+       if (mc->manual_update && mc->do_manual_update) {
                unsigned bpp;
                unsigned scale_x_m = w, scale_x_d = outw;
                unsigned scale_y_m = h, scale_y_d = outh;
@@ -775,7 +847,7 @@ static int configure_overlay(enum omap_plane plane)
                        return 0;
                }
 
-               switch (c->color_mode) {
+               switch (oi->color_mode) {
                case OMAP_DSS_COLOR_NV12:
                        bpp = 8;
                        break;
@@ -805,23 +877,23 @@ static int configure_overlay(enum omap_plane plane)
                        BUG();
                }
 
-               if (mc->x > c->pos_x) {
+               if (mc->x > oi->pos_x) {
                        x = 0;
-                       outw -= (mc->x - c->pos_x);
-                       paddr += (mc->x - c->pos_x) *
+                       outw -= (mc->x - oi->pos_x);
+                       paddr += (mc->x - oi->pos_x) *
                                scale_x_m / scale_x_d * bpp / 8;
                } else {
-                       x = c->pos_x - mc->x;
+                       x = oi->pos_x - mc->x;
                }
 
-               if (mc->y > c->pos_y) {
+               if (mc->y > oi->pos_y) {
                        y = 0;
-                       outh -= (mc->y - c->pos_y);
-                       paddr += (mc->y - c->pos_y) *
+                       outh -= (mc->y - oi->pos_y);
+                       paddr += (mc->y - oi->pos_y) *
                                scale_y_m / scale_y_d *
-                               c->screen_width * bpp / 8;
+                               oi->screen_width * bpp / 8;
                } else {
-                       y = c->pos_y - mc->y;
+                       y = oi->pos_y - mc->y;
                }
 
                if (mc->w < (x + outw))
@@ -840,8 +912,8 @@ static int configure_overlay(enum omap_plane plane)
                 * the width if the original width was bigger.
                 */
                if ((w & 1) &&
-                               (c->color_mode == OMAP_DSS_COLOR_YUV2 ||
-                                c->color_mode == OMAP_DSS_COLOR_UYVY)) {
+                               (oi->color_mode == OMAP_DSS_COLOR_YUV2 ||
+                                oi->color_mode == OMAP_DSS_COLOR_UYVY)) {
                        if (orig_w > w)
                                w += 1;
                        else
@@ -851,19 +923,19 @@ static int configure_overlay(enum omap_plane plane)
 
        r = dispc_setup_plane(plane,
                        paddr,
-                       c->screen_width,
+                       oi->screen_width,
                        x, y,
                        w, h,
                        outw, outh,
-                       c->color_mode,
+                       oi->color_mode,
                        c->ilace,
-                       c->rotation_type,
-                       c->rotation,
-                       c->mirror,
-                       c->global_alpha,
-                       c->pre_mult_alpha,
+                       oi->rotation_type,
+                       oi->rotation,
+                       oi->mirror,
+                       oi->global_alpha,
+                       oi->pre_mult_alpha,
                        c->channel,
-                       c->p_uv_addr);
+                       oi->p_uv_addr);
 
        if (r) {
                /* this shouldn't happen */
@@ -874,8 +946,7 @@ static int configure_overlay(enum omap_plane plane)
 
        dispc_enable_replication(plane, c->replication);
 
-       dispc_set_burst_size(plane, c->burst_size);
-       dispc_setup_plane_fifo(plane, c->fifo_low, c->fifo_high);
+       dispc_set_fifo_threshold(plane, c->fifo_low, c->fifo_high);
 
        dispc_enable_plane(plane, 1);
 
@@ -884,16 +955,21 @@ static int configure_overlay(enum omap_plane plane)
 
 static void configure_manager(enum omap_channel channel)
 {
-       struct manager_cache_data *c;
+       struct omap_overlay_manager_info *mi;
 
        DSSDBGF("%d", channel);
 
-       c = &dss_cache.manager_cache[channel];
+       /* picking info from the cache */
+       mi = &dss_cache.manager_cache[channel].info;
 
-       dispc_set_default_color(channel, c->default_color);
-       dispc_set_trans_key(channel, c->trans_key_type, c->trans_key);
-       dispc_enable_trans_key(channel, c->trans_enabled);
-       dispc_enable_alpha_blending(channel, c->alpha_enabled);
+       dispc_set_default_color(channel, mi->default_color);
+       dispc_set_trans_key(channel, mi->trans_key_type, mi->trans_key);
+       dispc_enable_trans_key(channel, mi->trans_enabled);
+       dispc_enable_alpha_blending(channel, mi->alpha_enabled);
+       if (dss_has_feature(FEAT_CPR)) {
+               dispc_enable_cpr(channel, mi->cpr_enable);
+               dispc_set_cpr_coef(channel, &mi->cpr_coefs);
+       }
 }
 
 /* configure_dispc() tries to write values from cache to shadow registers.
@@ -928,7 +1004,7 @@ static int configure_dispc(void)
                if (!oc->dirty)
                        continue;
 
-               if (oc->manual_update && !mc->do_manual_update)
+               if (mc->manual_update && !mc->do_manual_update)
                        continue;
 
                if (mgr_busy[oc->channel]) {
@@ -976,7 +1052,7 @@ static int configure_dispc(void)
                /* We don't need GO with manual update display. LCD iface will
                 * always be turned off after frame, and new settings will be
                 * taken in to use at next update */
-               if (!mc->manual_upd_display)
+               if (!mc->manual_update)
                        dispc_go(i);
        }
 
@@ -1011,6 +1087,7 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
 {
        struct overlay_cache_data *oc;
        struct manager_cache_data *mc;
+       struct omap_overlay_info *oi;
        const int num_ovls = dss_feat_get_num_ovls();
        struct omap_overlay_manager *mgr;
        int i;
@@ -1053,6 +1130,7 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
                        unsigned outw, outh;
 
                        oc = &dss_cache.overlay_cache[i];
+                       oi = &oc->info;
 
                        if (oc->channel != mgr->id)
                                continue;
@@ -1068,39 +1146,39 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
                        if (!dispc_is_overlay_scaled(oc))
                                continue;
 
-                       outw = oc->out_width == 0 ?
-                               oc->width : oc->out_width;
-                       outh = oc->out_height == 0 ?
-                               oc->height : oc->out_height;
+                       outw = oi->out_width == 0 ?
+                               oi->width : oi->out_width;
+                       outh = oi->out_height == 0 ?
+                               oi->height : oi->out_height;
 
                        /* is the overlay outside the update region? */
                        if (!rectangle_intersects(x, y, w, h,
-                                               oc->pos_x, oc->pos_y,
+                                               oi->pos_x, oi->pos_y,
                                                outw, outh))
                                continue;
 
                        /* if the overlay totally inside the update region? */
-                       if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh,
+                       if (rectangle_subset(oi->pos_x, oi->pos_y, outw, outh,
                                                x, y, w, h))
                                continue;
 
-                       if (x > oc->pos_x)
-                               x1 = oc->pos_x;
+                       if (x > oi->pos_x)
+                               x1 = oi->pos_x;
                        else
                                x1 = x;
 
-                       if (y > oc->pos_y)
-                               y1 = oc->pos_y;
+                       if (y > oi->pos_y)
+                               y1 = oi->pos_y;
                        else
                                y1 = y;
 
-                       if ((x + w) < (oc->pos_x + outw))
-                               x2 = oc->pos_x + outw;
+                       if ((x + w) < (oi->pos_x + outw))
+                               x2 = oi->pos_x + outw;
                        else
                                x2 = x + w;
 
-                       if ((y + h) < (oc->pos_y + outh))
-                               y2 = oc->pos_y + outh;
+                       if ((y + h) < (oi->pos_y + outh))
+                               y2 = oi->pos_y + outh;
                        else
                                y2 = y + h;
 
@@ -1236,6 +1314,10 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 
        DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
 
+       r = dispc_runtime_get();
+       if (r)
+               return r;
+
        spin_lock_irqsave(&dss_cache.lock, flags);
 
        /* Configure overlays */
@@ -1275,23 +1357,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 
                ovl->info_dirty = false;
                oc->dirty = true;
-
-               oc->paddr = ovl->info.paddr;
-               oc->vaddr = ovl->info.vaddr;
-               oc->p_uv_addr = ovl->info.p_uv_addr;
-               oc->screen_width = ovl->info.screen_width;
-               oc->width = ovl->info.width;
-               oc->height = ovl->info.height;
-               oc->color_mode = ovl->info.color_mode;
-               oc->rotation = ovl->info.rotation;
-               oc->rotation_type = ovl->info.rotation_type;
-               oc->mirror = ovl->info.mirror;
-               oc->pos_x = ovl->info.pos_x;
-               oc->pos_y = ovl->info.pos_y;
-               oc->out_width = ovl->info.out_width;
-               oc->out_height = ovl->info.out_height;
-               oc->global_alpha = ovl->info.global_alpha;
-               oc->pre_mult_alpha = ovl->info.pre_mult_alpha;
+               oc->info = ovl->info;
 
                oc->replication =
                        dss_use_replication(dssdev, ovl->info.color_mode);
@@ -1302,11 +1368,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 
                oc->enabled = true;
 
-               oc->manual_update =
-                       dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
-                       dssdev->driver->get_update_mode(dssdev) !=
-                               OMAP_DSS_UPDATE_AUTO;
-
                ++num_planes_enabled;
        }
 
@@ -1334,20 +1395,10 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 
                mgr->info_dirty = false;
                mc->dirty = true;
-
-               mc->default_color = mgr->info.default_color;
-               mc->trans_key_type = mgr->info.trans_key_type;
-               mc->trans_key = mgr->info.trans_key;
-               mc->trans_enabled = mgr->info.trans_enabled;
-               mc->alpha_enabled = mgr->info.alpha_enabled;
-
-               mc->manual_upd_display =
-                       dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
+               mc->info = mgr->info;
 
                mc->manual_update =
-                       dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
-                       dssdev->driver->get_update_mode(dssdev) !=
-                               OMAP_DSS_UPDATE_AUTO;
+                       dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
        }
 
        /* XXX TODO: Try to get fifomerge working. The problem is that it
@@ -1368,7 +1419,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
        /* Configure overlay fifos */
        for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
                struct omap_dss_device *dssdev;
-               u32 size;
+               u32 size, burst_size;
 
                ovl = omap_dss_get_overlay(i);
 
@@ -1386,6 +1437,8 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
                if (use_fifomerge)
                        size *= 3;
 
+               burst_size = dispc_get_burst_size(ovl->id);
+
                switch (dssdev->type) {
                case OMAP_DISPLAY_TYPE_DPI:
                case OMAP_DISPLAY_TYPE_DBI:
@@ -1393,13 +1446,13 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
                case OMAP_DISPLAY_TYPE_VENC:
                case OMAP_DISPLAY_TYPE_HDMI:
                        default_get_overlay_fifo_thresholds(ovl->id, size,
-                                       &oc->burst_size, &oc->fifo_low,
+                                       burst_size, &oc->fifo_low,
                                        &oc->fifo_high);
                        break;
 #ifdef CONFIG_OMAP2_DSS_DSI
                case OMAP_DISPLAY_TYPE_DSI:
                        dsi_get_overlay_fifo_thresholds(ovl->id, size,
-                                       &oc->burst_size, &oc->fifo_low,
+                                       burst_size, &oc->fifo_low,
                                        &oc->fifo_high);
                        break;
 #endif
@@ -1409,7 +1462,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
        }
 
        r = 0;
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
        if (!dss_cache.irq_enabled) {
                u32 mask;
 
@@ -1422,10 +1474,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
                dss_cache.irq_enabled = true;
        }
        configure_dispc();
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 
        spin_unlock_irqrestore(&dss_cache.lock, flags);
 
+       dispc_runtime_put();
+
        return r;
 }
 
index 0f08025..c84380c 100644 (file)
@@ -84,32 +84,42 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
 
        old_mgr = ovl->manager;
 
+       r = dispc_runtime_get();
+       if (r)
+               return r;
+
        /* detach old manager */
        if (old_mgr) {
                r = ovl->unset_manager(ovl);
                if (r) {
                        DSSERR("detach failed\n");
-                       return r;
+                       goto err;
                }
 
                r = old_mgr->apply(old_mgr);
                if (r)
-                       return r;
+                       goto err;
        }
 
        if (mgr) {
                r = ovl->set_manager(ovl, mgr);
                if (r) {
                        DSSERR("Failed to attach overlay\n");
-                       return r;
+                       goto err;
                }
 
                r = mgr->apply(mgr);
                if (r)
-                       return r;
+                       goto err;
        }
 
+       dispc_runtime_put();
+
        return size;
+
+err:
+       dispc_runtime_put();
+       return r;
 }
 
 static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
@@ -238,6 +248,9 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
        u8 alpha;
        struct omap_overlay_info info;
 
+       if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
+               return -ENODEV;
+
        r = kstrtou8(buf, 0, &alpha);
        if (r)
                return r;
@@ -504,7 +517,6 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
 
        ovl->manager = mgr;
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
        /* XXX: When there is an overlay on a DSI manual update display, and
         * the overlay is first disabled, then moved to tv, and enabled, we
         * seem to get SYNC_LOST_DIGIT error.
@@ -518,7 +530,6 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
         * the overlay, but before moving the overlay to TV.
         */
        dispc_set_channel_out(ovl->id, mgr->id);
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 
        return 0;
 }
@@ -719,6 +730,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
        }
 
        if (mgr) {
+               dispc_runtime_get();
+
                for (i = 0; i < dss_feat_get_num_ovls(); i++) {
                        struct omap_overlay *ovl;
                        ovl = omap_dss_get_overlay(i);
@@ -728,6 +741,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
                                omap_dss_set_manager(ovl, mgr);
                        }
                }
+
+               dispc_runtime_put();
        }
 }
 
index c06fbe0..39f4c59 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/hrtimer.h>
 #include <linux/seq_file.h>
 #include <linux/semaphore.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 
 #include <video/omapdss.h>
 #include "dss.h"
@@ -120,12 +122,25 @@ static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
        return __raw_readl(rfbi.base + idx.idx);
 }
 
-static void rfbi_enable_clocks(bool enable)
+static int rfbi_runtime_get(void)
 {
-       if (enable)
-               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
-       else
-               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       int r;
+
+       DSSDBG("rfbi_runtime_get\n");
+
+       r = pm_runtime_get_sync(&rfbi.pdev->dev);
+       WARN_ON(r < 0);
+       return r < 0 ? r : 0;
+}
+
+static void rfbi_runtime_put(void)
+{
+       int r;
+
+       DSSDBG("rfbi_runtime_put\n");
+
+       r = pm_runtime_put(&rfbi.pdev->dev);
+       WARN_ON(r < 0);
 }
 
 void rfbi_bus_lock(void)
@@ -805,7 +820,8 @@ void rfbi_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+       if (rfbi_runtime_get())
+               return;
 
        DUMPREG(RFBI_REVISION);
        DUMPREG(RFBI_SYSCONFIG);
@@ -836,7 +852,7 @@ void rfbi_dump_regs(struct seq_file *s)
        DUMPREG(RFBI_VSYNC_WIDTH);
        DUMPREG(RFBI_HSYNC_WIDTH);
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       rfbi_runtime_put();
 #undef DUMPREG
 }
 
@@ -844,7 +860,9 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
 {
        int r;
 
-       rfbi_enable_clocks(1);
+       r = rfbi_runtime_get();
+       if (r)
+               return r;
 
        r = omap_dss_start_device(dssdev);
        if (r) {
@@ -879,6 +897,7 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
 err1:
        omap_dss_stop_device(dssdev);
 err0:
+       rfbi_runtime_put();
        return r;
 }
 EXPORT_SYMBOL(omapdss_rfbi_display_enable);
@@ -889,7 +908,7 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
                        DISPC_IRQ_FRAMEDONE);
        omap_dss_stop_device(dssdev);
 
-       rfbi_enable_clocks(0);
+       rfbi_runtime_put();
 }
 EXPORT_SYMBOL(omapdss_rfbi_display_disable);
 
@@ -904,8 +923,9 @@ int rfbi_init_display(struct omap_dss_device *dssdev)
 static int omap_rfbihw_probe(struct platform_device *pdev)
 {
        u32 rev;
-       u32 l;
        struct resource *rfbi_mem;
+       struct clk *clk;
+       int r;
 
        rfbi.pdev = pdev;
 
@@ -914,46 +934,102 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
        rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
        if (!rfbi_mem) {
                DSSERR("can't get IORESOURCE_MEM RFBI\n");
-               return -EINVAL;
+               r = -EINVAL;
+               goto err_ioremap;
        }
        rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem));
        if (!rfbi.base) {
                DSSERR("can't ioremap RFBI\n");
-               return -ENOMEM;
+               r = -ENOMEM;
+               goto err_ioremap;
        }
 
-       rfbi_enable_clocks(1);
+       pm_runtime_enable(&pdev->dev);
+
+       r = rfbi_runtime_get();
+       if (r)
+               goto err_get_rfbi;
 
        msleep(10);
 
-       rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
+       if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap3630())
+               clk = dss_get_ick();
+       else
+               clk = clk_get(&pdev->dev, "ick");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get ick\n");
+               r = PTR_ERR(clk);
+               goto err_get_ick;
+       }
+
+       rfbi.l4_khz = clk_get_rate(clk) / 1000;
 
-       /* Enable autoidle and smart-idle */
-       l = rfbi_read_reg(RFBI_SYSCONFIG);
-       l |= (1 << 0) | (2 << 3);
-       rfbi_write_reg(RFBI_SYSCONFIG, l);
+       clk_put(clk);
 
        rev = rfbi_read_reg(RFBI_REVISION);
        dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n",
               FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
 
-       rfbi_enable_clocks(0);
+       rfbi_runtime_put();
 
        return 0;
+
+err_get_ick:
+       rfbi_runtime_put();
+err_get_rfbi:
+       pm_runtime_disable(&pdev->dev);
+       iounmap(rfbi.base);
+err_ioremap:
+       return r;
 }
 
 static int omap_rfbihw_remove(struct platform_device *pdev)
 {
+       pm_runtime_disable(&pdev->dev);
        iounmap(rfbi.base);
        return 0;
 }
 
+static int rfbi_runtime_suspend(struct device *dev)
+{
+       dispc_runtime_put();
+       dss_runtime_put();
+
+       return 0;
+}
+
+static int rfbi_runtime_resume(struct device *dev)
+{
+       int r;
+
+       r = dss_runtime_get();
+       if (r < 0)
+               goto err_get_dss;
+
+       r = dispc_runtime_get();
+       if (r < 0)
+               goto err_get_dispc;
+
+       return 0;
+
+err_get_dispc:
+       dss_runtime_put();
+err_get_dss:
+       return r;
+}
+
+static const struct dev_pm_ops rfbi_pm_ops = {
+       .runtime_suspend = rfbi_runtime_suspend,
+       .runtime_resume = rfbi_runtime_resume,
+};
+
 static struct platform_driver omap_rfbihw_driver = {
        .probe          = omap_rfbihw_probe,
        .remove         = omap_rfbihw_remove,
        .driver         = {
                .name   = "omapdss_rfbi",
                .owner  = THIS_MODULE,
+               .pm     = &rfbi_pm_ops,
        },
 };
 
index 0bd4b03..3a688c8 100644 (file)
 #define DSS_SUBSYS_NAME "SDI"
 
 #include <linux/kernel.h>
-#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/regulator/consumer.h>
 
 #include <video/omapdss.h>
-#include <plat/cpu.h>
 #include "dss.h"
 
 static struct {
@@ -60,14 +58,20 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
        r = omap_dss_start_device(dssdev);
        if (r) {
                DSSERR("failed to start device\n");
-               goto err0;
+               goto err_start_dev;
        }
 
        r = regulator_enable(sdi.vdds_sdi_reg);
        if (r)
-               goto err1;
+               goto err_reg_enable;
 
-       dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+       r = dss_runtime_get();
+       if (r)
+               goto err_get_dss;
+
+       r = dispc_runtime_get();
+       if (r)
+               goto err_get_dispc;
 
        sdi_basic_init(dssdev);
 
@@ -80,7 +84,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
        r = dss_calc_clock_div(1, t->pixel_clock * 1000,
                        &dss_cinfo, &dispc_cinfo);
        if (r)
-               goto err2;
+               goto err_calc_clock_div;
 
        fck = dss_cinfo.fck;
        lck_div = dispc_cinfo.lck_div;
@@ -101,27 +105,34 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 
        r = dss_set_clock_div(&dss_cinfo);
        if (r)
-               goto err2;
+               goto err_set_dss_clock_div;
 
        r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
        if (r)
-               goto err2;
+               goto err_set_dispc_clock_div;
 
        dss_sdi_init(dssdev->phy.sdi.datapairs);
        r = dss_sdi_enable();
        if (r)
-               goto err1;
+               goto err_sdi_enable;
        mdelay(2);
 
        dssdev->manager->enable(dssdev->manager);
 
        return 0;
-err2:
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+
+err_sdi_enable:
+err_set_dispc_clock_div:
+err_set_dss_clock_div:
+err_calc_clock_div:
+       dispc_runtime_put();
+err_get_dispc:
+       dss_runtime_put();
+err_get_dss:
        regulator_disable(sdi.vdds_sdi_reg);
-err1:
+err_reg_enable:
        omap_dss_stop_device(dssdev);
-err0:
+err_start_dev:
        return r;
 }
 EXPORT_SYMBOL(omapdss_sdi_display_enable);
@@ -132,7 +143,8 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
 
        dss_sdi_disable();
 
-       dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+       dispc_runtime_put();
+       dss_runtime_put();
 
        regulator_disable(sdi.vdds_sdi_reg);
 
index 980f919..173c664 100644 (file)
 #include <linux/seq_file.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
 
 #include <video/omapdss.h>
 #include <plat/cpu.h>
 
 #include "dss.h"
+#include "dss_features.h"
 
 /* Venc registers */
 #define VENC_REV_ID                            0x00
@@ -292,6 +294,9 @@ static struct {
        struct mutex venc_lock;
        u32 wss_data;
        struct regulator *vdda_dac_reg;
+
+       struct clk      *tv_clk;
+       struct clk      *tv_dac_clk;
 } venc;
 
 static inline void venc_write_reg(int idx, u32 val)
@@ -380,14 +385,25 @@ static void venc_reset(void)
 #endif
 }
 
-static void venc_enable_clocks(int enable)
+static int venc_runtime_get(void)
+{
+       int r;
+
+       DSSDBG("venc_runtime_get\n");
+
+       r = pm_runtime_get_sync(&venc.pdev->dev);
+       WARN_ON(r < 0);
+       return r < 0 ? r : 0;
+}
+
+static void venc_runtime_put(void)
 {
-       if (enable)
-               dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
-                               DSS_CLK_VIDFCK);
-       else
-               dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
-                               DSS_CLK_VIDFCK);
+       int r;
+
+       DSSDBG("venc_runtime_put\n");
+
+       r = pm_runtime_put(&venc.pdev->dev);
+       WARN_ON(r < 0);
 }
 
 static const struct venc_config *venc_timings_to_config(
@@ -406,8 +422,6 @@ static void venc_power_on(struct omap_dss_device *dssdev)
 {
        u32 l;
 
-       venc_enable_clocks(1);
-
        venc_reset();
        venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
 
@@ -448,8 +462,6 @@ static void venc_power_off(struct omap_dss_device *dssdev)
                dssdev->platform_disable(dssdev);
 
        regulator_disable(venc.vdda_dac_reg);
-
-       venc_enable_clocks(0);
 }
 
 
@@ -487,6 +499,10 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
                goto err1;
        }
 
+       r = venc_runtime_get();
+       if (r)
+               goto err1;
+
        venc_power_on(dssdev);
 
        venc.wss_data = 0;
@@ -520,6 +536,8 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
 
        venc_power_off(dssdev);
 
+       venc_runtime_put();
+
        dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 
        omap_dss_stop_device(dssdev);
@@ -538,20 +556,6 @@ static int venc_panel_resume(struct omap_dss_device *dssdev)
        return venc_panel_enable(dssdev);
 }
 
-static enum omap_dss_update_mode venc_get_update_mode(
-               struct omap_dss_device *dssdev)
-{
-       return OMAP_DSS_UPDATE_AUTO;
-}
-
-static int venc_set_update_mode(struct omap_dss_device *dssdev,
-               enum omap_dss_update_mode mode)
-{
-       if (mode != OMAP_DSS_UPDATE_AUTO)
-               return -EINVAL;
-       return 0;
-}
-
 static void venc_get_timings(struct omap_dss_device *dssdev,
                        struct omap_video_timings *timings)
 {
@@ -598,6 +602,7 @@ static u32 venc_get_wss(struct omap_dss_device *dssdev)
 static int venc_set_wss(struct omap_dss_device *dssdev,        u32 wss)
 {
        const struct venc_config *config;
+       int r;
 
        DSSDBG("venc_set_wss\n");
 
@@ -608,16 +613,19 @@ static int venc_set_wss(struct omap_dss_device *dssdev,   u32 wss)
        /* Invert due to VENC_L21_WC_CTL:INV=1 */
        venc.wss_data = (wss ^ 0xfffff) << 8;
 
-       venc_enable_clocks(1);
+       r = venc_runtime_get();
+       if (r)
+               goto err;
 
        venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
                        venc.wss_data);
 
-       venc_enable_clocks(0);
+       venc_runtime_put();
 
+err:
        mutex_unlock(&venc.venc_lock);
 
-       return 0;
+       return r;
 }
 
 static struct omap_dss_driver venc_driver = {
@@ -632,9 +640,6 @@ static struct omap_dss_driver venc_driver = {
        .get_resolution = omapdss_default_get_resolution,
        .get_recommended_bpp = omapdss_default_get_recommended_bpp,
 
-       .set_update_mode = venc_set_update_mode,
-       .get_update_mode = venc_get_update_mode,
-
        .get_timings    = venc_get_timings,
        .set_timings    = venc_set_timings,
        .check_timings  = venc_check_timings,
@@ -673,7 +678,8 @@ void venc_dump_regs(struct seq_file *s)
 {
 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
 
-       venc_enable_clocks(1);
+       if (venc_runtime_get())
+               return;
 
        DUMPREG(VENC_F_CONTROL);
        DUMPREG(VENC_VIDOUT_CTRL);
@@ -717,16 +723,56 @@ void venc_dump_regs(struct seq_file *s)
        DUMPREG(VENC_OUTPUT_CONTROL);
        DUMPREG(VENC_OUTPUT_TEST);
 
-       venc_enable_clocks(0);
+       venc_runtime_put();
 
 #undef DUMPREG
 }
 
+static int venc_get_clocks(struct platform_device *pdev)
+{
+       struct clk *clk;
+
+       clk = clk_get(&pdev->dev, "fck");
+       if (IS_ERR(clk)) {
+               DSSERR("can't get fck\n");
+               return PTR_ERR(clk);
+       }
+
+       venc.tv_clk = clk;
+
+       if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
+               if (cpu_is_omap34xx() || cpu_is_omap3630())
+                       clk = clk_get(&pdev->dev, "dss_96m_fck");
+               else
+                       clk = clk_get(&pdev->dev, "tv_dac_clk");
+               if (IS_ERR(clk)) {
+                       DSSERR("can't get tv_dac_clk\n");
+                       clk_put(venc.tv_clk);
+                       return PTR_ERR(clk);
+               }
+       } else {
+               clk = NULL;
+       }
+
+       venc.tv_dac_clk = clk;
+
+       return 0;
+}
+
+static void venc_put_clocks(void)
+{
+       if (venc.tv_clk)
+               clk_put(venc.tv_clk);
+       if (venc.tv_dac_clk)
+               clk_put(venc.tv_dac_clk);
+}
+
 /* VENC HW IP initialisation */
 static int omap_venchw_probe(struct platform_device *pdev)
 {
        u8 rev_id;
        struct resource *venc_mem;
+       int r;
 
        venc.pdev = pdev;
 
@@ -737,22 +783,40 @@ static int omap_venchw_probe(struct platform_device *pdev)
        venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
        if (!venc_mem) {
                DSSERR("can't get IORESOURCE_MEM VENC\n");
-               return -EINVAL;
+               r = -EINVAL;
+               goto err_ioremap;
        }
        venc.base = ioremap(venc_mem->start, resource_size(venc_mem));
        if (!venc.base) {
                DSSERR("can't ioremap VENC\n");
-               return -ENOMEM;
+               r = -ENOMEM;
+               goto err_ioremap;
        }
 
-       venc_enable_clocks(1);
+       r = venc_get_clocks(pdev);
+       if (r)
+               goto err_get_clk;
+
+       pm_runtime_enable(&pdev->dev);
+
+       r = venc_runtime_get();
+       if (r)
+               goto err_get_venc;
 
        rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
        dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
 
-       venc_enable_clocks(0);
+       venc_runtime_put();
 
        return omap_dss_register_driver(&venc_driver);
+
+err_get_venc:
+       pm_runtime_disable(&pdev->dev);
+       venc_put_clocks();
+err_get_clk:
+       iounmap(venc.base);
+err_ioremap:
+       return r;
 }
 
 static int omap_venchw_remove(struct platform_device *pdev)
@@ -763,16 +827,61 @@ static int omap_venchw_remove(struct platform_device *pdev)
        }
        omap_dss_unregister_driver(&venc_driver);
 
+       pm_runtime_disable(&pdev->dev);
+       venc_put_clocks();
+
        iounmap(venc.base);
        return 0;
 }
 
+static int venc_runtime_suspend(struct device *dev)
+{
+       if (venc.tv_dac_clk)
+               clk_disable(venc.tv_dac_clk);
+       clk_disable(venc.tv_clk);
+
+       dispc_runtime_put();
+       dss_runtime_put();
+
+       return 0;
+}
+
+static int venc_runtime_resume(struct device *dev)
+{
+       int r;
+
+       r = dss_runtime_get();
+       if (r < 0)
+               goto err_get_dss;
+
+       r = dispc_runtime_get();
+       if (r < 0)
+               goto err_get_dispc;
+
+       clk_enable(venc.tv_clk);
+       if (venc.tv_dac_clk)
+               clk_enable(venc.tv_dac_clk);
+
+       return 0;
+
+err_get_dispc:
+       dss_runtime_put();
+err_get_dss:
+       return r;
+}
+
+static const struct dev_pm_ops venc_pm_ops = {
+       .runtime_suspend = venc_runtime_suspend,
+       .runtime_resume = venc_runtime_resume,
+};
+
 static struct platform_driver omap_venchw_driver = {
        .probe          = omap_venchw_probe,
        .remove         = omap_venchw_remove,
        .driver         = {
                .name   = "omapdss_venc",
                .owner  = THIS_MODULE,
+               .pm     = &venc_pm_ops,
        },
 };
 
index cff4503..6b1ac23 100644 (file)
@@ -316,67 +316,67 @@ int omapfb_update_window(struct fb_info *fbi,
 }
 EXPORT_SYMBOL(omapfb_update_window);
 
-static int omapfb_set_update_mode(struct fb_info *fbi,
+int omapfb_set_update_mode(struct fb_info *fbi,
                                   enum omapfb_update_mode mode)
 {
        struct omap_dss_device *display = fb2display(fbi);
-       enum omap_dss_update_mode um;
+       struct omapfb_info *ofbi = FB2OFB(fbi);
+       struct omapfb2_device *fbdev = ofbi->fbdev;
+       struct omapfb_display_data *d;
        int r;
 
-       if (!display || !display->driver->set_update_mode)
+       if (!display)
                return -EINVAL;
 
-       switch (mode) {
-       case OMAPFB_UPDATE_DISABLED:
-               um = OMAP_DSS_UPDATE_DISABLED;
-               break;
+       if (mode != OMAPFB_AUTO_UPDATE && mode != OMAPFB_MANUAL_UPDATE)
+               return -EINVAL;
 
-       case OMAPFB_AUTO_UPDATE:
-               um = OMAP_DSS_UPDATE_AUTO;
-               break;
+       omapfb_lock(fbdev);
 
-       case OMAPFB_MANUAL_UPDATE:
-               um = OMAP_DSS_UPDATE_MANUAL;
-               break;
+       d = get_display_data(fbdev, display);
 
-       default:
-               return -EINVAL;
+       if (d->update_mode == mode) {
+               omapfb_unlock(fbdev);
+               return 0;
        }
 
-       r = display->driver->set_update_mode(display, um);
+       r = 0;
+
+       if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
+               if (mode == OMAPFB_AUTO_UPDATE)
+                       omapfb_start_auto_update(fbdev, display);
+               else /* MANUAL_UPDATE */
+                       omapfb_stop_auto_update(fbdev, display);
+
+               d->update_mode = mode;
+       } else { /* AUTO_UPDATE */
+               if (mode == OMAPFB_MANUAL_UPDATE)
+                       r = -EINVAL;
+       }
+
+       omapfb_unlock(fbdev);
 
        return r;
 }
 
-static int omapfb_get_update_mode(struct fb_info *fbi,
+int omapfb_get_update_mode(struct fb_info *fbi,
                enum omapfb_update_mode *mode)
 {
        struct omap_dss_device *display = fb2display(fbi);
-       enum omap_dss_update_mode m;
+       struct omapfb_info *ofbi = FB2OFB(fbi);
+       struct omapfb2_device *fbdev = ofbi->fbdev;
+       struct omapfb_display_data *d;
 
        if (!display)
                return -EINVAL;
 
-       if (!display->driver->get_update_mode) {
-               *mode = OMAPFB_AUTO_UPDATE;
-               return 0;
-       }
+       omapfb_lock(fbdev);
 
-       m = display->driver->get_update_mode(display);
+       d = get_display_data(fbdev, display);
 
-       switch (m) {
-       case OMAP_DSS_UPDATE_DISABLED:
-               *mode = OMAPFB_UPDATE_DISABLED;
-               break;
-       case OMAP_DSS_UPDATE_AUTO:
-               *mode = OMAPFB_AUTO_UPDATE;
-               break;
-       case OMAP_DSS_UPDATE_MANUAL:
-               *mode = OMAPFB_MANUAL_UPDATE;
-               break;
-       default:
-               BUG();
-       }
+       *mode = d->update_mode;
+
+       omapfb_unlock(fbdev);
 
        return 0;
 }
index 505bc12..602b71a 100644 (file)
@@ -46,6 +46,10 @@ static char *def_vram;
 static int def_vrfb;
 static int def_rotate;
 static int def_mirror;
+static bool auto_update;
+static unsigned int auto_update_freq;
+module_param(auto_update, bool, 0);
+module_param(auto_update_freq, uint, 0644);
 
 #ifdef DEBUG
 unsigned int omapfb_debug;
@@ -1242,6 +1246,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
        struct omapfb_info *ofbi = FB2OFB(fbi);
        struct omapfb2_device *fbdev = ofbi->fbdev;
        struct omap_dss_device *display = fb2display(fbi);
+       struct omapfb_display_data *d;
        int r = 0;
 
        if (!display)
@@ -1249,6 +1254,8 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
 
        omapfb_lock(fbdev);
 
+       d = get_display_data(fbdev, display);
+
        switch (blank) {
        case FB_BLANK_UNBLANK:
                if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
@@ -1257,6 +1264,11 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
                if (display->driver->resume)
                        r = display->driver->resume(display);
 
+               if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
+                               d->update_mode == OMAPFB_AUTO_UPDATE &&
+                               !d->auto_update_work_enabled)
+                       omapfb_start_auto_update(fbdev, display);
+
                break;
 
        case FB_BLANK_NORMAL:
@@ -1268,6 +1280,9 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
                if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
                        goto exit;
 
+               if (d->auto_update_work_enabled)
+                       omapfb_stop_auto_update(fbdev, display);
+
                if (display->driver->suspend)
                        r = display->driver->suspend(display);
 
@@ -1724,6 +1739,78 @@ err:
        return r;
 }
 
+static void omapfb_auto_update_work(struct work_struct *work)
+{
+       struct omap_dss_device *dssdev;
+       struct omap_dss_driver *dssdrv;
+       struct omapfb_display_data *d;
+       u16 w, h;
+       unsigned int freq;
+       struct omapfb2_device *fbdev;
+
+       d = container_of(work, struct omapfb_display_data,
+                       auto_update_work.work);
+
+       dssdev = d->dssdev;
+       dssdrv = dssdev->driver;
+       fbdev = d->fbdev;
+
+       if (!dssdrv || !dssdrv->update)
+               return;
+
+       if (dssdrv->sync)
+               dssdrv->sync(dssdev);
+
+       dssdrv->get_resolution(dssdev, &w, &h);
+       dssdrv->update(dssdev, 0, 0, w, h);
+
+       freq = auto_update_freq;
+       if (freq == 0)
+               freq = 20;
+       queue_delayed_work(fbdev->auto_update_wq,
+                       &d->auto_update_work, HZ / freq);
+}
+
+void omapfb_start_auto_update(struct omapfb2_device *fbdev,
+               struct omap_dss_device *display)
+{
+       struct omapfb_display_data *d;
+
+       if (fbdev->auto_update_wq == NULL) {
+               struct workqueue_struct *wq;
+
+               wq = create_singlethread_workqueue("omapfb_auto_update");
+
+               if (wq == NULL) {
+                       dev_err(fbdev->dev, "Failed to create workqueue for "
+                                       "auto-update\n");
+                       return;
+               }
+
+               fbdev->auto_update_wq = wq;
+       }
+
+       d = get_display_data(fbdev, display);
+
+       INIT_DELAYED_WORK(&d->auto_update_work, omapfb_auto_update_work);
+
+       d->auto_update_work_enabled = true;
+
+       omapfb_auto_update_work(&d->auto_update_work.work);
+}
+
+void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
+               struct omap_dss_device *display)
+{
+       struct omapfb_display_data *d;
+
+       d = get_display_data(fbdev, display);
+
+       cancel_delayed_work_sync(&d->auto_update_work);
+
+       d->auto_update_work_enabled = false;
+}
+
 /* initialize fb_info, var, fix to something sane based on the display */
 static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
 {
@@ -1858,10 +1945,21 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev)
        }
 
        for (i = 0; i < fbdev->num_displays; i++) {
-               if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED)
-                       fbdev->displays[i]->driver->disable(fbdev->displays[i]);
+               struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
+
+               if (fbdev->displays[i].auto_update_work_enabled)
+                       omapfb_stop_auto_update(fbdev, dssdev);
+
+               if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
+                       dssdev->driver->disable(dssdev);
+
+               omap_dss_put_device(dssdev);
+       }
 
-               omap_dss_put_device(fbdev->displays[i]);
+       if (fbdev->auto_update_wq != NULL) {
+               flush_workqueue(fbdev->auto_update_wq);
+               destroy_workqueue(fbdev->auto_update_wq);
+               fbdev->auto_update_wq = NULL;
        }
 
        dev_set_drvdata(fbdev->dev, NULL);
@@ -2084,14 +2182,14 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
        int r;
        u8 bpp;
        struct omap_video_timings timings, temp_timings;
+       struct omapfb_display_data *d;
 
        r = omapfb_mode_to_timings(mode_str, &timings, &bpp);
        if (r)
                return r;
 
-       fbdev->bpp_overrides[fbdev->num_bpp_overrides].dssdev = display;
-       fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp;
-       ++fbdev->num_bpp_overrides;
+       d = get_display_data(fbdev, display);
+       d->bpp_override = bpp;
 
        if (display->driver->check_timings) {
                r = display->driver->check_timings(display, &timings);
@@ -2117,14 +2215,14 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
 static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
                struct omap_dss_device *dssdev)
 {
-       int i;
+       struct omapfb_display_data *d;
 
        BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
 
-       for (i = 0; i < fbdev->num_bpp_overrides; ++i) {
-               if (dssdev == fbdev->bpp_overrides[i].dssdev)
-                       return fbdev->bpp_overrides[i].bpp;
-       }
+       d = get_display_data(fbdev, dssdev);
+
+       if (d->bpp_override != 0)
+               return d->bpp_override;
 
        return dssdev->driver->get_recommended_bpp(dssdev);
 }
@@ -2156,9 +2254,9 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
 
                display = NULL;
                for (i = 0; i < fbdev->num_displays; ++i) {
-                       if (strcmp(fbdev->displays[i]->name,
+                       if (strcmp(fbdev->displays[i].dssdev->name,
                                                display_str) == 0) {
-                               display = fbdev->displays[i];
+                               display = fbdev->displays[i].dssdev;
                                break;
                        }
                }
@@ -2182,6 +2280,7 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
                struct omap_dss_device *dssdev)
 {
        struct omap_dss_driver *dssdrv = dssdev->driver;
+       struct omapfb_display_data *d;
        int r;
 
        r = dssdrv->enable(dssdev);
@@ -2191,8 +2290,20 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
                return r;
        }
 
+       d = get_display_data(fbdev, dssdev);
+
+       d->fbdev = fbdev;
+
        if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
                u16 w, h;
+
+               if (auto_update) {
+                       omapfb_start_auto_update(fbdev, dssdev);
+                       d->update_mode = OMAPFB_AUTO_UPDATE;
+               } else {
+                       d->update_mode = OMAPFB_MANUAL_UPDATE;
+               }
+
                if (dssdrv->enable_te) {
                        r = dssdrv->enable_te(dssdev, 1);
                        if (r) {
@@ -2201,16 +2312,6 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
                        }
                }
 
-               if (dssdrv->set_update_mode) {
-                       r = dssdrv->set_update_mode(dssdev,
-                                       OMAP_DSS_UPDATE_MANUAL);
-                       if (r) {
-                               dev_err(fbdev->dev,
-                                               "Failed to set update mode\n");
-                               return r;
-                       }
-               }
-
                dssdrv->get_resolution(dssdev, &w, &h);
                r = dssdrv->update(dssdev, 0, 0, w, h);
                if (r) {
@@ -2219,15 +2320,7 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
                        return r;
                }
        } else {
-               if (dssdrv->set_update_mode) {
-                       r = dssdrv->set_update_mode(dssdev,
-                                       OMAP_DSS_UPDATE_AUTO);
-                       if (r) {
-                               dev_err(fbdev->dev,
-                                               "Failed to set update mode\n");
-                               return r;
-                       }
-               }
+               d->update_mode = OMAPFB_AUTO_UPDATE;
        }
 
        return 0;
@@ -2275,6 +2368,8 @@ static int omapfb_probe(struct platform_device *pdev)
        fbdev->num_displays = 0;
        dssdev = NULL;
        for_each_dss_dev(dssdev) {
+               struct omapfb_display_data *d;
+
                omap_dss_get_device(dssdev);
 
                if (!dssdev->driver) {
@@ -2282,7 +2377,12 @@ static int omapfb_probe(struct platform_device *pdev)
                        r = -ENODEV;
                }
 
-               fbdev->displays[fbdev->num_displays++] = dssdev;
+               d = &fbdev->displays[fbdev->num_displays++];
+               d->dssdev = dssdev;
+               if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
+                       d->update_mode = OMAPFB_MANUAL_UPDATE;
+               else
+                       d->update_mode = OMAPFB_AUTO_UPDATE;
        }
 
        if (r)
index 2f5e817..153bf1a 100644 (file)
@@ -518,6 +518,39 @@ static ssize_t show_virt(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr);
 }
 
+static ssize_t show_upd_mode(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct fb_info *fbi = dev_get_drvdata(dev);
+       enum omapfb_update_mode mode;
+       int r;
+
+       r = omapfb_get_update_mode(fbi, &mode);
+
+       if (r)
+               return r;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", (unsigned)mode);
+}
+
+static ssize_t store_upd_mode(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct fb_info *fbi = dev_get_drvdata(dev);
+       unsigned mode;
+       int r;
+
+       r = kstrtouint(buf, 0, &mode);
+       if (r)
+               return r;
+
+       r = omapfb_set_update_mode(fbi, mode);
+       if (r)
+               return r;
+
+       return count;
+}
+
 static struct device_attribute omapfb_attrs[] = {
        __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type,
                        store_rotate_type),
@@ -528,6 +561,7 @@ static struct device_attribute omapfb_attrs[] = {
                        store_overlays_rotate),
        __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
        __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
+       __ATTR(update_mode, S_IRUGO | S_IWUSR, show_upd_mode, store_upd_mode),
 };
 
 int omapfb_create_sysfs(struct omapfb2_device *fbdev)
index aa1b1d9..fdf0ede 100644 (file)
@@ -73,6 +73,15 @@ struct omapfb_info {
        bool mirror;
 };
 
+struct omapfb_display_data {
+       struct omapfb2_device *fbdev;
+       struct omap_dss_device *dssdev;
+       u8 bpp_override;
+       enum omapfb_update_mode update_mode;
+       bool auto_update_work_enabled;
+       struct delayed_work auto_update_work;
+};
+
 struct omapfb2_device {
        struct device *dev;
        struct mutex  mtx;
@@ -86,17 +95,13 @@ struct omapfb2_device {
        struct omapfb2_mem_region regions[10];
 
        unsigned num_displays;
-       struct omap_dss_device *displays[10];
+       struct omapfb_display_data displays[10];
        unsigned num_overlays;
        struct omap_overlay *overlays[10];
        unsigned num_managers;
        struct omap_overlay_manager *managers[10];
 
-       unsigned num_bpp_overrides;
-       struct {
-               struct omap_dss_device *dssdev;
-               u8 bpp;
-       } bpp_overrides[10];
+       struct workqueue_struct *auto_update_wq;
 };
 
 struct omapfb_colormode {
@@ -128,6 +133,13 @@ int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
 int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
                u16 posx, u16 posy, u16 outw, u16 outh);
 
+void omapfb_start_auto_update(struct omapfb2_device *fbdev,
+               struct omap_dss_device *display);
+void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
+               struct omap_dss_device *display);
+int omapfb_get_update_mode(struct fb_info *fbi, enum omapfb_update_mode *mode);
+int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode);
+
 /* find the display connected to this fb, if any */
 static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
 {
@@ -143,6 +155,19 @@ static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
        return NULL;
 }
 
+static inline struct omapfb_display_data *get_display_data(
+               struct omapfb2_device *fbdev, struct omap_dss_device *dssdev)
+{
+       int i;
+
+       for (i = 0; i < fbdev->num_displays; ++i)
+               if (fbdev->displays[i].dssdev == dssdev)
+                       return &fbdev->displays[i];
+
+       /* This should never happen */
+       BUG();
+}
+
 static inline void omapfb_lock(struct omapfb2_device *fbdev)
 {
        mutex_lock(&fbdev->mtx);
index e0b5d80..01cbfd5 100644 (file)
@@ -380,7 +380,7 @@ pnfs_roc_drain(struct inode *ino, u32 *barrier)
 }
 
 static inline void set_pnfs_layoutdriver(struct nfs_server *s,
-                                        const struct nfs_fh *mntfh, u32 id);
+                                        const struct nfs_fh *mntfh, u32 id)
 {
 }
 
index c2ebfe6..9d57a71 100644 (file)
@@ -162,6 +162,7 @@ extern int allocate_resource(struct resource *root, struct resource *new,
                                                       resource_size_t,
                                                       resource_size_t),
                             void *alignf_data);
+struct resource *lookup_resource(struct resource *root, resource_size_t start);
 int adjust_resource(struct resource *res, resource_size_t start,
                    resource_size_t size);
 resource_size_t resource_alignment(struct resource *res);
diff --git a/include/linux/mfd/aat2870.h b/include/linux/mfd/aat2870.h
new file mode 100644 (file)
index 0000000..89212df
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * linux/include/linux/mfd/aat2870.h
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ * Author: Jin Park <jinyoungp@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef __LINUX_MFD_AAT2870_H
+#define __LINUX_MFD_AAT2870_H
+
+#include <linux/debugfs.h>
+#include <linux/i2c.h>
+
+/* Register offsets */
+#define AAT2870_BL_CH_EN       0x00
+#define AAT2870_BLM            0x01
+#define AAT2870_BLS            0x02
+#define AAT2870_BL1            0x03
+#define AAT2870_BL2            0x04
+#define AAT2870_BL3            0x05
+#define AAT2870_BL4            0x06
+#define AAT2870_BL5            0x07
+#define AAT2870_BL6            0x08
+#define AAT2870_BL7            0x09
+#define AAT2870_BL8            0x0A
+#define AAT2870_FLR            0x0B
+#define AAT2870_FM             0x0C
+#define AAT2870_FS             0x0D
+#define AAT2870_ALS_CFG0       0x0E
+#define AAT2870_ALS_CFG1       0x0F
+#define AAT2870_ALS_CFG2       0x10
+#define AAT2870_AMB            0x11
+#define AAT2870_ALS0           0x12
+#define AAT2870_ALS1           0x13
+#define AAT2870_ALS2           0x14
+#define AAT2870_ALS3           0x15
+#define AAT2870_ALS4           0x16
+#define AAT2870_ALS5           0x17
+#define AAT2870_ALS6           0x18
+#define AAT2870_ALS7           0x19
+#define AAT2870_ALS8           0x1A
+#define AAT2870_ALS9           0x1B
+#define AAT2870_ALSA           0x1C
+#define AAT2870_ALSB           0x1D
+#define AAT2870_ALSC           0x1E
+#define AAT2870_ALSD           0x1F
+#define AAT2870_ALSE           0x20
+#define AAT2870_ALSF           0x21
+#define AAT2870_SUB_SET                0x22
+#define AAT2870_SUB_CTRL       0x23
+#define AAT2870_LDO_AB         0x24
+#define AAT2870_LDO_CD         0x25
+#define AAT2870_LDO_EN         0x26
+#define AAT2870_REG_NUM                0x27
+
+/* Device IDs */
+enum aat2870_id {
+       AAT2870_ID_BL,
+       AAT2870_ID_LDOA,
+       AAT2870_ID_LDOB,
+       AAT2870_ID_LDOC,
+       AAT2870_ID_LDOD
+};
+
+/* Backlight channels */
+#define AAT2870_BL_CH1         0x01
+#define AAT2870_BL_CH2         0x02
+#define AAT2870_BL_CH3         0x04
+#define AAT2870_BL_CH4         0x08
+#define AAT2870_BL_CH5         0x10
+#define AAT2870_BL_CH6         0x20
+#define AAT2870_BL_CH7         0x40
+#define AAT2870_BL_CH8         0x80
+#define AAT2870_BL_CH_ALL      0xFF
+
+/* Backlight current magnitude (mA) */
+enum aat2870_current {
+       AAT2870_CURRENT_0_45,
+       AAT2870_CURRENT_0_90,
+       AAT2870_CURRENT_1_80,
+       AAT2870_CURRENT_2_70,
+       AAT2870_CURRENT_3_60,
+       AAT2870_CURRENT_4_50,
+       AAT2870_CURRENT_5_40,
+       AAT2870_CURRENT_6_30,
+       AAT2870_CURRENT_7_20,
+       AAT2870_CURRENT_8_10,
+       AAT2870_CURRENT_9_00,
+       AAT2870_CURRENT_9_90,
+       AAT2870_CURRENT_10_8,
+       AAT2870_CURRENT_11_7,
+       AAT2870_CURRENT_12_6,
+       AAT2870_CURRENT_13_5,
+       AAT2870_CURRENT_14_4,
+       AAT2870_CURRENT_15_3,
+       AAT2870_CURRENT_16_2,
+       AAT2870_CURRENT_17_1,
+       AAT2870_CURRENT_18_0,
+       AAT2870_CURRENT_18_9,
+       AAT2870_CURRENT_19_8,
+       AAT2870_CURRENT_20_7,
+       AAT2870_CURRENT_21_6,
+       AAT2870_CURRENT_22_5,
+       AAT2870_CURRENT_23_4,
+       AAT2870_CURRENT_24_3,
+       AAT2870_CURRENT_25_2,
+       AAT2870_CURRENT_26_1,
+       AAT2870_CURRENT_27_0,
+       AAT2870_CURRENT_27_9
+};
+
+struct aat2870_register {
+       bool readable;
+       bool writeable;
+       u8 value;
+};
+
+struct aat2870_data {
+       struct device *dev;
+       struct i2c_client *client;
+
+       struct mutex io_lock;
+       struct aat2870_register *reg_cache; /* register cache */
+       int en_pin; /* enable GPIO pin (if < 0, ignore this value) */
+       bool is_enable;
+
+       /* init and uninit for platform specified */
+       int (*init)(struct aat2870_data *aat2870);
+       void (*uninit)(struct aat2870_data *aat2870);
+
+       /* i2c io funcntions */
+       int (*read)(struct aat2870_data *aat2870, u8 addr, u8 *val);
+       int (*write)(struct aat2870_data *aat2870, u8 addr, u8 val);
+       int (*update)(struct aat2870_data *aat2870, u8 addr, u8 mask, u8 val);
+
+       /* for debugfs */
+       struct dentry *dentry_root;
+       struct dentry *dentry_reg;
+};
+
+struct aat2870_subdev_info {
+       int id;
+       const char *name;
+       void *platform_data;
+};
+
+struct aat2870_platform_data {
+       int en_pin; /* enable GPIO pin (if < 0, ignore this value) */
+
+       struct aat2870_subdev_info *subdevs;
+       int num_subdevs;
+
+       /* init and uninit for platform specified */
+       int (*init)(struct aat2870_data *aat2870);
+       void (*uninit)(struct aat2870_data *aat2870);
+};
+
+struct aat2870_bl_platform_data {
+       /* backlight channels, default is AAT2870_BL_CH_ALL */
+       int channels;
+       /* backlight current magnitude, default is AAT2870_CURRENT_27_9 */
+       int max_current;
+       /* maximum brightness, default is 255 */
+       int max_brightness;
+};
+
+#endif /* __LINUX_MFD_AAT2870_H */
index b318430..838c6b4 100644 (file)
@@ -28,6 +28,7 @@
 #define AB8500_INTERRUPT       0xE
 #define AB8500_RTC             0xF
 #define AB8500_MISC            0x10
+#define AB8500_DEVELOPMENT     0x11
 #define AB8500_DEBUG           0x12
 #define AB8500_PROD_TEST       0x13
 #define AB8500_OTP_EMUL                0x15
 #define AB8500_INT_ACC_DETECT_21DB_F   37
 #define AB8500_INT_ACC_DETECT_21DB_R   38
 #define AB8500_INT_GP_SW_ADC_CONV_END  39
-#define AB8500_INT_ACC_DETECT_1DB_F    33
-#define AB8500_INT_ACC_DETECT_1DB_R    34
-#define AB8500_INT_ACC_DETECT_22DB_F   35
-#define AB8500_INT_ACC_DETECT_22DB_R   36
-#define AB8500_INT_ACC_DETECT_21DB_F   37
-#define AB8500_INT_ACC_DETECT_21DB_R   38
-#define AB8500_INT_GP_SW_ADC_CONV_END  39
 #define AB8500_INT_GPIO6R              40
 #define AB8500_INT_GPIO7R              41
 #define AB8500_INT_GPIO8R              42
index e762c27..be1af7c 100644 (file)
@@ -57,6 +57,7 @@ struct stmpe_variant_info;
  * @irq_lock: IRQ bus lock
  * @dev: device, mostly for dev_dbg()
  * @i2c: i2c client
+ * @partnum: part number
  * @variant: the detected STMPE model number
  * @regs: list of addresses of registers which are at different addresses on
  *       different variants.  Indexed by one of STMPE_IDX_*.
@@ -121,6 +122,8 @@ struct stmpe_keypad_platform_data {
  * @norequest_mask: bitmask specifying which GPIOs should _not_ be
  *                 requestable due to different usage (e.g. touch, keypad)
  *                 STMPE_GPIO_NOREQ_* macros can be used here.
+ * @setup: board specific setup callback.
+ * @remove: board specific remove callback
  */
 struct stmpe_gpio_platform_data {
        int gpio_base;
index 73572c6..82b4c88 100644 (file)
@@ -791,6 +791,7 @@ int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask);
 void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base);
 int tps65910_irq_init(struct tps65910 *tps65910, int irq,
                struct tps65910_platform_data *pdata);
+int tps65910_irq_exit(struct tps65910 *tps65910);
 
 static inline int tps65910_chip_id(struct tps65910 *tps65910)
 {
diff --git a/include/linux/mfd/tps65912.h b/include/linux/mfd/tps65912.h
new file mode 100644 (file)
index 0000000..aaceab4
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * tps65912.h  --  TI TPS6591x
+ *
+ * Copyright 2011 Texas Instruments Inc.
+ *
+ * Author: Margarita Olaya <magi@slimlogic.co.uk>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under  the terms of the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#ifndef __LINUX_MFD_TPS65912_H
+#define __LINUX_MFD_TPS65912_H
+
+/* TPS regulator type list */
+#define REGULATOR_LDO          0
+#define REGULATOR_DCDC         1
+
+/*
+ * List of registers for TPS65912
+ */
+
+#define TPS65912_DCDC1_CTRL            0x00
+#define TPS65912_DCDC2_CTRL            0x01
+#define TPS65912_DCDC3_CTRL            0x02
+#define TPS65912_DCDC4_CTRL            0x03
+#define TPS65912_DCDC1_OP              0x04
+#define TPS65912_DCDC1_AVS             0x05
+#define TPS65912_DCDC1_LIMIT           0x06
+#define TPS65912_DCDC2_OP              0x07
+#define TPS65912_DCDC2_AVS             0x08
+#define TPS65912_DCDC2_LIMIT           0x09
+#define TPS65912_DCDC3_OP              0x0A
+#define TPS65912_DCDC3_AVS             0x0B
+#define TPS65912_DCDC3_LIMIT           0x0C
+#define TPS65912_DCDC4_OP              0x0D
+#define TPS65912_DCDC4_AVS             0x0E
+#define TPS65912_DCDC4_LIMIT           0x0F
+#define TPS65912_LDO1_OP               0x10
+#define TPS65912_LDO1_AVS              0x11
+#define TPS65912_LDO1_LIMIT            0x12
+#define TPS65912_LDO2_OP               0x13
+#define TPS65912_LDO2_AVS              0x14
+#define TPS65912_LDO2_LIMIT            0x15
+#define TPS65912_LDO3_OP               0x16
+#define TPS65912_LDO3_AVS              0x17
+#define TPS65912_LDO3_LIMIT            0x18
+#define TPS65912_LDO4_OP               0x19
+#define TPS65912_LDO4_AVS              0x1A
+#define TPS65912_LDO4_LIMIT            0x1B
+#define TPS65912_LDO5                  0x1C
+#define TPS65912_LDO6                  0x1D
+#define TPS65912_LDO7                  0x1E
+#define TPS65912_LDO8                  0x1F
+#define TPS65912_LDO9                  0x20
+#define TPS65912_LDO10                 0x21
+#define TPS65912_THRM                  0x22
+#define TPS65912_CLK32OUT              0x23
+#define TPS65912_DEVCTRL               0x24
+#define TPS65912_DEVCTRL2              0x25
+#define TPS65912_I2C_SPI_CFG           0x26
+#define TPS65912_KEEP_ON               0x27
+#define TPS65912_KEEP_ON2              0x28
+#define TPS65912_SET_OFF1              0x29
+#define TPS65912_SET_OFF2              0x2A
+#define TPS65912_DEF_VOLT              0x2B
+#define TPS65912_DEF_VOLT_MAPPING      0x2C
+#define TPS65912_DISCHARGE             0x2D
+#define TPS65912_DISCHARGE2            0x2E
+#define TPS65912_EN1_SET1              0x2F
+#define TPS65912_EN1_SET2              0x30
+#define TPS65912_EN2_SET1              0x31
+#define TPS65912_EN2_SET2              0x32
+#define TPS65912_EN3_SET1              0x33
+#define TPS65912_EN3_SET2              0x34
+#define TPS65912_EN4_SET1              0x35
+#define TPS65912_EN4_SET2              0x36
+#define TPS65912_PGOOD                 0x37
+#define TPS65912_PGOOD2                        0x38
+#define TPS65912_INT_STS               0x39
+#define TPS65912_INT_MSK               0x3A
+#define TPS65912_INT_STS2              0x3B
+#define TPS65912_INT_MSK2              0x3C
+#define TPS65912_INT_STS3              0x3D
+#define TPS65912_INT_MSK3              0x3E
+#define TPS65912_INT_STS4              0x3F
+#define TPS65912_INT_MSK4              0x40
+#define TPS65912_GPIO1                 0x41
+#define TPS65912_GPIO2                 0x42
+#define TPS65912_GPIO3                 0x43
+#define TPS65912_GPIO4                 0x44
+#define TPS65912_GPIO5                 0x45
+#define TPS65912_VMON                  0x46
+#define TPS65912_LEDA_CTRL1            0x47
+#define TPS65912_LEDA_CTRL2            0x48
+#define TPS65912_LEDA_CTRL3            0x49
+#define TPS65912_LEDA_CTRL4            0x4A
+#define TPS65912_LEDA_CTRL5            0x4B
+#define TPS65912_LEDA_CTRL6            0x4C
+#define TPS65912_LEDA_CTRL7            0x4D
+#define TPS65912_LEDA_CTRL8            0x4E
+#define TPS65912_LEDB_CTRL1            0x4F
+#define TPS65912_LEDB_CTRL2            0x50
+#define TPS65912_LEDB_CTRL3            0x51
+#define TPS65912_LEDB_CTRL4            0x52
+#define TPS65912_LEDB_CTRL5            0x53
+#define TPS65912_LEDB_CTRL6            0x54
+#define TPS65912_LEDB_CTRL7            0x55
+#define TPS65912_LEDB_CTRL8            0x56
+#define TPS65912_LEDC_CTRL1            0x57
+#define TPS65912_LEDC_CTRL2            0x58
+#define TPS65912_LEDC_CTRL3            0x59
+#define TPS65912_LEDC_CTRL4            0x5A
+#define TPS65912_LEDC_CTRL5            0x5B
+#define TPS65912_LEDC_CTRL6            0x5C
+#define TPS65912_LEDC_CTRL7            0x5D
+#define TPS65912_LEDC_CTRL8            0x5E
+#define TPS65912_LED_RAMP_UP_TIME      0x5F
+#define TPS65912_LED_RAMP_DOWN_TIME    0x60
+#define TPS65912_LED_SEQ_EN            0x61
+#define TPS65912_LOADSWITCH            0x62
+#define TPS65912_SPARE                 0x63
+#define TPS65912_VERNUM                        0x64
+#define TPS6591X_MAX_REGISTER          0x64
+
+/* IRQ Definitions */
+#define TPS65912_IRQ_PWRHOLD_F         0
+#define TPS65912_IRQ_VMON              1
+#define TPS65912_IRQ_PWRON             2
+#define TPS65912_IRQ_PWRON_LP          3
+#define TPS65912_IRQ_PWRHOLD_R         4
+#define TPS65912_IRQ_HOTDIE            5
+#define TPS65912_IRQ_GPIO1_R           6
+#define TPS65912_IRQ_GPIO1_F           7
+#define TPS65912_IRQ_GPIO2_R           8
+#define TPS65912_IRQ_GPIO2_F           9
+#define TPS65912_IRQ_GPIO3_R           10
+#define TPS65912_IRQ_GPIO3_F           11
+#define TPS65912_IRQ_GPIO4_R           12
+#define TPS65912_IRQ_GPIO4_F           13
+#define TPS65912_IRQ_GPIO5_R           14
+#define TPS65912_IRQ_GPIO5_F           15
+#define TPS65912_IRQ_PGOOD_DCDC1       16
+#define TPS65912_IRQ_PGOOD_DCDC2       17
+#define TPS65912_IRQ_PGOOD_DCDC3       18
+#define TPS65912_IRQ_PGOOD_DCDC4       19
+#define TPS65912_IRQ_PGOOD_LDO1                20
+#define TPS65912_IRQ_PGOOD_LDO2                21
+#define TPS65912_IRQ_PGOOD_LDO3                22
+#define TPS65912_IRQ_PGOOD_LDO4                23
+#define TPS65912_IRQ_PGOOD_LDO5                24
+#define TPS65912_IRQ_PGOOD_LDO6                25
+#define TPS65912_IRQ_PGOOD_LDO7                26
+#define TPS65912_IRQ_PGOOD_LD08                27
+#define TPS65912_IRQ_PGOOD_LDO9                28
+#define TPS65912_IRQ_PGOOD_LDO10       29
+
+#define TPS65912_NUM_IRQ               30
+
+/* GPIO 1 and 2 Register Definitions */
+#define GPIO_SLEEP_MASK                        0x80
+#define GPIO_SLEEP_SHIFT               7
+#define GPIO_DEB_MASK                  0x10
+#define GPIO_DEB_SHIFT                 4
+#define GPIO_CFG_MASK                  0x04
+#define GPIO_CFG_SHIFT                 2
+#define GPIO_STS_MASK                  0x02
+#define GPIO_STS_SHIFT                 1
+#define GPIO_SET_MASK                  0x01
+#define GPIO_SET_SHIFT                 0
+
+/* GPIO 3 Register Definitions */
+#define GPIO3_SLEEP_MASK               0x80
+#define GPIO3_SLEEP_SHIFT              7
+#define GPIO3_SEL_MASK                 0x40
+#define GPIO3_SEL_SHIFT                        6
+#define GPIO3_ODEN_MASK                        0x20
+#define GPIO3_ODEN_SHIFT               5
+#define GPIO3_DEB_MASK                 0x10
+#define GPIO3_DEB_SHIFT                        4
+#define GPIO3_PDEN_MASK                        0x08
+#define GPIO3_PDEN_SHIFT               3
+#define GPIO3_CFG_MASK                 0x04
+#define GPIO3_CFG_SHIFT                        2
+#define GPIO3_STS_MASK                 0x02
+#define GPIO3_STS_SHIFT                        1
+#define GPIO3_SET_MASK                 0x01
+#define GPIO3_SET_SHIFT                        0
+
+/* GPIO 4 Register Definitions */
+#define GPIO4_SLEEP_MASK               0x80
+#define GPIO4_SLEEP_SHIFT              7
+#define GPIO4_SEL_MASK                 0x40
+#define GPIO4_SEL_SHIFT                        6
+#define GPIO4_ODEN_MASK                        0x20
+#define GPIO4_ODEN_SHIFT               5
+#define GPIO4_DEB_MASK                 0x10
+#define GPIO4_DEB_SHIFT                        4
+#define GPIO4_PDEN_MASK                        0x08
+#define GPIO4_PDEN_SHIFT               3
+#define GPIO4_CFG_MASK                 0x04
+#define GPIO4_CFG_SHIFT                        2
+#define GPIO4_STS_MASK                 0x02
+#define GPIO4_STS_SHIFT                        1
+#define GPIO4_SET_MASK                 0x01
+#define GPIO4_SET_SHIFT                        0
+
+/* Register THERM  (0x80) register.RegisterDescription */
+#define THERM_THERM_HD_MASK            0x20
+#define THERM_THERM_HD_SHIFT           5
+#define THERM_THERM_TS_MASK            0x10
+#define THERM_THERM_TS_SHIFT           4
+#define THERM_THERM_HDSEL_MASK         0x0C
+#define THERM_THERM_HDSEL_SHIFT                2
+#define THERM_RSVD1_MASK               0x02
+#define THERM_RSVD1_SHIFT              1
+#define THERM_THERM_STATE_MASK         0x01
+#define THERM_THERM_STATE_SHIFT                0
+
+/* Register DCDCCTRL1 register.RegisterDescription */
+#define DCDCCTRL_VCON_ENABLE_MASK      0x80
+#define DCDCCTRL_VCON_ENABLE_SHIFT     7
+#define DCDCCTRL_VCON_RANGE1_MASK      0x40
+#define DCDCCTRL_VCON_RANGE1_SHIFT     6
+#define DCDCCTRL_VCON_RANGE0_MASK      0x20
+#define DCDCCTRL_VCON_RANGE0_SHIFT     5
+#define DCDCCTRL_TSTEP2_MASK           0x10
+#define DCDCCTRL_TSTEP2_SHIFT          4
+#define DCDCCTRL_TSTEP1_MASK           0x08
+#define DCDCCTRL_TSTEP1_SHIFT          3
+#define DCDCCTRL_TSTEP0_MASK           0x04
+#define DCDCCTRL_TSTEP0_SHIFT          2
+#define DCDCCTRL_DCDC1_MODE_MASK       0x02
+#define DCDCCTRL_DCDC1_MODE_SHIFT      1
+
+/* Register DCDCCTRL2 and DCDCCTRL3 register.RegisterDescription */
+#define DCDCCTRL_TSTEP2_MASK           0x10
+#define DCDCCTRL_TSTEP2_SHIFT          4
+#define DCDCCTRL_TSTEP1_MASK           0x08
+#define DCDCCTRL_TSTEP1_SHIFT          3
+#define DCDCCTRL_TSTEP0_MASK           0x04
+#define DCDCCTRL_TSTEP0_SHIFT          2
+#define DCDCCTRL_DCDC_MODE_MASK                0x02
+#define DCDCCTRL_DCDC_MODE_SHIFT       1
+#define DCDCCTRL_RSVD0_MASK            0x01
+#define DCDCCTRL_RSVD0_SHIFT           0
+
+/* Register DCDCCTRL4 register.RegisterDescription */
+#define DCDCCTRL_RAMP_TIME_MASK                0x01
+#define DCDCCTRL_RAMP_TIME_SHIFT       0
+
+/* Register DCDCx_AVS */
+#define DCDC_AVS_ENABLE_MASK           0x80
+#define DCDC_AVS_ENABLE_SHIFT          7
+#define DCDC_AVS_ECO_MASK              0x40
+#define DCDC_AVS_ECO_SHIFT             6
+
+/* Register DCDCx_LIMIT */
+#define DCDC_LIMIT_RANGE_MASK          0xC0
+#define DCDC_LIMIT_RANGE_SHIFT         6
+#define DCDC_LIMIT_MAX_SEL_MASK                0x3F
+#define DCDC_LIMIT_MAX_SEL_SHIFT       0
+
+/**
+ * struct tps65912_board
+ * Board platform dat may be used to initialize regulators.
+ */
+struct tps65912_board {
+       int is_dcdc1_avs;
+       int is_dcdc2_avs;
+       int is_dcdc3_avs;
+       int is_dcdc4_avs;
+       int irq;
+       int irq_base;
+       int gpio_base;
+       struct regulator_init_data *tps65912_pmic_init_data;
+};
+
+/**
+ * struct tps65912 - tps65912 sub-driver chip access routines
+ */
+
+struct tps65912 {
+       struct device *dev;
+       /* for read/write acces */
+       struct mutex io_mutex;
+
+       /* For device IO interfaces: I2C or SPI */
+       void *control_data;
+
+       int (*read)(struct tps65912 *tps65912, u8 reg, int size, void *dest);
+       int (*write)(struct tps65912 *tps65912, u8 reg, int size, void *src);
+
+       /* Client devices */
+       struct tps65912_pmic *pmic;
+
+       /* GPIO Handling */
+       struct gpio_chip gpio;
+
+       /* IRQ Handling */
+       struct mutex irq_lock;
+       int chip_irq;
+       int irq_base;
+       int irq_num;
+       u32 irq_mask;
+};
+
+struct tps65912_platform_data {
+       int irq;
+       int irq_base;
+};
+
+unsigned int tps_chip(void);
+
+int tps65912_set_bits(struct tps65912 *tps65912, u8 reg, u8 mask);
+int tps65912_clear_bits(struct tps65912 *tps65912, u8 reg, u8 mask);
+int tps65912_reg_read(struct tps65912 *tps65912, u8 reg);
+int tps65912_reg_write(struct tps65912 *tps65912, u8 reg, u8 val);
+int tps65912_device_init(struct tps65912 *tps65912);
+void tps65912_device_exit(struct tps65912 *tps65912);
+int tps65912_irq_init(struct tps65912 *tps65912, int irq,
+                       struct tps65912_platform_data *pdata);
+
+#endif /*  __LINUX_MFD_TPS65912_H */
index 0d515ee..8dda8de 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/completion.h>
 #include <linux/interrupt.h>
+#include <linux/list.h>
 
 /*
  * Register values.
 #define WM831X_ON_PIN_TO_SHIFT                       0  /* ON_PIN_TO - [1:0] */
 #define WM831X_ON_PIN_TO_WIDTH                       2  /* ON_PIN_TO - [1:0] */
 
+/*
+ * R16528 (0x4090) - Clock Control 1
+ */
+#define WM831X_CLKOUT_ENA                       0x8000  /* CLKOUT_ENA */
+#define WM831X_CLKOUT_ENA_MASK                  0x8000  /* CLKOUT_ENA */
+#define WM831X_CLKOUT_ENA_SHIFT                     15  /* CLKOUT_ENA */
+#define WM831X_CLKOUT_ENA_WIDTH                      1  /* CLKOUT_ENA */
+#define WM831X_CLKOUT_OD                        0x2000  /* CLKOUT_OD */
+#define WM831X_CLKOUT_OD_MASK                   0x2000  /* CLKOUT_OD */
+#define WM831X_CLKOUT_OD_SHIFT                      13  /* CLKOUT_OD */
+#define WM831X_CLKOUT_OD_WIDTH                       1  /* CLKOUT_OD */
+#define WM831X_CLKOUT_SLOT_MASK                 0x0700  /* CLKOUT_SLOT - [10:8] */
+#define WM831X_CLKOUT_SLOT_SHIFT                     8  /* CLKOUT_SLOT - [10:8] */
+#define WM831X_CLKOUT_SLOT_WIDTH                     3  /* CLKOUT_SLOT - [10:8] */
+#define WM831X_CLKOUT_SLPSLOT_MASK              0x0070  /* CLKOUT_SLPSLOT - [6:4] */
+#define WM831X_CLKOUT_SLPSLOT_SHIFT                  4  /* CLKOUT_SLPSLOT - [6:4] */
+#define WM831X_CLKOUT_SLPSLOT_WIDTH                  3  /* CLKOUT_SLPSLOT - [6:4] */
+#define WM831X_CLKOUT_SRC                       0x0001  /* CLKOUT_SRC */
+#define WM831X_CLKOUT_SRC_MASK                  0x0001  /* CLKOUT_SRC */
+#define WM831X_CLKOUT_SRC_SHIFT                      0  /* CLKOUT_SRC */
+#define WM831X_CLKOUT_SRC_WIDTH                      1  /* CLKOUT_SRC */
+
+/*
+ * R16529 (0x4091) - Clock Control 2
+ */
+#define WM831X_XTAL_INH                         0x8000  /* XTAL_INH */
+#define WM831X_XTAL_INH_MASK                    0x8000  /* XTAL_INH */
+#define WM831X_XTAL_INH_SHIFT                       15  /* XTAL_INH */
+#define WM831X_XTAL_INH_WIDTH                        1  /* XTAL_INH */
+#define WM831X_XTAL_ENA                         0x2000  /* XTAL_ENA */
+#define WM831X_XTAL_ENA_MASK                    0x2000  /* XTAL_ENA */
+#define WM831X_XTAL_ENA_SHIFT                       13  /* XTAL_ENA */
+#define WM831X_XTAL_ENA_WIDTH                        1  /* XTAL_ENA */
+#define WM831X_XTAL_BKUPENA                     0x1000  /* XTAL_BKUPENA */
+#define WM831X_XTAL_BKUPENA_MASK                0x1000  /* XTAL_BKUPENA */
+#define WM831X_XTAL_BKUPENA_SHIFT                   12  /* XTAL_BKUPENA */
+#define WM831X_XTAL_BKUPENA_WIDTH                    1  /* XTAL_BKUPENA */
+#define WM831X_FLL_AUTO                         0x0080  /* FLL_AUTO */
+#define WM831X_FLL_AUTO_MASK                    0x0080  /* FLL_AUTO */
+#define WM831X_FLL_AUTO_SHIFT                        7  /* FLL_AUTO */
+#define WM831X_FLL_AUTO_WIDTH                        1  /* FLL_AUTO */
+#define WM831X_FLL_AUTO_FREQ_MASK               0x0007  /* FLL_AUTO_FREQ - [2:0] */
+#define WM831X_FLL_AUTO_FREQ_SHIFT                   0  /* FLL_AUTO_FREQ - [2:0] */
+#define WM831X_FLL_AUTO_FREQ_WIDTH                   3  /* FLL_AUTO_FREQ - [2:0] */
+
+/*
+ * R16530 (0x4092) - FLL Control 1
+ */
+#define WM831X_FLL_FRAC                         0x0004  /* FLL_FRAC */
+#define WM831X_FLL_FRAC_MASK                    0x0004  /* FLL_FRAC */
+#define WM831X_FLL_FRAC_SHIFT                        2  /* FLL_FRAC */
+#define WM831X_FLL_FRAC_WIDTH                        1  /* FLL_FRAC */
+#define WM831X_FLL_OSC_ENA                      0x0002  /* FLL_OSC_ENA */
+#define WM831X_FLL_OSC_ENA_MASK                 0x0002  /* FLL_OSC_ENA */
+#define WM831X_FLL_OSC_ENA_SHIFT                     1  /* FLL_OSC_ENA */
+#define WM831X_FLL_OSC_ENA_WIDTH                     1  /* FLL_OSC_ENA */
+#define WM831X_FLL_ENA                          0x0001  /* FLL_ENA */
+#define WM831X_FLL_ENA_MASK                     0x0001  /* FLL_ENA */
+#define WM831X_FLL_ENA_SHIFT                         0  /* FLL_ENA */
+#define WM831X_FLL_ENA_WIDTH                         1  /* FLL_ENA */
+
+/*
+ * R16531 (0x4093) - FLL Control 2
+ */
+#define WM831X_FLL_OUTDIV_MASK                  0x3F00  /* FLL_OUTDIV - [13:8] */
+#define WM831X_FLL_OUTDIV_SHIFT                      8  /* FLL_OUTDIV - [13:8] */
+#define WM831X_FLL_OUTDIV_WIDTH                      6  /* FLL_OUTDIV - [13:8] */
+#define WM831X_FLL_CTRL_RATE_MASK               0x0070  /* FLL_CTRL_RATE - [6:4] */
+#define WM831X_FLL_CTRL_RATE_SHIFT                   4  /* FLL_CTRL_RATE - [6:4] */
+#define WM831X_FLL_CTRL_RATE_WIDTH                   3  /* FLL_CTRL_RATE - [6:4] */
+#define WM831X_FLL_FRATIO_MASK                  0x0007  /* FLL_FRATIO - [2:0] */
+#define WM831X_FLL_FRATIO_SHIFT                      0  /* FLL_FRATIO - [2:0] */
+#define WM831X_FLL_FRATIO_WIDTH                      3  /* FLL_FRATIO - [2:0] */
+
+/*
+ * R16532 (0x4094) - FLL Control 3
+ */
+#define WM831X_FLL_K_MASK                       0xFFFF  /* FLL_K - [15:0] */
+#define WM831X_FLL_K_SHIFT                           0  /* FLL_K - [15:0] */
+#define WM831X_FLL_K_WIDTH                          16  /* FLL_K - [15:0] */
+
+/*
+ * R16533 (0x4095) - FLL Control 4
+ */
+#define WM831X_FLL_N_MASK                       0x7FE0  /* FLL_N - [14:5] */
+#define WM831X_FLL_N_SHIFT                           5  /* FLL_N - [14:5] */
+#define WM831X_FLL_N_WIDTH                          10  /* FLL_N - [14:5] */
+#define WM831X_FLL_GAIN_MASK                    0x000F  /* FLL_GAIN - [3:0] */
+#define WM831X_FLL_GAIN_SHIFT                        0  /* FLL_GAIN - [3:0] */
+#define WM831X_FLL_GAIN_WIDTH                        4  /* FLL_GAIN - [3:0] */
+
+/*
+ * R16534 (0x4096) - FLL Control 5
+ */
+#define WM831X_FLL_CLK_REF_DIV_MASK             0x0018  /* FLL_CLK_REF_DIV - [4:3] */
+#define WM831X_FLL_CLK_REF_DIV_SHIFT                 3  /* FLL_CLK_REF_DIV - [4:3] */
+#define WM831X_FLL_CLK_REF_DIV_WIDTH                 2  /* FLL_CLK_REF_DIV - [4:3] */
+#define WM831X_FLL_CLK_SRC_MASK                 0x0003  /* FLL_CLK_SRC - [1:0] */
+#define WM831X_FLL_CLK_SRC_SHIFT                     0  /* FLL_CLK_SRC - [1:0] */
+#define WM831X_FLL_CLK_SRC_WIDTH                     2  /* FLL_CLK_SRC - [1:0] */
+
 struct regulator_dev;
 
 #define WM831X_NUM_IRQ_REGS 5
+#define WM831X_NUM_GPIO_REGS 16
 
 enum wm831x_parent {
        WM8310 = 0x8310,
@@ -248,6 +351,12 @@ enum wm831x_parent {
        WM8326 = 0x8326,
 };
 
+struct wm831x;
+enum wm831x_auxadc;
+
+typedef int (*wm831x_auxadc_read_fn)(struct wm831x *wm831x,
+                                    enum wm831x_auxadc input);
+
 struct wm831x {
        struct mutex io_lock;
 
@@ -261,7 +370,7 @@ struct wm831x {
 
        int irq;  /* Our chip IRQ */
        struct mutex irq_lock;
-       unsigned int irq_base;
+       int irq_base;
        int irq_masks_cur[WM831X_NUM_IRQ_REGS];   /* Currently active value */
        int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */
 
@@ -272,8 +381,13 @@ struct wm831x {
 
        int num_gpio;
 
+       /* Used by the interrupt controller code to post writes */
+       int gpio_update[WM831X_NUM_GPIO_REGS];
+
        struct mutex auxadc_lock;
-       struct completion auxadc_done;
+       struct list_head auxadc_pending;
+       u16 auxadc_active;
+       wm831x_auxadc_read_fn auxadc_read;
 
        /* The WM831x has a security key blocking access to certain
         * registers.  The mutex is taken by the accessors for locking
@@ -300,5 +414,6 @@ void wm831x_device_exit(struct wm831x *wm831x);
 int wm831x_device_suspend(struct wm831x *wm831x);
 int wm831x_irq_init(struct wm831x *wm831x, int irq);
 void wm831x_irq_exit(struct wm831x *wm831x);
+void wm831x_auxadc_init(struct wm831x *wm831x);
 
 #endif
index ff42d70..0ba2459 100644 (file)
@@ -120,6 +120,9 @@ struct wm831x_pdata {
        /** Put the /IRQ line into CMOS mode */
        bool irq_cmos;
 
+       /** Disable the touchscreen */
+       bool disable_touch;
+
        int irq_base;
        int gpio_base;
        int gpio_defaults[WM831X_GPIO_NUM];
index 82fdfc7..b5479df 100644 (file)
@@ -131,6 +131,7 @@ struct nfs_server {
        struct fscache_cookie   *fscache;       /* superblock cookie */
 #endif
 
+       u32                     pnfs_blksize;   /* layout_blksize attr */
 #ifdef CONFIG_NFS_V4
        u32                     attr_bitmask[3];/* V4 bitmask representing the set
                                                   of attributes supported on this
@@ -145,7 +146,6 @@ struct nfs_server {
                                                   filesystem */
        struct pnfs_layoutdriver_type  *pnfs_curr_ld; /* Active layout driver */
        struct rpc_wait_queue   roc_rpcwaitq;
-       u32                     pnfs_blksize;   /* layout_blksize attr */
        void                    *pnfs_ld_data;  /* per mount point data */
 
        /* the following fields are protected by nfs_client->cl_lock */
index aec8025..52280a2 100644 (file)
@@ -57,6 +57,8 @@ extern int of_mm_gpiochip_add(struct device_node *np,
 extern void of_gpiochip_add(struct gpio_chip *gc);
 extern void of_gpiochip_remove(struct gpio_chip *gc);
 extern struct gpio_chip *of_node_to_gpiochip(struct device_node *np);
+extern int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
+                               const void *gpio_spec, u32 *flags);
 
 #else /* CONFIG_OF_GPIO */
 
@@ -72,6 +74,13 @@ static inline unsigned int of_gpio_count(struct device_node *np)
        return 0;
 }
 
+static inline int of_gpio_simple_xlate(struct gpio_chip *gc,
+                                      struct device_node *np,
+                                      const void *gpio_spec, u32 *flags)
+{
+       return -ENOSYS;
+}
+
 static inline void of_gpiochip_add(struct gpio_chip *gc) { }
 static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
 
index a2afc9f..8bffe9a 100644 (file)
@@ -8,6 +8,8 @@
  * Generic header for SuperH SCI(F) (used by sh/sh64/h8300 and related parts)
  */
 
+#define SCIx_NOT_SUPPORTED     (-1)
+
 enum {
        SCBRR_ALGO_1,           /* ((clk + 16 * bps) / (16 * bps) - 1) */
        SCBRR_ALGO_2,           /* ((clk + 16 * bps) / (32 * bps) - 1) */
@@ -25,6 +27,28 @@ enum {
 #define SCSCR_CKE1     (1 << 1)
 #define SCSCR_CKE0     (1 << 0)
 
+/* SCxSR SCI */
+#define SCI_TDRE  0x80
+#define SCI_RDRF  0x40
+#define SCI_ORER  0x20
+#define SCI_FER   0x10
+#define SCI_PER   0x08
+#define SCI_TEND  0x04
+
+#define SCI_DEFAULT_ERROR_MASK (SCI_PER | SCI_FER)
+
+/* SCxSR SCIF */
+#define SCIF_ER    0x0080
+#define SCIF_TEND  0x0040
+#define SCIF_TDFE  0x0020
+#define SCIF_BRK   0x0010
+#define SCIF_FER   0x0008
+#define SCIF_PER   0x0004
+#define SCIF_RDF   0x0002
+#define SCIF_DR    0x0001
+
+#define SCIF_DEFAULT_ERROR_MASK (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
+
 /* Offsets into the sci_port->irqs array */
 enum {
        SCIx_ERI_IRQ,
@@ -32,6 +56,24 @@ enum {
        SCIx_TXI_IRQ,
        SCIx_BRI_IRQ,
        SCIx_NR_IRQS,
+
+       SCIx_MUX_IRQ = SCIx_NR_IRQS,    /* special case */
+};
+
+enum {
+       SCIx_PROBE_REGTYPE,
+
+       SCIx_SCI_REGTYPE,
+       SCIx_IRDA_REGTYPE,
+       SCIx_SCIFA_REGTYPE,
+       SCIx_SCIFB_REGTYPE,
+       SCIx_SH3_SCIF_REGTYPE,
+       SCIx_SH4_SCIF_REGTYPE,
+       SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
+       SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+       SCIx_SH7705_SCIF_REGTYPE,
+
+       SCIx_NR_REGTYPES,
 };
 
 #define SCIx_IRQ_MUXED(irq)            \
@@ -42,8 +84,29 @@ enum {
        [SCIx_BRI_IRQ]  = (irq),        \
 }
 
+#define SCIx_IRQ_IS_MUXED(port)                        \
+       ((port)->cfg->irqs[SCIx_ERI_IRQ] ==     \
+        (port)->cfg->irqs[SCIx_RXI_IRQ]) ||    \
+       ((port)->cfg->irqs[SCIx_ERI_IRQ] &&     \
+        !(port)->cfg->irqs[SCIx_RXI_IRQ])
+/*
+ * SCI register subset common for all port types.
+ * Not all registers will exist on all parts.
+ */
+enum {
+       SCSMR, SCBRR, SCSCR, SCxSR,
+       SCFCR, SCFDR, SCxTDR, SCxRDR,
+       SCLSR, SCTFDR, SCRFDR, SCSPTR,
+
+       SCIx_NR_REGS,
+};
+
 struct device;
 
+struct plat_sci_port_ops {
+       void (*init_pins)(struct uart_port *, unsigned int cflag);
+};
+
 /*
  * Platform device specific platform_data struct
  */
@@ -56,6 +119,18 @@ struct plat_sci_port {
        unsigned int    scbrr_algo_id;          /* SCBRR calculation algo */
        unsigned int    scscr;                  /* SCSCR initialization */
 
+       /*
+        * Platform overrides if necessary, defaults otherwise.
+        */
+       int             overrun_bit;
+       unsigned int    error_mask;
+
+       int             port_reg;
+       unsigned char   regshift;
+       unsigned char   regtype;
+
+       struct plat_sci_port_ops        *ops;
+
        struct device   *dma_dev;
 
        unsigned int    dma_slave_tx;
index 9a52f72..3ccf186 100644 (file)
@@ -147,4 +147,8 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr,
 int sh_clk_div6_register(struct clk *clks, int nr);
 int sh_clk_div6_reparent_register(struct clk *clks, int nr);
 
+#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
+#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
+#define CLKDEV_ICK_ID(_cid, _did, _clk) { .con_id = _cid, .dev_id = _did, .clk = _clk }
+
 #endif /* __SH_CLOCK_H */
index b08cd4e..cb2dd11 100644 (file)
@@ -62,6 +62,12 @@ struct sh_dmae_pdata {
        const unsigned int *ts_shift;
        int ts_shift_num;
        u16 dmaor_init;
+       unsigned int chcr_offset;
+       u32 chcr_ie_bit;
+
+       unsigned int dmaor_is_32bit:1;
+       unsigned int needs_tend_set:1;
+       unsigned int no_dmars:1;
 };
 
 /* DMA register */
@@ -71,6 +77,8 @@ struct sh_dmae_pdata {
 #define CHCR   0x0C
 #define DMAOR  0x40
 
+#define TEND   0x18 /* USB-DMAC */
+
 /* DMAOR definitions */
 #define DMAOR_AE       0x00000004
 #define DMAOR_NMIF     0x00000002
index 892b97f..3b55ef2 100644 (file)
@@ -21,8 +21,6 @@
 #include <linux/list.h>
 #include <linux/kobject.h>
 #include <linux/device.h>
-#include <linux/platform_device.h>
-#include <asm/atomic.h>
 
 #define DISPC_IRQ_FRAMEDONE            (1 << 0)
 #define DISPC_IRQ_VSYNC                        (1 << 1)
@@ -136,12 +134,6 @@ enum omap_display_caps {
        OMAP_DSS_DISPLAY_CAP_TEAR_ELIM          = 1 << 1,
 };
 
-enum omap_dss_update_mode {
-       OMAP_DSS_UPDATE_DISABLED = 0,
-       OMAP_DSS_UPDATE_AUTO,
-       OMAP_DSS_UPDATE_MANUAL,
-};
-
 enum omap_dss_display_state {
        OMAP_DSS_DISPLAY_DISABLED = 0,
        OMAP_DSS_DISPLAY_ACTIVE,
@@ -246,7 +238,7 @@ int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel);
 
 /* Board specific data */
 struct omap_dss_board_info {
-       int (*get_last_off_on_transaction_id)(struct device *dev);
+       int (*get_context_loss_count)(struct device *dev);
        int num_devices;
        struct omap_dss_device **devices;
        struct omap_dss_device *default_device;
@@ -266,8 +258,6 @@ static inline int omap_display_init(struct omap_dss_board_info *board_data)
 struct omap_display_platform_data {
        struct omap_dss_board_info *board_data;
        /* TODO: Additional members to be added when PM is considered */
-
-       bool (*opt_clock_available)(const char *clk_role);
 };
 
 struct omap_video_timings {
@@ -300,6 +290,12 @@ extern const struct omap_video_timings omap_dss_pal_timings;
 extern const struct omap_video_timings omap_dss_ntsc_timings;
 #endif
 
+struct omap_dss_cpr_coefs {
+       s16 rr, rg, rb;
+       s16 gr, gg, gb;
+       s16 br, bg, bb;
+};
+
 struct omap_overlay_info {
        bool enabled;
 
@@ -359,6 +355,9 @@ struct omap_overlay_manager_info {
        bool trans_enabled;
 
        bool alpha_enabled;
+
+       bool cpr_enable;
+       struct omap_dss_cpr_coefs cpr_coefs;
 };
 
 struct omap_overlay_manager {
@@ -526,11 +525,6 @@ struct omap_dss_driver {
        int (*resume)(struct omap_dss_device *display);
        int (*run_test)(struct omap_dss_device *display, int test);
 
-       int (*set_update_mode)(struct omap_dss_device *dssdev,
-                       enum omap_dss_update_mode);
-       enum omap_dss_update_mode (*get_update_mode)(
-                       struct omap_dss_device *dssdev);
-
        int (*update)(struct omap_dss_device *dssdev,
                               u16 x, u16 y, u16 w, u16 h);
        int (*sync)(struct omap_dss_device *dssdev);
index 3ff4017..3b3cedc 100644 (file)
@@ -553,6 +553,27 @@ int allocate_resource(struct resource *root, struct resource *new,
 
 EXPORT_SYMBOL(allocate_resource);
 
+/**
+ * lookup_resource - find an existing resource by a resource start address
+ * @root: root resource descriptor
+ * @start: resource start address
+ *
+ * Returns a pointer to the resource if found, NULL otherwise
+ */
+struct resource *lookup_resource(struct resource *root, resource_size_t start)
+{
+       struct resource *res;
+
+       read_lock(&resource_lock);
+       for (res = root->child; res; res = res->sibling) {
+               if (res->start == start)
+                       break;
+       }
+       read_unlock(&resource_lock);
+
+       return res;
+}
+
 /*
  * Insert a resource into the resource tree. If successful, return NULL,
  * otherwise return the conflicting resource (compare to __request_resource())