summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2012-10-05 07:17:25 +0400
committerOlof Johansson <olof@lixom.net>2012-10-05 07:17:25 +0400
commit54d69df5849ec2e660aa12ac75562618c10fb499 (patch)
treeadbfb8bcc7cc73b83bf2b784fa331911ba03573a /drivers
parentad932bb6b549722a561fb31ac2fa50dcbcb3e36b (diff)
parent46f2007c1efadfa4071c17e75f140c47f09293de (diff)
downloadlinux-54d69df5849ec2e660aa12ac75562618c10fb499.tar.xz
Merge branch 'late/kirkwood' into late/soc
Merge in the late Kirkwood branch with the OMAP late branch for upstream submission. Final contents described in shared tag. Fixup remove/change conflicts in arch/arm/mach-omap2/devices.c and drivers/spi/spi-omap2-mcspi.c. Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/ata/pata_ep93xx.c2
-rw-r--r--drivers/ata/pata_pxa.c2
-rw-r--r--drivers/ata/pata_samsung_cf.c2
-rw-r--r--drivers/clk/Kconfig13
-rw-r--r--drivers/clk/Makefile10
-rw-r--r--drivers/clk/clk-bcm2835.c59
-rw-r--r--drivers/clk/clk-ls1x.c111
-rw-r--r--drivers/clk/clk-max77686.c244
-rw-r--r--drivers/clk/clk-prima2.c1171
-rw-r--r--drivers/clk/clk.c57
-rw-r--r--drivers/clk/mmp/Makefile9
-rw-r--r--drivers/clk/mmp/clk-apbc.c152
-rw-r--r--drivers/clk/mmp/clk-apmu.c97
-rw-r--r--drivers/clk/mmp/clk-frac.c153
-rw-r--r--drivers/clk/mmp/clk-mmp2.c449
-rw-r--r--drivers/clk/mmp/clk-pxa168.c346
-rw-r--r--drivers/clk/mmp/clk-pxa910.c320
-rw-r--r--drivers/clk/mmp/clk.h35
-rw-r--r--drivers/clk/mxs/clk-imx23.c55
-rw-r--r--drivers/clk/mxs/clk-imx28.c113
-rw-r--r--drivers/clk/ux500/Makefile12
-rw-r--r--drivers/clk/ux500/clk-prcc.c164
-rw-r--r--drivers/clk/ux500/clk-prcmu.c252
-rw-r--r--drivers/clk/ux500/clk.h48
-rw-r--r--drivers/clk/ux500/u8500_clk.c477
-rw-r--r--drivers/clk/ux500/u8540_clk.c21
-rw-r--r--drivers/clk/ux500/u9540_clk.c21
-rw-r--r--drivers/clk/versatile/Makefile1
-rw-r--r--drivers/clk/versatile/clk-realview.c114
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/bcm2835_timer.c161
-rw-r--r--drivers/crypto/mv_cesa.c17
-rw-r--r--drivers/crypto/ux500/cryp/cryp_core.c2
-rw-r--r--drivers/crypto/ux500/hash/hash_core.c2
-rw-r--r--drivers/dma/at_hdmac_regs.h2
-rw-r--r--drivers/dma/ep93xx_dma.c2
-rw-r--r--drivers/dma/imx-dma.c2
-rw-r--r--drivers/dma/imx-sdma.c4
-rw-r--r--drivers/dma/mmp_tdma.c2
-rw-r--r--drivers/dma/mv_xor.c2
-rw-r--r--drivers/gpio/Kconfig6
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-mvebu.c679
-rw-r--r--drivers/gpio/gpio-pxa.c77
-rw-r--r--drivers/gpio/gpio-samsung.c103
-rw-r--r--drivers/gpio/gpio-tegra.c3
-rw-r--r--drivers/gpio/gpio-twl4030.c77
-rw-r--r--drivers/hwmon/gpio-fan.c120
-rw-r--r--drivers/hwmon/s3c-hwmon.c2
-rw-r--r--drivers/i2c/busses/Kconfig2
-rw-r--r--drivers/i2c/busses/i2c-davinci.c2
-rw-r--r--drivers/i2c/busses/i2c-imx.c2
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c121
-rw-r--r--drivers/i2c/busses/i2c-nuc900.c2
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c2
-rw-r--r--drivers/input/keyboard/davinci_keyscan.c2
-rw-r--r--drivers/input/keyboard/ep93xx_keypad.c2
-rw-r--r--drivers/input/keyboard/nomadik-ske-keypad.c2
-rw-r--r--drivers/input/keyboard/omap-keypad.c2
-rw-r--r--drivers/input/keyboard/pxa27x_keypad.c2
-rw-r--r--drivers/input/keyboard/pxa930_rotary.c2
-rw-r--r--drivers/input/keyboard/spear-keyboard.c2
-rw-r--r--drivers/input/keyboard/w90p910_keypad.c2
-rw-r--r--drivers/input/mouse/pxa930_trkball.c2
-rw-r--r--drivers/input/mouse/rpcmouse.c2
-rw-r--r--drivers/input/serio/ams_delta_serio.c2
-rw-r--r--drivers/input/touchscreen/s3c2410_ts.c2
-rw-r--r--drivers/irqchip/Kconfig0
-rw-r--r--drivers/irqchip/Makefile1
-rw-r--r--drivers/irqchip/irq-bcm2835.c223
-rw-r--r--drivers/leds/leds-netxbig.c2
-rw-r--r--drivers/leds/leds-ns2.c2
-rw-r--r--drivers/leds/leds-s3c24xx.c2
-rw-r--r--drivers/media/video/davinci/vpbe_venc.c2
-rw-r--r--drivers/media/video/mx1_camera.c2
-rw-r--r--drivers/media/video/mx2_camera.c2
-rw-r--r--drivers/media/video/mx3_camera.c4
-rw-r--r--drivers/media/video/pxa_camera.c2
-rw-r--r--drivers/media/video/s5p-fimc/mipi-csis.c2
-rw-r--r--drivers/mfd/db8500-prcmu.c42
-rw-r--r--drivers/mfd/dbx500-prcmu-regs.h4
-rw-r--r--drivers/mfd/mcp-sa11x0.c2
-rw-r--r--drivers/mfd/tps6586x.c13
-rw-r--r--drivers/mmc/host/davinci_mmc.c2
-rw-r--r--drivers/mmc/host/msm_sdcc.c2
-rw-r--r--drivers/mmc/host/mvsdio.c2
-rw-r--r--drivers/mmc/host/mxcmmc.c4
-rw-r--r--drivers/mmc/host/omap.c1
-rw-r--r--drivers/mmc/host/pxamci.c2
-rw-r--r--drivers/mmc/host/s3cmci.c2
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c2
-rw-r--r--drivers/mmc/host/sdhci-tegra.c2
-rw-r--r--drivers/mtd/nand/ams-delta.c2
-rw-r--r--drivers/mtd/nand/bcm_umi_nand.c12
-rw-r--r--drivers/mtd/nand/davinci_nand.c4
-rw-r--r--drivers/mtd/nand/mxc_nand.c2
-rw-r--r--drivers/mtd/nand/nand_bcm_umi.h73
-rw-r--r--drivers/mtd/nand/nomadik_nand.c2
-rw-r--r--drivers/mtd/nand/omap2.c2
-rw-r--r--drivers/mtd/nand/orion_nand.c2
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c89
-rw-r--r--drivers/mtd/nand/s3c2410.c2
-rw-r--r--drivers/mtd/onenand/omap2.c2
-rw-r--r--drivers/net/ethernet/netx-eth.c2
-rw-r--r--drivers/net/ethernet/seeq/ether3.c4
-rw-r--r--drivers/net/irda/pxaficp_ir.c30
-rw-r--r--drivers/pcmcia/omap_cf.c2
-rw-r--r--drivers/pcmcia/pxa2xx_viper.c2
-rw-r--r--drivers/pinctrl/Kconfig22
-rw-r--r--drivers/pinctrl/Makefile5
-rw-r--r--drivers/pinctrl/pinctrl-armada-370.c421
-rw-r--r--drivers/pinctrl/pinctrl-armada-xp.c468
-rw-r--r--drivers/pinctrl/pinctrl-coh901.c220
-rw-r--r--drivers/pinctrl/pinctrl-dove.c620
-rw-r--r--drivers/pinctrl/pinctrl-kirkwood.c472
-rw-r--r--drivers/pinctrl/pinctrl-mvebu.c754
-rw-r--r--drivers/pinctrl/pinctrl-mvebu.h192
-rw-r--r--drivers/pinctrl/pinctrl-sirf.c58
-rw-r--r--drivers/regulator/tps6586x-regulator.c20
-rw-r--r--drivers/remoteproc/omap_remoteproc.c2
-rw-r--r--drivers/rtc/rtc-pxa.c11
-rw-r--r--drivers/scsi/arm/eesox.c2
-rw-r--r--drivers/sh/pfc/gpio.c1
-rw-r--r--drivers/spi/Kconfig2
-rw-r--r--drivers/spi/spi-davinci.c2
-rw-r--r--drivers/spi/spi-ep93xx.c4
-rw-r--r--drivers/spi/spi-imx.c2
-rw-r--r--drivers/spi/spi-nuc900.c2
-rw-r--r--drivers/spi/spi-omap-uwire.c2
-rw-r--r--drivers/spi/spi-omap2-mcspi.c2
-rw-r--r--drivers/spi/spi-s3c64xx.c2
-rw-r--r--drivers/spi/spi-tegra.c55
-rw-r--r--drivers/staging/ste_rmi4/board-mop500-u8500uib-rmi4.c1
-rw-r--r--drivers/staging/tidspbridge/core/dsp-clock.c2
-rw-r--r--drivers/staging/tidspbridge/core/tiomap3430.c2
-rw-r--r--drivers/staging/tidspbridge/core/tiomap3430_pwr.c2
-rw-r--r--drivers/staging/tidspbridge/core/tiomap_io.c2
-rw-r--r--drivers/staging/tidspbridge/rmgr/drv_interface.c2
-rw-r--r--drivers/tty/serial/imx.c2
-rw-r--r--drivers/tty/serial/serial_ks8695.c4
-rw-r--r--drivers/usb/Kconfig1
-rw-r--r--drivers/usb/gadget/imx_udc.c2
-rw-r--r--drivers/usb/gadget/pxa27x_udc.c2
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c2
-rw-r--r--drivers/usb/host/Kconfig2
-rw-r--r--drivers/usb/host/ehci-mxc.c2
-rw-r--r--drivers/usb/host/ehci-orion.c2
-rw-r--r--drivers/usb/host/ehci-s5p.c2
-rw-r--r--drivers/usb/host/imx21-hcd.h2
-rw-r--r--drivers/usb/host/ohci-da8xx.c2
-rw-r--r--drivers/usb/host/ohci-exynos.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c2
-rw-r--r--drivers/usb/host/ohci-nxp.c84
-rw-r--r--drivers/usb/host/ohci-omap.c2
-rw-r--r--drivers/usb/host/ohci-pxa27x.c4
-rw-r--r--drivers/usb/host/ohci-s3c2410.c2
-rw-r--r--drivers/usb/musb/da8xx.c2
-rw-r--r--drivers/usb/musb/tusb6010_omap.c1
-rw-r--r--drivers/usb/musb/ux500_dma.c2
-rw-r--r--drivers/usb/otg/isp1301_omap.c2
-rw-r--r--drivers/video/backlight/omap1_bl.c2
-rw-r--r--drivers/video/da8xx-fb.c8
-rw-r--r--drivers/video/ep93xx-fb.c2
-rw-r--r--drivers/video/imxfb.c2
-rw-r--r--drivers/video/msm/mddi.c2
-rw-r--r--drivers/video/msm/mddi_client_dummy.c2
-rw-r--r--drivers/video/msm/mddi_client_nt35399.c2
-rw-r--r--drivers/video/msm/mddi_client_toshiba.c2
-rw-r--r--drivers/video/msm/mdp.c2
-rw-r--r--drivers/video/msm/mdp_hw.h2
-rw-r--r--drivers/video/msm/mdp_ppp.c2
-rw-r--r--drivers/video/msm/msm_fb.c2
-rw-r--r--drivers/video/mx3fb.c4
-rw-r--r--drivers/video/nuc900fb.c2
-rw-r--r--drivers/video/nuc900fb.h2
-rw-r--r--drivers/video/omap/lcd_ams_delta.c3
-rw-r--r--drivers/video/omap/lcd_mipid.c2
-rw-r--r--drivers/video/omap/lcd_osk.c2
-rw-r--r--drivers/video/pxafb.c2
-rw-r--r--drivers/video/vt8500lcdfb.c2
-rw-r--r--drivers/video/wm8505fb.c2
-rw-r--r--drivers/watchdog/Kconfig6
-rw-r--r--drivers/watchdog/ks8695_wdt.c14
185 files changed, 9165 insertions, 876 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig
index ece958d3762e..36d3daa19a74 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -152,4 +152,6 @@ source "drivers/vme/Kconfig"
source "drivers/pwm/Kconfig"
+source "drivers/irqchip/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 5b421840c48d..8c30e73cd94c 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -5,6 +5,8 @@
# Rewritten to use lists instead of if-statements.
#
+obj-y += irqchip/
+
# GPIO must come after pinctrl as gpios may need to mux pins etc
obj-y += pinctrl/
obj-y += gpio/
diff --git a/drivers/ata/pata_ep93xx.c b/drivers/ata/pata_ep93xx.c
index 6ef2e3741f76..e056406d6a11 100644
--- a/drivers/ata/pata_ep93xx.c
+++ b/drivers/ata/pata_ep93xx.c
@@ -43,7 +43,7 @@
#include <linux/dmaengine.h>
#include <linux/ktime.h>
-#include <mach/dma.h>
+#include <linux/platform_data/dma-ep93xx.h>
#include <mach/platform.h>
#define DRV_NAME "ep93xx-ide"
diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c
index 0bb0fb7b26bc..4b8ba559fe24 100644
--- a/drivers/ata/pata_pxa.c
+++ b/drivers/ata/pata_pxa.c
@@ -32,7 +32,7 @@
#include <scsi/scsi_host.h>
#include <mach/pxa2xx-regs.h>
-#include <mach/pata_pxa.h>
+#include <linux/platform_data/ata-pxa.h>
#include <mach/dma.h>
#define DRV_NAME "pata_pxa"
diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c
index 1b372c297195..63ffb002ec67 100644
--- a/drivers/ata/pata_samsung_cf.c
+++ b/drivers/ata/pata_samsung_cf.c
@@ -23,7 +23,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <plat/ata.h>
+#include <linux/platform_data/ata-samsung_cf.h>
#include <plat/regs-ata.h>
#define DRV_NAME "pata_samsung_cf"
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 7f0b5ca78516..bace9e98f75d 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -40,4 +40,17 @@ config COMMON_CLK_WM831X
Supports the clocking subsystem of the WM831x/2x series of
PMICs from Wolfson Microlectronics.
+config COMMON_CLK_VERSATILE
+ bool "Clock driver for ARM Reference designs"
+ depends on ARCH_INTEGRATOR || ARCH_REALVIEW
+ ---help---
+ Supports clocking on ARM Reference designs Integrator/AP,
+ Integrator/CP, RealView PB1176, EB, PB11MP and PBX.
+
+config COMMON_CLK_MAX77686
+ tristate "Clock driver for Maxim 77686 MFD"
+ depends on MFD_MAX77686
+ ---help---
+ This driver supports Maxim 77686 crystal oscillator clock.
+
endmenu
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 5869ea387054..9184b5e19edf 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -3,13 +3,21 @@ obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o
obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \
clk-mux.o clk-divider.o clk-fixed-factor.o
# SoCs specific
+obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o
obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o
obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
obj-$(CONFIG_ARCH_MXS) += mxs/
obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/
obj-$(CONFIG_PLAT_SPEAR) += spear/
obj-$(CONFIG_ARCH_U300) += clk-u300.o
-obj-$(CONFIG_ARCH_INTEGRATOR) += versatile/
+obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/
+obj-$(CONFIG_ARCH_PRIMA2) += clk-prima2.o
+ifeq ($(CONFIG_COMMON_CLK), y)
+obj-$(CONFIG_ARCH_MMP) += mmp/
+endif
+obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
+obj-$(CONFIG_ARCH_U8500) += ux500/
# Chip specific
obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
+obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
diff --git a/drivers/clk/clk-bcm2835.c b/drivers/clk/clk-bcm2835.c
new file mode 100644
index 000000000000..67ad16b20b81
--- /dev/null
+++ b/drivers/clk/clk-bcm2835.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2010 Broadcom
+ * Copyright (C) 2012 Stephen Warren
+ *
+ * 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/bcm2835.h>
+
+/*
+ * These are fixed clocks. They're probably not all root clocks and it may
+ * be possible to turn them on and off but until this is mapped out better
+ * it's the only way they can be used.
+ */
+void __init bcm2835_init_clocks(void)
+{
+ struct clk *clk;
+ int ret;
+
+ clk = clk_register_fixed_rate(NULL, "sys_pclk", NULL, CLK_IS_ROOT,
+ 250000000);
+ if (!clk)
+ pr_err("sys_pclk not registered\n");
+
+ clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT,
+ 126000000);
+ if (!clk)
+ pr_err("apb_pclk not registered\n");
+
+ clk = clk_register_fixed_rate(NULL, "uart0_pclk", NULL, CLK_IS_ROOT,
+ 3000000);
+ if (!clk)
+ pr_err("uart0_pclk not registered\n");
+ ret = clk_register_clkdev(clk, NULL, "20201000.uart");
+ if (ret)
+ pr_err("uart0_pclk alias not registered\n");
+
+ clk = clk_register_fixed_rate(NULL, "uart1_pclk", NULL, CLK_IS_ROOT,
+ 125000000);
+ if (!clk)
+ pr_err("uart1_pclk not registered\n");
+ ret = clk_register_clkdev(clk, NULL, "20215000.uart");
+ if (ret)
+ pr_err("uart0_pclk alias not registered\n");
+}
diff --git a/drivers/clk/clk-ls1x.c b/drivers/clk/clk-ls1x.c
new file mode 100644
index 000000000000..f20b750235f6
--- /dev/null
+++ b/drivers/clk/clk-ls1x.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2012 Zhang, Keguang <keguang.zhang@gmail.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/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+#include <loongson1.h>
+
+#define OSC 33
+
+static DEFINE_SPINLOCK(_lock);
+
+static int ls1x_pll_clk_enable(struct clk_hw *hw)
+{
+ return 0;
+}
+
+static void ls1x_pll_clk_disable(struct clk_hw *hw)
+{
+}
+
+static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ u32 pll, rate;
+
+ pll = __raw_readl(LS1X_CLK_PLL_FREQ);
+ rate = ((12 + (pll & 0x3f)) * 1000000) +
+ ((((pll >> 8) & 0x3ff) * 1000000) >> 10);
+ rate *= OSC;
+ rate >>= 1;
+
+ return rate;
+}
+
+static const struct clk_ops ls1x_pll_clk_ops = {
+ .enable = ls1x_pll_clk_enable,
+ .disable = ls1x_pll_clk_disable,
+ .recalc_rate = ls1x_pll_recalc_rate,
+};
+
+static struct clk * __init clk_register_pll(struct device *dev,
+ const char *name, const char *parent_name, unsigned long flags)
+{
+ struct clk_hw *hw;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ /* allocate the divider */
+ hw = kzalloc(sizeof(struct clk_hw), GFP_KERNEL);
+ if (!hw) {
+ pr_err("%s: could not allocate clk_hw\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ init.name = name;
+ init.ops = &ls1x_pll_clk_ops;
+ init.flags = flags | CLK_IS_BASIC;
+ init.parent_names = (parent_name ? &parent_name : NULL);
+ init.num_parents = (parent_name ? 1 : 0);
+ hw->init = &init;
+
+ /* register the clock */
+ clk = clk_register(dev, hw);
+
+ if (IS_ERR(clk))
+ kfree(hw);
+
+ return clk;
+}
+
+void __init ls1x_clk_init(void)
+{
+ struct clk *clk;
+
+ clk = clk_register_pll(NULL, "pll_clk", NULL, CLK_IS_ROOT);
+ clk_prepare_enable(clk);
+
+ clk = clk_register_divider(NULL, "cpu_clk", "pll_clk",
+ CLK_SET_RATE_PARENT, LS1X_CLK_PLL_DIV, DIV_CPU_SHIFT,
+ DIV_CPU_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
+ clk_prepare_enable(clk);
+ clk_register_clkdev(clk, "cpu", NULL);
+
+ clk = clk_register_divider(NULL, "dc_clk", "pll_clk",
+ CLK_SET_RATE_PARENT, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
+ DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
+ clk_prepare_enable(clk);
+ clk_register_clkdev(clk, "dc", NULL);
+
+ clk = clk_register_divider(NULL, "ahb_clk", "pll_clk",
+ CLK_SET_RATE_PARENT, LS1X_CLK_PLL_DIV, DIV_DDR_SHIFT,
+ DIV_DDR_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
+ clk_prepare_enable(clk);
+ clk_register_clkdev(clk, "ahb", NULL);
+ clk_register_clkdev(clk, "stmmaceth", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1, 2);
+ clk_prepare_enable(clk);
+ clk_register_clkdev(clk, "apb", NULL);
+ clk_register_clkdev(clk, "serial8250", NULL);
+}
diff --git a/drivers/clk/clk-max77686.c b/drivers/clk/clk-max77686.c
new file mode 100644
index 000000000000..ac5f5434cb9a
--- /dev/null
+++ b/drivers/clk/clk-max77686.c
@@ -0,0 +1,244 @@
+/*
+ * clk-max77686.c - Clock driver for Maxim 77686
+ *
+ * Copyright (C) 2012 Samsung Electornics
+ * Jonghwa Lee <jonghwa3.lee@samsung.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.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/max77686.h>
+#include <linux/mfd/max77686-private.h>
+#include <linux/clk-provider.h>
+#include <linux/mutex.h>
+#include <linux/clkdev.h>
+
+enum {
+ MAX77686_CLK_AP = 0,
+ MAX77686_CLK_CP,
+ MAX77686_CLK_PMIC,
+ MAX77686_CLKS_NUM,
+};
+
+struct max77686_clk {
+ struct max77686_dev *iodev;
+ u32 mask;
+ struct clk_hw hw;
+ struct clk_lookup *lookup;
+};
+
+static struct max77686_clk *get_max77686_clk(struct clk_hw *hw)
+{
+ return container_of(hw, struct max77686_clk, hw);
+}
+
+static int max77686_clk_prepare(struct clk_hw *hw)
+{
+ struct max77686_clk *max77686;
+ int ret;
+
+ max77686 = get_max77686_clk(hw);
+ if (!max77686)
+ return -ENOMEM;
+
+ ret = regmap_update_bits(max77686->iodev->regmap,
+ MAX77686_REG_32KHZ, max77686->mask, max77686->mask);
+
+ return ret;
+}
+
+static void max77686_clk_unprepare(struct clk_hw *hw)
+{
+ struct max77686_clk *max77686;
+
+ max77686 = get_max77686_clk(hw);
+ if (!max77686)
+ return;
+
+ regmap_update_bits(max77686->iodev->regmap,
+ MAX77686_REG_32KHZ, max77686->mask, ~max77686->mask);
+}
+
+static int max77686_clk_is_enabled(struct clk_hw *hw)
+{
+ struct max77686_clk *max77686;
+ int ret;
+ u32 val;
+
+ max77686 = get_max77686_clk(hw);
+ if (!max77686)
+ return -ENOMEM;
+
+ ret = regmap_read(max77686->iodev->regmap,
+ MAX77686_REG_32KHZ, &val);
+
+ if (ret < 0)
+ return -EINVAL;
+
+ return val & max77686->mask;
+}
+
+static struct clk_ops max77686_clk_ops = {
+ .prepare = max77686_clk_prepare,
+ .unprepare = max77686_clk_unprepare,
+ .is_enabled = max77686_clk_is_enabled,
+};
+
+static struct clk_init_data max77686_clks_init[MAX77686_CLKS_NUM] = {
+ [MAX77686_CLK_AP] = {
+ .name = "32khz_ap",
+ .ops = &max77686_clk_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ [MAX77686_CLK_CP] = {
+ .name = "32khz_cp",
+ .ops = &max77686_clk_ops,
+ .flags = CLK_IS_ROOT,
+ },
+ [MAX77686_CLK_PMIC] = {
+ .name = "32khz_pmic",
+ .ops = &max77686_clk_ops,
+ .flags = CLK_IS_ROOT,
+ },
+};
+
+static int max77686_clk_register(struct device *dev,
+ struct max77686_clk *max77686)
+{
+ struct clk *clk;
+ struct clk_hw *hw = &max77686->hw;
+
+ clk = clk_register(dev, hw);
+
+ if (IS_ERR(clk))
+ return -ENOMEM;
+
+ max77686->lookup = devm_kzalloc(dev, sizeof(struct clk_lookup),
+ GFP_KERNEL);
+ if (IS_ERR(max77686->lookup))
+ return -ENOMEM;
+
+ max77686->lookup->con_id = hw->init->name;
+ max77686->lookup->clk = clk;
+
+ clkdev_add(max77686->lookup);
+
+ return 0;
+}
+
+static __devinit int max77686_clk_probe(struct platform_device *pdev)
+{
+ struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ struct max77686_clk **max77686_clks;
+ int i, ret;
+
+ max77686_clks = devm_kzalloc(&pdev->dev, sizeof(struct max77686_clk *)
+ * MAX77686_CLKS_NUM, GFP_KERNEL);
+ if (IS_ERR(max77686_clks))
+ return -ENOMEM;
+
+ for (i = 0; i < MAX77686_CLKS_NUM; i++) {
+ max77686_clks[i] = devm_kzalloc(&pdev->dev,
+ sizeof(struct max77686_clk), GFP_KERNEL);
+ if (IS_ERR(max77686_clks[i]))
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < MAX77686_CLKS_NUM; i++) {
+ max77686_clks[i]->iodev = iodev;
+ max77686_clks[i]->mask = 1 << i;
+ max77686_clks[i]->hw.init = &max77686_clks_init[i];
+
+ ret = max77686_clk_register(&pdev->dev, max77686_clks[i]);
+ if (ret) {
+ switch (i) {
+ case MAX77686_CLK_AP:
+ dev_err(&pdev->dev, "Fail to register CLK_AP\n");
+ goto err_clk_ap;
+ break;
+ case MAX77686_CLK_CP:
+ dev_err(&pdev->dev, "Fail to register CLK_CP\n");
+ goto err_clk_cp;
+ break;
+ case MAX77686_CLK_PMIC:
+ dev_err(&pdev->dev, "Fail to register CLK_PMIC\n");
+ goto err_clk_pmic;
+ }
+ }
+ }
+
+ platform_set_drvdata(pdev, max77686_clks);
+
+ goto out;
+
+err_clk_pmic:
+ clkdev_drop(max77686_clks[MAX77686_CLK_CP]->lookup);
+ kfree(max77686_clks[MAX77686_CLK_CP]->hw.clk);
+err_clk_cp:
+ clkdev_drop(max77686_clks[MAX77686_CLK_AP]->lookup);
+ kfree(max77686_clks[MAX77686_CLK_AP]->hw.clk);
+err_clk_ap:
+out:
+ return ret;
+}
+
+static int __devexit max77686_clk_remove(struct platform_device *pdev)
+{
+ struct max77686_clk **max77686_clks = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < MAX77686_CLKS_NUM; i++) {
+ clkdev_drop(max77686_clks[i]->lookup);
+ kfree(max77686_clks[i]->hw.clk);
+ }
+ return 0;
+}
+
+static const struct platform_device_id max77686_clk_id[] = {
+ { "max77686-clk", 0},
+ { },
+};
+MODULE_DEVICE_TABLE(platform, max77686_clk_id);
+
+static struct platform_driver max77686_clk_driver = {
+ .driver = {
+ .name = "max77686-clk",
+ .owner = THIS_MODULE,
+ },
+ .probe = max77686_clk_probe,
+ .remove = __devexit_p(max77686_clk_remove),
+ .id_table = max77686_clk_id,
+};
+
+static int __init max77686_clk_init(void)
+{
+ return platform_driver_register(&max77686_clk_driver);
+}
+subsys_initcall(max77686_clk_init);
+
+static void __init max77686_clk_cleanup(void)
+{
+ platform_driver_unregister(&max77686_clk_driver);
+}
+module_exit(max77686_clk_cleanup);
+
+MODULE_DESCRIPTION("MAXIM 77686 Clock Driver");
+MODULE_AUTHOR("Jonghwa Lee <jonghwa3.lee@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/clk-prima2.c b/drivers/clk/clk-prima2.c
new file mode 100644
index 000000000000..517874fa6858
--- /dev/null
+++ b/drivers/clk/clk-prima2.c
@@ -0,0 +1,1171 @@
+/*
+ * Clock tree for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+
+#define SIRFSOC_CLKC_CLK_EN0 0x0000
+#define SIRFSOC_CLKC_CLK_EN1 0x0004
+#define SIRFSOC_CLKC_REF_CFG 0x0014
+#define SIRFSOC_CLKC_CPU_CFG 0x0018
+#define SIRFSOC_CLKC_MEM_CFG 0x001c
+#define SIRFSOC_CLKC_SYS_CFG 0x0020
+#define SIRFSOC_CLKC_IO_CFG 0x0024
+#define SIRFSOC_CLKC_DSP_CFG 0x0028
+#define SIRFSOC_CLKC_GFX_CFG 0x002c
+#define SIRFSOC_CLKC_MM_CFG 0x0030
+#define SIRFSOC_CLKC_LCD_CFG 0x0034
+#define SIRFSOC_CLKC_MMC_CFG 0x0038
+#define SIRFSOC_CLKC_PLL1_CFG0 0x0040
+#define SIRFSOC_CLKC_PLL2_CFG0 0x0044
+#define SIRFSOC_CLKC_PLL3_CFG0 0x0048
+#define SIRFSOC_CLKC_PLL1_CFG1 0x004c
+#define SIRFSOC_CLKC_PLL2_CFG1 0x0050
+#define SIRFSOC_CLKC_PLL3_CFG1 0x0054
+#define SIRFSOC_CLKC_PLL1_CFG2 0x0058
+#define SIRFSOC_CLKC_PLL2_CFG2 0x005c
+#define SIRFSOC_CLKC_PLL3_CFG2 0x0060
+#define SIRFSOC_USBPHY_PLL_CTRL 0x0008
+#define SIRFSOC_USBPHY_PLL_POWERDOWN BIT(1)
+#define SIRFSOC_USBPHY_PLL_BYPASS BIT(2)
+#define SIRFSOC_USBPHY_PLL_LOCK BIT(3)
+
+static void *sirfsoc_clk_vbase, *sirfsoc_rsc_vbase;
+
+#define KHZ 1000
+#define MHZ (KHZ * KHZ)
+
+/*
+ * SiRFprimaII clock controller
+ * - 2 oscillators: osc-26MHz, rtc-32.768KHz
+ * - 3 standard configurable plls: pll1, pll2 & pll3
+ * - 2 exclusive plls: usb phy pll and sata phy pll
+ * - 8 clock domains: cpu/cpudiv, mem/memdiv, sys/io, dsp, graphic, multimedia,
+ * display and sdphy.
+ * Each clock domain can select its own clock source from five clock sources,
+ * X_XIN, X_XINW, PLL1, PLL2 and PLL3. The domain clock is used as the source
+ * clock of the group clock.
+ * - dsp domain: gps, mf
+ * - io domain: dmac, nand, audio, uart, i2c, spi, usp, pwm, pulse
+ * - sys domain: security
+ */
+
+struct clk_pll {
+ struct clk_hw hw;
+ unsigned short regofs; /* register offset */
+};
+
+#define to_pllclk(_hw) container_of(_hw, struct clk_pll, hw)
+
+struct clk_dmn {
+ struct clk_hw hw;
+ signed char enable_bit; /* enable bit: 0 ~ 63 */
+ unsigned short regofs; /* register offset */
+};
+
+#define to_dmnclk(_hw) container_of(_hw, struct clk_dmn, hw)
+
+struct clk_std {
+ struct clk_hw hw;
+ signed char enable_bit; /* enable bit: 0 ~ 63 */
+};
+
+#define to_stdclk(_hw) container_of(_hw, struct clk_std, hw)
+
+static int std_clk_is_enabled(struct clk_hw *hw);
+static int std_clk_enable(struct clk_hw *hw);
+static void std_clk_disable(struct clk_hw *hw);
+
+static inline unsigned long clkc_readl(unsigned reg)
+{
+ return readl(sirfsoc_clk_vbase + reg);
+}
+
+static inline void clkc_writel(u32 val, unsigned reg)
+{
+ writel(val, sirfsoc_clk_vbase + reg);
+}
+
+/*
+ * std pll
+ */
+
+static unsigned long pll_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned long fin = parent_rate;
+ struct clk_pll *clk = to_pllclk(hw);
+ u32 regcfg2 = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 -
+ SIRFSOC_CLKC_PLL1_CFG0;
+
+ if (clkc_readl(regcfg2) & BIT(2)) {
+ /* pll bypass mode */
+ return fin;
+ } else {
+ /* fout = fin * nf / nr / od */
+ u32 cfg0 = clkc_readl(clk->regofs);
+ u32 nf = (cfg0 & (BIT(13) - 1)) + 1;
+ u32 nr = ((cfg0 >> 13) & (BIT(6) - 1)) + 1;
+ u32 od = ((cfg0 >> 19) & (BIT(4) - 1)) + 1;
+ WARN_ON(fin % MHZ);
+ return fin / MHZ * nf / nr / od * MHZ;
+ }
+}
+
+static long pll_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ unsigned long fin, nf, nr, od;
+
+ /*
+ * fout = fin * nf / (nr * od);
+ * set od = 1, nr = fin/MHz, so fout = nf * MHz
+ */
+ rate = rate - rate % MHZ;
+
+ nf = rate / MHZ;
+ if (nf > BIT(13))
+ nf = BIT(13);
+ if (nf < 1)
+ nf = 1;
+
+ fin = *parent_rate;
+
+ nr = fin / MHZ;
+ if (nr > BIT(6))
+ nr = BIT(6);
+ od = 1;
+
+ return fin * nf / (nr * od);
+}
+
+static int pll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_pll *clk = to_pllclk(hw);
+ unsigned long fin, nf, nr, od, reg;
+
+ /*
+ * fout = fin * nf / (nr * od);
+ * set od = 1, nr = fin/MHz, so fout = nf * MHz
+ */
+
+ nf = rate / MHZ;
+ if (unlikely((rate % MHZ) || nf > BIT(13) || nf < 1))
+ return -EINVAL;
+
+ fin = parent_rate;
+ BUG_ON(fin < MHZ);
+
+ nr = fin / MHZ;
+ BUG_ON((fin % MHZ) || nr > BIT(6));
+
+ od = 1;
+
+ reg = (nf - 1) | ((nr - 1) << 13) | ((od - 1) << 19);
+ clkc_writel(reg, clk->regofs);
+
+ reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG1 - SIRFSOC_CLKC_PLL1_CFG0;
+ clkc_writel((nf >> 1) - 1, reg);
+
+ reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - SIRFSOC_CLKC_PLL1_CFG0;
+ while (!(clkc_readl(reg) & BIT(6)))
+ cpu_relax();
+
+ return 0;
+}
+
+static struct clk_ops std_pll_ops = {
+ .recalc_rate = pll_clk_recalc_rate,
+ .round_rate = pll_clk_round_rate,
+ .set_rate = pll_clk_set_rate,
+};
+
+static const char *pll_clk_parents[] = {
+ "osc",
+};
+
+static struct clk_init_data clk_pll1_init = {
+ .name = "pll1",
+ .ops = &std_pll_ops,
+ .parent_names = pll_clk_parents,
+ .num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_init_data clk_pll2_init = {
+ .name = "pll2",
+ .ops = &std_pll_ops,
+ .parent_names = pll_clk_parents,
+ .num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_init_data clk_pll3_init = {
+ .name = "pll3",
+ .ops = &std_pll_ops,
+ .parent_names = pll_clk_parents,
+ .num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_pll1 = {
+ .regofs = SIRFSOC_CLKC_PLL1_CFG0,
+ .hw = {
+ .init = &clk_pll1_init,
+ },
+};
+
+static struct clk_pll clk_pll2 = {
+ .regofs = SIRFSOC_CLKC_PLL2_CFG0,
+ .hw = {
+ .init = &clk_pll2_init,
+ },
+};
+
+static struct clk_pll clk_pll3 = {
+ .regofs = SIRFSOC_CLKC_PLL3_CFG0,
+ .hw = {
+ .init = &clk_pll3_init,
+ },
+};
+
+/*
+ * usb uses specified pll
+ */
+
+static int usb_pll_clk_enable(struct clk_hw *hw)
+{
+ u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL);
+ reg &= ~(SIRFSOC_USBPHY_PLL_POWERDOWN | SIRFSOC_USBPHY_PLL_BYPASS);
+ writel(reg, sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL);
+ while (!(readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL) &
+ SIRFSOC_USBPHY_PLL_LOCK))
+ cpu_relax();
+
+ return 0;
+}
+
+static void usb_pll_clk_disable(struct clk_hw *clk)
+{
+ u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL);
+ reg |= (SIRFSOC_USBPHY_PLL_POWERDOWN | SIRFSOC_USBPHY_PLL_BYPASS);
+ writel(reg, sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL);
+}
+
+static unsigned long usb_pll_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+ u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL);
+ return (reg & SIRFSOC_USBPHY_PLL_BYPASS) ? parent_rate : 48*MHZ;
+}
+
+static struct clk_ops usb_pll_ops = {
+ .enable = usb_pll_clk_enable,
+ .disable = usb_pll_clk_disable,
+ .recalc_rate = usb_pll_clk_recalc_rate,
+};
+
+static struct clk_init_data clk_usb_pll_init = {
+ .name = "usb_pll",
+ .ops = &usb_pll_ops,
+ .parent_names = pll_clk_parents,
+ .num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_hw usb_pll_clk_hw = {
+ .init = &clk_usb_pll_init,
+};
+
+/*
+ * clock domains - cpu, mem, sys/io, dsp, gfx
+ */
+
+static const char *dmn_clk_parents[] = {
+ "rtc",
+ "osc",
+ "pll1",
+ "pll2",
+ "pll3",
+};
+
+static u8 dmn_clk_get_parent(struct clk_hw *hw)
+{
+ struct clk_dmn *clk = to_dmnclk(hw);
+ u32 cfg = clkc_readl(clk->regofs);
+
+ /* parent of io domain can only be pll3 */
+ if (strcmp(hw->init->name, "io") == 0)
+ return 4;
+
+ WARN_ON((cfg & (BIT(3) - 1)) > 4);
+
+ return cfg & (BIT(3) - 1);
+}
+
+static int dmn_clk_set_parent(struct clk_hw *hw, u8 parent)
+{
+ struct clk_dmn *clk = to_dmnclk(hw);
+ u32 cfg = clkc_readl(clk->regofs);
+
+ /* parent of io domain can only be pll3 */
+ if (strcmp(hw->init->name, "io") == 0)
+ return -EINVAL;
+
+ cfg &= ~(BIT(3) - 1);
+ clkc_writel(cfg | parent, clk->regofs);
+ /* BIT(3) - switching status: 1 - busy, 0 - done */
+ while (clkc_readl(clk->regofs) & BIT(3))
+ cpu_relax();
+
+ return 0;
+}
+
+static unsigned long dmn_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+
+{
+ unsigned long fin = parent_rate;
+ struct clk_dmn *clk = to_dmnclk(hw);
+
+ u32 cfg = clkc_readl(clk->regofs);
+
+ if (cfg & BIT(24)) {
+ /* fcd bypass mode */
+ return fin;
+ } else {
+ /*
+ * wait count: bit[19:16], hold count: bit[23:20]
+ */
+ u32 wait = (cfg >> 16) & (BIT(4) - 1);
+ u32 hold = (cfg >> 20) & (BIT(4) - 1);
+
+ return fin / (wait + hold + 2);
+ }
+}
+
+static long dmn_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ unsigned long fin;
+ unsigned ratio, wait, hold;
+ unsigned bits = (strcmp(hw->init->name, "mem") == 0) ? 3 : 4;
+
+ fin = *parent_rate;
+ ratio = fin / rate;
+
+ if (ratio < 2)
+ ratio = 2;
+ if (ratio > BIT(bits + 1))
+ ratio = BIT(bits + 1);
+
+ wait = (ratio >> 1) - 1;
+ hold = ratio - wait - 2;
+
+ return fin / (wait + hold + 2);
+}
+
+static int dmn_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_dmn *clk = to_dmnclk(hw);
+ unsigned long fin;
+ unsigned ratio, wait, hold, reg;
+ unsigned bits = (strcmp(hw->init->name, "mem") == 0) ? 3 : 4;
+
+ fin = parent_rate;
+ ratio = fin / rate;
+
+ if (unlikely(ratio < 2 || ratio > BIT(bits + 1)))
+ return -EINVAL;
+
+ WARN_ON(fin % rate);
+
+ wait = (ratio >> 1) - 1;
+ hold = ratio - wait - 2;
+
+ reg = clkc_readl(clk->regofs);
+ reg &= ~(((BIT(bits) - 1) << 16) | ((BIT(bits) - 1) << 20));
+ reg |= (wait << 16) | (hold << 20) | BIT(25);
+ clkc_writel(reg, clk->regofs);
+
+ /* waiting FCD been effective */
+ while (clkc_readl(clk->regofs) & BIT(25))
+ cpu_relax();
+
+ return 0;
+}
+
+static struct clk_ops msi_ops = {
+ .set_rate = dmn_clk_set_rate,
+ .round_rate = dmn_clk_round_rate,
+ .recalc_rate = dmn_clk_recalc_rate,
+ .set_parent = dmn_clk_set_parent,
+ .get_parent = dmn_clk_get_parent,
+};
+
+static struct clk_init_data clk_mem_init = {
+ .name = "mem",
+ .ops = &msi_ops,
+ .parent_names = dmn_clk_parents,
+ .num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_mem = {
+ .regofs = SIRFSOC_CLKC_MEM_CFG,
+ .hw = {
+ .init = &clk_mem_init,
+ },
+};
+
+static struct clk_init_data clk_sys_init = {
+ .name = "sys",
+ .ops = &msi_ops,
+ .parent_names = dmn_clk_parents,
+ .num_parents = ARRAY_SIZE(dmn_clk_parents),
+ .flags = CLK_SET_RATE_GATE,
+};
+
+static struct clk_dmn clk_sys = {
+ .regofs = SIRFSOC_CLKC_SYS_CFG,
+ .hw = {
+ .init = &clk_sys_init,
+ },
+};
+
+static struct clk_init_data clk_io_init = {
+ .name = "io",
+ .ops = &msi_ops,
+ .parent_names = dmn_clk_parents,
+ .num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_io = {
+ .regofs = SIRFSOC_CLKC_IO_CFG,
+ .hw = {
+ .init = &clk_io_init,
+ },
+};
+
+static struct clk_ops cpu_ops = {
+ .set_parent = dmn_clk_set_parent,
+ .get_parent = dmn_clk_get_parent,
+};
+
+static struct clk_init_data clk_cpu_init = {
+ .name = "cpu",
+ .ops = &cpu_ops,
+ .parent_names = dmn_clk_parents,
+ .num_parents = ARRAY_SIZE(dmn_clk_parents),
+ .flags = CLK_SET_RATE_PARENT,
+};
+
+static struct clk_dmn clk_cpu = {
+ .regofs = SIRFSOC_CLKC_CPU_CFG,
+ .hw = {
+ .init = &clk_cpu_init,
+ },
+};
+
+static struct clk_ops dmn_ops = {
+ .is_enabled = std_clk_is_enabled,
+ .enable = std_clk_enable,
+ .disable = std_clk_disable,
+ .set_rate = dmn_clk_set_rate,
+ .round_rate = dmn_clk_round_rate,
+ .recalc_rate = dmn_clk_recalc_rate,
+ .set_parent = dmn_clk_set_parent,
+ .get_parent = dmn_clk_get_parent,
+};
+
+/* dsp, gfx, mm, lcd and vpp domain */
+
+static struct clk_init_data clk_dsp_init = {
+ .name = "dsp",
+ .ops = &dmn_ops,
+ .parent_names = dmn_clk_parents,
+ .num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_dsp = {
+ .regofs = SIRFSOC_CLKC_DSP_CFG,
+ .enable_bit = 0,
+ .hw = {
+ .init = &clk_dsp_init,
+ },
+};
+
+static struct clk_init_data clk_gfx_init = {
+ .name = "gfx",
+ .ops = &dmn_ops,
+ .parent_names = dmn_clk_parents,
+ .num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_gfx = {
+ .regofs = SIRFSOC_CLKC_GFX_CFG,
+ .enable_bit = 8,
+ .hw = {
+ .init = &clk_gfx_init,
+ },
+};
+
+static struct clk_init_data clk_mm_init = {
+ .name = "mm",
+ .ops = &dmn_ops,
+ .parent_names = dmn_clk_parents,
+ .num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_mm = {
+ .regofs = SIRFSOC_CLKC_MM_CFG,
+ .enable_bit = 9,
+ .hw = {
+ .init = &clk_mm_init,
+ },
+};
+
+static struct clk_init_data clk_lcd_init = {
+ .name = "lcd",
+ .ops = &dmn_ops,
+ .parent_names = dmn_clk_parents,
+ .num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_lcd = {
+ .regofs = SIRFSOC_CLKC_LCD_CFG,
+ .enable_bit = 10,
+ .hw = {
+ .init = &clk_lcd_init,
+ },
+};
+
+static struct clk_init_data clk_vpp_init = {
+ .name = "vpp",
+ .ops = &dmn_ops,
+ .parent_names = dmn_clk_parents,
+ .num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_vpp = {
+ .regofs = SIRFSOC_CLKC_LCD_CFG,
+ .enable_bit = 11,
+ .hw = {
+ .init = &clk_vpp_init,
+ },
+};
+
+static struct clk_init_data clk_mmc01_init = {
+ .name = "mmc01",
+ .ops = &dmn_ops,
+ .parent_names = dmn_clk_parents,
+ .num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_mmc01 = {
+ .regofs = SIRFSOC_CLKC_MMC_CFG,
+ .enable_bit = 59,
+ .hw = {
+ .init = &clk_mmc01_init,
+ },
+};
+
+static struct clk_init_data clk_mmc23_init = {
+ .name = "mmc23",
+ .ops = &dmn_ops,
+ .parent_names = dmn_clk_parents,
+ .num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_mmc23 = {
+ .regofs = SIRFSOC_CLKC_MMC_CFG,
+ .enable_bit = 60,
+ .hw = {
+ .init = &clk_mmc23_init,
+ },
+};
+
+static struct clk_init_data clk_mmc45_init = {
+ .name = "mmc45",
+ .ops = &dmn_ops,
+ .parent_names = dmn_clk_parents,
+ .num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_mmc45 = {
+ .regofs = SIRFSOC_CLKC_MMC_CFG,
+ .enable_bit = 61,
+ .hw = {
+ .init = &clk_mmc45_init,
+ },
+};
+
+/*
+ * peripheral controllers in io domain
+ */
+
+static int std_clk_is_enabled(struct clk_hw *hw)
+{
+ u32 reg;
+ int bit;
+ struct clk_std *clk = to_stdclk(hw);
+
+ bit = clk->enable_bit % 32;
+ reg = clk->enable_bit / 32;
+ reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg);
+
+ return !!(clkc_readl(reg) & BIT(bit));
+}
+
+static int std_clk_enable(struct clk_hw *hw)
+{
+ u32 val, reg;
+ int bit;
+ struct clk_std *clk = to_stdclk(hw);
+
+ BUG_ON(clk->enable_bit < 0 || clk->enable_bit > 63);
+
+ bit = clk->enable_bit % 32;
+ reg = clk->enable_bit / 32;
+ reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg);
+
+ val = clkc_readl(reg) | BIT(bit);
+ clkc_writel(val, reg);
+ return 0;
+}
+
+static void std_clk_disable(struct clk_hw *hw)
+{
+ u32 val, reg;
+ int bit;
+ struct clk_std *clk = to_stdclk(hw);
+
+ BUG_ON(clk->enable_bit < 0 || clk->enable_bit > 63);
+
+ bit = clk->enable_bit % 32;
+ reg = clk->enable_bit / 32;
+ reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg);
+
+ val = clkc_readl(reg) & ~BIT(bit);
+ clkc_writel(val, reg);
+}
+
+static const char *std_clk_io_parents[] = {
+ "io",
+};
+
+static struct clk_ops ios_ops = {
+ .is_enabled = std_clk_is_enabled,
+ .enable = std_clk_enable,
+ .disable = std_clk_disable,
+};
+
+static struct clk_init_data clk_dmac0_init = {
+ .name = "dmac0",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_dmac0 = {
+ .enable_bit = 32,
+ .hw = {
+ .init = &clk_dmac0_init,
+ },
+};
+
+static struct clk_init_data clk_dmac1_init = {
+ .name = "dmac1",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_dmac1 = {
+ .enable_bit = 33,
+ .hw = {
+ .init = &clk_dmac1_init,
+ },
+};
+
+static struct clk_init_data clk_nand_init = {
+ .name = "nand",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_nand = {
+ .enable_bit = 34,
+ .hw = {
+ .init = &clk_nand_init,
+ },
+};
+
+static struct clk_init_data clk_audio_init = {
+ .name = "audio",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_audio = {
+ .enable_bit = 35,
+ .hw = {
+ .init = &clk_audio_init,
+ },
+};
+
+static struct clk_init_data clk_uart0_init = {
+ .name = "uart0",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_uart0 = {
+ .enable_bit = 36,
+ .hw = {
+ .init = &clk_uart0_init,
+ },
+};
+
+static struct clk_init_data clk_uart1_init = {
+ .name = "uart1",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_uart1 = {
+ .enable_bit = 37,
+ .hw = {
+ .init = &clk_uart1_init,
+ },
+};
+
+static struct clk_init_data clk_uart2_init = {
+ .name = "uart2",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_uart2 = {
+ .enable_bit = 38,
+ .hw = {
+ .init = &clk_uart2_init,
+ },
+};
+
+static struct clk_init_data clk_usp0_init = {
+ .name = "usp0",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_usp0 = {
+ .enable_bit = 39,
+ .hw = {
+ .init = &clk_usp0_init,
+ },
+};
+
+static struct clk_init_data clk_usp1_init = {
+ .name = "usp1",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_usp1 = {
+ .enable_bit = 40,
+ .hw = {
+ .init = &clk_usp1_init,
+ },
+};
+
+static struct clk_init_data clk_usp2_init = {
+ .name = "usp2",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_usp2 = {
+ .enable_bit = 41,
+ .hw = {
+ .init = &clk_usp2_init,
+ },
+};
+
+static struct clk_init_data clk_vip_init = {
+ .name = "vip",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_vip = {
+ .enable_bit = 42,
+ .hw = {
+ .init = &clk_vip_init,
+ },
+};
+
+static struct clk_init_data clk_spi0_init = {
+ .name = "spi0",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_spi0 = {
+ .enable_bit = 43,
+ .hw = {
+ .init = &clk_spi0_init,
+ },
+};
+
+static struct clk_init_data clk_spi1_init = {
+ .name = "spi1",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_spi1 = {
+ .enable_bit = 44,
+ .hw = {
+ .init = &clk_spi1_init,
+ },
+};
+
+static struct clk_init_data clk_tsc_init = {
+ .name = "tsc",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_tsc = {
+ .enable_bit = 45,
+ .hw = {
+ .init = &clk_tsc_init,
+ },
+};
+
+static struct clk_init_data clk_i2c0_init = {
+ .name = "i2c0",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_i2c0 = {
+ .enable_bit = 46,
+ .hw = {
+ .init = &clk_i2c0_init,
+ },
+};
+
+static struct clk_init_data clk_i2c1_init = {
+ .name = "i2c1",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_i2c1 = {
+ .enable_bit = 47,
+ .hw = {
+ .init = &clk_i2c1_init,
+ },
+};
+
+static struct clk_init_data clk_pwmc_init = {
+ .name = "pwmc",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_pwmc = {
+ .enable_bit = 48,
+ .hw = {
+ .init = &clk_pwmc_init,
+ },
+};
+
+static struct clk_init_data clk_efuse_init = {
+ .name = "efuse",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_efuse = {
+ .enable_bit = 49,
+ .hw = {
+ .init = &clk_efuse_init,
+ },
+};
+
+static struct clk_init_data clk_pulse_init = {
+ .name = "pulse",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_pulse = {
+ .enable_bit = 50,
+ .hw = {
+ .init = &clk_pulse_init,
+ },
+};
+
+static const char *std_clk_dsp_parents[] = {
+ "dsp",
+};
+
+static struct clk_init_data clk_gps_init = {
+ .name = "gps",
+ .ops = &ios_ops,
+ .parent_names = std_clk_dsp_parents,
+ .num_parents = ARRAY_SIZE(std_clk_dsp_parents),
+};
+
+static struct clk_std clk_gps = {
+ .enable_bit = 1,
+ .hw = {
+ .init = &clk_gps_init,
+ },
+};
+
+static struct clk_init_data clk_mf_init = {
+ .name = "mf",
+ .ops = &ios_ops,
+ .parent_names = std_clk_io_parents,
+ .num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_mf = {
+ .enable_bit = 2,
+ .hw = {
+ .init = &clk_mf_init,
+ },
+};
+
+static const char *std_clk_sys_parents[] = {
+ "sys",
+};
+
+static struct clk_init_data clk_security_init = {
+ .name = "mf",
+ .ops = &ios_ops,
+ .parent_names = std_clk_sys_parents,
+ .num_parents = ARRAY_SIZE(std_clk_sys_parents),
+};
+
+static struct clk_std clk_security = {
+ .enable_bit = 19,
+ .hw = {
+ .init = &clk_security_init,
+ },
+};
+
+static const char *std_clk_usb_parents[] = {
+ "usb_pll",
+};
+
+static struct clk_init_data clk_usb0_init = {
+ .name = "usb0",
+ .ops = &ios_ops,
+ .parent_names = std_clk_usb_parents,
+ .num_parents = ARRAY_SIZE(std_clk_usb_parents),
+};
+
+static struct clk_std clk_usb0 = {
+ .enable_bit = 16,
+ .hw = {
+ .init = &clk_usb0_init,
+ },
+};
+
+static struct clk_init_data clk_usb1_init = {
+ .name = "usb1",
+ .ops = &ios_ops,
+ .parent_names = std_clk_usb_parents,
+ .num_parents = ARRAY_SIZE(std_clk_usb_parents),
+};
+
+static struct clk_std clk_usb1 = {
+ .enable_bit = 17,
+ .hw = {
+ .init = &clk_usb1_init,
+ },
+};
+
+static struct of_device_id clkc_ids[] = {
+ { .compatible = "sirf,prima2-clkc" },
+ {},
+};
+
+static struct of_device_id rsc_ids[] = {
+ { .compatible = "sirf,prima2-rsc" },
+ {},
+};
+
+void __init sirfsoc_of_clk_init(void)
+{
+ struct clk *clk;
+ struct device_node *np;
+
+ np = of_find_matching_node(NULL, clkc_ids);
+ if (!np)
+ panic("unable to find compatible clkc node in dtb\n");
+
+ sirfsoc_clk_vbase = of_iomap(np, 0);
+ if (!sirfsoc_clk_vbase)
+ panic("unable to map clkc registers\n");
+
+ of_node_put(np);
+
+ np = of_find_matching_node(NULL, rsc_ids);
+ if (!np)
+ panic("unable to find compatible rsc node in dtb\n");
+
+ sirfsoc_rsc_vbase = of_iomap(np, 0);
+ if (!sirfsoc_rsc_vbase)
+ panic("unable to map rsc registers\n");
+
+ of_node_put(np);
+
+
+ /* These are always available (RTC and 26MHz OSC)*/
+ clk = clk_register_fixed_rate(NULL, "rtc", NULL,
+ CLK_IS_ROOT, 32768);
+ BUG_ON(!clk);
+ clk = clk_register_fixed_rate(NULL, "osc", NULL,
+ CLK_IS_ROOT, 26000000);
+ BUG_ON(!clk);
+
+ clk = clk_register(NULL, &clk_pll1.hw);
+ BUG_ON(!clk);
+ clk = clk_register(NULL, &clk_pll2.hw);
+ BUG_ON(!clk);
+ clk = clk_register(NULL, &clk_pll3.hw);
+ BUG_ON(!clk);
+ clk = clk_register(NULL, &clk_mem.hw);
+ BUG_ON(!clk);
+ clk = clk_register(NULL, &clk_sys.hw);
+ BUG_ON(!clk);
+ clk = clk_register(NULL, &clk_security.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b8030000.security");
+ clk = clk_register(NULL, &clk_dsp.hw);
+ BUG_ON(!clk);
+ clk = clk_register(NULL, &clk_gps.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "a8010000.gps");
+ clk = clk_register(NULL, &clk_mf.hw);
+ BUG_ON(!clk);
+ clk = clk_register(NULL, &clk_io.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "io");
+ clk = clk_register(NULL, &clk_cpu.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "cpu");
+ clk = clk_register(NULL, &clk_uart0.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b0050000.uart");
+ clk = clk_register(NULL, &clk_uart1.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b0060000.uart");
+ clk = clk_register(NULL, &clk_uart2.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b0070000.uart");
+ clk = clk_register(NULL, &clk_tsc.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b0110000.tsc");
+ clk = clk_register(NULL, &clk_i2c0.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b00e0000.i2c");
+ clk = clk_register(NULL, &clk_i2c1.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b00f0000.i2c");
+ clk = clk_register(NULL, &clk_spi0.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b00d0000.spi");
+ clk = clk_register(NULL, &clk_spi1.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b0170000.spi");
+ clk = clk_register(NULL, &clk_pwmc.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b0130000.pwm");
+ clk = clk_register(NULL, &clk_efuse.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b0140000.efusesys");
+ clk = clk_register(NULL, &clk_pulse.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b0150000.pulsec");
+ clk = clk_register(NULL, &clk_dmac0.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b00b0000.dma-controller");
+ clk = clk_register(NULL, &clk_dmac1.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b0160000.dma-controller");
+ clk = clk_register(NULL, &clk_nand.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b0030000.nand");
+ clk = clk_register(NULL, &clk_audio.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b0040000.audio");
+ clk = clk_register(NULL, &clk_usp0.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b0080000.usp");
+ clk = clk_register(NULL, &clk_usp1.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b0090000.usp");
+ clk = clk_register(NULL, &clk_usp2.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b00a0000.usp");
+ clk = clk_register(NULL, &clk_vip.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b00c0000.vip");
+ clk = clk_register(NULL, &clk_gfx.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "98000000.graphics");
+ clk = clk_register(NULL, &clk_mm.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "a0000000.multimedia");
+ clk = clk_register(NULL, &clk_lcd.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "90010000.display");
+ clk = clk_register(NULL, &clk_vpp.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "90020000.vpp");
+ clk = clk_register(NULL, &clk_mmc01.hw);
+ BUG_ON(!clk);
+ clk = clk_register(NULL, &clk_mmc23.hw);
+ BUG_ON(!clk);
+ clk = clk_register(NULL, &clk_mmc45.hw);
+ BUG_ON(!clk);
+ clk = clk_register(NULL, &usb_pll_clk_hw);
+ BUG_ON(!clk);
+ clk = clk_register(NULL, &clk_usb0.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b00e0000.usb");
+ clk = clk_register(NULL, &clk_usb1.hw);
+ BUG_ON(!clk);
+ clk_register_clkdev(clk, NULL, "b00f0000.usb");
+}
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index efdfd009c270..56e4495ebeb1 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -558,25 +558,6 @@ int clk_enable(struct clk *clk)
EXPORT_SYMBOL_GPL(clk_enable);
/**
- * clk_get_rate - return the rate of clk
- * @clk: the clk whose rate is being returned
- *
- * Simply returns the cached rate of the clk. Does not query the hardware. If
- * clk is NULL then returns 0.
- */
-unsigned long clk_get_rate(struct clk *clk)
-{
- unsigned long rate;
-
- mutex_lock(&prepare_lock);
- rate = __clk_get_rate(clk);
- mutex_unlock(&prepare_lock);
-
- return rate;
-}
-EXPORT_SYMBOL_GPL(clk_get_rate);
-
-/**
* __clk_round_rate - round the given rate for a clk
* @clk: round the rate of this clock
*
@@ -702,6 +683,30 @@ static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
}
/**
+ * clk_get_rate - return the rate of clk
+ * @clk: the clk whose rate is being returned
+ *
+ * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag
+ * is set, which means a recalc_rate will be issued.
+ * If clk is NULL then returns 0.
+ */
+unsigned long clk_get_rate(struct clk *clk)
+{
+ unsigned long rate;
+
+ mutex_lock(&prepare_lock);
+
+ if (clk && (clk->flags & CLK_GET_RATE_NOCACHE))
+ __clk_recalc_rates(clk, 0);
+
+ rate = __clk_get_rate(clk);
+ mutex_unlock(&prepare_lock);
+
+ return rate;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+/**
* __clk_speculate_rates
* @clk: first clk in the subtree
* @parent_rate: the "future" rate of clk's parent
@@ -1582,6 +1587,20 @@ struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
}
EXPORT_SYMBOL_GPL(of_clk_src_simple_get);
+struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data)
+{
+ struct clk_onecell_data *clk_data = data;
+ unsigned int idx = clkspec->args[0];
+
+ if (idx >= clk_data->clk_num) {
+ pr_err("%s: invalid clock index %d\n", __func__, idx);
+ return ERR_PTR(-EINVAL);
+ }
+
+ return clk_data->clks[idx];
+}
+EXPORT_SYMBOL_GPL(of_clk_src_onecell_get);
+
/**
* of_clk_add_provider() - Register a clock provider for a node
* @np: Device node pointer associated with clock provider
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
new file mode 100644
index 000000000000..392d78044ce3
--- /dev/null
+++ b/drivers/clk/mmp/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for mmp specific clk
+#
+
+obj-y += clk-apbc.o clk-apmu.o clk-frac.o
+
+obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
+obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
+obj-$(CONFIG_CPU_MMP2) += clk-mmp2.o
diff --git a/drivers/clk/mmp/clk-apbc.c b/drivers/clk/mmp/clk-apbc.c
new file mode 100644
index 000000000000..d14120eaa71f
--- /dev/null
+++ b/drivers/clk/mmp/clk-apbc.c
@@ -0,0 +1,152 @@
+/*
+ * mmp APB clock operation source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie <xiechao.mail@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include "clk.h"
+
+/* Common APB clock register bit definitions */
+#define APBC_APBCLK (1 << 0) /* APB Bus Clock Enable */
+#define APBC_FNCLK (1 << 1) /* Functional Clock Enable */
+#define APBC_RST (1 << 2) /* Reset Generation */
+#define APBC_POWER (1 << 7) /* Reset Generation */
+
+#define to_clk_apbc(hw) container_of(hw, struct clk_apbc, hw)
+struct clk_apbc {
+ struct clk_hw hw;
+ void __iomem *base;
+ unsigned int delay;
+ unsigned int flags;
+ spinlock_t *lock;
+};
+
+static int clk_apbc_prepare(struct clk_hw *hw)
+{
+ struct clk_apbc *apbc = to_clk_apbc(hw);
+ unsigned int data;
+ unsigned long flags = 0;
+
+ /*
+ * It may share same register as MUX clock,
+ * and it will impact FNCLK enable. Spinlock is needed
+ */
+ if (apbc->lock)
+ spin_lock_irqsave(apbc->lock, flags);
+
+ data = readl_relaxed(apbc->base);
+ if (apbc->flags & APBC_POWER_CTRL)
+ data |= APBC_POWER;
+ data |= APBC_FNCLK;
+ writel_relaxed(data, apbc->base);
+
+ if (apbc->lock)
+ spin_unlock_irqrestore(apbc->lock, flags);
+
+ udelay(apbc->delay);
+
+ if (apbc->lock)
+ spin_lock_irqsave(apbc->lock, flags);
+
+ data = readl_relaxed(apbc->base);
+ data |= APBC_APBCLK;
+ writel_relaxed(data, apbc->base);
+
+ if (apbc->lock)
+ spin_unlock_irqrestore(apbc->lock, flags);
+
+ udelay(apbc->delay);
+
+ if (!(apbc->flags & APBC_NO_BUS_CTRL)) {
+ if (apbc->lock)
+ spin_lock_irqsave(apbc->lock, flags);
+
+ data = readl_relaxed(apbc->base);
+ data &= ~APBC_RST;
+ writel_relaxed(data, apbc->base);
+
+ if (apbc->lock)
+ spin_unlock_irqrestore(apbc->lock, flags);
+ }
+
+ return 0;
+}
+
+static void clk_apbc_unprepare(struct clk_hw *hw)
+{
+ struct clk_apbc *apbc = to_clk_apbc(hw);
+ unsigned long data;
+ unsigned long flags = 0;
+
+ if (apbc->lock)
+ spin_lock_irqsave(apbc->lock, flags);
+
+ data = readl_relaxed(apbc->base);
+ if (apbc->flags & APBC_POWER_CTRL)
+ data &= ~APBC_POWER;
+ data &= ~APBC_FNCLK;
+ writel_relaxed(data, apbc->base);
+
+ if (apbc->lock)
+ spin_unlock_irqrestore(apbc->lock, flags);
+
+ udelay(10);
+
+ if (apbc->lock)
+ spin_lock_irqsave(apbc->lock, flags);
+
+ data = readl_relaxed(apbc->base);
+ data &= ~APBC_APBCLK;
+ writel_relaxed(data, apbc->base);
+
+ if (apbc->lock)
+ spin_unlock_irqrestore(apbc->lock, flags);
+}
+
+struct clk_ops clk_apbc_ops = {
+ .prepare = clk_apbc_prepare,
+ .unprepare = clk_apbc_unprepare,
+};
+
+struct clk *mmp_clk_register_apbc(const char *name, const char *parent_name,
+ void __iomem *base, unsigned int delay,
+ unsigned int apbc_flags, spinlock_t *lock)
+{
+ struct clk_apbc *apbc;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ apbc = kzalloc(sizeof(*apbc), GFP_KERNEL);
+ if (!apbc)
+ return NULL;
+
+ init.name = name;
+ init.ops = &clk_apbc_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.parent_names = (parent_name ? &parent_name : NULL);
+ init.num_parents = (parent_name ? 1 : 0);
+
+ apbc->base = base;
+ apbc->delay = delay;
+ apbc->flags = apbc_flags;
+ apbc->lock = lock;
+ apbc->hw.init = &init;
+
+ clk = clk_register(NULL, &apbc->hw);
+ if (IS_ERR(clk))
+ kfree(apbc);
+
+ return clk;
+}
diff --git a/drivers/clk/mmp/clk-apmu.c b/drivers/clk/mmp/clk-apmu.c
new file mode 100644
index 000000000000..abe182b2377f
--- /dev/null
+++ b/drivers/clk/mmp/clk-apmu.c
@@ -0,0 +1,97 @@
+/*
+ * mmp AXI peripharal clock operation source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie <xiechao.mail@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include "clk.h"
+
+#define to_clk_apmu(clk) (container_of(clk, struct clk_apmu, clk))
+struct clk_apmu {
+ struct clk_hw hw;
+ void __iomem *base;
+ u32 rst_mask;
+ u32 enable_mask;
+ spinlock_t *lock;
+};
+
+static int clk_apmu_enable(struct clk_hw *hw)
+{
+ struct clk_apmu *apmu = to_clk_apmu(hw);
+ unsigned long data;
+ unsigned long flags = 0;
+
+ if (apmu->lock)
+ spin_lock_irqsave(apmu->lock, flags);
+
+ data = readl_relaxed(apmu->base) | apmu->enable_mask;
+ writel_relaxed(data, apmu->base);
+
+ if (apmu->lock)
+ spin_unlock_irqrestore(apmu->lock, flags);
+
+ return 0;
+}
+
+static void clk_apmu_disable(struct clk_hw *hw)
+{
+ struct clk_apmu *apmu = to_clk_apmu(hw);
+ unsigned long data;
+ unsigned long flags = 0;
+
+ if (apmu->lock)
+ spin_lock_irqsave(apmu->lock, flags);
+
+ data = readl_relaxed(apmu->base) & ~apmu->enable_mask;
+ writel_relaxed(data, apmu->base);
+
+ if (apmu->lock)
+ spin_unlock_irqrestore(apmu->lock, flags);
+}
+
+struct clk_ops clk_apmu_ops = {
+ .enable = clk_apmu_enable,
+ .disable = clk_apmu_disable,
+};
+
+struct clk *mmp_clk_register_apmu(const char *name, const char *parent_name,
+ void __iomem *base, u32 enable_mask, spinlock_t *lock)
+{
+ struct clk_apmu *apmu;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ apmu = kzalloc(sizeof(*apmu), GFP_KERNEL);
+ if (!apmu)
+ return NULL;
+
+ init.name = name;
+ init.ops = &clk_apmu_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.parent_names = (parent_name ? &parent_name : NULL);
+ init.num_parents = (parent_name ? 1 : 0);
+
+ apmu->base = base;
+ apmu->enable_mask = enable_mask;
+ apmu->lock = lock;
+ apmu->hw.init = &init;
+
+ clk = clk_register(NULL, &apmu->hw);
+
+ if (IS_ERR(clk))
+ kfree(apmu);
+
+ return clk;
+}
diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
new file mode 100644
index 000000000000..80c1dd15d15c
--- /dev/null
+++ b/drivers/clk/mmp/clk-frac.c
@@ -0,0 +1,153 @@
+/*
+ * mmp factor clock operation source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie <xiechao.mail@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+
+#include "clk.h"
+/*
+ * It is M/N clock
+ *
+ * Fout from synthesizer can be given from two equations:
+ * numerator/denominator = Fin / (Fout * factor)
+ */
+
+#define to_clk_factor(hw) container_of(hw, struct clk_factor, hw)
+struct clk_factor {
+ struct clk_hw hw;
+ void __iomem *base;
+ struct clk_factor_masks *masks;
+ struct clk_factor_tbl *ftbl;
+ unsigned int ftbl_cnt;
+};
+
+static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long *prate)
+{
+ struct clk_factor *factor = to_clk_factor(hw);
+ unsigned long rate = 0, prev_rate;
+ int i;
+
+ for (i = 0; i < factor->ftbl_cnt; i++) {
+ prev_rate = rate;
+ rate = (((*prate / 10000) * factor->ftbl[i].num) /
+ (factor->ftbl[i].den * factor->masks->factor)) * 10000;
+ if (rate > drate)
+ break;
+ }
+ if (i == 0)
+ return rate;
+ else
+ return prev_rate;
+}
+
+static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_factor *factor = to_clk_factor(hw);
+ struct clk_factor_masks *masks = factor->masks;
+ unsigned int val, num, den;
+
+ val = readl_relaxed(factor->base);
+
+ /* calculate numerator */
+ num = (val >> masks->num_shift) & masks->num_mask;
+
+ /* calculate denominator */
+ den = (val >> masks->den_shift) & masks->num_mask;
+
+ if (!den)
+ return 0;
+
+ return (((parent_rate / 10000) * den) /
+ (num * factor->masks->factor)) * 10000;
+}
+
+/* Configures new clock rate*/
+static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long prate)
+{
+ struct clk_factor *factor = to_clk_factor(hw);
+ struct clk_factor_masks *masks = factor->masks;
+ int i;
+ unsigned long val;
+ unsigned long prev_rate, rate = 0;
+
+ for (i = 0; i < factor->ftbl_cnt; i++) {
+ prev_rate = rate;
+ rate = (((prate / 10000) * factor->ftbl[i].num) /
+ (factor->ftbl[i].den * factor->masks->factor)) * 10000;
+ if (rate > drate)
+ break;
+ }
+ if (i > 0)
+ i--;
+
+ val = readl_relaxed(factor->base);
+
+ val &= ~(masks->num_mask << masks->num_shift);
+ val |= (factor->ftbl[i].num & masks->num_mask) << masks->num_shift;
+
+ val &= ~(masks->den_mask << masks->den_shift);
+ val |= (factor->ftbl[i].den & masks->den_mask) << masks->den_shift;
+
+ writel_relaxed(val, factor->base);
+
+ return 0;
+}
+
+static struct clk_ops clk_factor_ops = {
+ .recalc_rate = clk_factor_recalc_rate,
+ .round_rate = clk_factor_round_rate,
+ .set_rate = clk_factor_set_rate,
+};
+
+struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
+ unsigned long flags, void __iomem *base,
+ struct clk_factor_masks *masks, struct clk_factor_tbl *ftbl,
+ unsigned int ftbl_cnt)
+{
+ struct clk_factor *factor;
+ struct clk_init_data init;
+ struct clk *clk;
+
+ if (!masks) {
+ pr_err("%s: must pass a clk_factor_mask\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+ factor = kzalloc(sizeof(*factor), GFP_KERNEL);
+ if (!factor) {
+ pr_err("%s: could not allocate factor clk\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* struct clk_aux assignments */
+ factor->base = base;
+ factor->masks = masks;
+ factor->ftbl = ftbl;
+ factor->ftbl_cnt = ftbl_cnt;
+ factor->hw.init = &init;
+
+ init.name = name;
+ init.ops = &clk_factor_ops;
+ init.flags = flags;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ clk = clk_register(NULL, &factor->hw);
+ if (IS_ERR_OR_NULL(clk))
+ kfree(factor);
+
+ return clk;
+}
diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c
new file mode 100644
index 000000000000..ade435820c7e
--- /dev/null
+++ b/drivers/clk/mmp/clk-mmp2.c
@@ -0,0 +1,449 @@
+/*
+ * mmp2 clock framework source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie <xiechao.mail@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+
+#include <mach/addr-map.h>
+
+#include "clk.h"
+
+#define APBC_RTC 0x0
+#define APBC_TWSI0 0x4
+#define APBC_TWSI1 0x8
+#define APBC_TWSI2 0xc
+#define APBC_TWSI3 0x10
+#define APBC_TWSI4 0x7c
+#define APBC_TWSI5 0x80
+#define APBC_KPC 0x18
+#define APBC_UART0 0x2c
+#define APBC_UART1 0x30
+#define APBC_UART2 0x34
+#define APBC_UART3 0x88
+#define APBC_GPIO 0x38
+#define APBC_PWM0 0x3c
+#define APBC_PWM1 0x40
+#define APBC_PWM2 0x44
+#define APBC_PWM3 0x48
+#define APBC_SSP0 0x50
+#define APBC_SSP1 0x54
+#define APBC_SSP2 0x58
+#define APBC_SSP3 0x5c
+#define APMU_SDH0 0x54
+#define APMU_SDH1 0x58
+#define APMU_SDH2 0xe8
+#define APMU_SDH3 0xec
+#define APMU_USB 0x5c
+#define APMU_DISP0 0x4c
+#define APMU_DISP1 0x110
+#define APMU_CCIC0 0x50
+#define APMU_CCIC1 0xf4
+#define MPMU_UART_PLL 0x14
+
+static DEFINE_SPINLOCK(clk_lock);
+
+static struct clk_factor_masks uart_factor_masks = {
+ .factor = 2,
+ .num_mask = 0x1fff,
+ .den_mask = 0x1fff,
+ .num_shift = 16,
+ .den_shift = 0,
+};
+
+static struct clk_factor_tbl uart_factor_tbl[] = {
+ {.num = 14634, .den = 2165}, /*14.745MHZ */
+ {.num = 3521, .den = 689}, /*19.23MHZ */
+ {.num = 9679, .den = 5728}, /*58.9824MHZ */
+ {.num = 15850, .den = 9451}, /*59.429MHZ */
+};
+
+static const char *uart_parent[] = {"uart_pll", "vctcxo"};
+static const char *ssp_parent[] = {"vctcxo_4", "vctcxo_2", "vctcxo", "pll1_16"};
+static const char *sdh_parent[] = {"pll1_4", "pll2", "usb_pll", "pll1"};
+static const char *disp_parent[] = {"pll1", "pll1_16", "pll2", "vctcxo"};
+static const char *ccic_parent[] = {"pll1_2", "pll1_16", "vctcxo"};
+
+void __init mmp2_clk_init(void)
+{
+ struct clk *clk;
+ struct clk *vctcxo;
+ void __iomem *mpmu_base;
+ void __iomem *apmu_base;
+ void __iomem *apbc_base;
+
+ mpmu_base = ioremap(APB_PHYS_BASE + 0x50000, SZ_4K);
+ if (mpmu_base == NULL) {
+ pr_err("error to ioremap MPMU base\n");
+ return;
+ }
+
+ apmu_base = ioremap(AXI_PHYS_BASE + 0x82800, SZ_4K);
+ if (apmu_base == NULL) {
+ pr_err("error to ioremap APMU base\n");
+ return;
+ }
+
+ apbc_base = ioremap(APB_PHYS_BASE + 0x15000, SZ_4K);
+ if (apbc_base == NULL) {
+ pr_err("error to ioremap APBC base\n");
+ return;
+ }
+
+ clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200);
+ clk_register_clkdev(clk, "clk32", NULL);
+
+ vctcxo = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT,
+ 26000000);
+ clk_register_clkdev(vctcxo, "vctcxo", NULL);
+
+ clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT,
+ 800000000);
+ clk_register_clkdev(clk, "pll1", NULL);
+
+ clk = clk_register_fixed_rate(NULL, "usb_pll", NULL, CLK_IS_ROOT,
+ 480000000);
+ clk_register_clkdev(clk, "usb_pll", NULL);
+
+ clk = clk_register_fixed_rate(NULL, "pll2", NULL, CLK_IS_ROOT,
+ 960000000);
+ clk_register_clkdev(clk, "pll2", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_2", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_4", "pll1_2",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_4", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_8", "pll1_4",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_8", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_16", "pll1_8",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_16", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_20", "pll1_4",
+ CLK_SET_RATE_PARENT, 1, 5);
+ clk_register_clkdev(clk, "pll1_20", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_3", "pll1",
+ CLK_SET_RATE_PARENT, 1, 3);
+ clk_register_clkdev(clk, "pll1_3", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_6", "pll1_3",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_6", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_12", "pll1_6",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_12", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll2_2", "pll2",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll2_2", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll2_4", "pll2_2",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll2_4", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll2_8", "pll2_4",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll2_8", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll2_16", "pll2_8",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll2_16", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll2_3", "pll2",
+ CLK_SET_RATE_PARENT, 1, 3);
+ clk_register_clkdev(clk, "pll2_3", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll2_6", "pll2_3",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll2_6", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll2_12", "pll2_6",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll2_12", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "vctcxo_2", "vctcxo",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "vctcxo_2", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "vctcxo_4", "vctcxo_2",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "vctcxo_4", NULL);
+
+ clk = mmp_clk_register_factor("uart_pll", "pll1_4", 0,
+ mpmu_base + MPMU_UART_PLL,
+ &uart_factor_masks, uart_factor_tbl,
+ ARRAY_SIZE(uart_factor_tbl));
+ clk_set_rate(clk, 14745600);
+ clk_register_clkdev(clk, "uart_pll", NULL);
+
+ clk = mmp_clk_register_apbc("twsi0", "vctcxo",
+ apbc_base + APBC_TWSI0, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-i2c.0");
+
+ clk = mmp_clk_register_apbc("twsi1", "vctcxo",
+ apbc_base + APBC_TWSI1, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-i2c.1");
+
+ clk = mmp_clk_register_apbc("twsi2", "vctcxo",
+ apbc_base + APBC_TWSI2, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-i2c.2");
+
+ clk = mmp_clk_register_apbc("twsi3", "vctcxo",
+ apbc_base + APBC_TWSI3, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-i2c.3");
+
+ clk = mmp_clk_register_apbc("twsi4", "vctcxo",
+ apbc_base + APBC_TWSI4, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-i2c.4");
+
+ clk = mmp_clk_register_apbc("twsi5", "vctcxo",
+ apbc_base + APBC_TWSI5, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-i2c.5");
+
+ clk = mmp_clk_register_apbc("gpio", "vctcxo",
+ apbc_base + APBC_GPIO, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa-gpio");
+
+ clk = mmp_clk_register_apbc("kpc", "clk32",
+ apbc_base + APBC_KPC, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa27x-keypad");
+
+ clk = mmp_clk_register_apbc("rtc", "clk32",
+ apbc_base + APBC_RTC, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp-rtc");
+
+ clk = mmp_clk_register_apbc("pwm0", "vctcxo",
+ apbc_base + APBC_PWM0, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp2-pwm.0");
+
+ clk = mmp_clk_register_apbc("pwm1", "vctcxo",
+ apbc_base + APBC_PWM1, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp2-pwm.1");
+
+ clk = mmp_clk_register_apbc("pwm2", "vctcxo",
+ apbc_base + APBC_PWM2, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp2-pwm.2");
+
+ clk = mmp_clk_register_apbc("pwm3", "vctcxo",
+ apbc_base + APBC_PWM3, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp2-pwm.3");
+
+ clk = clk_register_mux(NULL, "uart0_mux", uart_parent,
+ ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_UART0, 4, 3, 0, &clk_lock);
+ clk_set_parent(clk, vctcxo);
+ clk_register_clkdev(clk, "uart_mux.0", NULL);
+
+ clk = mmp_clk_register_apbc("uart0", "uart0_mux",
+ apbc_base + APBC_UART0, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-uart.0");
+
+ clk = clk_register_mux(NULL, "uart1_mux", uart_parent,
+ ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_UART1, 4, 3, 0, &clk_lock);
+ clk_set_parent(clk, vctcxo);
+ clk_register_clkdev(clk, "uart_mux.1", NULL);
+
+ clk = mmp_clk_register_apbc("uart1", "uart1_mux",
+ apbc_base + APBC_UART1, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-uart.1");
+
+ clk = clk_register_mux(NULL, "uart2_mux", uart_parent,
+ ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_UART2, 4, 3, 0, &clk_lock);
+ clk_set_parent(clk, vctcxo);
+ clk_register_clkdev(clk, "uart_mux.2", NULL);
+
+ clk = mmp_clk_register_apbc("uart2", "uart2_mux",
+ apbc_base + APBC_UART2, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-uart.2");
+
+ clk = clk_register_mux(NULL, "uart3_mux", uart_parent,
+ ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_UART3, 4, 3, 0, &clk_lock);
+ clk_set_parent(clk, vctcxo);
+ clk_register_clkdev(clk, "uart_mux.3", NULL);
+
+ clk = mmp_clk_register_apbc("uart3", "uart3_mux",
+ apbc_base + APBC_UART3, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-uart.3");
+
+ clk = clk_register_mux(NULL, "ssp0_mux", ssp_parent,
+ ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_SSP0, 4, 3, 0, &clk_lock);
+ clk_register_clkdev(clk, "uart_mux.0", NULL);
+
+ clk = mmp_clk_register_apbc("ssp0", "ssp0_mux",
+ apbc_base + APBC_SSP0, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp-ssp.0");
+
+ clk = clk_register_mux(NULL, "ssp1_mux", ssp_parent,
+ ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_SSP1, 4, 3, 0, &clk_lock);
+ clk_register_clkdev(clk, "ssp_mux.1", NULL);
+
+ clk = mmp_clk_register_apbc("ssp1", "ssp1_mux",
+ apbc_base + APBC_SSP1, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp-ssp.1");
+
+ clk = clk_register_mux(NULL, "ssp2_mux", ssp_parent,
+ ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_SSP2, 4, 3, 0, &clk_lock);
+ clk_register_clkdev(clk, "ssp_mux.2", NULL);
+
+ clk = mmp_clk_register_apbc("ssp2", "ssp2_mux",
+ apbc_base + APBC_SSP2, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp-ssp.2");
+
+ clk = clk_register_mux(NULL, "ssp3_mux", ssp_parent,
+ ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_SSP3, 4, 3, 0, &clk_lock);
+ clk_register_clkdev(clk, "ssp_mux.3", NULL);
+
+ clk = mmp_clk_register_apbc("ssp3", "ssp3_mux",
+ apbc_base + APBC_SSP3, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp-ssp.3");
+
+ clk = clk_register_mux(NULL, "sdh_mux", sdh_parent,
+ ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT,
+ apmu_base + APMU_SDH0, 8, 2, 0, &clk_lock);
+ clk_register_clkdev(clk, "sdh_mux", NULL);
+
+ clk = clk_register_divider(NULL, "sdh_div", "sdh_mux",
+ CLK_SET_RATE_PARENT, apmu_base + APMU_SDH0,
+ 10, 4, CLK_DIVIDER_ONE_BASED, &clk_lock);
+ clk_register_clkdev(clk, "sdh_div", NULL);
+
+ clk = mmp_clk_register_apmu("sdh0", "sdh_div", apmu_base + APMU_SDH0,
+ 0x1b, &clk_lock);
+ clk_register_clkdev(clk, NULL, "sdhci-pxav3.0");
+
+ clk = mmp_clk_register_apmu("sdh1", "sdh_div", apmu_base + APMU_SDH1,
+ 0x1b, &clk_lock);
+ clk_register_clkdev(clk, NULL, "sdhci-pxav3.1");
+
+ clk = mmp_clk_register_apmu("sdh2", "sdh_div", apmu_base + APMU_SDH2,
+ 0x1b, &clk_lock);
+ clk_register_clkdev(clk, NULL, "sdhci-pxav3.2");
+
+ clk = mmp_clk_register_apmu("sdh3", "sdh_div", apmu_base + APMU_SDH3,
+ 0x1b, &clk_lock);
+ clk_register_clkdev(clk, NULL, "sdhci-pxav3.3");
+
+ clk = mmp_clk_register_apmu("usb", "usb_pll", apmu_base + APMU_USB,
+ 0x9, &clk_lock);
+ clk_register_clkdev(clk, "usb_clk", NULL);
+
+ clk = clk_register_mux(NULL, "disp0_mux", disp_parent,
+ ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT,
+ apmu_base + APMU_DISP0, 6, 2, 0, &clk_lock);
+ clk_register_clkdev(clk, "disp_mux.0", NULL);
+
+ clk = clk_register_divider(NULL, "disp0_div", "disp0_mux",
+ CLK_SET_RATE_PARENT, apmu_base + APMU_DISP0,
+ 8, 4, CLK_DIVIDER_ONE_BASED, &clk_lock);
+ clk_register_clkdev(clk, "disp_div.0", NULL);
+
+ clk = mmp_clk_register_apmu("disp0", "disp0_div",
+ apmu_base + APMU_DISP0, 0x1b, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp-disp.0");
+
+ clk = clk_register_divider(NULL, "disp0_sphy_div", "disp0_mux", 0,
+ apmu_base + APMU_DISP0, 15, 5, 0, &clk_lock);
+ clk_register_clkdev(clk, "disp_sphy_div.0", NULL);
+
+ clk = mmp_clk_register_apmu("disp0_sphy", "disp0_sphy_div",
+ apmu_base + APMU_DISP0, 0x1024, &clk_lock);
+ clk_register_clkdev(clk, "disp_sphy.0", NULL);
+
+ clk = clk_register_mux(NULL, "disp1_mux", disp_parent,
+ ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT,
+ apmu_base + APMU_DISP1, 6, 2, 0, &clk_lock);
+ clk_register_clkdev(clk, "disp_mux.1", NULL);
+
+ clk = clk_register_divider(NULL, "disp1_div", "disp1_mux",
+ CLK_SET_RATE_PARENT, apmu_base + APMU_DISP1,
+ 8, 4, CLK_DIVIDER_ONE_BASED, &clk_lock);
+ clk_register_clkdev(clk, "disp_div.1", NULL);
+
+ clk = mmp_clk_register_apmu("disp1", "disp1_div",
+ apmu_base + APMU_DISP1, 0x1b, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp-disp.1");
+
+ clk = mmp_clk_register_apmu("ccic_arbiter", "vctcxo",
+ apmu_base + APMU_CCIC0, 0x1800, &clk_lock);
+ clk_register_clkdev(clk, "ccic_arbiter", NULL);
+
+ clk = clk_register_mux(NULL, "ccic0_mux", ccic_parent,
+ ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT,
+ apmu_base + APMU_CCIC0, 6, 2, 0, &clk_lock);
+ clk_register_clkdev(clk, "ccic_mux.0", NULL);
+
+ clk = clk_register_divider(NULL, "ccic0_div", "ccic0_mux",
+ CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0,
+ 17, 4, CLK_DIVIDER_ONE_BASED, &clk_lock);
+ clk_register_clkdev(clk, "ccic_div.0", NULL);
+
+ clk = mmp_clk_register_apmu("ccic0", "ccic0_div",
+ apmu_base + APMU_CCIC0, 0x1b, &clk_lock);
+ clk_register_clkdev(clk, "fnclk", "mmp-ccic.0");
+
+ clk = mmp_clk_register_apmu("ccic0_phy", "ccic0_div",
+ apmu_base + APMU_CCIC0, 0x24, &clk_lock);
+ clk_register_clkdev(clk, "phyclk", "mmp-ccic.0");
+
+ clk = clk_register_divider(NULL, "ccic0_sphy_div", "ccic0_div",
+ CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0,
+ 10, 5, 0, &clk_lock);
+ clk_register_clkdev(clk, "sphyclk_div", "mmp-ccic.0");
+
+ clk = mmp_clk_register_apmu("ccic0_sphy", "ccic0_sphy_div",
+ apmu_base + APMU_CCIC0, 0x300, &clk_lock);
+ clk_register_clkdev(clk, "sphyclk", "mmp-ccic.0");
+
+ clk = clk_register_mux(NULL, "ccic1_mux", ccic_parent,
+ ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT,
+ apmu_base + APMU_CCIC1, 6, 2, 0, &clk_lock);
+ clk_register_clkdev(clk, "ccic_mux.1", NULL);
+
+ clk = clk_register_divider(NULL, "ccic1_div", "ccic1_mux",
+ CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC1,
+ 16, 4, CLK_DIVIDER_ONE_BASED, &clk_lock);
+ clk_register_clkdev(clk, "ccic_div.1", NULL);
+
+ clk = mmp_clk_register_apmu("ccic1", "ccic1_div",
+ apmu_base + APMU_CCIC1, 0x1b, &clk_lock);
+ clk_register_clkdev(clk, "fnclk", "mmp-ccic.1");
+
+ clk = mmp_clk_register_apmu("ccic1_phy", "ccic1_div",
+ apmu_base + APMU_CCIC1, 0x24, &clk_lock);
+ clk_register_clkdev(clk, "phyclk", "mmp-ccic.1");
+
+ clk = clk_register_divider(NULL, "ccic1_sphy_div", "ccic1_div",
+ CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC1,
+ 10, 5, 0, &clk_lock);
+ clk_register_clkdev(clk, "sphyclk_div", "mmp-ccic.1");
+
+ clk = mmp_clk_register_apmu("ccic1_sphy", "ccic1_sphy_div",
+ apmu_base + APMU_CCIC1, 0x300, &clk_lock);
+ clk_register_clkdev(clk, "sphyclk", "mmp-ccic.1");
+}
diff --git a/drivers/clk/mmp/clk-pxa168.c b/drivers/clk/mmp/clk-pxa168.c
new file mode 100644
index 000000000000..e8d036c12cbf
--- /dev/null
+++ b/drivers/clk/mmp/clk-pxa168.c
@@ -0,0 +1,346 @@
+/*
+ * pxa168 clock framework source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie <xiechao.mail@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+
+#include <mach/addr-map.h>
+
+#include "clk.h"
+
+#define APBC_RTC 0x28
+#define APBC_TWSI0 0x2c
+#define APBC_KPC 0x30
+#define APBC_UART0 0x0
+#define APBC_UART1 0x4
+#define APBC_GPIO 0x8
+#define APBC_PWM0 0xc
+#define APBC_PWM1 0x10
+#define APBC_PWM2 0x14
+#define APBC_PWM3 0x18
+#define APBC_SSP0 0x81c
+#define APBC_SSP1 0x820
+#define APBC_SSP2 0x84c
+#define APBC_SSP3 0x858
+#define APBC_SSP4 0x85c
+#define APBC_TWSI1 0x6c
+#define APBC_UART2 0x70
+#define APMU_SDH0 0x54
+#define APMU_SDH1 0x58
+#define APMU_USB 0x5c
+#define APMU_DISP0 0x4c
+#define APMU_CCIC0 0x50
+#define APMU_DFC 0x60
+#define MPMU_UART_PLL 0x14
+
+static DEFINE_SPINLOCK(clk_lock);
+
+static struct clk_factor_masks uart_factor_masks = {
+ .factor = 2,
+ .num_mask = 0x1fff,
+ .den_mask = 0x1fff,
+ .num_shift = 16,
+ .den_shift = 0,
+};
+
+static struct clk_factor_tbl uart_factor_tbl[] = {
+ {.num = 8125, .den = 1536}, /*14.745MHZ */
+};
+
+static const char *uart_parent[] = {"pll1_3_16", "uart_pll"};
+static const char *ssp_parent[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"};
+static const char *sdh_parent[] = {"pll1_12", "pll1_13"};
+static const char *disp_parent[] = {"pll1_2", "pll1_12"};
+static const char *ccic_parent[] = {"pll1_2", "pll1_12"};
+static const char *ccic_phy_parent[] = {"pll1_6", "pll1_12"};
+
+void __init pxa168_clk_init(void)
+{
+ struct clk *clk;
+ struct clk *uart_pll;
+ void __iomem *mpmu_base;
+ void __iomem *apmu_base;
+ void __iomem *apbc_base;
+
+ mpmu_base = ioremap(APB_PHYS_BASE + 0x50000, SZ_4K);
+ if (mpmu_base == NULL) {
+ pr_err("error to ioremap MPMU base\n");
+ return;
+ }
+
+ apmu_base = ioremap(AXI_PHYS_BASE + 0x82800, SZ_4K);
+ if (apmu_base == NULL) {
+ pr_err("error to ioremap APMU base\n");
+ return;
+ }
+
+ apbc_base = ioremap(APB_PHYS_BASE + 0x15000, SZ_4K);
+ if (apbc_base == NULL) {
+ pr_err("error to ioremap APBC base\n");
+ return;
+ }
+
+ clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200);
+ clk_register_clkdev(clk, "clk32", NULL);
+
+ clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT,
+ 26000000);
+ clk_register_clkdev(clk, "vctcxo", NULL);
+
+ clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT,
+ 624000000);
+ clk_register_clkdev(clk, "pll1", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_2", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_4", "pll1_2",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_4", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_8", "pll1_4",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_8", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_16", "pll1_8",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_16", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_6", "pll1_2",
+ CLK_SET_RATE_PARENT, 1, 3);
+ clk_register_clkdev(clk, "pll1_6", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_12", "pll1_6",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_12", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_24", "pll1_12",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_24", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_48", "pll1_24",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_48", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_96", "pll1_48",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_96", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_13", "pll1",
+ CLK_SET_RATE_PARENT, 1, 13);
+ clk_register_clkdev(clk, "pll1_13", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_13_1_5", "pll1",
+ CLK_SET_RATE_PARENT, 2, 3);
+ clk_register_clkdev(clk, "pll1_13_1_5", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_2_1_5", "pll1",
+ CLK_SET_RATE_PARENT, 2, 3);
+ clk_register_clkdev(clk, "pll1_2_1_5", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_3_16", "pll1",
+ CLK_SET_RATE_PARENT, 3, 16);
+ clk_register_clkdev(clk, "pll1_3_16", NULL);
+
+ uart_pll = mmp_clk_register_factor("uart_pll", "pll1_4", 0,
+ mpmu_base + MPMU_UART_PLL,
+ &uart_factor_masks, uart_factor_tbl,
+ ARRAY_SIZE(uart_factor_tbl));
+ clk_set_rate(uart_pll, 14745600);
+ clk_register_clkdev(uart_pll, "uart_pll", NULL);
+
+ clk = mmp_clk_register_apbc("twsi0", "pll1_13_1_5",
+ apbc_base + APBC_TWSI0, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-i2c.0");
+
+ clk = mmp_clk_register_apbc("twsi1", "pll1_13_1_5",
+ apbc_base + APBC_TWSI1, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-i2c.1");
+
+ clk = mmp_clk_register_apbc("gpio", "vctcxo",
+ apbc_base + APBC_GPIO, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa-gpio");
+
+ clk = mmp_clk_register_apbc("kpc", "clk32",
+ apbc_base + APBC_KPC, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa27x-keypad");
+
+ clk = mmp_clk_register_apbc("rtc", "clk32",
+ apbc_base + APBC_RTC, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "sa1100-rtc");
+
+ clk = mmp_clk_register_apbc("pwm0", "pll1_48",
+ apbc_base + APBC_PWM0, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa168-pwm.0");
+
+ clk = mmp_clk_register_apbc("pwm1", "pll1_48",
+ apbc_base + APBC_PWM1, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa168-pwm.1");
+
+ clk = mmp_clk_register_apbc("pwm2", "pll1_48",
+ apbc_base + APBC_PWM2, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa168-pwm.2");
+
+ clk = mmp_clk_register_apbc("pwm3", "pll1_48",
+ apbc_base + APBC_PWM3, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa168-pwm.3");
+
+ clk = clk_register_mux(NULL, "uart0_mux", uart_parent,
+ ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_UART0, 4, 3, 0, &clk_lock);
+ clk_set_parent(clk, uart_pll);
+ clk_register_clkdev(clk, "uart_mux.0", NULL);
+
+ clk = mmp_clk_register_apbc("uart0", "uart0_mux",
+ apbc_base + APBC_UART0, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-uart.0");
+
+ clk = clk_register_mux(NULL, "uart1_mux", uart_parent,
+ ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_UART1, 4, 3, 0, &clk_lock);
+ clk_set_parent(clk, uart_pll);
+ clk_register_clkdev(clk, "uart_mux.1", NULL);
+
+ clk = mmp_clk_register_apbc("uart1", "uart1_mux",
+ apbc_base + APBC_UART1, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-uart.1");
+
+ clk = clk_register_mux(NULL, "uart2_mux", uart_parent,
+ ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_UART2, 4, 3, 0, &clk_lock);
+ clk_set_parent(clk, uart_pll);
+ clk_register_clkdev(clk, "uart_mux.2", NULL);
+
+ clk = mmp_clk_register_apbc("uart2", "uart2_mux",
+ apbc_base + APBC_UART2, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-uart.2");
+
+ clk = clk_register_mux(NULL, "ssp0_mux", ssp_parent,
+ ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_SSP0, 4, 3, 0, &clk_lock);
+ clk_register_clkdev(clk, "uart_mux.0", NULL);
+
+ clk = mmp_clk_register_apbc("ssp0", "ssp0_mux", apbc_base + APBC_SSP0,
+ 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp-ssp.0");
+
+ clk = clk_register_mux(NULL, "ssp1_mux", ssp_parent,
+ ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_SSP1, 4, 3, 0, &clk_lock);
+ clk_register_clkdev(clk, "ssp_mux.1", NULL);
+
+ clk = mmp_clk_register_apbc("ssp1", "ssp1_mux", apbc_base + APBC_SSP1,
+ 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp-ssp.1");
+
+ clk = clk_register_mux(NULL, "ssp2_mux", ssp_parent,
+ ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_SSP2, 4, 3, 0, &clk_lock);
+ clk_register_clkdev(clk, "ssp_mux.2", NULL);
+
+ clk = mmp_clk_register_apbc("ssp2", "ssp1_mux", apbc_base + APBC_SSP2,
+ 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp-ssp.2");
+
+ clk = clk_register_mux(NULL, "ssp3_mux", ssp_parent,
+ ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_SSP3, 4, 3, 0, &clk_lock);
+ clk_register_clkdev(clk, "ssp_mux.3", NULL);
+
+ clk = mmp_clk_register_apbc("ssp3", "ssp1_mux", apbc_base + APBC_SSP3,
+ 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp-ssp.3");
+
+ clk = clk_register_mux(NULL, "ssp4_mux", ssp_parent,
+ ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_SSP4, 4, 3, 0, &clk_lock);
+ clk_register_clkdev(clk, "ssp_mux.4", NULL);
+
+ clk = mmp_clk_register_apbc("ssp4", "ssp1_mux", apbc_base + APBC_SSP4,
+ 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp-ssp.4");
+
+ clk = mmp_clk_register_apmu("dfc", "pll1_4", apmu_base + APMU_DFC,
+ 0x19b, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa3xx-nand.0");
+
+ clk = clk_register_mux(NULL, "sdh0_mux", sdh_parent,
+ ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT,
+ apmu_base + APMU_SDH0, 6, 1, 0, &clk_lock);
+ clk_register_clkdev(clk, "sdh0_mux", NULL);
+
+ clk = mmp_clk_register_apmu("sdh0", "sdh_mux", apmu_base + APMU_SDH0,
+ 0x1b, &clk_lock);
+ clk_register_clkdev(clk, NULL, "sdhci-pxa.0");
+
+ clk = clk_register_mux(NULL, "sdh1_mux", sdh_parent,
+ ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT,
+ apmu_base + APMU_SDH1, 6, 1, 0, &clk_lock);
+ clk_register_clkdev(clk, "sdh1_mux", NULL);
+
+ clk = mmp_clk_register_apmu("sdh1", "sdh1_mux", apmu_base + APMU_SDH1,
+ 0x1b, &clk_lock);
+ clk_register_clkdev(clk, NULL, "sdhci-pxa.1");
+
+ clk = mmp_clk_register_apmu("usb", "usb_pll", apmu_base + APMU_USB,
+ 0x9, &clk_lock);
+ clk_register_clkdev(clk, "usb_clk", NULL);
+
+ clk = mmp_clk_register_apmu("sph", "usb_pll", apmu_base + APMU_USB,
+ 0x12, &clk_lock);
+ clk_register_clkdev(clk, "sph_clk", NULL);
+
+ clk = clk_register_mux(NULL, "disp0_mux", disp_parent,
+ ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT,
+ apmu_base + APMU_DISP0, 6, 1, 0, &clk_lock);
+ clk_register_clkdev(clk, "disp_mux.0", NULL);
+
+ clk = mmp_clk_register_apmu("disp0", "disp0_mux",
+ apmu_base + APMU_DISP0, 0x1b, &clk_lock);
+ clk_register_clkdev(clk, "fnclk", "mmp-disp.0");
+
+ clk = mmp_clk_register_apmu("disp0_hclk", "disp0_mux",
+ apmu_base + APMU_DISP0, 0x24, &clk_lock);
+ clk_register_clkdev(clk, "hclk", "mmp-disp.0");
+
+ clk = clk_register_mux(NULL, "ccic0_mux", ccic_parent,
+ ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT,
+ apmu_base + APMU_CCIC0, 6, 1, 0, &clk_lock);
+ clk_register_clkdev(clk, "ccic_mux.0", NULL);
+
+ clk = mmp_clk_register_apmu("ccic0", "ccic0_mux",
+ apmu_base + APMU_CCIC0, 0x1b, &clk_lock);
+ clk_register_clkdev(clk, "fnclk", "mmp-ccic.0");
+
+ clk = clk_register_mux(NULL, "ccic0_phy_mux", ccic_phy_parent,
+ ARRAY_SIZE(ccic_phy_parent),
+ CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0,
+ 7, 1, 0, &clk_lock);
+ clk_register_clkdev(clk, "ccic_phy_mux.0", NULL);
+
+ clk = mmp_clk_register_apmu("ccic0_phy", "ccic0_phy_mux",
+ apmu_base + APMU_CCIC0, 0x24, &clk_lock);
+ clk_register_clkdev(clk, "phyclk", "mmp-ccic.0");
+
+ clk = clk_register_divider(NULL, "ccic0_sphy_div", "ccic0_mux",
+ CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0,
+ 10, 5, 0, &clk_lock);
+ clk_register_clkdev(clk, "sphyclk_div", NULL);
+
+ clk = mmp_clk_register_apmu("ccic0_sphy", "ccic0_sphy_div",
+ apmu_base + APMU_CCIC0, 0x300, &clk_lock);
+ clk_register_clkdev(clk, "sphyclk", "mmp-ccic.0");
+}
diff --git a/drivers/clk/mmp/clk-pxa910.c b/drivers/clk/mmp/clk-pxa910.c
new file mode 100644
index 000000000000..7048c31d6e7e
--- /dev/null
+++ b/drivers/clk/mmp/clk-pxa910.c
@@ -0,0 +1,320 @@
+/*
+ * pxa910 clock framework source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie <xiechao.mail@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+
+#include <mach/addr-map.h>
+
+#include "clk.h"
+
+#define APBC_RTC 0x28
+#define APBC_TWSI0 0x2c
+#define APBC_KPC 0x18
+#define APBC_UART0 0x0
+#define APBC_UART1 0x4
+#define APBC_GPIO 0x8
+#define APBC_PWM0 0xc
+#define APBC_PWM1 0x10
+#define APBC_PWM2 0x14
+#define APBC_PWM3 0x18
+#define APBC_SSP0 0x1c
+#define APBC_SSP1 0x20
+#define APBC_SSP2 0x4c
+#define APBCP_TWSI1 0x28
+#define APBCP_UART2 0x1c
+#define APMU_SDH0 0x54
+#define APMU_SDH1 0x58
+#define APMU_USB 0x5c
+#define APMU_DISP0 0x4c
+#define APMU_CCIC0 0x50
+#define APMU_DFC 0x60
+#define MPMU_UART_PLL 0x14
+
+static DEFINE_SPINLOCK(clk_lock);
+
+static struct clk_factor_masks uart_factor_masks = {
+ .factor = 2,
+ .num_mask = 0x1fff,
+ .den_mask = 0x1fff,
+ .num_shift = 16,
+ .den_shift = 0,
+};
+
+static struct clk_factor_tbl uart_factor_tbl[] = {
+ {.num = 8125, .den = 1536}, /*14.745MHZ */
+};
+
+static const char *uart_parent[] = {"pll1_3_16", "uart_pll"};
+static const char *ssp_parent[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"};
+static const char *sdh_parent[] = {"pll1_12", "pll1_13"};
+static const char *disp_parent[] = {"pll1_2", "pll1_12"};
+static const char *ccic_parent[] = {"pll1_2", "pll1_12"};
+static const char *ccic_phy_parent[] = {"pll1_6", "pll1_12"};
+
+void __init pxa910_clk_init(void)
+{
+ struct clk *clk;
+ struct clk *uart_pll;
+ void __iomem *mpmu_base;
+ void __iomem *apmu_base;
+ void __iomem *apbcp_base;
+ void __iomem *apbc_base;
+
+ mpmu_base = ioremap(APB_PHYS_BASE + 0x50000, SZ_4K);
+ if (mpmu_base == NULL) {
+ pr_err("error to ioremap MPMU base\n");
+ return;
+ }
+
+ apmu_base = ioremap(AXI_PHYS_BASE + 0x82800, SZ_4K);
+ if (apmu_base == NULL) {
+ pr_err("error to ioremap APMU base\n");
+ return;
+ }
+
+ apbcp_base = ioremap(APB_PHYS_BASE + 0x3b000, SZ_4K);
+ if (apbcp_base == NULL) {
+ pr_err("error to ioremap APBC extension base\n");
+ return;
+ }
+
+ apbc_base = ioremap(APB_PHYS_BASE + 0x15000, SZ_4K);
+ if (apbc_base == NULL) {
+ pr_err("error to ioremap APBC base\n");
+ return;
+ }
+
+ clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200);
+ clk_register_clkdev(clk, "clk32", NULL);
+
+ clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT,
+ 26000000);
+ clk_register_clkdev(clk, "vctcxo", NULL);
+
+ clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT,
+ 624000000);
+ clk_register_clkdev(clk, "pll1", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_2", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_4", "pll1_2",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_4", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_8", "pll1_4",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_8", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_16", "pll1_8",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_16", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_6", "pll1_2",
+ CLK_SET_RATE_PARENT, 1, 3);
+ clk_register_clkdev(clk, "pll1_6", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_12", "pll1_6",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_12", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_24", "pll1_12",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_24", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_48", "pll1_24",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_48", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_96", "pll1_48",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll1_96", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_13", "pll1",
+ CLK_SET_RATE_PARENT, 1, 13);
+ clk_register_clkdev(clk, "pll1_13", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_13_1_5", "pll1",
+ CLK_SET_RATE_PARENT, 2, 3);
+ clk_register_clkdev(clk, "pll1_13_1_5", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_2_1_5", "pll1",
+ CLK_SET_RATE_PARENT, 2, 3);
+ clk_register_clkdev(clk, "pll1_2_1_5", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "pll1_3_16", "pll1",
+ CLK_SET_RATE_PARENT, 3, 16);
+ clk_register_clkdev(clk, "pll1_3_16", NULL);
+
+ uart_pll = mmp_clk_register_factor("uart_pll", "pll1_4", 0,
+ mpmu_base + MPMU_UART_PLL,
+ &uart_factor_masks, uart_factor_tbl,
+ ARRAY_SIZE(uart_factor_tbl));
+ clk_set_rate(uart_pll, 14745600);
+ clk_register_clkdev(uart_pll, "uart_pll", NULL);
+
+ clk = mmp_clk_register_apbc("twsi0", "pll1_13_1_5",
+ apbc_base + APBC_TWSI0, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-i2c.0");
+
+ clk = mmp_clk_register_apbc("twsi1", "pll1_13_1_5",
+ apbcp_base + APBCP_TWSI1, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-i2c.1");
+
+ clk = mmp_clk_register_apbc("gpio", "vctcxo",
+ apbc_base + APBC_GPIO, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa-gpio");
+
+ clk = mmp_clk_register_apbc("kpc", "clk32",
+ apbc_base + APBC_KPC, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa27x-keypad");
+
+ clk = mmp_clk_register_apbc("rtc", "clk32",
+ apbc_base + APBC_RTC, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "sa1100-rtc");
+
+ clk = mmp_clk_register_apbc("pwm0", "pll1_48",
+ apbc_base + APBC_PWM0, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa910-pwm.0");
+
+ clk = mmp_clk_register_apbc("pwm1", "pll1_48",
+ apbc_base + APBC_PWM1, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa910-pwm.1");
+
+ clk = mmp_clk_register_apbc("pwm2", "pll1_48",
+ apbc_base + APBC_PWM2, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa910-pwm.2");
+
+ clk = mmp_clk_register_apbc("pwm3", "pll1_48",
+ apbc_base + APBC_PWM3, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa910-pwm.3");
+
+ clk = clk_register_mux(NULL, "uart0_mux", uart_parent,
+ ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_UART0, 4, 3, 0, &clk_lock);
+ clk_set_parent(clk, uart_pll);
+ clk_register_clkdev(clk, "uart_mux.0", NULL);
+
+ clk = mmp_clk_register_apbc("uart0", "uart0_mux",
+ apbc_base + APBC_UART0, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-uart.0");
+
+ clk = clk_register_mux(NULL, "uart1_mux", uart_parent,
+ ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_UART1, 4, 3, 0, &clk_lock);
+ clk_set_parent(clk, uart_pll);
+ clk_register_clkdev(clk, "uart_mux.1", NULL);
+
+ clk = mmp_clk_register_apbc("uart1", "uart1_mux",
+ apbc_base + APBC_UART1, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-uart.1");
+
+ clk = clk_register_mux(NULL, "uart2_mux", uart_parent,
+ ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+ apbcp_base + APBCP_UART2, 4, 3, 0, &clk_lock);
+ clk_set_parent(clk, uart_pll);
+ clk_register_clkdev(clk, "uart_mux.2", NULL);
+
+ clk = mmp_clk_register_apbc("uart2", "uart2_mux",
+ apbcp_base + APBCP_UART2, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa2xx-uart.2");
+
+ clk = clk_register_mux(NULL, "ssp0_mux", ssp_parent,
+ ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_SSP0, 4, 3, 0, &clk_lock);
+ clk_register_clkdev(clk, "uart_mux.0", NULL);
+
+ clk = mmp_clk_register_apbc("ssp0", "ssp0_mux",
+ apbc_base + APBC_SSP0, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp-ssp.0");
+
+ clk = clk_register_mux(NULL, "ssp1_mux", ssp_parent,
+ ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+ apbc_base + APBC_SSP1, 4, 3, 0, &clk_lock);
+ clk_register_clkdev(clk, "ssp_mux.1", NULL);
+
+ clk = mmp_clk_register_apbc("ssp1", "ssp1_mux",
+ apbc_base + APBC_SSP1, 10, 0, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp-ssp.1");
+
+ clk = mmp_clk_register_apmu("dfc", "pll1_4",
+ apmu_base + APMU_DFC, 0x19b, &clk_lock);
+ clk_register_clkdev(clk, NULL, "pxa3xx-nand.0");
+
+ clk = clk_register_mux(NULL, "sdh0_mux", sdh_parent,
+ ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT,
+ apmu_base + APMU_SDH0, 6, 1, 0, &clk_lock);
+ clk_register_clkdev(clk, "sdh0_mux", NULL);
+
+ clk = mmp_clk_register_apmu("sdh0", "sdh_mux",
+ apmu_base + APMU_SDH0, 0x1b, &clk_lock);
+ clk_register_clkdev(clk, NULL, "sdhci-pxa.0");
+
+ clk = clk_register_mux(NULL, "sdh1_mux", sdh_parent,
+ ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT,
+ apmu_base + APMU_SDH1, 6, 1, 0, &clk_lock);
+ clk_register_clkdev(clk, "sdh1_mux", NULL);
+
+ clk = mmp_clk_register_apmu("sdh1", "sdh1_mux",
+ apmu_base + APMU_SDH1, 0x1b, &clk_lock);
+ clk_register_clkdev(clk, NULL, "sdhci-pxa.1");
+
+ clk = mmp_clk_register_apmu("usb", "usb_pll",
+ apmu_base + APMU_USB, 0x9, &clk_lock);
+ clk_register_clkdev(clk, "usb_clk", NULL);
+
+ clk = mmp_clk_register_apmu("sph", "usb_pll",
+ apmu_base + APMU_USB, 0x12, &clk_lock);
+ clk_register_clkdev(clk, "sph_clk", NULL);
+
+ clk = clk_register_mux(NULL, "disp0_mux", disp_parent,
+ ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT,
+ apmu_base + APMU_DISP0, 6, 1, 0, &clk_lock);
+ clk_register_clkdev(clk, "disp_mux.0", NULL);
+
+ clk = mmp_clk_register_apmu("disp0", "disp0_mux",
+ apmu_base + APMU_DISP0, 0x1b, &clk_lock);
+ clk_register_clkdev(clk, NULL, "mmp-disp.0");
+
+ clk = clk_register_mux(NULL, "ccic0_mux", ccic_parent,
+ ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT,
+ apmu_base + APMU_CCIC0, 6, 1, 0, &clk_lock);
+ clk_register_clkdev(clk, "ccic_mux.0", NULL);
+
+ clk = mmp_clk_register_apmu("ccic0", "ccic0_mux",
+ apmu_base + APMU_CCIC0, 0x1b, &clk_lock);
+ clk_register_clkdev(clk, "fnclk", "mmp-ccic.0");
+
+ clk = clk_register_mux(NULL, "ccic0_phy_mux", ccic_phy_parent,
+ ARRAY_SIZE(ccic_phy_parent),
+ CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0,
+ 7, 1, 0, &clk_lock);
+ clk_register_clkdev(clk, "ccic_phy_mux.0", NULL);
+
+ clk = mmp_clk_register_apmu("ccic0_phy", "ccic0_phy_mux",
+ apmu_base + APMU_CCIC0, 0x24, &clk_lock);
+ clk_register_clkdev(clk, "phyclk", "mmp-ccic.0");
+
+ clk = clk_register_divider(NULL, "ccic0_sphy_div", "ccic0_mux",
+ CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0,
+ 10, 5, 0, &clk_lock);
+ clk_register_clkdev(clk, "sphyclk_div", NULL);
+
+ clk = mmp_clk_register_apmu("ccic0_sphy", "ccic0_sphy_div",
+ apmu_base + APMU_CCIC0, 0x300, &clk_lock);
+ clk_register_clkdev(clk, "sphyclk", "mmp-ccic.0");
+}
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
new file mode 100644
index 000000000000..ab86dd4a416a
--- /dev/null
+++ b/drivers/clk/mmp/clk.h
@@ -0,0 +1,35 @@
+#ifndef __MACH_MMP_CLK_H
+#define __MACH_MMP_CLK_H
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+
+#define APBC_NO_BUS_CTRL BIT(0)
+#define APBC_POWER_CTRL BIT(1)
+
+struct clk_factor_masks {
+ unsigned int factor;
+ unsigned int num_mask;
+ unsigned int den_mask;
+ unsigned int num_shift;
+ unsigned int den_shift;
+};
+
+struct clk_factor_tbl {
+ unsigned int num;
+ unsigned int den;
+};
+
+extern struct clk *mmp_clk_register_pll2(const char *name,
+ const char *parent_name, unsigned long flags);
+extern struct clk *mmp_clk_register_apbc(const char *name,
+ const char *parent_name, void __iomem *base,
+ unsigned int delay, unsigned int apbc_flags, spinlock_t *lock);
+extern struct clk *mmp_clk_register_apmu(const char *name,
+ const char *parent_name, void __iomem *base, u32 enable_mask,
+ spinlock_t *lock);
+extern struct clk *mmp_clk_register_factor(const char *name,
+ const char *parent_name, unsigned long flags,
+ void __iomem *base, struct clk_factor_masks *masks,
+ struct clk_factor_tbl *ftbl, unsigned int ftbl_cnt);
+#endif
diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c
index 844043ad0fe4..9f6d15546cbe 100644
--- a/drivers/clk/mxs/clk-imx23.c
+++ b/drivers/clk/mxs/clk-imx23.c
@@ -14,6 +14,7 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/of.h>
#include <mach/common.h>
#include <mach/mx23.h>
#include "clk.h"
@@ -71,44 +72,6 @@ static void __init clk_misc_init(void)
__mxs_setl(30 << BP_FRAC_IOFRAC, FRAC);
}
-static struct clk_lookup uart_lookups[] = {
- { .dev_id = "duart", },
- { .dev_id = "mxs-auart.0", },
- { .dev_id = "mxs-auart.1", },
- { .dev_id = "8006c000.serial", },
- { .dev_id = "8006e000.serial", },
- { .dev_id = "80070000.serial", },
-};
-
-static struct clk_lookup hbus_lookups[] = {
- { .dev_id = "imx23-dma-apbh", },
- { .dev_id = "80004000.dma-apbh", },
-};
-
-static struct clk_lookup xbus_lookups[] = {
- { .dev_id = "duart", .con_id = "apb_pclk"},
- { .dev_id = "80070000.serial", .con_id = "apb_pclk"},
- { .dev_id = "imx23-dma-apbx", },
- { .dev_id = "80024000.dma-apbx", },
-};
-
-static struct clk_lookup ssp_lookups[] = {
- { .dev_id = "imx23-mmc.0", },
- { .dev_id = "imx23-mmc.1", },
- { .dev_id = "80010000.ssp", },
- { .dev_id = "80034000.ssp", },
-};
-
-static struct clk_lookup lcdif_lookups[] = {
- { .dev_id = "imx23-fb", },
- { .dev_id = "80030000.lcdif", },
-};
-
-static struct clk_lookup gpmi_lookups[] = {
- { .dev_id = "imx23-gpmi-nand", },
- { .dev_id = "8000c000.gpmi-nand", },
-};
-
static const char *sel_pll[] __initconst = { "pll", "ref_xtal", };
static const char *sel_cpu[] __initconst = { "ref_cpu", "ref_xtal", };
static const char *sel_pix[] __initconst = { "ref_pix", "ref_xtal", };
@@ -127,6 +90,7 @@ enum imx23_clk {
};
static struct clk *clks[clk_max];
+static struct clk_onecell_data clk_data;
static enum imx23_clk clks_init_on[] __initdata = {
cpu, hbus, xbus, emi, uart,
@@ -134,6 +98,7 @@ static enum imx23_clk clks_init_on[] __initdata = {
int __init mx23_clocks_init(void)
{
+ struct device_node *np;
int i;
clk_misc_init();
@@ -188,14 +153,14 @@ int __init mx23_clocks_init(void)
return PTR_ERR(clks[i]);
}
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx23-clkctrl");
+ if (np) {
+ clk_data.clks = clks;
+ clk_data.clk_num = ARRAY_SIZE(clks);
+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+ }
+
clk_register_clkdev(clks[clk32k], NULL, "timrot");
- clk_register_clkdev(clks[pwm], NULL, "80064000.pwm");
- clk_register_clkdevs(clks[hbus], hbus_lookups, ARRAY_SIZE(hbus_lookups));
- clk_register_clkdevs(clks[xbus], xbus_lookups, ARRAY_SIZE(xbus_lookups));
- clk_register_clkdevs(clks[uart], uart_lookups, ARRAY_SIZE(uart_lookups));
- clk_register_clkdevs(clks[ssp], ssp_lookups, ARRAY_SIZE(ssp_lookups));
- clk_register_clkdevs(clks[gpmi], gpmi_lookups, ARRAY_SIZE(gpmi_lookups));
- clk_register_clkdevs(clks[lcdif], lcdif_lookups, ARRAY_SIZE(lcdif_lookups));
for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
clk_prepare_enable(clks[clks_init_on[i]]);
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
index e3aab67b3eb7..613e76f3758e 100644
--- a/drivers/clk/mxs/clk-imx28.c
+++ b/drivers/clk/mxs/clk-imx28.c
@@ -14,6 +14,7 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/of.h>
#include <mach/common.h>
#include <mach/mx28.h>
#include "clk.h"
@@ -120,90 +121,6 @@ static void __init clk_misc_init(void)
writel_relaxed(val, FRAC0);
}
-static struct clk_lookup uart_lookups[] = {
- { .dev_id = "duart", },
- { .dev_id = "mxs-auart.0", },
- { .dev_id = "mxs-auart.1", },
- { .dev_id = "mxs-auart.2", },
- { .dev_id = "mxs-auart.3", },
- { .dev_id = "mxs-auart.4", },
- { .dev_id = "8006a000.serial", },
- { .dev_id = "8006c000.serial", },
- { .dev_id = "8006e000.serial", },
- { .dev_id = "80070000.serial", },
- { .dev_id = "80072000.serial", },
- { .dev_id = "80074000.serial", },
-};
-
-static struct clk_lookup hbus_lookups[] = {
- { .dev_id = "imx28-dma-apbh", },
- { .dev_id = "80004000.dma-apbh", },
-};
-
-static struct clk_lookup xbus_lookups[] = {
- { .dev_id = "duart", .con_id = "apb_pclk"},
- { .dev_id = "80074000.serial", .con_id = "apb_pclk"},
- { .dev_id = "imx28-dma-apbx", },
- { .dev_id = "80024000.dma-apbx", },
-};
-
-static struct clk_lookup ssp0_lookups[] = {
- { .dev_id = "imx28-mmc.0", },
- { .dev_id = "80010000.ssp", },
-};
-
-static struct clk_lookup ssp1_lookups[] = {
- { .dev_id = "imx28-mmc.1", },
- { .dev_id = "80012000.ssp", },
-};
-
-static struct clk_lookup ssp2_lookups[] = {
- { .dev_id = "imx28-mmc.2", },
- { .dev_id = "80014000.ssp", },
-};
-
-static struct clk_lookup ssp3_lookups[] = {
- { .dev_id = "imx28-mmc.3", },
- { .dev_id = "80016000.ssp", },
-};
-
-static struct clk_lookup lcdif_lookups[] = {
- { .dev_id = "imx28-fb", },
- { .dev_id = "80030000.lcdif", },
-};
-
-static struct clk_lookup gpmi_lookups[] = {
- { .dev_id = "imx28-gpmi-nand", },
- { .dev_id = "8000c000.gpmi-nand", },
-};
-
-static struct clk_lookup fec_lookups[] = {
- { .dev_id = "imx28-fec.0", },
- { .dev_id = "imx28-fec.1", },
- { .dev_id = "800f0000.ethernet", },
- { .dev_id = "800f4000.ethernet", },
-};
-
-static struct clk_lookup can0_lookups[] = {
- { .dev_id = "flexcan.0", },
- { .dev_id = "80032000.can", },
-};
-
-static struct clk_lookup can1_lookups[] = {
- { .dev_id = "flexcan.1", },
- { .dev_id = "80034000.can", },
-};
-
-static struct clk_lookup saif0_lookups[] = {
- { .dev_id = "mxs-saif.0", },
- { .dev_id = "80042000.saif", },
-};
-
-static struct clk_lookup saif1_lookups[] = {
- { .dev_id = "mxs-saif.1", },
- { .dev_id = "80046000.saif", },
-};
-
static const char *sel_cpu[] __initconst = { "ref_cpu", "ref_xtal", };
static const char *sel_io0[] __initconst = { "ref_io0", "ref_xtal", };
static const char *sel_io1[] __initconst = { "ref_io1", "ref_xtal", };
@@ -228,6 +145,7 @@ enum imx28_clk {
};
static struct clk *clks[clk_max];
+static struct clk_onecell_data clk_data;
static enum imx28_clk clks_init_on[] __initdata = {
cpu, hbus, xbus, emi, uart,
@@ -235,6 +153,7 @@ static enum imx28_clk clks_init_on[] __initdata = {
int __init mx28_clocks_init(void)
{
+ struct device_node *np;
int i;
clk_misc_init();
@@ -312,27 +231,15 @@ int __init mx28_clocks_init(void)
return PTR_ERR(clks[i]);
}
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx28-clkctrl");
+ if (np) {
+ clk_data.clks = clks;
+ clk_data.clk_num = ARRAY_SIZE(clks);
+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+ }
+
clk_register_clkdev(clks[clk32k], NULL, "timrot");
clk_register_clkdev(clks[enet_out], NULL, "enet_out");
- clk_register_clkdev(clks[pwm], NULL, "80064000.pwm");
- clk_register_clkdevs(clks[hbus], hbus_lookups, ARRAY_SIZE(hbus_lookups));
- clk_register_clkdevs(clks[xbus], xbus_lookups, ARRAY_SIZE(xbus_lookups));
- clk_register_clkdevs(clks[uart], uart_lookups, ARRAY_SIZE(uart_lookups));
- clk_register_clkdevs(clks[ssp0], ssp0_lookups, ARRAY_SIZE(ssp0_lookups));
- clk_register_clkdevs(clks[ssp1], ssp1_lookups, ARRAY_SIZE(ssp1_lookups));
- clk_register_clkdevs(clks[ssp2], ssp2_lookups, ARRAY_SIZE(ssp2_lookups));
- clk_register_clkdevs(clks[ssp3], ssp3_lookups, ARRAY_SIZE(ssp3_lookups));
- clk_register_clkdevs(clks[gpmi], gpmi_lookups, ARRAY_SIZE(gpmi_lookups));
- clk_register_clkdevs(clks[saif0], saif0_lookups, ARRAY_SIZE(saif0_lookups));
- clk_register_clkdevs(clks[saif1], saif1_lookups, ARRAY_SIZE(saif1_lookups));
- clk_register_clkdevs(clks[lcdif], lcdif_lookups, ARRAY_SIZE(lcdif_lookups));
- clk_register_clkdevs(clks[fec], fec_lookups, ARRAY_SIZE(fec_lookups));
- clk_register_clkdevs(clks[can0], can0_lookups, ARRAY_SIZE(can0_lookups));
- clk_register_clkdevs(clks[can1], can1_lookups, ARRAY_SIZE(can1_lookups));
- clk_register_clkdev(clks[usb0_pwr], NULL, "8007c000.usbphy");
- clk_register_clkdev(clks[usb1_pwr], NULL, "8007e000.usbphy");
- clk_register_clkdev(clks[usb0], NULL, "80080000.usb");
- clk_register_clkdev(clks[usb1], NULL, "80090000.usb");
for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
clk_prepare_enable(clks[clks_init_on[i]]);
diff --git a/drivers/clk/ux500/Makefile b/drivers/clk/ux500/Makefile
new file mode 100644
index 000000000000..858fbfe66281
--- /dev/null
+++ b/drivers/clk/ux500/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for ux500 clocks
+#
+
+# Clock types
+obj-y += clk-prcc.o
+obj-y += clk-prcmu.o
+
+# Clock definitions
+obj-y += u8500_clk.o
+obj-y += u9540_clk.o
+obj-y += u8540_clk.o
diff --git a/drivers/clk/ux500/clk-prcc.c b/drivers/clk/ux500/clk-prcc.c
new file mode 100644
index 000000000000..7eee7f768355
--- /dev/null
+++ b/drivers/clk/ux500/clk-prcc.c
@@ -0,0 +1,164 @@
+/*
+ * PRCC clock implementation for ux500 platform.
+ *
+ * Copyright (C) 2012 ST-Ericsson SA
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk-private.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <mach/hardware.h>
+
+#include "clk.h"
+
+#define PRCC_PCKEN 0x000
+#define PRCC_PCKDIS 0x004
+#define PRCC_KCKEN 0x008
+#define PRCC_KCKDIS 0x00C
+#define PRCC_PCKSR 0x010
+#define PRCC_KCKSR 0x014
+
+#define to_clk_prcc(_hw) container_of(_hw, struct clk_prcc, hw)
+
+struct clk_prcc {
+ struct clk_hw hw;
+ void __iomem *base;
+ u32 cg_sel;
+ int is_enabled;
+};
+
+/* PRCC clock operations. */
+
+static int clk_prcc_pclk_enable(struct clk_hw *hw)
+{
+ struct clk_prcc *clk = to_clk_prcc(hw);
+
+ writel(clk->cg_sel, (clk->base + PRCC_PCKEN));
+ while (!(readl(clk->base + PRCC_PCKSR) & clk->cg_sel))
+ cpu_relax();
+
+ clk->is_enabled = 1;
+ return 0;
+}
+
+static void clk_prcc_pclk_disable(struct clk_hw *hw)
+{
+ struct clk_prcc *clk = to_clk_prcc(hw);
+
+ writel(clk->cg_sel, (clk->base + PRCC_PCKDIS));
+ clk->is_enabled = 0;
+}
+
+static int clk_prcc_kclk_enable(struct clk_hw *hw)
+{
+ struct clk_prcc *clk = to_clk_prcc(hw);
+
+ writel(clk->cg_sel, (clk->base + PRCC_KCKEN));
+ while (!(readl(clk->base + PRCC_KCKSR) & clk->cg_sel))
+ cpu_relax();
+
+ clk->is_enabled = 1;
+ return 0;
+}
+
+static void clk_prcc_kclk_disable(struct clk_hw *hw)
+{
+ struct clk_prcc *clk = to_clk_prcc(hw);
+
+ writel(clk->cg_sel, (clk->base + PRCC_KCKDIS));
+ clk->is_enabled = 0;
+}
+
+static int clk_prcc_is_enabled(struct clk_hw *hw)
+{
+ struct clk_prcc *clk = to_clk_prcc(hw);
+ return clk->is_enabled;
+}
+
+static struct clk_ops clk_prcc_pclk_ops = {
+ .enable = clk_prcc_pclk_enable,
+ .disable = clk_prcc_pclk_disable,
+ .is_enabled = clk_prcc_is_enabled,
+};
+
+static struct clk_ops clk_prcc_kclk_ops = {
+ .enable = clk_prcc_kclk_enable,
+ .disable = clk_prcc_kclk_disable,
+ .is_enabled = clk_prcc_is_enabled,
+};
+
+static struct clk *clk_reg_prcc(const char *name,
+ const char *parent_name,
+ resource_size_t phy_base,
+ u32 cg_sel,
+ unsigned long flags,
+ struct clk_ops *clk_prcc_ops)
+{
+ struct clk_prcc *clk;
+ struct clk_init_data clk_prcc_init;
+ struct clk *clk_reg;
+
+ if (!name) {
+ pr_err("clk_prcc: %s invalid arguments passed\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+ clk = kzalloc(sizeof(struct clk_prcc), GFP_KERNEL);
+ if (!clk) {
+ pr_err("clk_prcc: %s could not allocate clk\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ clk->base = ioremap(phy_base, SZ_4K);
+ if (!clk->base)
+ goto free_clk;
+
+ clk->cg_sel = cg_sel;
+ clk->is_enabled = 1;
+
+ clk_prcc_init.name = name;
+ clk_prcc_init.ops = clk_prcc_ops;
+ clk_prcc_init.flags = flags;
+ clk_prcc_init.parent_names = (parent_name ? &parent_name : NULL);
+ clk_prcc_init.num_parents = (parent_name ? 1 : 0);
+ clk->hw.init = &clk_prcc_init;
+
+ clk_reg = clk_register(NULL, &clk->hw);
+ if (IS_ERR_OR_NULL(clk_reg))
+ goto unmap_clk;
+
+ return clk_reg;
+
+unmap_clk:
+ iounmap(clk->base);
+free_clk:
+ kfree(clk);
+ pr_err("clk_prcc: %s failed to register clk\n", __func__);
+ return ERR_PTR(-ENOMEM);
+}
+
+struct clk *clk_reg_prcc_pclk(const char *name,
+ const char *parent_name,
+ resource_size_t phy_base,
+ u32 cg_sel,
+ unsigned long flags)
+{
+ return clk_reg_prcc(name, parent_name, phy_base, cg_sel, flags,
+ &clk_prcc_pclk_ops);
+}
+
+struct clk *clk_reg_prcc_kclk(const char *name,
+ const char *parent_name,
+ resource_size_t phy_base,
+ u32 cg_sel,
+ unsigned long flags)
+{
+ return clk_reg_prcc(name, parent_name, phy_base, cg_sel, flags,
+ &clk_prcc_kclk_ops);
+}
diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c
new file mode 100644
index 000000000000..930cdfeb47ab
--- /dev/null
+++ b/drivers/clk/ux500/clk-prcmu.c
@@ -0,0 +1,252 @@
+/*
+ * PRCMU clock implementation for ux500 platform.
+ *
+ * Copyright (C) 2012 ST-Ericsson SA
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk-private.h>
+#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include "clk.h"
+
+#define to_clk_prcmu(_hw) container_of(_hw, struct clk_prcmu, hw)
+
+struct clk_prcmu {
+ struct clk_hw hw;
+ u8 cg_sel;
+ int is_enabled;
+};
+
+/* PRCMU clock operations. */
+
+static int clk_prcmu_prepare(struct clk_hw *hw)
+{
+ struct clk_prcmu *clk = to_clk_prcmu(hw);
+ return prcmu_request_clock(clk->cg_sel, true);
+}
+
+static void clk_prcmu_unprepare(struct clk_hw *hw)
+{
+ struct clk_prcmu *clk = to_clk_prcmu(hw);
+ if (prcmu_request_clock(clk->cg_sel, false))
+ pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
+ hw->init->name);
+}
+
+static int clk_prcmu_enable(struct clk_hw *hw)
+{
+ struct clk_prcmu *clk = to_clk_prcmu(hw);
+ clk->is_enabled = 1;
+ return 0;
+}
+
+static void clk_prcmu_disable(struct clk_hw *hw)
+{
+ struct clk_prcmu *clk = to_clk_prcmu(hw);
+ clk->is_enabled = 0;
+}
+
+static int clk_prcmu_is_enabled(struct clk_hw *hw)
+{
+ struct clk_prcmu *clk = to_clk_prcmu(hw);
+ return clk->is_enabled;
+}
+
+static unsigned long clk_prcmu_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_prcmu *clk = to_clk_prcmu(hw);
+ return prcmu_clock_rate(clk->cg_sel);
+}
+
+static long clk_prcmu_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct clk_prcmu *clk = to_clk_prcmu(hw);
+ return prcmu_round_clock_rate(clk->cg_sel, rate);
+}
+
+static int clk_prcmu_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_prcmu *clk = to_clk_prcmu(hw);
+ return prcmu_set_clock_rate(clk->cg_sel, rate);
+}
+
+static int request_ape_opp100(bool enable)
+{
+ static int reqs;
+ int err = 0;
+
+ if (enable) {
+ if (!reqs)
+ err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP,
+ "clock", 100);
+ if (!err)
+ reqs++;
+ } else {
+ reqs--;
+ if (!reqs)
+ prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
+ "clock");
+ }
+ return err;
+}
+
+static int clk_prcmu_opp_prepare(struct clk_hw *hw)
+{
+ int err;
+ struct clk_prcmu *clk = to_clk_prcmu(hw);
+
+ err = request_ape_opp100(true);
+ if (err) {
+ pr_err("clk_prcmu: %s failed to request APE OPP100 for %s.\n",
+ __func__, hw->init->name);
+ return err;
+ }
+
+ err = prcmu_request_clock(clk->cg_sel, true);
+ if (err)
+ request_ape_opp100(false);
+
+ return err;
+}
+
+static void clk_prcmu_opp_unprepare(struct clk_hw *hw)
+{
+ struct clk_prcmu *clk = to_clk_prcmu(hw);
+
+ if (prcmu_request_clock(clk->cg_sel, false))
+ goto out_error;
+ if (request_ape_opp100(false))
+ goto out_error;
+ return;
+
+out_error:
+ pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
+ hw->init->name);
+}
+
+static struct clk_ops clk_prcmu_scalable_ops = {
+ .prepare = clk_prcmu_prepare,
+ .unprepare = clk_prcmu_unprepare,
+ .enable = clk_prcmu_enable,
+ .disable = clk_prcmu_disable,
+ .is_enabled = clk_prcmu_is_enabled,
+ .recalc_rate = clk_prcmu_recalc_rate,
+ .round_rate = clk_prcmu_round_rate,
+ .set_rate = clk_prcmu_set_rate,
+};
+
+static struct clk_ops clk_prcmu_gate_ops = {
+ .prepare = clk_prcmu_prepare,
+ .unprepare = clk_prcmu_unprepare,
+ .enable = clk_prcmu_enable,
+ .disable = clk_prcmu_disable,
+ .is_enabled = clk_prcmu_is_enabled,
+ .recalc_rate = clk_prcmu_recalc_rate,
+};
+
+static struct clk_ops clk_prcmu_rate_ops = {
+ .is_enabled = clk_prcmu_is_enabled,
+ .recalc_rate = clk_prcmu_recalc_rate,
+};
+
+static struct clk_ops clk_prcmu_opp_gate_ops = {
+ .prepare = clk_prcmu_opp_prepare,
+ .unprepare = clk_prcmu_opp_unprepare,
+ .enable = clk_prcmu_enable,
+ .disable = clk_prcmu_disable,
+ .is_enabled = clk_prcmu_is_enabled,
+ .recalc_rate = clk_prcmu_recalc_rate,
+};
+
+static struct clk *clk_reg_prcmu(const char *name,
+ const char *parent_name,
+ u8 cg_sel,
+ unsigned long rate,
+ unsigned long flags,
+ struct clk_ops *clk_prcmu_ops)
+{
+ struct clk_prcmu *clk;
+ struct clk_init_data clk_prcmu_init;
+ struct clk *clk_reg;
+
+ if (!name) {
+ pr_err("clk_prcmu: %s invalid arguments passed\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+
+ clk = kzalloc(sizeof(struct clk_prcmu), GFP_KERNEL);
+ if (!clk) {
+ pr_err("clk_prcmu: %s could not allocate clk\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ clk->cg_sel = cg_sel;
+ clk->is_enabled = 1;
+ /* "rate" can be used for changing the initial frequency */
+ if (rate)
+ prcmu_set_clock_rate(cg_sel, rate);
+
+ clk_prcmu_init.name = name;
+ clk_prcmu_init.ops = clk_prcmu_ops;
+ clk_prcmu_init.flags = flags;
+ clk_prcmu_init.parent_names = (parent_name ? &parent_name : NULL);
+ clk_prcmu_init.num_parents = (parent_name ? 1 : 0);
+ clk->hw.init = &clk_prcmu_init;
+
+ clk_reg = clk_register(NULL, &clk->hw);
+ if (IS_ERR_OR_NULL(clk_reg))
+ goto free_clk;
+
+ return clk_reg;
+
+free_clk:
+ kfree(clk);
+ pr_err("clk_prcmu: %s failed to register clk\n", __func__);
+ return ERR_PTR(-ENOMEM);
+}
+
+struct clk *clk_reg_prcmu_scalable(const char *name,
+ const char *parent_name,
+ u8 cg_sel,
+ unsigned long rate,
+ unsigned long flags)
+{
+ return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
+ &clk_prcmu_scalable_ops);
+}
+
+struct clk *clk_reg_prcmu_gate(const char *name,
+ const char *parent_name,
+ u8 cg_sel,
+ unsigned long flags)
+{
+ return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
+ &clk_prcmu_gate_ops);
+}
+
+struct clk *clk_reg_prcmu_rate(const char *name,
+ const char *parent_name,
+ u8 cg_sel,
+ unsigned long flags)
+{
+ return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
+ &clk_prcmu_rate_ops);
+}
+
+struct clk *clk_reg_prcmu_opp_gate(const char *name,
+ const char *parent_name,
+ u8 cg_sel,
+ unsigned long flags)
+{
+ return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
+ &clk_prcmu_opp_gate_ops);
+}
diff --git a/drivers/clk/ux500/clk.h b/drivers/clk/ux500/clk.h
new file mode 100644
index 000000000000..836d7d16751e
--- /dev/null
+++ b/drivers/clk/ux500/clk.h
@@ -0,0 +1,48 @@
+/*
+ * Clocks for ux500 platforms
+ *
+ * Copyright (C) 2012 ST-Ericsson SA
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __UX500_CLK_H
+#define __UX500_CLK_H
+
+#include <linux/clk.h>
+
+struct clk *clk_reg_prcc_pclk(const char *name,
+ const char *parent_name,
+ unsigned int phy_base,
+ u32 cg_sel,
+ unsigned long flags);
+
+struct clk *clk_reg_prcc_kclk(const char *name,
+ const char *parent_name,
+ unsigned int phy_base,
+ u32 cg_sel,
+ unsigned long flags);
+
+struct clk *clk_reg_prcmu_scalable(const char *name,
+ const char *parent_name,
+ u8 cg_sel,
+ unsigned long rate,
+ unsigned long flags);
+
+struct clk *clk_reg_prcmu_gate(const char *name,
+ const char *parent_name,
+ u8 cg_sel,
+ unsigned long flags);
+
+struct clk *clk_reg_prcmu_rate(const char *name,
+ const char *parent_name,
+ u8 cg_sel,
+ unsigned long flags);
+
+struct clk *clk_reg_prcmu_opp_gate(const char *name,
+ const char *parent_name,
+ u8 cg_sel,
+ unsigned long flags);
+
+#endif /* __UX500_CLK_H */
diff --git a/drivers/clk/ux500/u8500_clk.c b/drivers/clk/ux500/u8500_clk.c
new file mode 100644
index 000000000000..ca4a25ed844c
--- /dev/null
+++ b/drivers/clk/ux500/u8500_clk.c
@@ -0,0 +1,477 @@
+/*
+ * Clock definitions for u8500 platform.
+ *
+ * Copyright (C) 2012 ST-Ericsson SA
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/platform_data/clk-ux500.h>
+
+#include "clk.h"
+
+void u8500_clk_init(void)
+{
+ struct prcmu_fw_version *fw_version;
+ const char *sgaclk_parent = NULL;
+ struct clk *clk;
+
+ /* Clock sources */
+ clk = clk_reg_prcmu_gate("soc0_pll", NULL, PRCMU_PLLSOC0,
+ CLK_IS_ROOT|CLK_IGNORE_UNUSED);
+ clk_register_clkdev(clk, "soc0_pll", NULL);
+
+ clk = clk_reg_prcmu_gate("soc1_pll", NULL, PRCMU_PLLSOC1,
+ CLK_IS_ROOT|CLK_IGNORE_UNUSED);
+ clk_register_clkdev(clk, "soc1_pll", NULL);
+
+ clk = clk_reg_prcmu_gate("ddr_pll", NULL, PRCMU_PLLDDR,
+ CLK_IS_ROOT|CLK_IGNORE_UNUSED);
+ clk_register_clkdev(clk, "ddr_pll", NULL);
+
+ /* FIXME: Add sys, ulp and int clocks here. */
+
+ clk = clk_register_fixed_rate(NULL, "rtc32k", "NULL",
+ CLK_IS_ROOT|CLK_IGNORE_UNUSED,
+ 32768);
+ clk_register_clkdev(clk, "clk32k", NULL);
+ clk_register_clkdev(clk, NULL, "rtc-pl031");
+
+ /* PRCMU clocks */
+ fw_version = prcmu_get_fw_version();
+ if (fw_version != NULL) {
+ switch (fw_version->project) {
+ case PRCMU_FW_PROJECT_U8500_C2:
+ case PRCMU_FW_PROJECT_U8520:
+ case PRCMU_FW_PROJECT_U8420:
+ sgaclk_parent = "soc0_pll";
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (sgaclk_parent)
+ clk = clk_reg_prcmu_gate("sgclk", sgaclk_parent,
+ PRCMU_SGACLK, 0);
+ else
+ clk = clk_reg_prcmu_gate("sgclk", NULL,
+ PRCMU_SGACLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "mali");
+
+ clk = clk_reg_prcmu_gate("uartclk", NULL, PRCMU_UARTCLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "UART");
+
+ clk = clk_reg_prcmu_gate("msp02clk", NULL, PRCMU_MSP02CLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "MSP02");
+
+ clk = clk_reg_prcmu_gate("msp1clk", NULL, PRCMU_MSP1CLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "MSP1");
+
+ clk = clk_reg_prcmu_gate("i2cclk", NULL, PRCMU_I2CCLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "I2C");
+
+ clk = clk_reg_prcmu_gate("slimclk", NULL, PRCMU_SLIMCLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "slim");
+
+ clk = clk_reg_prcmu_gate("per1clk", NULL, PRCMU_PER1CLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "PERIPH1");
+
+ clk = clk_reg_prcmu_gate("per2clk", NULL, PRCMU_PER2CLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "PERIPH2");
+
+ clk = clk_reg_prcmu_gate("per3clk", NULL, PRCMU_PER3CLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "PERIPH3");
+
+ clk = clk_reg_prcmu_gate("per5clk", NULL, PRCMU_PER5CLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "PERIPH5");
+
+ clk = clk_reg_prcmu_gate("per6clk", NULL, PRCMU_PER6CLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "PERIPH6");
+
+ clk = clk_reg_prcmu_gate("per7clk", NULL, PRCMU_PER7CLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "PERIPH7");
+
+ clk = clk_reg_prcmu_scalable("lcdclk", NULL, PRCMU_LCDCLK, 0,
+ CLK_IS_ROOT|CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "lcd");
+ clk_register_clkdev(clk, "lcd", "mcde");
+
+ clk = clk_reg_prcmu_opp_gate("bmlclk", NULL, PRCMU_BMLCLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "bml");
+
+ clk = clk_reg_prcmu_scalable("hsitxclk", NULL, PRCMU_HSITXCLK, 0,
+ CLK_IS_ROOT|CLK_SET_RATE_GATE);
+
+ clk = clk_reg_prcmu_scalable("hsirxclk", NULL, PRCMU_HSIRXCLK, 0,
+ CLK_IS_ROOT|CLK_SET_RATE_GATE);
+
+ clk = clk_reg_prcmu_scalable("hdmiclk", NULL, PRCMU_HDMICLK, 0,
+ CLK_IS_ROOT|CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "hdmi");
+ clk_register_clkdev(clk, "hdmi", "mcde");
+
+ clk = clk_reg_prcmu_gate("apeatclk", NULL, PRCMU_APEATCLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "apeat");
+
+ clk = clk_reg_prcmu_gate("apetraceclk", NULL, PRCMU_APETRACECLK,
+ CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "apetrace");
+
+ clk = clk_reg_prcmu_gate("mcdeclk", NULL, PRCMU_MCDECLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "mcde");
+ clk_register_clkdev(clk, "mcde", "mcde");
+ clk_register_clkdev(clk, "dsisys", "dsilink.0");
+ clk_register_clkdev(clk, "dsisys", "dsilink.1");
+ clk_register_clkdev(clk, "dsisys", "dsilink.2");
+
+ clk = clk_reg_prcmu_opp_gate("ipi2cclk", NULL, PRCMU_IPI2CCLK,
+ CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "ipi2");
+
+ clk = clk_reg_prcmu_gate("dsialtclk", NULL, PRCMU_DSIALTCLK,
+ CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "dsialt");
+
+ clk = clk_reg_prcmu_gate("dmaclk", NULL, PRCMU_DMACLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "dma40.0");
+
+ clk = clk_reg_prcmu_gate("b2r2clk", NULL, PRCMU_B2R2CLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "b2r2");
+ clk_register_clkdev(clk, NULL, "b2r2_core");
+ clk_register_clkdev(clk, NULL, "U8500-B2R2.0");
+
+ clk = clk_reg_prcmu_scalable("tvclk", NULL, PRCMU_TVCLK, 0,
+ CLK_IS_ROOT|CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "tv");
+ clk_register_clkdev(clk, "tv", "mcde");
+
+ clk = clk_reg_prcmu_gate("sspclk", NULL, PRCMU_SSPCLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "SSP");
+
+ clk = clk_reg_prcmu_gate("rngclk", NULL, PRCMU_RNGCLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "rngclk");
+
+ clk = clk_reg_prcmu_gate("uiccclk", NULL, PRCMU_UICCCLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "uicc");
+
+ /*
+ * FIXME: The MTU clocks might need some kind of "parent muxed join"
+ * and these have no K-clocks. For now, we ignore the missing
+ * connection to the corresponding P-clocks, p6_mtu0_clk and
+ * p6_mtu1_clk. Instead timclk is used which is the valid parent.
+ */
+ clk = clk_reg_prcmu_gate("timclk", NULL, PRCMU_TIMCLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "mtu0");
+ clk_register_clkdev(clk, NULL, "mtu1");
+
+ clk = clk_reg_prcmu_gate("sdmmcclk", NULL, PRCMU_SDMMCCLK, CLK_IS_ROOT);
+ clk_register_clkdev(clk, NULL, "sdmmc");
+
+
+ clk = clk_reg_prcmu_scalable("dsi_pll", "hdmiclk",
+ PRCMU_PLLDSI, 0, CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, "dsihs2", "mcde");
+ clk_register_clkdev(clk, "dsihs2", "dsilink.2");
+
+
+ clk = clk_reg_prcmu_scalable("dsi0clk", "dsi_pll",
+ PRCMU_DSI0CLK, 0, CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, "dsihs0", "mcde");
+ clk_register_clkdev(clk, "dsihs0", "dsilink.0");
+
+ clk = clk_reg_prcmu_scalable("dsi1clk", "dsi_pll",
+ PRCMU_DSI1CLK, 0, CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, "dsihs1", "mcde");
+ clk_register_clkdev(clk, "dsihs1", "dsilink.1");
+
+ clk = clk_reg_prcmu_scalable("dsi0escclk", "tvclk",
+ PRCMU_DSI0ESCCLK, 0, CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, "dsilp0", "dsilink.0");
+ clk_register_clkdev(clk, "dsilp0", "mcde");
+
+ clk = clk_reg_prcmu_scalable("dsi1escclk", "tvclk",
+ PRCMU_DSI1ESCCLK, 0, CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, "dsilp1", "dsilink.1");
+ clk_register_clkdev(clk, "dsilp1", "mcde");
+
+ clk = clk_reg_prcmu_scalable("dsi2escclk", "tvclk",
+ PRCMU_DSI2ESCCLK, 0, CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, "dsilp2", "dsilink.2");
+ clk_register_clkdev(clk, "dsilp2", "mcde");
+
+ clk = clk_reg_prcmu_rate("smp_twd", NULL, PRCMU_ARMSS,
+ CLK_IS_ROOT|CLK_GET_RATE_NOCACHE|
+ CLK_IGNORE_UNUSED);
+ clk_register_clkdev(clk, NULL, "smp_twd");
+
+ /*
+ * FIXME: Add special handled PRCMU clocks here:
+ * 1. clk_arm, use PRCMU_ARMCLK.
+ * 2. clkout0yuv, use PRCMU as parent + need regulator + pinctrl.
+ * 3. ab9540_clkout1yuv, see clkout0yuv
+ */
+
+ /* PRCC P-clocks */
+ clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", U8500_CLKRST1_BASE,
+ BIT(0), 0);
+ clk_register_clkdev(clk, "apb_pclk", "uart0");
+
+ clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", U8500_CLKRST1_BASE,
+ BIT(1), 0);
+ clk_register_clkdev(clk, "apb_pclk", "uart1");
+
+ clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", U8500_CLKRST1_BASE,
+ BIT(2), 0);
+ clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", U8500_CLKRST1_BASE,
+ BIT(3), 0);
+ clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", U8500_CLKRST1_BASE,
+ BIT(4), 0);
+
+ clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", U8500_CLKRST1_BASE,
+ BIT(5), 0);
+ clk_register_clkdev(clk, "apb_pclk", "sdi0");
+
+ clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", U8500_CLKRST1_BASE,
+ BIT(6), 0);
+
+ clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", U8500_CLKRST1_BASE,
+ BIT(7), 0);
+ clk_register_clkdev(clk, NULL, "spi3");
+
+ clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", U8500_CLKRST1_BASE,
+ BIT(8), 0);
+
+ clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", U8500_CLKRST1_BASE,
+ BIT(9), 0);
+ clk_register_clkdev(clk, NULL, "gpio.0");
+ clk_register_clkdev(clk, NULL, "gpio.1");
+ clk_register_clkdev(clk, NULL, "gpioblock0");
+
+ clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", U8500_CLKRST1_BASE,
+ BIT(10), 0);
+ clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", U8500_CLKRST1_BASE,
+ BIT(11), 0);
+
+ clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", U8500_CLKRST2_BASE,
+ BIT(0), 0);
+
+ clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", U8500_CLKRST2_BASE,
+ BIT(1), 0);
+ clk_register_clkdev(clk, NULL, "spi2");
+
+ clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", U8500_CLKRST2_BASE,
+ BIT(2), 0);
+ clk_register_clkdev(clk, NULL, "spi1");
+
+ clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", U8500_CLKRST2_BASE,
+ BIT(3), 0);
+ clk_register_clkdev(clk, NULL, "pwl");
+
+ clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", U8500_CLKRST2_BASE,
+ BIT(4), 0);
+ clk_register_clkdev(clk, "apb_pclk", "sdi4");
+
+ clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", U8500_CLKRST2_BASE,
+ BIT(5), 0);
+
+ clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", U8500_CLKRST2_BASE,
+ BIT(6), 0);
+ clk_register_clkdev(clk, "apb_pclk", "sdi1");
+
+
+ clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", U8500_CLKRST2_BASE,
+ BIT(7), 0);
+ clk_register_clkdev(clk, "apb_pclk", "sdi3");
+
+ clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", U8500_CLKRST2_BASE,
+ BIT(8), 0);
+ clk_register_clkdev(clk, NULL, "spi0");
+
+ clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", U8500_CLKRST2_BASE,
+ BIT(9), 0);
+ clk_register_clkdev(clk, "hsir_hclk", "ste_hsi.0");
+
+ clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", U8500_CLKRST2_BASE,
+ BIT(10), 0);
+ clk_register_clkdev(clk, "hsit_hclk", "ste_hsi.0");
+
+ clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", U8500_CLKRST2_BASE,
+ BIT(11), 0);
+ clk_register_clkdev(clk, NULL, "gpio.6");
+ clk_register_clkdev(clk, NULL, "gpio.7");
+ clk_register_clkdev(clk, NULL, "gpioblock1");
+
+ clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", U8500_CLKRST2_BASE,
+ BIT(11), 0);
+
+ clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", U8500_CLKRST3_BASE,
+ BIT(0), 0);
+ clk_register_clkdev(clk, NULL, "fsmc");
+
+ clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", U8500_CLKRST3_BASE,
+ BIT(1), 0);
+ clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", U8500_CLKRST3_BASE,
+ BIT(2), 0);
+ clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", U8500_CLKRST3_BASE,
+ BIT(3), 0);
+
+ clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", U8500_CLKRST3_BASE,
+ BIT(4), 0);
+ clk_register_clkdev(clk, "apb_pclk", "sdi2");
+
+ clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", U8500_CLKRST3_BASE,
+ BIT(5), 0);
+
+ clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", U8500_CLKRST3_BASE,
+ BIT(6), 0);
+ clk_register_clkdev(clk, "apb_pclk", "uart2");
+
+ clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", U8500_CLKRST3_BASE,
+ BIT(7), 0);
+ clk_register_clkdev(clk, "apb_pclk", "sdi5");
+
+ clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", U8500_CLKRST3_BASE,
+ BIT(8), 0);
+ clk_register_clkdev(clk, NULL, "gpio.2");
+ clk_register_clkdev(clk, NULL, "gpio.3");
+ clk_register_clkdev(clk, NULL, "gpio.4");
+ clk_register_clkdev(clk, NULL, "gpio.5");
+ clk_register_clkdev(clk, NULL, "gpioblock2");
+
+ clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", U8500_CLKRST5_BASE,
+ BIT(0), 0);
+ clk_register_clkdev(clk, "usb", "musb-ux500.0");
+
+ clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", U8500_CLKRST5_BASE,
+ BIT(1), 0);
+ clk_register_clkdev(clk, NULL, "gpio.8");
+ clk_register_clkdev(clk, NULL, "gpioblock3");
+
+ clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", U8500_CLKRST6_BASE,
+ BIT(0), 0);
+
+ clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", U8500_CLKRST6_BASE,
+ BIT(1), 0);
+ clk_register_clkdev(clk, NULL, "cryp0");
+ clk_register_clkdev(clk, NULL, "cryp1");
+
+ clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", U8500_CLKRST6_BASE,
+ BIT(2), 0);
+ clk_register_clkdev(clk, NULL, "hash0");
+
+ clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", U8500_CLKRST6_BASE,
+ BIT(3), 0);
+ clk_register_clkdev(clk, NULL, "pka");
+
+ clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", U8500_CLKRST6_BASE,
+ BIT(4), 0);
+ clk_register_clkdev(clk, NULL, "hash1");
+
+ clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", U8500_CLKRST6_BASE,
+ BIT(5), 0);
+ clk_register_clkdev(clk, NULL, "cfgreg");
+
+ clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", U8500_CLKRST6_BASE,
+ BIT(6), 0);
+ clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", U8500_CLKRST6_BASE,
+ BIT(7), 0);
+
+ /* PRCC K-clocks
+ *
+ * FIXME: Some drivers requires PERPIH[n| to be automatically enabled
+ * by enabling just the K-clock, even if it is not a valid parent to
+ * the K-clock. Until drivers get fixed we might need some kind of
+ * "parent muxed join".
+ */
+
+ /* Periph1 */
+ clk = clk_reg_prcc_kclk("p1_uart0_kclk", "uartclk",
+ U8500_CLKRST1_BASE, BIT(0), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "uart0");
+
+ clk = clk_reg_prcc_kclk("p1_uart1_kclk", "uartclk",
+ U8500_CLKRST1_BASE, BIT(1), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "uart1");
+
+ clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk",
+ U8500_CLKRST1_BASE, BIT(2), CLK_SET_RATE_GATE);
+ clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk",
+ U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE);
+ clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk",
+ U8500_CLKRST1_BASE, BIT(4), CLK_SET_RATE_GATE);
+
+ clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmcclk",
+ U8500_CLKRST1_BASE, BIT(5), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "sdi0");
+
+ clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk",
+ U8500_CLKRST1_BASE, BIT(6), CLK_SET_RATE_GATE);
+ clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk",
+ U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE);
+ /* FIXME: Redefinition of BIT(3). */
+ clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk",
+ U8500_CLKRST1_BASE, BIT(9), CLK_SET_RATE_GATE);
+ clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk",
+ U8500_CLKRST1_BASE, BIT(10), CLK_SET_RATE_GATE);
+
+ /* Periph2 */
+ clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk",
+ U8500_CLKRST2_BASE, BIT(0), CLK_SET_RATE_GATE);
+
+ clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmcclk",
+ U8500_CLKRST2_BASE, BIT(2), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "sdi4");
+
+ clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk",
+ U8500_CLKRST2_BASE, BIT(3), CLK_SET_RATE_GATE);
+
+ clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmcclk",
+ U8500_CLKRST2_BASE, BIT(4), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "sdi1");
+
+ clk = clk_reg_prcc_kclk("p2_sdi3_kclk", "sdmmcclk",
+ U8500_CLKRST2_BASE, BIT(5), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "sdi3");
+
+ /* Note that rate is received from parent. */
+ clk = clk_reg_prcc_kclk("p2_ssirx_kclk", "hsirxclk",
+ U8500_CLKRST2_BASE, BIT(6),
+ CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
+ clk = clk_reg_prcc_kclk("p2_ssitx_kclk", "hsitxclk",
+ U8500_CLKRST2_BASE, BIT(7),
+ CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
+
+ /* Periph3 */
+ clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk",
+ U8500_CLKRST3_BASE, BIT(1), CLK_SET_RATE_GATE);
+ clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk",
+ U8500_CLKRST3_BASE, BIT(2), CLK_SET_RATE_GATE);
+ clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk",
+ U8500_CLKRST3_BASE, BIT(3), CLK_SET_RATE_GATE);
+
+ clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmcclk",
+ U8500_CLKRST3_BASE, BIT(4), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "sdi2");
+
+ clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k",
+ U8500_CLKRST3_BASE, BIT(5), CLK_SET_RATE_GATE);
+
+ clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk",
+ U8500_CLKRST3_BASE, BIT(6), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "uart2");
+
+ clk = clk_reg_prcc_kclk("p3_sdi5_kclk", "sdmmcclk",
+ U8500_CLKRST3_BASE, BIT(7), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "sdi5");
+
+ /* Periph6 */
+ clk = clk_reg_prcc_kclk("p3_rng_kclk", "rngclk",
+ U8500_CLKRST6_BASE, BIT(0), CLK_SET_RATE_GATE);
+
+}
diff --git a/drivers/clk/ux500/u8540_clk.c b/drivers/clk/ux500/u8540_clk.c
new file mode 100644
index 000000000000..10adfd2ead21
--- /dev/null
+++ b/drivers/clk/ux500/u8540_clk.c
@@ -0,0 +1,21 @@
+/*
+ * Clock definitions for u8540 platform.
+ *
+ * Copyright (C) 2012 ST-Ericsson SA
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/platform_data/clk-ux500.h>
+
+#include "clk.h"
+
+void u8540_clk_init(void)
+{
+ /* register clocks here */
+}
diff --git a/drivers/clk/ux500/u9540_clk.c b/drivers/clk/ux500/u9540_clk.c
new file mode 100644
index 000000000000..dbc0191e16c8
--- /dev/null
+++ b/drivers/clk/ux500/u9540_clk.c
@@ -0,0 +1,21 @@
+/*
+ * Clock definitions for u9540 platform.
+ *
+ * Copyright (C) 2012 ST-Ericsson SA
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/platform_data/clk-ux500.h>
+
+#include "clk.h"
+
+void u9540_clk_init(void)
+{
+ /* register clocks here */
+}
diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile
index 50cf6a2ee693..c0a0f6478798 100644
--- a/drivers/clk/versatile/Makefile
+++ b/drivers/clk/versatile/Makefile
@@ -1,3 +1,4 @@
# Makefile for Versatile-specific clocks
obj-$(CONFIG_ICST) += clk-icst.o
obj-$(CONFIG_ARCH_INTEGRATOR) += clk-integrator.o
+obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o
diff --git a/drivers/clk/versatile/clk-realview.c b/drivers/clk/versatile/clk-realview.c
new file mode 100644
index 000000000000..e21a99cef378
--- /dev/null
+++ b/drivers/clk/versatile/clk-realview.c
@@ -0,0 +1,114 @@
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+
+#include "clk-icst.h"
+
+/*
+ * Implementation of the ARM RealView clock trees.
+ */
+
+static void __iomem *sys_lock;
+static void __iomem *sys_vcoreg;
+
+/**
+ * realview_oscvco_get() - get ICST OSC settings for the RealView
+ */
+static struct icst_vco realview_oscvco_get(void)
+{
+ u32 val;
+ struct icst_vco vco;
+
+ val = readl(sys_vcoreg);
+ vco.v = val & 0x1ff;
+ vco.r = (val >> 9) & 0x7f;
+ vco.s = (val >> 16) & 03;
+ return vco;
+}
+
+static void realview_oscvco_set(struct icst_vco vco)
+{
+ u32 val;
+
+ val = readl(sys_vcoreg) & ~0x7ffff;
+ val |= vco.v | (vco.r << 9) | (vco.s << 16);
+
+ /* This magic unlocks the CM VCO so it can be controlled */
+ writel(0xa05f, sys_lock);
+ writel(val, sys_vcoreg);
+ /* This locks the CM again */
+ writel(0, sys_lock);
+}
+
+static const struct icst_params realview_oscvco_params = {
+ .ref = 24000000,
+ .vco_max = ICST307_VCO_MAX,
+ .vco_min = ICST307_VCO_MIN,
+ .vd_min = 4 + 8,
+ .vd_max = 511 + 8,
+ .rd_min = 1 + 2,
+ .rd_max = 127 + 2,
+ .s2div = icst307_s2div,
+ .idx2s = icst307_idx2s,
+};
+
+static const struct clk_icst_desc __initdata realview_icst_desc = {
+ .params = &realview_oscvco_params,
+ .getvco = realview_oscvco_get,
+ .setvco = realview_oscvco_set,
+};
+
+/*
+ * realview_clk_init() - set up the RealView clock tree
+ */
+void __init realview_clk_init(void __iomem *sysbase, bool is_pb1176)
+{
+ struct clk *clk;
+
+ sys_lock = sysbase + REALVIEW_SYS_LOCK_OFFSET;
+ if (is_pb1176)
+ sys_vcoreg = sysbase + REALVIEW_SYS_OSC0_OFFSET;
+ else
+ sys_vcoreg = sysbase + REALVIEW_SYS_OSC4_OFFSET;
+
+
+ /* APB clock dummy */
+ clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
+ clk_register_clkdev(clk, "apb_pclk", NULL);
+
+ /* 24 MHz clock */
+ clk = clk_register_fixed_rate(NULL, "clk24mhz", NULL, CLK_IS_ROOT,
+ 24000000);
+ clk_register_clkdev(clk, NULL, "dev:uart0");
+ clk_register_clkdev(clk, NULL, "dev:uart1");
+ clk_register_clkdev(clk, NULL, "dev:uart2");
+ clk_register_clkdev(clk, NULL, "fpga:kmi0");
+ clk_register_clkdev(clk, NULL, "fpga:kmi1");
+ clk_register_clkdev(clk, NULL, "fpga:mmc0");
+ clk_register_clkdev(clk, NULL, "dev:ssp0");
+ if (is_pb1176) {
+ /*
+ * UART3 is on the dev chip in PB1176
+ * UART4 only exists in PB1176
+ */
+ clk_register_clkdev(clk, NULL, "dev:uart3");
+ clk_register_clkdev(clk, NULL, "dev:uart4");
+ } else
+ clk_register_clkdev(clk, NULL, "fpga:uart3");
+
+
+ /* 1 MHz clock */
+ clk = clk_register_fixed_rate(NULL, "clk1mhz", NULL, CLK_IS_ROOT,
+ 1000000);
+ clk_register_clkdev(clk, NULL, "sp804");
+
+ /* ICST VCO clock */
+ clk = icst_clk_register(NULL, &realview_icst_desc);
+ clk_register_clkdev(clk, NULL, "dev:clcd");
+ clk_register_clkdev(clk, NULL, "issp:clcd");
+}
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index b65d0c56ab35..d496a55f6bb0 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o
obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o
obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o
obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o
+obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o
diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c
new file mode 100644
index 000000000000..bc19f12c20ce
--- /dev/null
+++ b/drivers/clocksource/bcm2835_timer.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2012 Simon Arlott
+ *
+ * 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/bcm2835_timer.h>
+#include <linux/bitops.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/interrupt.h>
+#include <linux/irqreturn.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <asm/sched_clock.h>
+#include <asm/irq.h>
+
+#define REG_CONTROL 0x00
+#define REG_COUNTER_LO 0x04
+#define REG_COUNTER_HI 0x08
+#define REG_COMPARE(n) (0x0c + (n) * 4)
+#define MAX_TIMER 3
+#define DEFAULT_TIMER 3
+
+struct bcm2835_timer {
+ void __iomem *control;
+ void __iomem *compare;
+ int match_mask;
+ struct clock_event_device evt;
+ struct irqaction act;
+};
+
+static void __iomem *system_clock __read_mostly;
+
+static u32 notrace bcm2835_sched_read(void)
+{
+ return readl_relaxed(system_clock);
+}
+
+static void bcm2835_time_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt_dev)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_RESUME:
+ break;
+ default:
+ WARN(1, "%s: unhandled event mode %d\n", __func__, mode);
+ break;
+ }
+}
+
+static int bcm2835_time_set_next_event(unsigned long event,
+ struct clock_event_device *evt_dev)
+{
+ struct bcm2835_timer *timer = container_of(evt_dev,
+ struct bcm2835_timer, evt);
+ writel_relaxed(readl_relaxed(system_clock) + event,
+ timer->compare);
+ return 0;
+}
+
+static irqreturn_t bcm2835_time_interrupt(int irq, void *dev_id)
+{
+ struct bcm2835_timer *timer = dev_id;
+ void (*event_handler)(struct clock_event_device *);
+ if (readl_relaxed(timer->control) & timer->match_mask) {
+ writel_relaxed(timer->match_mask, timer->control);
+
+ event_handler = ACCESS_ONCE(timer->evt.event_handler);
+ if (event_handler)
+ event_handler(&timer->evt);
+ return IRQ_HANDLED;
+ } else {
+ return IRQ_NONE;
+ }
+}
+
+static struct of_device_id bcm2835_time_match[] __initconst = {
+ { .compatible = "brcm,bcm2835-system-timer" },
+ {}
+};
+
+static void __init bcm2835_time_init(void)
+{
+ struct device_node *node;
+ void __iomem *base;
+ u32 freq;
+ int irq;
+ struct bcm2835_timer *timer;
+
+ node = of_find_matching_node(NULL, bcm2835_time_match);
+ if (!node)
+ panic("No bcm2835 timer node");
+
+ base = of_iomap(node, 0);
+ if (!base)
+ panic("Can't remap registers");
+
+ if (of_property_read_u32(node, "clock-frequency", &freq))
+ panic("Can't read clock-frequency");
+
+ system_clock = base + REG_COUNTER_LO;
+ setup_sched_clock(bcm2835_sched_read, 32, freq);
+
+ clocksource_mmio_init(base + REG_COUNTER_LO, node->name,
+ freq, 300, 32, clocksource_mmio_readl_up);
+
+ irq = irq_of_parse_and_map(node, DEFAULT_TIMER);
+ if (irq <= 0)
+ panic("Can't parse IRQ");
+
+ timer = kzalloc(sizeof(*timer), GFP_KERNEL);
+ if (!timer)
+ panic("Can't allocate timer struct\n");
+
+ timer->control = base + REG_CONTROL;
+ timer->compare = base + REG_COMPARE(DEFAULT_TIMER);
+ timer->match_mask = BIT(DEFAULT_TIMER);
+ timer->evt.name = node->name;
+ timer->evt.rating = 300;
+ timer->evt.features = CLOCK_EVT_FEAT_ONESHOT;
+ timer->evt.set_mode = bcm2835_time_set_mode;
+ timer->evt.set_next_event = bcm2835_time_set_next_event;
+ timer->evt.cpumask = cpumask_of(0);
+ timer->act.name = node->name;
+ timer->act.flags = IRQF_TIMER | IRQF_SHARED;
+ timer->act.dev_id = timer;
+ timer->act.handler = bcm2835_time_interrupt;
+
+ if (setup_irq(irq, &timer->act))
+ panic("Can't set up timer IRQ\n");
+
+ clockevents_config_and_register(&timer->evt, freq, 0xf, 0xffffffff);
+
+ pr_info("bcm2835: system timer (irq = %d)\n", irq);
+}
+
+struct sys_timer bcm2835_timer = {
+ .init = bcm2835_time_init,
+};
diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c
index 21c1a87032b7..24ccae453e79 100644
--- a/drivers/crypto/mv_cesa.c
+++ b/drivers/crypto/mv_cesa.c
@@ -19,6 +19,9 @@
#include <linux/clk.h>
#include <crypto/internal/hash.h>
#include <crypto/sha.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
#include "mv_cesa.h"
@@ -1062,7 +1065,10 @@ static int mv_probe(struct platform_device *pdev)
goto err_unmap_reg;
}
- irq = platform_get_irq(pdev, 0);
+ if (pdev->dev.of_node)
+ irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+ else
+ irq = platform_get_irq(pdev, 0);
if (irq < 0 || irq == NO_IRQ) {
ret = irq;
goto err_unmap_sram;
@@ -1170,12 +1176,19 @@ static int mv_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id mv_cesa_of_match_table[] = {
+ { .compatible = "marvell,orion-crypto", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, mv_cesa_of_match_table);
+
static struct platform_driver marvell_crypto = {
.probe = mv_probe,
- .remove = mv_remove,
+ .remove = __devexit_p(mv_remove),
.driver = {
.owner = THIS_MODULE,
.name = "mv_crypto",
+ .of_match_table = of_match_ptr(mv_cesa_of_match_table),
},
};
MODULE_ALIAS("platform:mv_crypto");
diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c
index 1c307e1b840c..ef17e3871c71 100644
--- a/drivers/crypto/ux500/cryp/cryp_core.c
+++ b/drivers/crypto/ux500/cryp/cryp_core.c
@@ -32,7 +32,7 @@
#include <plat/ste_dma40.h>
-#include <mach/crypto-ux500.h>
+#include <linux/platform_data/crypto-ux500.h>
#include <mach/hardware.h>
#include "cryp_p.h"
diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c
index 08d5032cb564..08765072a2b3 100644
--- a/drivers/crypto/ux500/hash/hash_core.c
+++ b/drivers/crypto/ux500/hash/hash_core.c
@@ -31,7 +31,7 @@
#include <crypto/scatterwalk.h>
#include <crypto/algapi.h>
-#include <mach/crypto-ux500.h>
+#include <linux/platform_data/crypto-ux500.h>
#include <mach/hardware.h>
#include "hash_alg.h"
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
index 8a6c8e8b2940..116e4adffb08 100644
--- a/drivers/dma/at_hdmac_regs.h
+++ b/drivers/dma/at_hdmac_regs.h
@@ -11,7 +11,7 @@
#ifndef AT_HDMAC_REGS_H
#define AT_HDMAC_REGS_H
-#include <mach/at_hdmac.h>
+#include <linux/platform_data/dma-atmel.h>
#define AT_DMA_MAX_NR_CHANNELS 8
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
index c64917ec313d..4aeaea77f72e 100644
--- a/drivers/dma/ep93xx_dma.c
+++ b/drivers/dma/ep93xx_dma.c
@@ -26,7 +26,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <mach/dma.h>
+#include <linux/platform_data/dma-ep93xx.h>
#include "dmaengine.h"
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index 5084975d793c..b90aaec4ccc4 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -28,7 +28,7 @@
#include <linux/module.h>
#include <asm/irq.h>
-#include <mach/dma.h>
+#include <linux/platform_data/dma-imx.h>
#include <mach/hardware.h>
#include "dmaengine.h"
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 1dc2a4ad0026..1b781d6ac425 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -38,8 +38,8 @@
#include <linux/of_device.h>
#include <asm/irq.h>
-#include <mach/sdma.h>
-#include <mach/dma.h>
+#include <linux/platform_data/dma-imx-sdma.h>
+#include <linux/platform_data/dma-imx.h>
#include <mach/hardware.h>
#include "dmaengine.h"
diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c
index 8a15cf2163dc..07fa48688ba9 100644
--- a/drivers/dma/mmp_tdma.c
+++ b/drivers/dma/mmp_tdma.c
@@ -19,7 +19,7 @@
#include <linux/platform_device.h>
#include <linux/device.h>
#include <mach/regs-icu.h>
-#include <mach/sram.h>
+#include <linux/platform_data/dma-mmp_tdma.h>
#include "dmaengine.h"
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 0b12e68bf79c..e362e2b80efb 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -26,7 +26,7 @@
#include <linux/platform_device.h>
#include <linux/memory.h>
#include <linux/clk.h>
-#include <plat/mv_xor.h>
+#include <linux/platform_data/dma-mv_xor.h>
#include "dmaengine.h"
#include "mv_xor.h"
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index ba7926f5c099..66a59510887f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -150,6 +150,12 @@ config GPIO_MSM_V2
Qualcomm MSM chips. Most of the pins on the MSM can be
selected for GPIO, and are controlled by this driver.
+config GPIO_MVEBU
+ def_bool y
+ depends on ARCH_MVEBU
+ select GPIO_GENERIC
+ select GENERIC_IRQ_CHIP
+
config GPIO_MXC
def_bool y
depends on ARCH_MXC
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 153caceeb053..1a33e6716e10 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o
obj-$(CONFIG_GPIO_MSM_V1) += gpio-msm-v1.o
obj-$(CONFIG_GPIO_MSM_V2) += gpio-msm-v2.o
+obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o
obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o
obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o
obj-$(CONFIG_ARCH_OMAP) += gpio-omap.o
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
new file mode 100644
index 000000000000..902af437eaf2
--- /dev/null
+++ b/drivers/gpio/gpio-mvebu.c
@@ -0,0 +1,679 @@
+/*
+ * GPIO driver for Marvell SoCs
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ * Andrew Lunn <andrew@lunn.ch>
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * This driver is a fairly straightforward GPIO driver for the
+ * complete family of Marvell EBU SoC platforms (Orion, Dove,
+ * Kirkwood, Discovery, Armada 370/XP). The only complexity of this
+ * driver is the different register layout that exists between the
+ * non-SMP platforms (Orion, Dove, Kirkwood, Armada 370) and the SMP
+ * platforms (MV78200 from the Discovery family and the Armada
+ * XP). Therefore, this driver handles three variants of the GPIO
+ * block:
+ * - the basic variant, called "orion-gpio", with the simplest
+ * register set. Used on Orion, Dove, Kirkwoord, Armada 370 and
+ * non-SMP Discovery systems
+ * - the mv78200 variant for MV78200 Discovery systems. This variant
+ * turns the edge mask and level mask registers into CPU0 edge
+ * mask/level mask registers, and adds CPU1 edge mask/level mask
+ * registers.
+ * - the armadaxp variant for Armada XP systems. This variant keeps
+ * the normal cause/edge mask/level mask registers when the global
+ * interrupts are used, but adds per-CPU cause/edge mask/level mask
+ * registers n a separate memory area for the per-CPU GPIO
+ * interrupts.
+ */
+
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/of_irq.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/consumer.h>
+
+/*
+ * GPIO unit register offsets.
+ */
+#define GPIO_OUT_OFF 0x0000
+#define GPIO_IO_CONF_OFF 0x0004
+#define GPIO_BLINK_EN_OFF 0x0008
+#define GPIO_IN_POL_OFF 0x000c
+#define GPIO_DATA_IN_OFF 0x0010
+#define GPIO_EDGE_CAUSE_OFF 0x0014
+#define GPIO_EDGE_MASK_OFF 0x0018
+#define GPIO_LEVEL_MASK_OFF 0x001c
+
+/* The MV78200 has per-CPU registers for edge mask and level mask */
+#define GPIO_EDGE_MASK_MV78200_OFF(cpu) ((cpu) ? 0x30 : 0x18)
+#define GPIO_LEVEL_MASK_MV78200_OFF(cpu) ((cpu) ? 0x34 : 0x1C)
+
+/* The Armada XP has per-CPU registers for interrupt cause, interrupt
+ * mask and interrupt level mask. Those are relative to the
+ * percpu_membase. */
+#define GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu) ((cpu) * 0x4)
+#define GPIO_EDGE_MASK_ARMADAXP_OFF(cpu) (0x10 + (cpu) * 0x4)
+#define GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu) (0x20 + (cpu) * 0x4)
+
+#define MVEBU_GPIO_SOC_VARIANT_ORION 0x1
+#define MVEBU_GPIO_SOC_VARIANT_MV78200 0x2
+#define MVEBU_GPIO_SOC_VARIANT_ARMADAXP 0x3
+
+#define MVEBU_MAX_GPIO_PER_BANK 32
+
+struct mvebu_gpio_chip {
+ struct gpio_chip chip;
+ spinlock_t lock;
+ void __iomem *membase;
+ void __iomem *percpu_membase;
+ unsigned int irqbase;
+ struct irq_domain *domain;
+ int soc_variant;
+};
+
+/*
+ * Functions returning addresses of individual registers for a given
+ * GPIO controller.
+ */
+static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip)
+{
+ return mvchip->membase + GPIO_OUT_OFF;
+}
+
+static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip)
+{
+ return mvchip->membase + GPIO_IO_CONF_OFF;
+}
+
+static inline void __iomem *mvebu_gpioreg_in_pol(struct mvebu_gpio_chip *mvchip)
+{
+ return mvchip->membase + GPIO_IN_POL_OFF;
+}
+
+static inline void __iomem *mvebu_gpioreg_data_in(struct mvebu_gpio_chip *mvchip)
+{
+ return mvchip->membase + GPIO_DATA_IN_OFF;
+}
+
+static inline void __iomem *mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip)
+{
+ int cpu;
+
+ switch(mvchip->soc_variant) {
+ case MVEBU_GPIO_SOC_VARIANT_ORION:
+ case MVEBU_GPIO_SOC_VARIANT_MV78200:
+ return mvchip->membase + GPIO_EDGE_CAUSE_OFF;
+ case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
+ cpu = smp_processor_id();
+ return mvchip->percpu_membase + GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu);
+ default:
+ BUG();
+ }
+}
+
+static inline void __iomem *mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvchip)
+{
+ int cpu;
+
+ switch(mvchip->soc_variant) {
+ case MVEBU_GPIO_SOC_VARIANT_ORION:
+ return mvchip->membase + GPIO_EDGE_MASK_OFF;
+ case MVEBU_GPIO_SOC_VARIANT_MV78200:
+ cpu = smp_processor_id();
+ return mvchip->membase + GPIO_EDGE_MASK_MV78200_OFF(cpu);
+ case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
+ cpu = smp_processor_id();
+ return mvchip->percpu_membase + GPIO_EDGE_MASK_ARMADAXP_OFF(cpu);
+ default:
+ BUG();
+ }
+}
+
+static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip)
+{
+ int cpu;
+
+ switch(mvchip->soc_variant) {
+ case MVEBU_GPIO_SOC_VARIANT_ORION:
+ return mvchip->membase + GPIO_LEVEL_MASK_OFF;
+ case MVEBU_GPIO_SOC_VARIANT_MV78200:
+ cpu = smp_processor_id();
+ return mvchip->membase + GPIO_LEVEL_MASK_MV78200_OFF(cpu);
+ case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
+ cpu = smp_processor_id();
+ return mvchip->percpu_membase + GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu);
+ default:
+ BUG();
+ }
+}
+
+/*
+ * Functions implementing the gpio_chip methods
+ */
+
+int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin)
+{
+ return pinctrl_request_gpio(chip->base + pin);
+}
+
+void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin)
+{
+ pinctrl_free_gpio(chip->base + pin);
+}
+
+static void mvebu_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
+{
+ struct mvebu_gpio_chip *mvchip =
+ container_of(chip, struct mvebu_gpio_chip, chip);
+ unsigned long flags;
+ u32 u;
+
+ spin_lock_irqsave(&mvchip->lock, flags);
+ u = readl_relaxed(mvebu_gpioreg_out(mvchip));
+ if (value)
+ u |= 1 << pin;
+ else
+ u &= ~(1 << pin);
+ writel_relaxed(u, mvebu_gpioreg_out(mvchip));
+ spin_unlock_irqrestore(&mvchip->lock, flags);
+}
+
+static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin)
+{
+ struct mvebu_gpio_chip *mvchip =
+ container_of(chip, struct mvebu_gpio_chip, chip);
+ u32 u;
+
+ if (readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin)) {
+ u = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) ^
+ readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
+ } else {
+ u = readl_relaxed(mvebu_gpioreg_out(mvchip));
+ }
+
+ return (u >> pin) & 1;
+}
+
+static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
+{
+ struct mvebu_gpio_chip *mvchip =
+ container_of(chip, struct mvebu_gpio_chip, chip);
+ unsigned long flags;
+ int ret;
+ u32 u;
+
+ /* Check with the pinctrl driver whether this pin is usable as
+ * an input GPIO */
+ ret = pinctrl_gpio_direction_input(chip->base + pin);
+ if (ret)
+ return ret;
+
+ spin_lock_irqsave(&mvchip->lock, flags);
+ u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
+ u |= 1 << pin;
+ writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip));
+ spin_unlock_irqrestore(&mvchip->lock, flags);
+
+ return 0;
+}
+
+static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
+ int value)
+{
+ struct mvebu_gpio_chip *mvchip =
+ container_of(chip, struct mvebu_gpio_chip, chip);
+ unsigned long flags;
+ int ret;
+ u32 u;
+
+ /* Check with the pinctrl driver whether this pin is usable as
+ * an output GPIO */
+ ret = pinctrl_gpio_direction_output(chip->base + pin);
+ if (ret)
+ return ret;
+
+ spin_lock_irqsave(&mvchip->lock, flags);
+ u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
+ u &= ~(1 << pin);
+ writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip));
+ spin_unlock_irqrestore(&mvchip->lock, flags);
+
+ return 0;
+}
+
+static int mvebu_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
+{
+ struct mvebu_gpio_chip *mvchip =
+ container_of(chip, struct mvebu_gpio_chip, chip);
+ return irq_create_mapping(mvchip->domain, pin);
+}
+
+/*
+ * Functions implementing the irq_chip methods
+ */
+static void mvebu_gpio_irq_ack(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct mvebu_gpio_chip *mvchip = gc->private;
+ u32 mask = ~(1 << (d->irq - gc->irq_base));
+
+ irq_gc_lock(gc);
+ writel_relaxed(mask, mvebu_gpioreg_edge_cause(mvchip));
+ irq_gc_unlock(gc);
+}
+
+static void mvebu_gpio_edge_irq_mask(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct mvebu_gpio_chip *mvchip = gc->private;
+ u32 mask = 1 << (d->irq - gc->irq_base);
+
+ irq_gc_lock(gc);
+ gc->mask_cache &= ~mask;
+ writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip));
+ irq_gc_unlock(gc);
+}
+
+static void mvebu_gpio_edge_irq_unmask(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct mvebu_gpio_chip *mvchip = gc->private;
+ u32 mask = 1 << (d->irq - gc->irq_base);
+
+ irq_gc_lock(gc);
+ gc->mask_cache |= mask;
+ writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip));
+ irq_gc_unlock(gc);
+}
+
+static void mvebu_gpio_level_irq_mask(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct mvebu_gpio_chip *mvchip = gc->private;
+ u32 mask = 1 << (d->irq - gc->irq_base);
+
+ irq_gc_lock(gc);
+ gc->mask_cache &= ~mask;
+ writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip));
+ irq_gc_unlock(gc);
+}
+
+static void mvebu_gpio_level_irq_unmask(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct mvebu_gpio_chip *mvchip = gc->private;
+ u32 mask = 1 << (d->irq - gc->irq_base);
+
+ irq_gc_lock(gc);
+ gc->mask_cache |= mask;
+ writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip));
+ irq_gc_unlock(gc);
+}
+
+/*****************************************************************************
+ * MVEBU GPIO IRQ
+ *
+ * GPIO_IN_POL register controls whether GPIO_DATA_IN will hold the same
+ * value of the line or the opposite value.
+ *
+ * Level IRQ handlers: DATA_IN is used directly as cause register.
+ * Interrupt are masked by LEVEL_MASK registers.
+ * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE.
+ * Interrupt are masked by EDGE_MASK registers.
+ * Both-edge handlers: Similar to regular Edge handlers, but also swaps
+ * the polarity to catch the next line transaction.
+ * This is a race condition that might not perfectly
+ * work on some use cases.
+ *
+ * Every eight GPIO lines are grouped (OR'ed) before going up to main
+ * cause register.
+ *
+ * EDGE cause mask
+ * data-in /--------| |-----| |----\
+ * -----| |----- ---- to main cause reg
+ * X \----------------| |----/
+ * polarity LEVEL mask
+ *
+ ****************************************************************************/
+
+static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
+ struct mvebu_gpio_chip *mvchip = gc->private;
+ int pin;
+ u32 u;
+
+ pin = d->hwirq;
+
+ u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin);
+ if (!u) {
+ return -EINVAL;
+ }
+
+ type &= IRQ_TYPE_SENSE_MASK;
+ if (type == IRQ_TYPE_NONE)
+ return -EINVAL;
+
+ /* Check if we need to change chip and handler */
+ if (!(ct->type & type))
+ if (irq_setup_alt_chip(d, type))
+ return -EINVAL;
+
+ /*
+ * Configure interrupt polarity.
+ */
+ switch(type) {
+ case IRQ_TYPE_EDGE_RISING:
+ case IRQ_TYPE_LEVEL_HIGH:
+ u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
+ u &= ~(1 << pin);
+ writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
+ case IRQ_TYPE_EDGE_FALLING:
+ case IRQ_TYPE_LEVEL_LOW:
+ u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
+ u |= 1 << pin;
+ writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
+ case IRQ_TYPE_EDGE_BOTH: {
+ u32 v;
+
+ v = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)) ^
+ readl_relaxed(mvebu_gpioreg_data_in(mvchip));
+
+ /*
+ * set initial polarity based on current input level
+ */
+ u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
+ if (v & (1 << pin))
+ u |= 1 << pin; /* falling */
+ else
+ u &= ~(1 << pin); /* rising */
+ writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
+ }
+ }
+ return 0;
+}
+
+static void mvebu_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+ struct mvebu_gpio_chip *mvchip = irq_get_handler_data(irq);
+ u32 cause, type;
+ int i;
+
+ if (mvchip == NULL)
+ return;
+
+ cause = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) &
+ readl_relaxed(mvebu_gpioreg_level_mask(mvchip));
+ cause |= readl_relaxed(mvebu_gpioreg_edge_cause(mvchip)) &
+ readl_relaxed(mvebu_gpioreg_edge_mask(mvchip));
+
+ for (i = 0; i < mvchip->chip.ngpio; i++) {
+ int irq;
+
+ irq = mvchip->irqbase + i;
+
+ if (!(cause & (1 << i)))
+ continue;
+
+ type = irqd_get_trigger_type(irq_get_irq_data(irq));
+ if ((type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+ /* Swap polarity (race with GPIO line) */
+ u32 polarity;
+
+ polarity = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
+ polarity ^= 1 << i;
+ writel_relaxed(polarity, mvebu_gpioreg_in_pol(mvchip));
+ }
+ generic_handle_irq(irq);
+ }
+}
+
+static struct platform_device_id mvebu_gpio_ids[] = {
+ {
+ .name = "orion-gpio",
+ }, {
+ .name = "mv78200-gpio",
+ }, {
+ .name = "armadaxp-gpio",
+ }, {
+ /* sentinel */
+ },
+};
+MODULE_DEVICE_TABLE(platform, mvebu_gpio_ids);
+
+static struct of_device_id mvebu_gpio_of_match[] __devinitdata = {
+ {
+ .compatible = "marvell,orion-gpio",
+ .data = (void*) MVEBU_GPIO_SOC_VARIANT_ORION,
+ },
+ {
+ .compatible = "marvell,mv78200-gpio",
+ .data = (void*) MVEBU_GPIO_SOC_VARIANT_MV78200,
+ },
+ {
+ .compatible = "marvell,armadaxp-gpio",
+ .data = (void*) MVEBU_GPIO_SOC_VARIANT_ARMADAXP,
+ },
+ {
+ /* sentinel */
+ },
+};
+MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match);
+
+static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
+{
+ struct mvebu_gpio_chip *mvchip;
+ const struct of_device_id *match;
+ struct device_node *np = pdev->dev.of_node;
+ struct resource *res;
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+ unsigned int ngpios;
+ int soc_variant;
+ int i, cpu, id;
+
+ match = of_match_device(mvebu_gpio_of_match, &pdev->dev);
+ if (match)
+ soc_variant = (int) match->data;
+ else
+ soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (! res) {
+ dev_err(&pdev->dev, "Cannot get memory resource\n");
+ return -ENODEV;
+ }
+
+ mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), GFP_KERNEL);
+ if (! mvchip){
+ dev_err(&pdev->dev, "Cannot allocate memory\n");
+ return -ENOMEM;
+ }
+
+ if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {
+ dev_err(&pdev->dev, "Missing ngpios OF property\n");
+ return -ENODEV;
+ }
+
+ id = of_alias_get_id(pdev->dev.of_node, "gpio");
+ if (id < 0) {
+ dev_err(&pdev->dev, "Couldn't get OF id\n");
+ return id;
+ }
+
+ mvchip->soc_variant = soc_variant;
+ mvchip->chip.label = dev_name(&pdev->dev);
+ mvchip->chip.dev = &pdev->dev;
+ mvchip->chip.request = mvebu_gpio_request;
+ mvchip->chip.direction_input = mvebu_gpio_direction_input;
+ mvchip->chip.get = mvebu_gpio_get;
+ mvchip->chip.direction_output = mvebu_gpio_direction_output;
+ mvchip->chip.set = mvebu_gpio_set;
+ mvchip->chip.to_irq = mvebu_gpio_to_irq;
+ mvchip->chip.base = id * MVEBU_MAX_GPIO_PER_BANK;
+ mvchip->chip.ngpio = ngpios;
+ mvchip->chip.can_sleep = 0;
+#ifdef CONFIG_OF
+ mvchip->chip.of_node = np;
+#endif
+
+ spin_lock_init(&mvchip->lock);
+ mvchip->membase = devm_request_and_ioremap(&pdev->dev, res);
+ if (! mvchip->membase) {
+ dev_err(&pdev->dev, "Cannot ioremap\n");
+ kfree(mvchip->chip.label);
+ return -ENOMEM;
+ }
+
+ /* The Armada XP has a second range of registers for the
+ * per-CPU registers */
+ if (soc_variant == MVEBU_GPIO_SOC_VARIANT_ARMADAXP) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (! res) {
+ dev_err(&pdev->dev, "Cannot get memory resource\n");
+ kfree(mvchip->chip.label);
+ return -ENODEV;
+ }
+
+ mvchip->percpu_membase = devm_request_and_ioremap(&pdev->dev, res);
+ if (! mvchip->percpu_membase) {
+ dev_err(&pdev->dev, "Cannot ioremap\n");
+ kfree(mvchip->chip.label);
+ return -ENOMEM;
+ }
+ }
+
+ /*
+ * Mask and clear GPIO interrupts.
+ */
+ switch(soc_variant) {
+ case MVEBU_GPIO_SOC_VARIANT_ORION:
+ writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF);
+ writel_relaxed(0, mvchip->membase + GPIO_EDGE_MASK_OFF);
+ writel_relaxed(0, mvchip->membase + GPIO_LEVEL_MASK_OFF);
+ break;
+ case MVEBU_GPIO_SOC_VARIANT_MV78200:
+ writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF);
+ for (cpu = 0; cpu < 2; cpu++) {
+ writel_relaxed(0, mvchip->membase +
+ GPIO_EDGE_MASK_MV78200_OFF(cpu));
+ writel_relaxed(0, mvchip->membase +
+ GPIO_LEVEL_MASK_MV78200_OFF(cpu));
+ }
+ break;
+ case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
+ writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF);
+ writel_relaxed(0, mvchip->membase + GPIO_EDGE_MASK_OFF);
+ writel_relaxed(0, mvchip->membase + GPIO_LEVEL_MASK_OFF);
+ for (cpu = 0; cpu < 4; cpu++) {
+ writel_relaxed(0, mvchip->percpu_membase +
+ GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu));
+ writel_relaxed(0, mvchip->percpu_membase +
+ GPIO_EDGE_MASK_ARMADAXP_OFF(cpu));
+ writel_relaxed(0, mvchip->percpu_membase +
+ GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu));
+ }
+ break;
+ default:
+ BUG();
+ }
+
+ gpiochip_add(&mvchip->chip);
+
+ /* Some gpio controllers do not provide irq support */
+ if (!of_irq_count(np))
+ return 0;
+
+ /* Setup the interrupt handlers. Each chip can have up to 4
+ * interrupt handlers, with each handler dealing with 8 GPIO
+ * pins. */
+ for (i = 0; i < 4; i++) {
+ int irq;
+ irq = platform_get_irq(pdev, i);
+ if (irq < 0)
+ continue;
+ irq_set_handler_data(irq, mvchip);
+ irq_set_chained_handler(irq, mvebu_gpio_irq_handler);
+ }
+
+ mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1);
+ if (mvchip->irqbase < 0) {
+ dev_err(&pdev->dev, "no irqs\n");
+ kfree(mvchip->chip.label);
+ return -ENOMEM;
+ }
+
+ gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase,
+ mvchip->membase, handle_level_irq);
+ if (! gc) {
+ dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n");
+ kfree(mvchip->chip.label);
+ return -ENOMEM;
+ }
+
+ gc->private = mvchip;
+ ct = &gc->chip_types[0];
+ ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
+ ct->chip.irq_mask = mvebu_gpio_level_irq_mask;
+ ct->chip.irq_unmask = mvebu_gpio_level_irq_unmask;
+ ct->chip.irq_set_type = mvebu_gpio_irq_set_type;
+ ct->chip.name = mvchip->chip.label;
+
+ ct = &gc->chip_types[1];
+ ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+ ct->chip.irq_ack = mvebu_gpio_irq_ack;
+ ct->chip.irq_mask = mvebu_gpio_edge_irq_mask;
+ ct->chip.irq_unmask = mvebu_gpio_edge_irq_unmask;
+ ct->chip.irq_set_type = mvebu_gpio_irq_set_type;
+ ct->handler = handle_edge_irq;
+ ct->chip.name = mvchip->chip.label;
+
+ irq_setup_generic_chip(gc, IRQ_MSK(ngpios), IRQ_GC_INIT_MASK_CACHE,
+ IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
+
+ /* Setup irq domain on top of the generic chip. */
+ mvchip->domain = irq_domain_add_legacy(np, mvchip->chip.ngpio,
+ mvchip->irqbase, 0,
+ &irq_domain_simple_ops,
+ mvchip);
+ if (!mvchip->domain) {
+ dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n",
+ mvchip->chip.label);
+ irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST,
+ IRQ_LEVEL | IRQ_NOPROBE);
+ kfree(gc);
+ kfree(mvchip->chip.label);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static struct platform_driver mvebu_gpio_driver = {
+ .driver = {
+ .name = "mvebu-gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = mvebu_gpio_of_match,
+ },
+ .probe = mvebu_gpio_probe,
+ .id_table = mvebu_gpio_ids,
+};
+
+static int __init mvebu_gpio_init(void)
+{
+ return platform_driver_register(&mvebu_gpio_driver);
+}
+postcore_initcall(mvebu_gpio_init);
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index 9cac88a65f78..9528779ca463 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -26,6 +26,8 @@
#include <linux/syscore_ops.h>
#include <linux/slab.h>
+#include <asm/mach/irq.h>
+
#include <mach/irqs.h>
/*
@@ -59,6 +61,7 @@
#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
int pxa_last_gpio;
+static int irq_base;
#ifdef CONFIG_OF
static struct irq_domain *domain;
@@ -167,63 +170,14 @@ static inline int __gpio_is_occupied(unsigned gpio)
return ret;
}
-#ifdef CONFIG_ARCH_PXA
-static inline int __pxa_gpio_to_irq(int gpio)
-{
- if (gpio_is_pxa_type(gpio_type))
- return PXA_GPIO_TO_IRQ(gpio);
- return -1;
-}
-
-static inline int __pxa_irq_to_gpio(int irq)
-{
- if (gpio_is_pxa_type(gpio_type))
- return irq - PXA_GPIO_TO_IRQ(0);
- return -1;
-}
-#else
-static inline int __pxa_gpio_to_irq(int gpio) { return -1; }
-static inline int __pxa_irq_to_gpio(int irq) { return -1; }
-#endif
-
-#ifdef CONFIG_ARCH_MMP
-static inline int __mmp_gpio_to_irq(int gpio)
-{
- if (gpio_is_mmp_type(gpio_type))
- return MMP_GPIO_TO_IRQ(gpio);
- return -1;
-}
-
-static inline int __mmp_irq_to_gpio(int irq)
-{
- if (gpio_is_mmp_type(gpio_type))
- return irq - MMP_GPIO_TO_IRQ(0);
- return -1;
-}
-#else
-static inline int __mmp_gpio_to_irq(int gpio) { return -1; }
-static inline int __mmp_irq_to_gpio(int irq) { return -1; }
-#endif
-
static int pxa_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
- int gpio, ret;
-
- gpio = chip->base + offset;
- ret = __pxa_gpio_to_irq(gpio);
- if (ret >= 0)
- return ret;
- return __mmp_gpio_to_irq(gpio);
+ return chip->base + offset + irq_base;
}
int pxa_irq_to_gpio(int irq)
{
- int ret;
-
- ret = __pxa_irq_to_gpio(irq);
- if (ret >= 0)
- return ret;
- return __mmp_irq_to_gpio(irq);
+ return irq - irq_base;
}
static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -403,6 +357,9 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
struct pxa_gpio_chip *c;
int loop, gpio, gpio_base, n;
unsigned long gedr;
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+
+ chained_irq_enter(chip, desc);
do {
loop = 0;
@@ -422,6 +379,8 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
}
}
} while (loop);
+
+ chained_irq_exit(chip, desc);
}
static void pxa_ack_muxed_gpio(struct irq_data *d)
@@ -535,7 +494,7 @@ const struct irq_domain_ops pxa_irq_domain_ops = {
static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev)
{
- int ret, nr_banks, nr_gpios, irq_base;
+ int ret, nr_banks, nr_gpios;
struct device_node *prev, *next, *np = pdev->dev.of_node;
const struct of_device_id *of_id =
of_match_device(pxa_gpio_dt_ids, &pdev->dev);
@@ -590,10 +549,20 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev)
int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0;
ret = pxa_gpio_probe_dt(pdev);
- if (ret < 0)
+ if (ret < 0) {
pxa_last_gpio = pxa_gpio_nums();
- else
+#ifdef CONFIG_ARCH_PXA
+ if (gpio_is_pxa_type(gpio_type))
+ irq_base = PXA_GPIO_TO_IRQ(0);
+#endif
+#ifdef CONFIG_ARCH_MMP
+ if (gpio_is_mmp_type(gpio_type))
+ irq_base = MMP_GPIO_TO_IRQ(0);
+#endif
+ } else {
use_of = 1;
+ }
+
if (!pxa_last_gpio)
return -EINVAL;
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index ba126cc04073..8af4b06e80f7 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -938,6 +938,67 @@ static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
s3c_gpiolib_track(chip);
}
+#if defined(CONFIG_PLAT_S3C24XX) && defined(CONFIG_OF)
+static int s3c24xx_gpio_xlate(struct gpio_chip *gc,
+ const struct of_phandle_args *gpiospec, u32 *flags)
+{
+ unsigned int pin;
+
+ if (WARN_ON(gc->of_gpio_n_cells < 3))
+ return -EINVAL;
+
+ if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
+ return -EINVAL;
+
+ if (gpiospec->args[0] > gc->ngpio)
+ return -EINVAL;
+
+ pin = gc->base + gpiospec->args[0];
+
+ if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1])))
+ pr_warn("gpio_xlate: failed to set pin function\n");
+ if (s3c_gpio_setpull(pin, gpiospec->args[2] & 0xffff))
+ pr_warn("gpio_xlate: failed to set pin pull up/down\n");
+
+ if (flags)
+ *flags = gpiospec->args[2] >> 16;
+
+ return gpiospec->args[0];
+}
+
+static const struct of_device_id s3c24xx_gpio_dt_match[] __initdata = {
+ { .compatible = "samsung,s3c24xx-gpio", },
+ {}
+};
+
+static __init void s3c24xx_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
+ u64 base, u64 offset)
+{
+ struct gpio_chip *gc = &chip->chip;
+ u64 address;
+
+ if (!of_have_populated_dt())
+ return;
+
+ address = chip->base ? base + ((u32)chip->base & 0xfff) : base + offset;
+ gc->of_node = of_find_matching_node_by_address(NULL,
+ s3c24xx_gpio_dt_match, address);
+ if (!gc->of_node) {
+ pr_info("gpio: device tree node not found for gpio controller"
+ " with base address %08llx\n", address);
+ return;
+ }
+ gc->of_gpio_n_cells = 3;
+ gc->of_xlate = s3c24xx_gpio_xlate;
+}
+#else
+static __init void s3c24xx_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
+ u64 base, u64 offset)
+{
+ return;
+}
+#endif /* defined(CONFIG_PLAT_S3C24XX) && defined(CONFIG_OF) */
+
static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
int nr_chips, void __iomem *base)
{
@@ -962,6 +1023,8 @@ static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
gc->direction_output = samsung_gpiolib_2bit_output;
samsung_gpiolib_add(chip);
+
+ s3c24xx_gpiolib_attach_ofnode(chip, S3C24XX_PA_GPIO, i * 0x10);
}
}
@@ -3131,46 +3194,6 @@ samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
}
EXPORT_SYMBOL(s3c_gpio_getpull);
-/* gpiolib wrappers until these are totally eliminated */
-
-void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
-{
- int ret;
-
- WARN_ON(to); /* should be none of these left */
-
- if (!to) {
- /* if pull is enabled, try first with up, and if that
- * fails, try using down */
-
- ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP);
- if (ret)
- s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN);
- } else {
- s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
- }
-}
-EXPORT_SYMBOL(s3c2410_gpio_pullup);
-
-void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
-{
- /* do this via gpiolib until all users removed */
-
- gpio_request(pin, "temporary");
- gpio_set_value(pin, to);
- gpio_free(pin);
-}
-EXPORT_SYMBOL(s3c2410_gpio_setpin);
-
-unsigned int s3c2410_gpio_getpin(unsigned int pin)
-{
- struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
- unsigned long offs = pin - chip->chip.base;
-
- return __raw_readl(chip->base + 0x04) & (1 << offs);
-}
-EXPORT_SYMBOL(s3c2410_gpio_getpin);
-
#ifdef CONFIG_S5P_GPIO_DRVSTR
s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
{
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index dc5184d57892..d982593d7563 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -30,9 +30,6 @@
#include <asm/mach/irq.h>
-#include <mach/iomap.h>
-#include <mach/suspend.h>
-
#define GPIO_BANK(x) ((x) >> 5)
#define GPIO_PORT(x) (((x) >> 3) & 0x3)
#define GPIO_BIT(x) ((x) & 0x7)
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
index f030880bc9bb..c5f8ca233e1f 100644
--- a/drivers/gpio/gpio-twl4030.c
+++ b/drivers/gpio/gpio-twl4030.c
@@ -396,6 +396,29 @@ static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
static int gpio_twl4030_remove(struct platform_device *pdev);
+static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev)
+{
+ struct twl4030_gpio_platform_data *omap_twl_info;
+
+ omap_twl_info = devm_kzalloc(dev, sizeof(*omap_twl_info), GFP_KERNEL);
+ if (!omap_twl_info)
+ return NULL;
+
+ omap_twl_info->use_leds = of_property_read_bool(dev->of_node,
+ "ti,use-leds");
+
+ of_property_read_u32(dev->of_node, "ti,debounce",
+ &omap_twl_info->debounce);
+ of_property_read_u32(dev->of_node, "ti,mmc-cd",
+ (u32 *)&omap_twl_info->mmc_cd);
+ of_property_read_u32(dev->of_node, "ti,pullups",
+ &omap_twl_info->pullups);
+ of_property_read_u32(dev->of_node, "ti,pulldowns",
+ &omap_twl_info->pulldowns);
+
+ return omap_twl_info;
+}
+
static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
{
struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
@@ -428,33 +451,37 @@ no_irqs:
twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
twl_gpiochip.dev = &pdev->dev;
- if (pdata) {
- /*
- * NOTE: boards may waste power if they don't set pullups
- * and pulldowns correctly ... default for non-ULPI pins is
- * pulldown, and some other pins may have external pullups
- * or pulldowns. Careful!
- */
- ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns);
- if (ret)
- dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n",
- pdata->pullups, pdata->pulldowns,
- ret);
-
- ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd);
- if (ret)
- dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n",
- pdata->debounce, pdata->mmc_cd,
- ret);
-
- /*
- * NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE,
- * is (still) clear if use_leds is set.
- */
- if (pdata->use_leds)
- twl_gpiochip.ngpio += 2;
+ if (node)
+ pdata = of_gpio_twl4030(&pdev->dev);
+
+ if (pdata == NULL) {
+ dev_err(&pdev->dev, "Platform data is missing\n");
+ return -ENXIO;
}
+ /*
+ * NOTE: boards may waste power if they don't set pullups
+ * and pulldowns correctly ... default for non-ULPI pins is
+ * pulldown, and some other pins may have external pullups
+ * or pulldowns. Careful!
+ */
+ ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns);
+ if (ret)
+ dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n",
+ pdata->pullups, pdata->pulldowns, ret);
+
+ ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd);
+ if (ret)
+ dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n",
+ pdata->debounce, pdata->mmc_cd, ret);
+
+ /*
+ * NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE,
+ * is (still) clear if use_leds is set.
+ */
+ if (pdata->use_leds)
+ twl_gpiochip.ngpio += 2;
+
ret = gpiochip_add(&twl_gpiochip);
if (ret < 0) {
dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret);
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
index 2f4b01bda87c..36509ae32083 100644
--- a/drivers/hwmon/gpio-fan.c
+++ b/drivers/hwmon/gpio-fan.c
@@ -31,6 +31,8 @@
#include <linux/hwmon.h>
#include <linux/gpio.h>
#include <linux/gpio-fan.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
struct gpio_fan_data {
struct platform_device *pdev;
@@ -400,14 +402,131 @@ static ssize_t show_name(struct device *dev,
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+#ifdef CONFIG_OF_GPIO
+/*
+ * Translate OpenFirmware node properties into platform_data
+ */
+static int gpio_fan_get_of_pdata(struct device *dev,
+ struct gpio_fan_platform_data *pdata)
+{
+ struct device_node *node;
+ struct gpio_fan_speed *speed;
+ unsigned *ctrl;
+ unsigned i;
+ u32 u;
+ struct property *prop;
+ const __be32 *p;
+
+ node = dev->of_node;
+
+ /* Fill GPIO pin array */
+ pdata->num_ctrl = of_gpio_count(node);
+ if (!pdata->num_ctrl) {
+ dev_err(dev, "gpios DT property empty / missing");
+ return -ENODEV;
+ }
+ ctrl = devm_kzalloc(dev, pdata->num_ctrl * sizeof(unsigned),
+ GFP_KERNEL);
+ if (!ctrl)
+ return -ENOMEM;
+ for (i = 0; i < pdata->num_ctrl; i++) {
+ int val;
+
+ val = of_get_gpio(node, i);
+ if (val < 0)
+ return val;
+ ctrl[i] = val;
+ }
+ pdata->ctrl = ctrl;
+
+ /* Get number of RPM/ctrl_val pairs in speed map */
+ prop = of_find_property(node, "gpio-fan,speed-map", &i);
+ if (!prop) {
+ dev_err(dev, "gpio-fan,speed-map DT property missing");
+ return -ENODEV;
+ }
+ i = i / sizeof(u32);
+ if (i == 0 || i & 1) {
+ dev_err(dev, "gpio-fan,speed-map contains zero/odd number of entries");
+ return -ENODEV;
+ }
+ pdata->num_speed = i / 2;
+
+ /*
+ * Populate speed map
+ * Speed map is in the form <RPM ctrl_val RPM ctrl_val ...>
+ * this needs splitting into pairs to create gpio_fan_speed structs
+ */
+ speed = devm_kzalloc(dev,
+ pdata->num_speed * sizeof(struct gpio_fan_speed),
+ GFP_KERNEL);
+ if (!speed)
+ return -ENOMEM;
+ p = NULL;
+ for (i = 0; i < pdata->num_speed; i++) {
+ p = of_prop_next_u32(prop, p, &u);
+ if (!p)
+ return -ENODEV;
+ speed[i].rpm = u;
+ p = of_prop_next_u32(prop, p, &u);
+ if (!p)
+ return -ENODEV;
+ speed[i].ctrl_val = u;
+ }
+ pdata->speed = speed;
+
+ /* Alarm GPIO if one exists */
+ if (of_gpio_named_count(node, "alarm-gpios")) {
+ struct gpio_fan_alarm *alarm;
+ int val;
+ enum of_gpio_flags flags;
+
+ alarm = devm_kzalloc(dev, sizeof(struct gpio_fan_alarm),
+ GFP_KERNEL);
+ if (!alarm)
+ return -ENOMEM;
+
+ val = of_get_named_gpio_flags(node, "alarm-gpios", 0, &flags);
+ if (val < 0)
+ return val;
+ alarm->gpio = val;
+ alarm->active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+ pdata->alarm = alarm;
+ }
+
+ return 0;
+}
+
+static struct of_device_id of_gpio_fan_match[] __devinitdata = {
+ { .compatible = "gpio-fan", },
+ {},
+};
+#endif /* CONFIG_OF_GPIO */
+
static int __devinit gpio_fan_probe(struct platform_device *pdev)
{
int err;
struct gpio_fan_data *fan_data;
struct gpio_fan_platform_data *pdata = pdev->dev.platform_data;
+#ifdef CONFIG_OF_GPIO
+ if (!pdata) {
+ pdata = devm_kzalloc(&pdev->dev,
+ sizeof(struct gpio_fan_platform_data),
+ GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ err = gpio_fan_get_of_pdata(&pdev->dev, pdata);
+ if (err)
+ return err;
+ }
+#else /* CONFIG_OF_GPIO */
if (!pdata)
return -EINVAL;
+#endif /* CONFIG_OF_GPIO */
fan_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_fan_data),
GFP_KERNEL);
@@ -511,6 +630,7 @@ static struct platform_driver gpio_fan_driver = {
.driver = {
.name = "gpio-fan",
.pm = GPIO_FAN_PM,
+ .of_match_table = of_match_ptr(of_gpio_fan_match),
},
};
diff --git a/drivers/hwmon/s3c-hwmon.c b/drivers/hwmon/s3c-hwmon.c
index b7975f858cff..fe11b95670bd 100644
--- a/drivers/hwmon/s3c-hwmon.c
+++ b/drivers/hwmon/s3c-hwmon.c
@@ -34,7 +34,7 @@
#include <linux/hwmon-sysfs.h>
#include <plat/adc.h>
-#include <plat/hwmon.h>
+#include <linux/platform_data/hwmon-s3c.h>
struct s3c_hwmon_attr {
struct sensor_device_attribute in;
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 970a1612e795..42d9fdd63de0 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -551,7 +551,7 @@ config I2C_PMCMSP
config I2C_PNX
tristate "I2C bus support for Philips PNX and NXP LPC targets"
- depends on ARCH_PNX4008 || ARCH_LPC32XX
+ depends on ARCH_LPC32XX
help
This driver supports the Philips IP3204 I2C IP block master and/or
slave controller
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 79b4bcb3b85c..79a2542d8c41 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -40,7 +40,7 @@
#include <linux/gpio.h>
#include <mach/hardware.h>
-#include <mach/i2c.h>
+#include <linux/platform_data/i2c-davinci.h>
/* ----- global defines ----------------------------------------------- */
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 0722f869465c..b7907ba7448a 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -54,7 +54,7 @@
#include <linux/pinctrl/consumer.h>
#include <mach/hardware.h>
-#include <mach/i2c.h>
+#include <linux/platform_data/i2c-imx.h>
/** Defines ********************************************************************
*******************************************************************************/
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 93f147a96b62..2f99613fd677 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -4,13 +4,13 @@
/* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd
* <Peter dot Milne at D hyphen TACQ dot com>
*
- * With acknowledgements to i2c-algo-ibm_ocp.c by
+ * With acknowledgements to i2c-algo-ibm_ocp.c by
* Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com
*
* And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund:
*
* Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund
- *
+ *
* And which acknowledged Kyösti Mälkki <kmalkki@cc.hut.fi>,
* Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com>
*
@@ -39,14 +39,15 @@
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/io.h>
+#include <linux/gpio.h>
#include "i2c-iop3xx.h"
/* global unit counter */
static int i2c_id;
-static inline unsigned char
-iic_cook_addr(struct i2c_msg *msg)
+static inline unsigned char
+iic_cook_addr(struct i2c_msg *msg)
{
unsigned char addr;
@@ -55,38 +56,38 @@ iic_cook_addr(struct i2c_msg *msg)
if (msg->flags & I2C_M_RD)
addr |= 1;
- return addr;
+ return addr;
}
-static void
+static void
iop3xx_i2c_reset(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
/* Follows devman 9.3 */
__raw_writel(IOP3XX_ICR_UNIT_RESET, iop3xx_adap->ioaddr + CR_OFFSET);
__raw_writel(IOP3XX_ISR_CLEARBITS, iop3xx_adap->ioaddr + SR_OFFSET);
__raw_writel(0, iop3xx_adap->ioaddr + CR_OFFSET);
-}
+}
-static void
+static void
iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
u32 cr = IOP3XX_ICR_GCD | IOP3XX_ICR_SCLEN | IOP3XX_ICR_UE;
- /*
+ /*
* Every time unit enable is asserted, GPOD needs to be cleared
* on IOP3XX to avoid data corruption on the bus.
*/
#if defined(CONFIG_ARCH_IOP32X) || defined(CONFIG_ARCH_IOP33X)
if (iop3xx_adap->id == 0) {
- gpio_line_set(IOP3XX_GPIO_LINE(7), GPIO_LOW);
- gpio_line_set(IOP3XX_GPIO_LINE(6), GPIO_LOW);
+ gpio_set_value(7, 0);
+ gpio_set_value(6, 0);
} else {
- gpio_line_set(IOP3XX_GPIO_LINE(5), GPIO_LOW);
- gpio_line_set(IOP3XX_GPIO_LINE(4), GPIO_LOW);
+ gpio_set_value(5, 0);
+ gpio_set_value(4, 0);
}
#endif
/* NB SR bits not same position as CR IE bits :-( */
- iop3xx_adap->SR_enabled =
+ iop3xx_adap->SR_enabled =
IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD |
IOP3XX_ISR_RXFULL | IOP3XX_ISR_TXEMPTY;
@@ -96,23 +97,23 @@ iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
__raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
}
-static void
+static void
iop3xx_i2c_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
-
- cr &= ~(IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE |
+
+ cr &= ~(IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE |
IOP3XX_ICR_MSTOP | IOP3XX_ICR_SCLEN);
__raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
}
-/*
- * NB: the handler has to clear the source of the interrupt!
+/*
+ * NB: the handler has to clear the source of the interrupt!
* Then it passes the SR flags of interest to BH via adap data
*/
-static irqreturn_t
-iop3xx_i2c_irq_handler(int this_irq, void *dev_id)
+static irqreturn_t
+iop3xx_i2c_irq_handler(int this_irq, void *dev_id)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id;
u32 sr = __raw_readl(iop3xx_adap->ioaddr + SR_OFFSET);
@@ -126,7 +127,7 @@ iop3xx_i2c_irq_handler(int this_irq, void *dev_id)
}
/* check all error conditions, clear them , report most important */
-static int
+static int
iop3xx_i2c_error(u32 sr)
{
int rc = 0;
@@ -135,12 +136,12 @@ iop3xx_i2c_error(u32 sr)
if ( !rc ) rc = -I2C_ERR_BERR;
}
if ((sr & IOP3XX_ISR_ALD)) {
- if ( !rc ) rc = -I2C_ERR_ALD;
+ if ( !rc ) rc = -I2C_ERR_ALD;
}
- return rc;
+ return rc;
}
-static inline u32
+static inline u32
iop3xx_i2c_get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
unsigned long flags;
@@ -161,8 +162,8 @@ iop3xx_i2c_get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)
typedef int (* compare_func)(unsigned test, unsigned mask);
/* returns 1 on correct comparison */
-static int
-iop3xx_i2c_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
+static int
+iop3xx_i2c_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
unsigned flags, unsigned* status,
compare_func compare)
{
@@ -192,47 +193,47 @@ iop3xx_i2c_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
}
/*
- * Concrete compare_funcs
+ * Concrete compare_funcs
*/
-static int
+static int
all_bits_clear(unsigned test, unsigned mask)
{
return (test & mask) == 0;
}
-static int
+static int
any_bits_set(unsigned test, unsigned mask)
{
return (test & mask) != 0;
}
-static int
+static int
iop3xx_i2c_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
{
- return iop3xx_i2c_wait_event(
- iop3xx_adap,
+ return iop3xx_i2c_wait_event(
+ iop3xx_adap,
IOP3XX_ISR_TXEMPTY | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD,
status, any_bits_set);
}
-static int
+static int
iop3xx_i2c_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
{
- return iop3xx_i2c_wait_event(
- iop3xx_adap,
+ return iop3xx_i2c_wait_event(
+ iop3xx_adap,
IOP3XX_ISR_RXFULL | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD,
status, any_bits_set);
}
-static int
+static int
iop3xx_i2c_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
{
- return iop3xx_i2c_wait_event(
+ return iop3xx_i2c_wait_event(
iop3xx_adap, IOP3XX_ISR_UNITBUSY, status, all_bits_clear);
}
-static int
-iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
+static int
+iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
struct i2c_msg* msg)
{
unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
@@ -247,7 +248,7 @@ iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
}
__raw_writel(iic_cook_addr(msg), iop3xx_adap->ioaddr + DBR_OFFSET);
-
+
cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK);
cr |= IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE;
@@ -257,8 +258,8 @@ iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
return rc;
}
-static int
-iop3xx_i2c_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte,
+static int
+iop3xx_i2c_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte,
int stop)
{
unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
@@ -277,10 +278,10 @@ iop3xx_i2c_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte,
rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status);
return rc;
-}
+}
-static int
-iop3xx_i2c_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char* byte,
+static int
+iop3xx_i2c_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char* byte,
int stop)
{
unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
@@ -304,19 +305,19 @@ iop3xx_i2c_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char* byte,
return rc;
}
-static int
+static int
iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap, const char *buf, int count)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
int ii;
int rc = 0;
- for (ii = 0; rc == 0 && ii != count; ++ii)
+ for (ii = 0; rc == 0 && ii != count; ++ii)
rc = iop3xx_i2c_write_byte(iop3xx_adap, buf[ii], ii==count-1);
return rc;
}
-static int
+static int
iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
@@ -325,7 +326,7 @@ iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count)
for (ii = 0; rc == 0 && ii != count; ++ii)
rc = iop3xx_i2c_read_byte(iop3xx_adap, &buf[ii], ii==count-1);
-
+
return rc;
}
@@ -336,8 +337,8 @@ iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count)
* Each transfer (i.e. a read or a write) is separated by a repeated start
* condition.
*/
-static int
-iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)
+static int
+iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
int rc;
@@ -357,8 +358,8 @@ iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)
/*
* master_xfer() - main read/write entry
*/
-static int
-iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
+static int
+iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
int num)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
@@ -375,14 +376,14 @@ iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
}
iop3xx_i2c_transaction_cleanup(iop3xx_adap);
-
+
if(ret)
return ret;
- return im;
+ return im;
}
-static u32
+static u32
iop3xx_i2c_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
@@ -393,11 +394,11 @@ static const struct i2c_algorithm iop3xx_i2c_algo = {
.functionality = iop3xx_i2c_func,
};
-static int
+static int
iop3xx_i2c_remove(struct platform_device *pdev)
{
struct i2c_adapter *padapter = platform_get_drvdata(pdev);
- struct i2c_algo_iop3xx_data *adapter_data =
+ struct i2c_algo_iop3xx_data *adapter_data =
(struct i2c_algo_iop3xx_data *)padapter->algo_data;
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
unsigned long cr = __raw_readl(adapter_data->ioaddr + CR_OFFSET);
@@ -419,7 +420,7 @@ iop3xx_i2c_remove(struct platform_device *pdev)
return 0;
}
-static int
+static int
iop3xx_i2c_probe(struct platform_device *pdev)
{
struct resource *res;
diff --git a/drivers/i2c/busses/i2c-nuc900.c b/drivers/i2c/busses/i2c-nuc900.c
index a26dfb8cd586..f41502ef3f55 100644
--- a/drivers/i2c/busses/i2c-nuc900.c
+++ b/drivers/i2c/busses/i2c-nuc900.c
@@ -29,7 +29,7 @@
#include <linux/io.h>
#include <mach/mfp.h>
-#include <mach/i2c.h>
+#include <linux/platform_data/i2c-nuc900.h>
/* nuc900 i2c registers offset */
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 5ae3b0236bd3..4d07dea9bca9 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -42,7 +42,7 @@
#include <asm/irq.h>
#include <plat/regs-iic.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
/* Treat S3C2410 as baseline hardware, anything else is supported via quirks */
#define QUIRK_S3C2440 (1 << 0)
diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c
index 9d82b3aeff5e..d5bacbb479b0 100644
--- a/drivers/input/keyboard/davinci_keyscan.c
+++ b/drivers/input/keyboard/davinci_keyscan.c
@@ -36,7 +36,7 @@
#include <mach/hardware.h>
#include <mach/irqs.h>
-#include <mach/keyscan.h>
+#include <linux/platform_data/keyscan-davinci.h>
/* Key scan registers */
#define DAVINCI_KEYSCAN_KEYCTRL 0x0000
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c
index c46fc8185469..7363402de8d4 100644
--- a/drivers/input/keyboard/ep93xx_keypad.c
+++ b/drivers/input/keyboard/ep93xx_keypad.c
@@ -29,7 +29,7 @@
#include <linux/slab.h>
#include <mach/hardware.h>
-#include <mach/ep93xx_keypad.h>
+#include <linux/platform_data/keypad-ep93xx.h>
/*
* Keypad Interface Register offsets
diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c
index a880e7414202..49f5fa64e0b1 100644
--- a/drivers/input/keyboard/nomadik-ske-keypad.c
+++ b/drivers/input/keyboard/nomadik-ske-keypad.c
@@ -20,7 +20,7 @@
#include <linux/clk.h>
#include <linux/module.h>
-#include <plat/ske.h>
+#include <linux/platform_data/keypad-nomadik-ske.h>
/* SKE_CR bits */
#define SKE_KPMLT (0x1 << 6)
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
index 2bda5f0b9c6e..6d6b1427ae12 100644
--- a/drivers/input/keyboard/omap-keypad.c
+++ b/drivers/input/keyboard/omap-keypad.c
@@ -37,7 +37,7 @@
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/platform_data/gpio-omap.h>
-#include <plat/keypad.h>
+#include <linux/platform_data/keypad-omap.h>
#undef NEW_BOARD_LEARNING_MODE
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 7f7b72464a37..803ff6fe021e 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -32,7 +32,7 @@
#include <asm/mach/map.h>
#include <mach/hardware.h>
-#include <plat/pxa27x_keypad.h>
+#include <linux/platform_data/keypad-pxa27x.h>
/*
* Keypad Controller registers
*/
diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c
index d7f1134b789e..41488f9add20 100644
--- a/drivers/input/keyboard/pxa930_rotary.c
+++ b/drivers/input/keyboard/pxa930_rotary.c
@@ -15,7 +15,7 @@
#include <linux/io.h>
#include <linux/slab.h>
-#include <mach/pxa930_rotary.h>
+#include <linux/platform_data/keyboard-pxa930_rotary.h>
#define SBCR (0x04)
#define ERCR (0x0c)
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c
index 72ef01be3360..c7ca97f44bfb 100644
--- a/drivers/input/keyboard/spear-keyboard.c
+++ b/drivers/input/keyboard/spear-keyboard.c
@@ -24,7 +24,7 @@
#include <linux/pm_wakeup.h>
#include <linux/slab.h>
#include <linux/types.h>
-#include <plat/keyboard.h>
+#include <linux/platform_data/keyboard-spear.h>
/* Keyboard Registers */
#define MODE_CTL_REG 0x00
diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c
index 085ede4d972d..e0f6cd1ad0fd 100644
--- a/drivers/input/keyboard/w90p910_keypad.c
+++ b/drivers/input/keyboard/w90p910_keypad.c
@@ -21,7 +21,7 @@
#include <linux/io.h>
#include <linux/slab.h>
-#include <mach/w90p910_keypad.h>
+#include <linux/platform_data/keypad-w90p910.h>
/* Keypad Interface Control Registers */
#define KPI_CONF 0x00
diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c
index a9e4bfdf31f4..4fe055f2c536 100644
--- a/drivers/input/mouse/pxa930_trkball.c
+++ b/drivers/input/mouse/pxa930_trkball.c
@@ -20,7 +20,7 @@
#include <linux/slab.h>
#include <mach/hardware.h>
-#include <mach/pxa930_trkball.h>
+#include <linux/platform_data/mouse-pxa930_trkball.h>
/* Trackball Controller Register Definitions */
#define TBCR (0x000C)
diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c
index 272deddc8db6..21c60fea5d31 100644
--- a/drivers/input/mouse/rpcmouse.c
+++ b/drivers/input/mouse/rpcmouse.c
@@ -42,7 +42,7 @@ static irqreturn_t rpcmouse_irq(int irq, void *dev_id)
x = (short) iomd_readl(IOMD_MOUSEX);
y = (short) iomd_readl(IOMD_MOUSEY);
- b = (short) (__raw_readl(0xe0310000) ^ 0x70);
+ b = (short) (__raw_readl(IOMEM(0xe0310000)) ^ 0x70);
dx = x - rpcmouse_lastx;
dy = y - rpcmouse_lasty;
diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c
index f5fbdf94de3b..45887e31242a 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -27,7 +27,7 @@
#include <linux/module.h>
#include <asm/mach-types.h>
-#include <plat/board-ams-delta.h>
+#include <mach/board-ams-delta.h>
#include <mach/ams-delta-fiq.h>
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
index bf1a06400067..df9e816d55e4 100644
--- a/drivers/input/touchscreen/s3c2410_ts.c
+++ b/drivers/input/touchscreen/s3c2410_ts.c
@@ -37,7 +37,7 @@
#include <plat/adc.h>
#include <plat/regs-adc.h>
-#include <plat/ts.h>
+#include <linux/platform_data/touchscreen-s3c2410.h>
#define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0))
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/drivers/irqchip/Kconfig
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
new file mode 100644
index 000000000000..054321db4350
--- /dev/null
+++ b/drivers/irqchip/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o
diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c
new file mode 100644
index 000000000000..dc670ccc6978
--- /dev/null
+++ b/drivers/irqchip/irq-bcm2835.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2010 Broadcom
+ * Copyright 2012 Simon Arlott, Chris Boot, Stephen Warren
+ *
+ * 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 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.
+ *
+ * Quirk 1: Shortcut interrupts don't set the bank 1/2 register pending bits
+ *
+ * If an interrupt fires on bank 1 that isn't in the shortcuts list, bit 8
+ * on bank 0 is set to signify that an interrupt in bank 1 has fired, and
+ * to look in the bank 1 status register for more information.
+ *
+ * If an interrupt fires on bank 1 that _is_ in the shortcuts list, its
+ * shortcut bit in bank 0 is set as well as its interrupt bit in the bank 1
+ * status register, but bank 0 bit 8 is _not_ set.
+ *
+ * Quirk 2: You can't mask the register 1/2 pending interrupts
+ *
+ * In a proper cascaded interrupt controller, the interrupt lines with
+ * cascaded interrupt controllers on them are just normal interrupt lines.
+ * You can mask the interrupts and get on with things. With this controller
+ * you can't do that.
+ *
+ * Quirk 3: The shortcut interrupts can't be (un)masked in bank 0
+ *
+ * Those interrupts that have shortcuts can only be masked/unmasked in
+ * their respective banks' enable/disable registers. Doing so in the bank 0
+ * enable/disable registers has no effect.
+ *
+ * The FIQ control register:
+ * Bits 0-6: IRQ (index in order of interrupts from banks 1, 2, then 0)
+ * Bit 7: Enable FIQ generation
+ * Bits 8+: Unused
+ *
+ * An interrupt must be disabled before configuring it for FIQ generation
+ * otherwise both handlers will fire at the same time!
+ */
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/bcm2835.h>
+
+#include <asm/exception.h>
+
+/* Put the bank and irq (32 bits) into the hwirq */
+#define MAKE_HWIRQ(b, n) ((b << 5) | (n))
+#define HWIRQ_BANK(i) (i >> 5)
+#define HWIRQ_BIT(i) BIT(i & 0x1f)
+
+#define NR_IRQS_BANK0 8
+#define BANK0_HWIRQ_MASK 0xff
+/* Shortcuts can't be disabled so any unknown new ones need to be masked */
+#define SHORTCUT1_MASK 0x00007c00
+#define SHORTCUT2_MASK 0x001f8000
+#define SHORTCUT_SHIFT 10
+#define BANK1_HWIRQ BIT(8)
+#define BANK2_HWIRQ BIT(9)
+#define BANK0_VALID_MASK (BANK0_HWIRQ_MASK | BANK1_HWIRQ | BANK2_HWIRQ \
+ | SHORTCUT1_MASK | SHORTCUT2_MASK)
+
+#define REG_FIQ_CONTROL 0x0c
+
+#define NR_BANKS 3
+#define IRQS_PER_BANK 32
+
+static int reg_pending[] __initconst = { 0x00, 0x04, 0x08 };
+static int reg_enable[] __initconst = { 0x18, 0x10, 0x14 };
+static int reg_disable[] __initconst = { 0x24, 0x1c, 0x20 };
+static int bank_irqs[] __initconst = { 8, 32, 32 };
+
+static const int shortcuts[] = {
+ 7, 9, 10, 18, 19, /* Bank 1 */
+ 21, 22, 23, 24, 25, 30 /* Bank 2 */
+};
+
+struct armctrl_ic {
+ void __iomem *base;
+ void __iomem *pending[NR_BANKS];
+ void __iomem *enable[NR_BANKS];
+ void __iomem *disable[NR_BANKS];
+ struct irq_domain *domain;
+};
+
+static struct armctrl_ic intc __read_mostly;
+
+static void armctrl_mask_irq(struct irq_data *d)
+{
+ writel_relaxed(HWIRQ_BIT(d->hwirq), intc.disable[HWIRQ_BANK(d->hwirq)]);
+}
+
+static void armctrl_unmask_irq(struct irq_data *d)
+{
+ writel_relaxed(HWIRQ_BIT(d->hwirq), intc.enable[HWIRQ_BANK(d->hwirq)]);
+}
+
+static struct irq_chip armctrl_chip = {
+ .name = "ARMCTRL-level",
+ .irq_mask = armctrl_mask_irq,
+ .irq_unmask = armctrl_unmask_irq
+};
+
+static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr,
+ const u32 *intspec, unsigned int intsize,
+ unsigned long *out_hwirq, unsigned int *out_type)
+{
+ if (WARN_ON(intsize != 2))
+ return -EINVAL;
+
+ if (WARN_ON(intspec[0] >= NR_BANKS))
+ return -EINVAL;
+
+ if (WARN_ON(intspec[1] >= IRQS_PER_BANK))
+ return -EINVAL;
+
+ if (WARN_ON(intspec[0] == 0 && intspec[1] >= NR_IRQS_BANK0))
+ return -EINVAL;
+
+ *out_hwirq = MAKE_HWIRQ(intspec[0], intspec[1]);
+ *out_type = IRQ_TYPE_NONE;
+ return 0;
+}
+
+static struct irq_domain_ops armctrl_ops = {
+ .xlate = armctrl_xlate
+};
+
+static int __init armctrl_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ void __iomem *base;
+ int irq, b, i;
+
+ base = of_iomap(node, 0);
+ if (!base)
+ panic("%s: unable to map IC registers\n",
+ node->full_name);
+
+ intc.domain = irq_domain_add_linear(node, MAKE_HWIRQ(NR_BANKS, 0),
+ &armctrl_ops, NULL);
+ if (!intc.domain)
+ panic("%s: unable to create IRQ domain\n", node->full_name);
+
+ for (b = 0; b < NR_BANKS; b++) {
+ intc.pending[b] = base + reg_pending[b];
+ intc.enable[b] = base + reg_enable[b];
+ intc.disable[b] = base + reg_disable[b];
+
+ for (i = 0; i < bank_irqs[b]; i++) {
+ irq = irq_create_mapping(intc.domain, MAKE_HWIRQ(b, i));
+ BUG_ON(irq <= 0);
+ irq_set_chip_and_handler(irq, &armctrl_chip,
+ handle_level_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ }
+ }
+ return 0;
+}
+
+static struct of_device_id irq_of_match[] __initconst = {
+ { .compatible = "brcm,bcm2835-armctrl-ic", .data = armctrl_of_init }
+};
+
+void __init bcm2835_init_irq(void)
+{
+ of_irq_init(irq_of_match);
+}
+
+/*
+ * Handle each interrupt across the entire interrupt controller. This reads the
+ * status register before handling each interrupt, which is necessary given that
+ * handle_IRQ may briefly re-enable interrupts for soft IRQ handling.
+ */
+
+static void armctrl_handle_bank(int bank, struct pt_regs *regs)
+{
+ u32 stat, irq;
+
+ while ((stat = readl_relaxed(intc.pending[bank]))) {
+ irq = MAKE_HWIRQ(bank, ffs(stat) - 1);
+ handle_IRQ(irq_linear_revmap(intc.domain, irq), regs);
+ }
+}
+
+static void armctrl_handle_shortcut(int bank, struct pt_regs *regs,
+ u32 stat)
+{
+ u32 irq = MAKE_HWIRQ(bank, shortcuts[ffs(stat >> SHORTCUT_SHIFT) - 1]);
+ handle_IRQ(irq_linear_revmap(intc.domain, irq), regs);
+}
+
+asmlinkage void __exception_irq_entry bcm2835_handle_irq(
+ struct pt_regs *regs)
+{
+ u32 stat, irq;
+
+ while ((stat = readl_relaxed(intc.pending[0]) & BANK0_VALID_MASK)) {
+ if (stat & BANK0_HWIRQ_MASK) {
+ irq = MAKE_HWIRQ(0, ffs(stat & BANK0_HWIRQ_MASK) - 1);
+ handle_IRQ(irq_linear_revmap(intc.domain, irq), regs);
+ } else if (stat & SHORTCUT1_MASK) {
+ armctrl_handle_shortcut(1, regs, stat & SHORTCUT1_MASK);
+ } else if (stat & SHORTCUT2_MASK) {
+ armctrl_handle_shortcut(2, regs, stat & SHORTCUT2_MASK);
+ } else if (stat & BANK1_HWIRQ) {
+ armctrl_handle_bank(1, regs);
+ } else if (stat & BANK2_HWIRQ) {
+ armctrl_handle_bank(2, regs);
+ } else {
+ BUG();
+ }
+ }
+}
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
index e37618e363cf..461bbf9b33fa 100644
--- a/drivers/leds/leds-netxbig.c
+++ b/drivers/leds/leds-netxbig.c
@@ -28,7 +28,7 @@
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/leds.h>
-#include <mach/leds-netxbig.h>
+#include <linux/platform_data/leds-kirkwood-netxbig.h>
/*
* GPIO extension bus.
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index 10528dafb043..d176ec83f5d9 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -29,7 +29,7 @@
#include <linux/gpio.h>
#include <linux/leds.h>
#include <linux/module.h>
-#include <mach/leds-ns2.h>
+#include <linux/platform_data/leds-kirkwood-ns2.h>
/*
* The Network Space v2 dual-GPIO LED is wired to a CPLD and can blink in
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c
index 942f0ea18178..e1a0df63a37f 100644
--- a/drivers/leds/leds-s3c24xx.c
+++ b/drivers/leds/leds-s3c24xx.c
@@ -21,7 +21,7 @@
#include <mach/hardware.h>
#include <mach/regs-gpio.h>
-#include <mach/leds-gpio.h>
+#include <linux/platform_data/leds-s3c24xx.h>
/* our context */
diff --git a/drivers/media/video/davinci/vpbe_venc.c b/drivers/media/video/davinci/vpbe_venc.c
index b21ecc8d134d..0302669622d6 100644
--- a/drivers/media/video/davinci/vpbe_venc.c
+++ b/drivers/media/video/davinci/vpbe_venc.c
@@ -27,7 +27,7 @@
#include <mach/hardware.h>
#include <mach/mux.h>
-#include <mach/i2c.h>
+#include <linux/platform_data/i2c-davinci.h>
#include <linux/io.h>
diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c
index 560a65aa7038..bbe70991d30b 100644
--- a/drivers/media/video/mx1_camera.c
+++ b/drivers/media/video/mx1_camera.c
@@ -44,7 +44,7 @@
#include <mach/dma-mx1-mx2.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
-#include <mach/mx1_camera.h>
+#include <linux/platform_data/camera-mx1.h>
/*
* CSI registers
diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c
index ac175406e582..965427f279a5 100644
--- a/drivers/media/video/mx2_camera.c
+++ b/drivers/media/video/mx2_camera.c
@@ -40,7 +40,7 @@
#include <linux/videodev2.h>
-#include <mach/mx2_cam.h>
+#include <linux/platform_data/camera-mx2.h>
#include <mach/hardware.h>
#include <asm/dma.h>
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
index af2297dd49c8..1481b0d419da 100644
--- a/drivers/media/video/mx3_camera.c
+++ b/drivers/media/video/mx3_camera.c
@@ -25,8 +25,8 @@
#include <media/soc_mediabus.h>
#include <mach/ipu.h>
-#include <mach/mx3_camera.h>
-#include <mach/dma.h>
+#include <linux/platform_data/camera-mx3.h>
+#include <linux/platform_data/dma-imx.h>
#define MX3_CAM_DRV_NAME "mx3-camera"
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index 9c21e01f2c24..1e3776d08dac 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -37,7 +37,7 @@
#include <linux/videodev2.h>
#include <mach/dma.h>
-#include <mach/camera.h>
+#include <linux/platform_data/camera-pxa.h>
#define PXA_CAM_VERSION "0.0.6"
#define PXA_CAM_DRV_NAME "pxa27x-camera"
diff --git a/drivers/media/video/s5p-fimc/mipi-csis.c b/drivers/media/video/s5p-fimc/mipi-csis.c
index 2f73d9e3d0b7..5e898432883a 100644
--- a/drivers/media/video/s5p-fimc/mipi-csis.c
+++ b/drivers/media/video/s5p-fimc/mipi-csis.c
@@ -26,7 +26,7 @@
#include <linux/spinlock.h>
#include <linux/videodev2.h>
#include <media/v4l2-subdev.h>
-#include <plat/mipi_csis.h>
+#include <linux/platform_data/mipi-csis.h>
#include "mipi-csis.h"
static int debug;
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 0e63cdd9b52a..6b67edbdbd01 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -418,6 +418,9 @@ static struct {
static atomic_t ac_wake_req_state = ATOMIC_INIT(0);
+/* Functions definition */
+static void compute_armss_rate(void);
+
/* Spinlocks */
static DEFINE_SPINLOCK(prcmu_lock);
static DEFINE_SPINLOCK(clkout_lock);
@@ -517,6 +520,7 @@ static struct dsiescclk dsiescclk[3] = {
}
};
+
/*
* Used by MCDE to setup all necessary PRCMU registers
*/
@@ -1013,6 +1017,7 @@ int db8500_prcmu_set_arm_opp(u8 opp)
(mb1_transfer.ack.arm_opp != opp))
r = -EIO;
+ compute_armss_rate();
mutex_unlock(&mb1_transfer.lock);
return r;
@@ -1612,6 +1617,7 @@ static unsigned long pll_rate(void __iomem *reg, unsigned long src_rate,
if ((branch == PLL_FIX) || ((branch == PLL_DIV) &&
(val & PRCM_PLL_FREQ_DIV2EN) &&
((reg == PRCM_PLLSOC0_FREQ) ||
+ (reg == PRCM_PLLARM_FREQ) ||
(reg == PRCM_PLLDDR_FREQ))))
div *= 2;
@@ -1661,6 +1667,39 @@ static unsigned long clock_rate(u8 clock)
else
return 0;
}
+static unsigned long latest_armss_rate;
+static unsigned long armss_rate(void)
+{
+ return latest_armss_rate;
+}
+
+static void compute_armss_rate(void)
+{
+ u32 r;
+ unsigned long rate;
+
+ r = readl(PRCM_ARM_CHGCLKREQ);
+
+ if (r & PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ) {
+ /* External ARMCLKFIX clock */
+
+ rate = pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_FIX);
+
+ /* Check PRCM_ARM_CHGCLKREQ divider */
+ if (!(r & PRCM_ARM_CHGCLKREQ_PRCM_ARM_DIVSEL))
+ rate /= 2;
+
+ /* Check PRCM_ARMCLKFIX_MGT divider */
+ r = readl(PRCM_ARMCLKFIX_MGT);
+ r &= PRCM_CLK_MGT_CLKPLLDIV_MASK;
+ rate /= r;
+
+ } else {/* ARM PLL */
+ rate = pll_rate(PRCM_PLLARM_FREQ, ROOT_CLOCK_RATE, PLL_DIV);
+ }
+
+ latest_armss_rate = rate;
+}
static unsigned long dsiclk_rate(u8 n)
{
@@ -1707,6 +1746,8 @@ unsigned long prcmu_clock_rate(u8 clock)
return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
else if (clock == PRCMU_PLLSOC1)
return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
+ else if (clock == PRCMU_ARMSS)
+ return armss_rate();
else if (clock == PRCMU_PLLDDR)
return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
else if (clock == PRCMU_PLLDSI)
@@ -2693,6 +2734,7 @@ void __init db8500_prcmu_early_init(void)
handle_simple_irq);
set_irq_flags(irq, IRQF_VALID);
}
+ compute_armss_rate();
}
static void __init init_prcm_registers(void)
diff --git a/drivers/mfd/dbx500-prcmu-regs.h b/drivers/mfd/dbx500-prcmu-regs.h
index 23108a6e3167..79c76ebdba52 100644
--- a/drivers/mfd/dbx500-prcmu-regs.h
+++ b/drivers/mfd/dbx500-prcmu-regs.h
@@ -61,7 +61,8 @@
#define PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3 0x2
#define PRCM_ARM_CHGCLKREQ (_PRCMU_BASE + 0x114)
-#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ 0x1
+#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ BIT(0)
+#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_DIVSEL BIT(16)
#define PRCM_PLLARM_ENABLE (_PRCMU_BASE + 0x98)
#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE 0x1
@@ -140,6 +141,7 @@
/* PRCMU clock/PLL/reset registers */
#define PRCM_PLLSOC0_FREQ (_PRCMU_BASE + 0x080)
#define PRCM_PLLSOC1_FREQ (_PRCMU_BASE + 0x084)
+#define PRCM_PLLARM_FREQ (_PRCMU_BASE + 0x088)
#define PRCM_PLLDDR_FREQ (_PRCMU_BASE + 0x08C)
#define PRCM_PLL_FREQ_D_SHIFT 0
#define PRCM_PLL_FREQ_D_MASK BITS(0, 7)
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c
index c54e244ca0cf..f99d6299ec24 100644
--- a/drivers/mfd/mcp-sa11x0.c
+++ b/drivers/mfd/mcp-sa11x0.c
@@ -24,7 +24,7 @@
#include <mach/hardware.h>
#include <asm/mach-types.h>
-#include <mach/mcp.h>
+#include <linux/platform_data/mfd-mcp-sa11x0.h>
#define DRIVER_NAME "sa11x0-mcp"
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index 5f58370ccf55..345960ca2fd8 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -25,6 +25,7 @@
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/regulator/of_regulator.h>
+#include <linux/regulator/machine.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tps6586x.h>
@@ -346,6 +347,7 @@ failed:
#ifdef CONFIG_OF
static struct of_regulator_match tps6586x_matches[] = {
+ { .name = "sys", .driver_data = (void *)TPS6586X_ID_SYS },
{ .name = "sm0", .driver_data = (void *)TPS6586X_ID_SM_0 },
{ .name = "sm1", .driver_data = (void *)TPS6586X_ID_SM_1 },
{ .name = "sm2", .driver_data = (void *)TPS6586X_ID_SM_2 },
@@ -369,6 +371,7 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien
struct tps6586x_platform_data *pdata;
struct tps6586x_subdev_info *devs;
struct device_node *regs;
+ const char *sys_rail_name = NULL;
unsigned int count;
unsigned int i, j;
int err;
@@ -391,12 +394,22 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien
return NULL;
for (i = 0, j = 0; i < num && j < count; i++) {
+ struct regulator_init_data *reg_idata;
+
if (!tps6586x_matches[i].init_data)
continue;
+ reg_idata = tps6586x_matches[i].init_data;
devs[j].name = "tps6586x-regulator";
devs[j].platform_data = tps6586x_matches[i].init_data;
devs[j].id = (int)tps6586x_matches[i].driver_data;
+ if (devs[j].id == TPS6586X_ID_SYS)
+ sys_rail_name = reg_idata->constraints.name;
+
+ if ((devs[j].id == TPS6586X_ID_LDO_5) ||
+ (devs[j].id == TPS6586X_ID_LDO_RTC))
+ reg_idata->supply_regulator = sys_rail_name;
+
devs[j].of_node = tps6586x_matches[i].of_node;
j++;
}
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 7cf6c624bf73..3dfd3473269d 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -33,7 +33,7 @@
#include <linux/dma-mapping.h>
#include <linux/mmc/mmc.h>
-#include <mach/mmc.h>
+#include <linux/platform_data/mmc-davinci.h>
#include <mach/edma.h>
/*
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 1d14cda95e56..7c0af0e80047 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -42,7 +42,7 @@
#include <asm/div64.h>
#include <asm/sizes.h>
-#include <mach/mmc.h>
+#include <linux/platform_data/mmc-msm_sdcc.h>
#include <mach/msm_iomap.h>
#include <mach/dma.h>
#include <mach/clk.h>
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index a61cb5fca22d..de4c20b3936c 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -25,7 +25,7 @@
#include <asm/sizes.h>
#include <asm/unaligned.h>
-#include <plat/mvsdio.h>
+#include <linux/platform_data/mmc-mvsdio.h>
#include "mvsdio.h"
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index 28ed52d58f7f..7b1161de01d6 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -38,9 +38,9 @@
#include <asm/dma.h>
#include <asm/irq.h>
#include <asm/sizes.h>
-#include <mach/mmc.h>
+#include <linux/platform_data/mmc-mxcmmc.h>
-#include <mach/dma.h>
+#include <linux/platform_data/dma-imx.h>
#include <mach/hardware.h>
#define DRIVER_NAME "mxc-mmc"
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 87c0293a1eef..c6259a829544 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -36,7 +36,6 @@
#include <plat/mmc.h>
#include <asm/gpio.h>
#include <plat/dma.h>
-#include <plat/mux.h>
#include <plat/fpga.h>
#define OMAP_MMC_REG_CMD 0x00
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index cb2dc0e75ba7..ca3915dac03d 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -35,7 +35,7 @@
#include <mach/hardware.h>
#include <mach/dma.h>
-#include <mach/mmc.h>
+#include <linux/platform_data/mmc-pxamci.h>
#include "pxamci.h"
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index bd5a5cce122c..4638ddab97b8 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -27,7 +27,7 @@
#include <mach/regs-sdi.h>
-#include <plat/mci.h>
+#include <linux/platform_data/mmc-s3cmci.h>
#include "s3cmci.h"
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index e23f8134591c..c4c504c4802b 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -25,7 +25,7 @@
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h>
-#include <mach/esdhc.h>
+#include <linux/platform_data/mmc-esdhc-imx.h>
#include "sdhci-pltfm.h"
#include "sdhci-esdhc.h"
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 0810ccc23d7e..d43e7462941f 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -28,7 +28,7 @@
#include <asm/gpio.h>
#include <mach/gpio-tegra.h>
-#include <mach/sdhci.h>
+#include <linux/platform_data/mmc-sdhci-tegra.h>
#include "sdhci-pltfm.h"
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
index 78a524b49357..a7040af08536 100644
--- a/drivers/mtd/nand/ams-delta.c
+++ b/drivers/mtd/nand/ams-delta.c
@@ -29,7 +29,7 @@
#include <asm/io.h>
#include <asm/sizes.h>
-#include <plat/board-ams-delta.h>
+#include <mach/board-ams-delta.h>
#include <mach/hardware.h>
diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c
index c855e7cd337b..d0d1bd4d0e7d 100644
--- a/drivers/mtd/nand/bcm_umi_nand.c
+++ b/drivers/mtd/nand/bcm_umi_nand.c
@@ -249,20 +249,20 @@ static int nand_dev_ready(struct mtd_info *mtd)
int bcm_umi_nand_inithw(void)
{
/* Configure nand timing parameters */
- REG_UMI_NAND_TCR &= ~0x7ffff;
- REG_UMI_NAND_TCR |= HW_CFG_NAND_TCR;
+ writel(readl(&REG_UMI_NAND_TCR) & ~0x7ffff, &REG_UMI_NAND_TCR);
+ writel(readl(&REG_UMI_NAND_TCR) | HW_CFG_NAND_TCR, &REG_UMI_NAND_TCR);
#if !defined(CONFIG_MTD_NAND_BCM_UMI_HWCS)
/* enable software control of CS */
- REG_UMI_NAND_TCR |= REG_UMI_NAND_TCR_CS_SWCTRL;
+ writel(readl(&REG_UMI_NAND_TCR) | REG_UMI_NAND_TCR_CS_SWCTRL, &REG_UMI_NAND_TCR);
#endif
/* keep NAND chip select asserted */
- REG_UMI_NAND_RCSR |= REG_UMI_NAND_RCSR_CS_ASSERTED;
+ writel(readl(&REG_UMI_NAND_RCSR) | REG_UMI_NAND_RCSR_CS_ASSERTED, &REG_UMI_NAND_RCSR);
- REG_UMI_NAND_TCR &= ~REG_UMI_NAND_TCR_WORD16;
+ writel(readl(&REG_UMI_NAND_TCR) & ~REG_UMI_NAND_TCR_WORD16, &REG_UMI_NAND_TCR);
/* enable writes to flash */
- REG_UMI_MMD_ICR |= REG_UMI_MMD_ICR_FLASH_WP;
+ writel(readl(&REG_UMI_MMD_ICR) | REG_UMI_MMD_ICR_FLASH_WP, &REG_UMI_MMD_ICR);
writel(NAND_CMD_RESET, bcm_umi_io_base + REG_NAND_CMD_OFFSET);
nand_bcm_umi_wait_till_ready();
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index d94b03c207af..f1deb1ee2c95 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -34,8 +34,8 @@
#include <linux/mtd/partitions.h>
#include <linux/slab.h>
-#include <mach/nand.h>
-#include <mach/aemif.h>
+#include <linux/platform_data/mtd-davinci.h>
+#include <linux/platform_data/mtd-davinci-aemif.h>
/*
* This is a device driver for the NAND flash controller found on the
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 6acc790c2fbb..5683604967d7 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -36,7 +36,7 @@
#include <linux/of_mtd.h>
#include <asm/mach/flash.h>
-#include <mach/mxc_nand.h>
+#include <linux/platform_data/mtd-mxc_nand.h>
#include <mach/hardware.h>
#define DRIVER_NAME "mxc_nand"
diff --git a/drivers/mtd/nand/nand_bcm_umi.h b/drivers/mtd/nand/nand_bcm_umi.h
index 198b304d6f72..d90186684db8 100644
--- a/drivers/mtd/nand/nand_bcm_umi.h
+++ b/drivers/mtd/nand/nand_bcm_umi.h
@@ -17,7 +17,7 @@
/* ---- Include Files ---------------------------------------------------- */
#include <mach/reg_umi.h>
#include <mach/reg_nand.h>
-#include <cfg_global.h>
+#include <mach/cfg_global.h>
/* ---- Constants and Types ---------------------------------------------- */
#if (CFG_GLOBAL_CHIP_FAMILY == CFG_GLOBAL_CHIP_FAMILY_BCMRING)
@@ -48,7 +48,7 @@ int nand_bcm_umi_bch_correct_page(uint8_t *datap, uint8_t *readEccData,
/* Check in device is ready */
static inline int nand_bcm_umi_dev_ready(void)
{
- return REG_UMI_NAND_RCSR & REG_UMI_NAND_RCSR_RDY;
+ return readl(&REG_UMI_NAND_RCSR) & REG_UMI_NAND_RCSR_RDY;
}
/* Wait until device is ready */
@@ -62,10 +62,11 @@ static inline void nand_bcm_umi_wait_till_ready(void)
static inline void nand_bcm_umi_hamming_enable_hwecc(void)
{
/* disable and reset ECC, 512 byte page */
- REG_UMI_NAND_ECC_CSR &= ~(REG_UMI_NAND_ECC_CSR_ECC_ENABLE |
- REG_UMI_NAND_ECC_CSR_256BYTE);
+ writel(readl(&REG_UMI_NAND_ECC_CSR) & ~(REG_UMI_NAND_ECC_CSR_ECC_ENABLE |
+ REG_UMI_NAND_ECC_CSR_256BYTE), &REG_UMI_NAND_ECC_CSR);
/* enable ECC */
- REG_UMI_NAND_ECC_CSR |= REG_UMI_NAND_ECC_CSR_ECC_ENABLE;
+ writel(readl(&REG_UMI_NAND_ECC_CSR) | REG_UMI_NAND_ECC_CSR_ECC_ENABLE,
+ &REG_UMI_NAND_ECC_CSR);
}
#if NAND_ECC_BCH
@@ -76,18 +77,18 @@ static inline void nand_bcm_umi_hamming_enable_hwecc(void)
static inline void nand_bcm_umi_bch_enable_read_hwecc(void)
{
/* disable and reset ECC */
- REG_UMI_BCH_CTRL_STATUS = REG_UMI_BCH_CTRL_STATUS_RD_ECC_VALID;
+ writel(REG_UMI_BCH_CTRL_STATUS_RD_ECC_VALID, &REG_UMI_BCH_CTRL_STATUS);
/* Turn on ECC */
- REG_UMI_BCH_CTRL_STATUS = REG_UMI_BCH_CTRL_STATUS_ECC_RD_EN;
+ writel(REG_UMI_BCH_CTRL_STATUS_ECC_RD_EN, &REG_UMI_BCH_CTRL_STATUS);
}
/* Enable BCH Write ECC */
static inline void nand_bcm_umi_bch_enable_write_hwecc(void)
{
/* disable and reset ECC */
- REG_UMI_BCH_CTRL_STATUS = REG_UMI_BCH_CTRL_STATUS_WR_ECC_VALID;
+ writel(REG_UMI_BCH_CTRL_STATUS_WR_ECC_VALID, &REG_UMI_BCH_CTRL_STATUS);
/* Turn on ECC */
- REG_UMI_BCH_CTRL_STATUS = REG_UMI_BCH_CTRL_STATUS_ECC_WR_EN;
+ writel(REG_UMI_BCH_CTRL_STATUS_ECC_WR_EN, &REG_UMI_BCH_CTRL_STATUS);
}
/* Config number of BCH ECC bytes */
@@ -99,9 +100,9 @@ static inline void nand_bcm_umi_bch_config_ecc(uint8_t numEccBytes)
uint32_t numBits = numEccBytes * 8;
/* disable and reset ECC */
- REG_UMI_BCH_CTRL_STATUS =
- REG_UMI_BCH_CTRL_STATUS_WR_ECC_VALID |
- REG_UMI_BCH_CTRL_STATUS_RD_ECC_VALID;
+ writel(REG_UMI_BCH_CTRL_STATUS_WR_ECC_VALID |
+ REG_UMI_BCH_CTRL_STATUS_RD_ECC_VALID,
+ &REG_UMI_BCH_CTRL_STATUS);
/* Every correctible bit requires 13 ECC bits */
tValue = (uint32_t) (numBits / ECC_BITS_PER_CORRECTABLE_BIT);
@@ -113,23 +114,21 @@ static inline void nand_bcm_umi_bch_config_ecc(uint8_t numEccBytes)
kValue = nValue - (tValue * ECC_BITS_PER_CORRECTABLE_BIT);
/* Write the settings */
- REG_UMI_BCH_N = nValue;
- REG_UMI_BCH_T = tValue;
- REG_UMI_BCH_K = kValue;
+ writel(nValue, &REG_UMI_BCH_N);
+ writel(tValue, &REG_UMI_BCH_T);
+ writel(kValue, &REG_UMI_BCH_K);
}
/* Pause during ECC read calculation to skip bytes in OOB */
static inline void nand_bcm_umi_bch_pause_read_ecc_calc(void)
{
- REG_UMI_BCH_CTRL_STATUS =
- REG_UMI_BCH_CTRL_STATUS_ECC_RD_EN |
- REG_UMI_BCH_CTRL_STATUS_PAUSE_ECC_DEC;
+ writel(REG_UMI_BCH_CTRL_STATUS_ECC_RD_EN | REG_UMI_BCH_CTRL_STATUS_PAUSE_ECC_DEC, &REG_UMI_BCH_CTRL_STATUS);
}
/* Resume during ECC read calculation after skipping bytes in OOB */
static inline void nand_bcm_umi_bch_resume_read_ecc_calc(void)
{
- REG_UMI_BCH_CTRL_STATUS = REG_UMI_BCH_CTRL_STATUS_ECC_RD_EN;
+ writel(REG_UMI_BCH_CTRL_STATUS_ECC_RD_EN, &REG_UMI_BCH_CTRL_STATUS);
}
/* Poll read ECC calc to check when hardware completes */
@@ -139,7 +138,7 @@ static inline uint32_t nand_bcm_umi_bch_poll_read_ecc_calc(void)
do {
/* wait for ECC to be valid */
- regVal = REG_UMI_BCH_CTRL_STATUS;
+ regVal = readl(&REG_UMI_BCH_CTRL_STATUS);
} while ((regVal & REG_UMI_BCH_CTRL_STATUS_RD_ECC_VALID) == 0);
return regVal;
@@ -149,7 +148,7 @@ static inline uint32_t nand_bcm_umi_bch_poll_read_ecc_calc(void)
static inline void nand_bcm_umi_bch_poll_write_ecc_calc(void)
{
/* wait for ECC to be valid */
- while ((REG_UMI_BCH_CTRL_STATUS & REG_UMI_BCH_CTRL_STATUS_WR_ECC_VALID)
+ while ((readl(&REG_UMI_BCH_CTRL_STATUS) & REG_UMI_BCH_CTRL_STATUS_WR_ECC_VALID)
== 0)
;
}
@@ -170,9 +169,9 @@ static inline void nand_bcm_umi_bch_read_oobEcc(uint32_t pageSize,
if (pageSize != NAND_DATA_ACCESS_SIZE) {
/* skip BI */
#if defined(__KERNEL__) && !defined(STANDALONE)
- *oobp++ = REG_NAND_DATA8;
+ *oobp++ = readb(&REG_NAND_DATA8);
#else
- REG_NAND_DATA8;
+ readb(&REG_NAND_DATA8);
#endif
numToRead--;
}
@@ -180,9 +179,9 @@ static inline void nand_bcm_umi_bch_read_oobEcc(uint32_t pageSize,
while (numToRead > numEccBytes) {
/* skip free oob region */
#if defined(__KERNEL__) && !defined(STANDALONE)
- *oobp++ = REG_NAND_DATA8;
+ *oobp++ = readb(&REG_NAND_DATA8);
#else
- REG_NAND_DATA8;
+ readb(&REG_NAND_DATA8);
#endif
numToRead--;
}
@@ -193,11 +192,11 @@ static inline void nand_bcm_umi_bch_read_oobEcc(uint32_t pageSize,
while (numToRead > 11) {
#if defined(__KERNEL__) && !defined(STANDALONE)
- *oobp = REG_NAND_DATA8;
+ *oobp = readb(&REG_NAND_DATA8);
eccCalc[eccPos++] = *oobp;
oobp++;
#else
- eccCalc[eccPos++] = REG_NAND_DATA8;
+ eccCalc[eccPos++] = readb(&REG_NAND_DATA8);
#endif
numToRead--;
}
@@ -207,9 +206,9 @@ static inline void nand_bcm_umi_bch_read_oobEcc(uint32_t pageSize,
if (numToRead == 11) {
/* read BI */
#if defined(__KERNEL__) && !defined(STANDALONE)
- *oobp++ = REG_NAND_DATA8;
+ *oobp++ = readb(&REG_NAND_DATA8);
#else
- REG_NAND_DATA8;
+ readb(&REG_NAND_DATA8);
#endif
numToRead--;
}
@@ -219,11 +218,11 @@ static inline void nand_bcm_umi_bch_read_oobEcc(uint32_t pageSize,
nand_bcm_umi_bch_resume_read_ecc_calc();
while (numToRead) {
#if defined(__KERNEL__) && !defined(STANDALONE)
- *oobp = REG_NAND_DATA8;
+ *oobp = readb(&REG_NAND_DATA8);
eccCalc[eccPos++] = *oobp;
oobp++;
#else
- eccCalc[eccPos++] = REG_NAND_DATA8;
+ eccCalc[eccPos++] = readb(&REG_NAND_DATA8);
#endif
numToRead--;
}
@@ -255,7 +254,7 @@ static inline void nand_bcm_umi_bch_write_oobEcc(uint32_t pageSize,
if (pageSize == NAND_DATA_ACCESS_SIZE) {
/* Now fill in the ECC bytes */
if (numEccBytes >= 13)
- eccVal = REG_UMI_BCH_WR_ECC_3;
+ eccVal = readl(&REG_UMI_BCH_WR_ECC_3);
/* Usually we skip CM in oob[0,1] */
NAND_BCM_UMI_ECC_WRITE(numEccBytes, 15, &oobp[0],
@@ -268,7 +267,7 @@ static inline void nand_bcm_umi_bch_write_oobEcc(uint32_t pageSize,
eccVal & 0xff); /* ECC 12 */
if (numEccBytes >= 9)
- eccVal = REG_UMI_BCH_WR_ECC_2;
+ eccVal = readl(&REG_UMI_BCH_WR_ECC_2);
NAND_BCM_UMI_ECC_WRITE(numEccBytes, 12, &oobp[3],
(eccVal >> 24) & 0xff); /* ECC11 */
@@ -281,7 +280,7 @@ static inline void nand_bcm_umi_bch_write_oobEcc(uint32_t pageSize,
/* Now fill in the ECC bytes */
if (numEccBytes >= 13)
- eccVal = REG_UMI_BCH_WR_ECC_3;
+ eccVal = readl(&REG_UMI_BCH_WR_ECC_3);
/* Usually skip CM in oob[1,2] */
NAND_BCM_UMI_ECC_WRITE(numEccBytes, 15, &oobp[1],
@@ -294,7 +293,7 @@ static inline void nand_bcm_umi_bch_write_oobEcc(uint32_t pageSize,
eccVal & 0xff); /* ECC12 */
if (numEccBytes >= 9)
- eccVal = REG_UMI_BCH_WR_ECC_2;
+ eccVal = readl(&REG_UMI_BCH_WR_ECC_2);
NAND_BCM_UMI_ECC_WRITE(numEccBytes, 12, &oobp[4],
(eccVal >> 24) & 0xff); /* ECC11 */
@@ -309,7 +308,7 @@ static inline void nand_bcm_umi_bch_write_oobEcc(uint32_t pageSize,
eccVal & 0xff); /* ECC8 */
if (numEccBytes >= 5)
- eccVal = REG_UMI_BCH_WR_ECC_1;
+ eccVal = readl(&REG_UMI_BCH_WR_ECC_1);
NAND_BCM_UMI_ECC_WRITE(numEccBytes, 8, &oobp[8],
(eccVal >> 24) & 0xff); /* ECC7 */
@@ -321,7 +320,7 @@ static inline void nand_bcm_umi_bch_write_oobEcc(uint32_t pageSize,
eccVal & 0xff); /* ECC4 */
if (numEccBytes >= 1)
- eccVal = REG_UMI_BCH_WR_ECC_0;
+ eccVal = readl(&REG_UMI_BCH_WR_ECC_0);
NAND_BCM_UMI_ECC_WRITE(numEccBytes, 4, &oobp[12],
(eccVal >> 24) & 0xff); /* ECC3 */
diff --git a/drivers/mtd/nand/nomadik_nand.c b/drivers/mtd/nand/nomadik_nand.c
index a86aa812ca13..9ee0c4edfacf 100644
--- a/drivers/mtd/nand/nomadik_nand.c
+++ b/drivers/mtd/nand/nomadik_nand.c
@@ -31,7 +31,7 @@
#include <linux/mtd/partitions.h>
#include <linux/io.h>
#include <linux/slab.h>
-#include <mach/nand.h>
+#include <linux/platform_data/mtd-nomadik-nand.h>
#include <mach/fsmc.h>
#include <mtd/mtd-abi.h>
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 27293e328517..fc8111278d12 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -29,7 +29,7 @@
#include <plat/dma.h>
#include <plat/gpmc.h>
-#include <plat/nand.h>
+#include <linux/platform_data/mtd-nand-omap2.h>
#define DRIVER_NAME "omap2-nand"
#define OMAP_NAND_TIMEOUT_MS 5000
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index fc5a868c436e..131b58a133f1 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -22,7 +22,7 @@
#include <asm/io.h>
#include <asm/sizes.h>
#include <mach/hardware.h>
-#include <plat/orion_nand.h>
+#include <linux/platform_data/mtd-orion_nand.h>
static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 252aaefcacfa..c45227173efd 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -22,9 +22,11 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <mach/dma.h>
-#include <plat/pxa3xx_nand.h>
+#include <linux/platform_data/mtd-nand-pxa3xx.h>
#define CHIP_DELAY_TIMEOUT (2 * HZ/10)
#define NAND_STOP_DELAY (2 * HZ/50)
@@ -1032,7 +1034,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
struct pxa3xx_nand_platform_data *pdata;
struct pxa3xx_nand_info *info;
struct pxa3xx_nand_host *host;
- struct nand_chip *chip;
+ struct nand_chip *chip = NULL;
struct mtd_info *mtd;
struct resource *r;
int ret, irq, cs;
@@ -1081,21 +1083,31 @@ static int alloc_nand_resource(struct platform_device *pdev)
}
clk_enable(info->clk);
- r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (r == NULL) {
- dev_err(&pdev->dev, "no resource defined for data DMA\n");
- ret = -ENXIO;
- goto fail_put_clk;
- }
- info->drcmr_dat = r->start;
+ /*
+ * This is a dirty hack to make this driver work from devicetree
+ * bindings. It can be removed once we have a prober DMA controller
+ * framework for DT.
+ */
+ if (pdev->dev.of_node && cpu_is_pxa3xx()) {
+ info->drcmr_dat = 97;
+ info->drcmr_cmd = 99;
+ } else {
+ r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (r == NULL) {
+ dev_err(&pdev->dev, "no resource defined for data DMA\n");
+ ret = -ENXIO;
+ goto fail_put_clk;
+ }
+ info->drcmr_dat = r->start;
- r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
- if (r == NULL) {
- dev_err(&pdev->dev, "no resource defined for command DMA\n");
- ret = -ENXIO;
- goto fail_put_clk;
+ r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (r == NULL) {
+ dev_err(&pdev->dev, "no resource defined for command DMA\n");
+ ret = -ENXIO;
+ goto fail_put_clk;
+ }
+ info->drcmr_cmd = r->start;
}
- info->drcmr_cmd = r->start;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
@@ -1200,12 +1212,55 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_OF
+static struct of_device_id pxa3xx_nand_dt_ids[] = {
+ { .compatible = "marvell,pxa3xx-nand" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids);
+
+static int pxa3xx_nand_probe_dt(struct platform_device *pdev)
+{
+ struct pxa3xx_nand_platform_data *pdata;
+ struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *of_id =
+ of_match_device(pxa3xx_nand_dt_ids, &pdev->dev);
+
+ if (!of_id)
+ return 0;
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ if (of_get_property(np, "marvell,nand-enable-arbiter", NULL))
+ pdata->enable_arbiter = 1;
+ if (of_get_property(np, "marvell,nand-keep-config", NULL))
+ pdata->keep_config = 1;
+ of_property_read_u32(np, "num-cs", &pdata->num_cs);
+
+ pdev->dev.platform_data = pdata;
+
+ return 0;
+}
+#else
+static inline int pxa3xx_nand_probe_dt(struct platform_device *pdev)
+{
+ return 0;
+}
+#endif
+
static int pxa3xx_nand_probe(struct platform_device *pdev)
{
struct pxa3xx_nand_platform_data *pdata;
+ struct mtd_part_parser_data ppdata = {};
struct pxa3xx_nand_info *info;
int ret, cs, probe_success;
+ ret = pxa3xx_nand_probe_dt(pdev);
+ if (ret)
+ return ret;
+
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "no platform data defined\n");
@@ -1229,8 +1284,9 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
continue;
}
+ ppdata.of_node = pdev->dev.of_node;
ret = mtd_device_parse_register(info->host[cs]->mtd, NULL,
- NULL, pdata->parts[cs],
+ &ppdata, pdata->parts[cs],
pdata->nr_parts[cs]);
if (!ret)
probe_success = 1;
@@ -1306,6 +1362,7 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
static struct platform_driver pxa3xx_nand_driver = {
.driver = {
.name = "pxa3xx-nand",
+ .of_match_table = of_match_ptr(pxa3xx_nand_dt_ids),
},
.probe = pxa3xx_nand_probe,
.remove = pxa3xx_nand_remove,
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 91121f33f743..d8040619ad8d 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -46,7 +46,7 @@
#include <asm/io.h>
#include <plat/regs-nand.h>
-#include <plat/nand.h>
+#include <linux/platform_data/mtd-nand-s3c2410.h>
#ifdef CONFIG_MTD_NAND_S3C2410_HWECC
static int hardware_ecc = 1;
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 9d49b1f4ff53..1961be985171 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -39,7 +39,7 @@
#include <asm/mach/flash.h>
#include <plat/gpmc.h>
-#include <plat/onenand.h>
+#include <linux/platform_data/mtd-onenand-omap2.h>
#include <asm/gpio.h>
#include <plat/dma.h>
diff --git a/drivers/net/ethernet/netx-eth.c b/drivers/net/ethernet/netx-eth.c
index 9d11ab7521bc..63e7af44366f 100644
--- a/drivers/net/ethernet/netx-eth.c
+++ b/drivers/net/ethernet/netx-eth.c
@@ -34,7 +34,7 @@
#include <mach/netx-regs.h>
#include <mach/pfifo.h>
#include <mach/xc.h>
-#include <mach/eth.h>
+#include <linux/platform_data/eth-netx.h>
/* XC Fifo Offsets */
#define EMPTY_PTR_FIFO(xcno) (0 + ((xcno) << 3)) /* Index of the empty pointer FIFO */
diff --git a/drivers/net/ethernet/seeq/ether3.c b/drivers/net/ethernet/seeq/ether3.c
index df808ac8cb65..6a40dd03a32f 100644
--- a/drivers/net/ethernet/seeq/ether3.c
+++ b/drivers/net/ethernet/seeq/ether3.c
@@ -99,13 +99,13 @@ typedef enum {
* The SEEQ8005 doesn't like us writing to its registers
* too quickly.
*/
-static inline void ether3_outb(int v, const void __iomem *r)
+static inline void ether3_outb(int v, void __iomem *r)
{
writeb(v, r);
udelay(1);
}
-static inline void ether3_outw(int v, const void __iomem *r)
+static inline void ether3_outw(int v, void __iomem *r)
{
writew(v, r);
udelay(1);
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 8d5476707912..002a442bf73f 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -28,9 +28,9 @@
#include <net/irda/irda_device.h>
#include <mach/dma.h>
-#include <mach/irda.h>
-#include <mach/regs-uart.h>
+#include <linux/platform_data/irda-pxaficp.h>
#include <mach/regs-ost.h>
+#include <mach/regs-uart.h>
#define FICP __REG(0x40800000) /* Start of FICP area */
#define ICCR0 __REG(0x40800000) /* ICP Control Register 0 */
@@ -112,6 +112,9 @@ struct pxa_irda {
int txdma;
int rxdma;
+ int uart_irq;
+ int icp_irq;
+
struct irlap_cb *irlap;
struct qos_info qos;
@@ -672,19 +675,19 @@ static int pxa_irda_start(struct net_device *dev)
si->speed = 9600;
- err = request_irq(IRQ_STUART, pxa_irda_sir_irq, 0, dev->name, dev);
+ err = request_irq(si->uart_irq, pxa_irda_sir_irq, 0, dev->name, dev);
if (err)
goto err_irq1;
- err = request_irq(IRQ_ICP, pxa_irda_fir_irq, 0, dev->name, dev);
+ err = request_irq(si->icp_irq, pxa_irda_fir_irq, 0, dev->name, dev);
if (err)
goto err_irq2;
/*
* The interrupt must remain disabled for now.
*/
- disable_irq(IRQ_STUART);
- disable_irq(IRQ_ICP);
+ disable_irq(si->uart_irq);
+ disable_irq(si->icp_irq);
err = -EBUSY;
si->rxdma = pxa_request_dma("FICP_RX",DMA_PRIO_LOW, pxa_irda_fir_dma_rx_irq, dev);
@@ -720,8 +723,8 @@ static int pxa_irda_start(struct net_device *dev)
/*
* Now enable the interrupt and start the queue
*/
- enable_irq(IRQ_STUART);
- enable_irq(IRQ_ICP);
+ enable_irq(si->uart_irq);
+ enable_irq(si->icp_irq);
netif_start_queue(dev);
printk(KERN_DEBUG "pxa_ir: irda driver opened\n");
@@ -738,9 +741,9 @@ err_dma_rx_buff:
err_tx_dma:
pxa_free_dma(si->rxdma);
err_rx_dma:
- free_irq(IRQ_ICP, dev);
+ free_irq(si->icp_irq, dev);
err_irq2:
- free_irq(IRQ_STUART, dev);
+ free_irq(si->uart_irq, dev);
err_irq1:
return err;
@@ -760,8 +763,8 @@ static int pxa_irda_stop(struct net_device *dev)
si->irlap = NULL;
}
- free_irq(IRQ_STUART, dev);
- free_irq(IRQ_ICP, dev);
+ free_irq(si->uart_irq, dev);
+ free_irq(si->icp_irq, dev);
pxa_free_dma(si->rxdma);
pxa_free_dma(si->txdma);
@@ -851,6 +854,9 @@ static int pxa_irda_probe(struct platform_device *pdev)
si->dev = &pdev->dev;
si->pdata = pdev->dev.platform_data;
+ si->uart_irq = platform_get_irq(pdev, 0);
+ si->icp_irq = platform_get_irq(pdev, 1);
+
si->sir_clk = clk_get(&pdev->dev, "UARTCLK");
si->fir_clk = clk_get(&pdev->dev, "FICPCLK");
if (IS_ERR(si->sir_clk) || IS_ERR(si->fir_clk)) {
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index 0ad06a3bd562..fa74efe82206 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -24,7 +24,7 @@
#include <asm/io.h>
#include <asm/sizes.h>
-#include <plat/mux.h>
+#include <mach/mux.h>
#include <plat/tc.h>
diff --git a/drivers/pcmcia/pxa2xx_viper.c b/drivers/pcmcia/pxa2xx_viper.c
index cb0c37ec7f24..a76f495953ab 100644
--- a/drivers/pcmcia/pxa2xx_viper.c
+++ b/drivers/pcmcia/pxa2xx_viper.c
@@ -25,7 +25,7 @@
#include <asm/irq.h>
-#include <mach/arcom-pcmcia.h>
+#include <linux/platform_data/pcmcia-pxa2xx_viper.h>
#include "soc_common.h"
#include "pxa2xx_base.h"
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 54e3588bef62..a75414496369 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -145,6 +145,28 @@ config PINCTRL_COH901
COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
ports of 8 GPIO pins each.
+config PINCTRL_MVEBU
+ bool
+ depends on ARCH_MVEBU
+ select PINMUX
+ select PINCONF
+
+config PINCTRL_DOVE
+ bool
+ select PINCTRL_MVEBU
+
+config PINCTRL_KIRKWOOD
+ bool
+ select PINCTRL_MVEBU
+
+config PINCTRL_ARMADA_370
+ bool
+ select PINCTRL_MVEBU
+
+config PINCTRL_ARMADA_XP
+ bool
+ select PINCTRL_MVEBU
+
source "drivers/pinctrl/spear/Kconfig"
endmenu
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index f40b1f81ff2c..f2ea0504efc7 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -29,5 +29,10 @@ obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o
obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o
obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
+obj-$(CONFIG_PINCTRL_MVEBU) += pinctrl-mvebu.o
+obj-$(CONFIG_PINCTRL_DOVE) += pinctrl-dove.o
+obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o
+obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o
+obj-$(CONFIG_PINCTRL_ARMADA_XP) += pinctrl-armada-xp.o
obj-$(CONFIG_PLAT_SPEAR) += spear/
diff --git a/drivers/pinctrl/pinctrl-armada-370.c b/drivers/pinctrl/pinctrl-armada-370.c
new file mode 100644
index 000000000000..c907647de6ad
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-armada-370.c
@@ -0,0 +1,421 @@
+/*
+ * Marvell Armada 370 pinctrl driver based on mvebu pinctrl core
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.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/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-mvebu.h"
+
+static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = {
+ MPP_MODE(0,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "uart0", "rxd")),
+ MPP_MODE(1,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "uart0", "txd")),
+ MPP_MODE(2,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "i2c0", "sck"),
+ MPP_FUNCTION(0x2, "uart0", "txd")),
+ MPP_MODE(3,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "i2c0", "sda"),
+ MPP_FUNCTION(0x2, "uart0", "rxd")),
+ MPP_MODE(4,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "cpu_pd", "vdd")),
+ MPP_MODE(5,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txclko"),
+ MPP_FUNCTION(0x2, "uart1", "txd"),
+ MPP_FUNCTION(0x4, "spi1", "clk"),
+ MPP_FUNCTION(0x5, "audio", "mclk")),
+ MPP_MODE(6,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txd0"),
+ MPP_FUNCTION(0x2, "sata0", "prsnt"),
+ MPP_FUNCTION(0x4, "tdm", "rst"),
+ MPP_FUNCTION(0x5, "audio", "sdo")),
+ MPP_MODE(7,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txd1"),
+ MPP_FUNCTION(0x4, "tdm", "tdx"),
+ MPP_FUNCTION(0x5, "audio", "lrclk")),
+ MPP_MODE(8,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txd2"),
+ MPP_FUNCTION(0x2, "uart0", "rts"),
+ MPP_FUNCTION(0x4, "tdm", "drx"),
+ MPP_FUNCTION(0x5, "audio", "bclk")),
+ MPP_MODE(9,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txd3"),
+ MPP_FUNCTION(0x2, "uart1", "txd"),
+ MPP_FUNCTION(0x3, "sd0", "clk"),
+ MPP_FUNCTION(0x5, "audio", "spdifo")),
+ MPP_MODE(10,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txctl"),
+ MPP_FUNCTION(0x2, "uart0", "cts"),
+ MPP_FUNCTION(0x4, "tdm", "fsync"),
+ MPP_FUNCTION(0x5, "audio", "sdi")),
+ MPP_MODE(11,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxd0"),
+ MPP_FUNCTION(0x2, "uart1", "rxd"),
+ MPP_FUNCTION(0x3, "sd0", "cmd"),
+ MPP_FUNCTION(0x4, "spi0", "cs1"),
+ MPP_FUNCTION(0x5, "sata1", "prsnt"),
+ MPP_FUNCTION(0x6, "spi1", "cs1")),
+ MPP_MODE(12,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxd1"),
+ MPP_FUNCTION(0x2, "i2c1", "sda"),
+ MPP_FUNCTION(0x3, "sd0", "d0"),
+ MPP_FUNCTION(0x4, "spi1", "cs0"),
+ MPP_FUNCTION(0x5, "audio", "spdifi")),
+ MPP_MODE(13,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxd2"),
+ MPP_FUNCTION(0x2, "i2c1", "sck"),
+ MPP_FUNCTION(0x3, "sd0", "d1"),
+ MPP_FUNCTION(0x4, "tdm", "pclk"),
+ MPP_FUNCTION(0x5, "audio", "rmclk")),
+ MPP_MODE(14,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxd3"),
+ MPP_FUNCTION(0x2, "pcie", "clkreq0"),
+ MPP_FUNCTION(0x3, "sd0", "d2"),
+ MPP_FUNCTION(0x4, "spi1", "mosi"),
+ MPP_FUNCTION(0x5, "spi0", "cs2")),
+ MPP_MODE(15,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxctl"),
+ MPP_FUNCTION(0x2, "pcie", "clkreq1"),
+ MPP_FUNCTION(0x3, "sd0", "d3"),
+ MPP_FUNCTION(0x4, "spi1", "miso"),
+ MPP_FUNCTION(0x5, "spi0", "cs3")),
+ MPP_MODE(16,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxclk"),
+ MPP_FUNCTION(0x2, "uart1", "rxd"),
+ MPP_FUNCTION(0x4, "tdm", "int"),
+ MPP_FUNCTION(0x5, "audio", "extclk")),
+ MPP_MODE(17,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "ge", "mdc")),
+ MPP_MODE(18,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge", "mdio")),
+ MPP_MODE(19,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txclk"),
+ MPP_FUNCTION(0x2, "ge1", "txclkout"),
+ MPP_FUNCTION(0x4, "tdm", "pclk")),
+ MPP_MODE(20,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txd4"),
+ MPP_FUNCTION(0x2, "ge1", "txd0")),
+ MPP_MODE(21,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txd5"),
+ MPP_FUNCTION(0x2, "ge1", "txd1"),
+ MPP_FUNCTION(0x4, "uart1", "txd")),
+ MPP_MODE(22,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txd6"),
+ MPP_FUNCTION(0x2, "ge1", "txd2"),
+ MPP_FUNCTION(0x4, "uart0", "rts")),
+ MPP_MODE(23,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txd7"),
+ MPP_FUNCTION(0x2, "ge1", "txd3"),
+ MPP_FUNCTION(0x4, "spi1", "mosi")),
+ MPP_MODE(24,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "col"),
+ MPP_FUNCTION(0x2, "ge1", "txctl"),
+ MPP_FUNCTION(0x4, "spi1", "cs0")),
+ MPP_MODE(25,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxerr"),
+ MPP_FUNCTION(0x2, "ge1", "rxd0"),
+ MPP_FUNCTION(0x4, "uart1", "rxd")),
+ MPP_MODE(26,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "crs"),
+ MPP_FUNCTION(0x2, "ge1", "rxd1"),
+ MPP_FUNCTION(0x4, "spi1", "miso")),
+ MPP_MODE(27,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxd4"),
+ MPP_FUNCTION(0x2, "ge1", "rxd2"),
+ MPP_FUNCTION(0x4, "uart0", "cts")),
+ MPP_MODE(28,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxd5"),
+ MPP_FUNCTION(0x2, "ge1", "rxd3")),
+ MPP_MODE(29,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxd6"),
+ MPP_FUNCTION(0x2, "ge1", "rxctl"),
+ MPP_FUNCTION(0x4, "i2c1", "sda")),
+ MPP_MODE(30,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxd7"),
+ MPP_FUNCTION(0x2, "ge1", "rxclk"),
+ MPP_FUNCTION(0x4, "i2c1", "sck")),
+ MPP_MODE(31,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x3, "tclk", NULL),
+ MPP_FUNCTION(0x4, "ge0", "txerr")),
+ MPP_MODE(32,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "spi0", "cs0")),
+ MPP_MODE(33,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "bootcs"),
+ MPP_FUNCTION(0x2, "spi0", "cs0")),
+ MPP_MODE(34,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "wen0"),
+ MPP_FUNCTION(0x2, "spi0", "mosi")),
+ MPP_MODE(35,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "oen"),
+ MPP_FUNCTION(0x2, "spi0", "sck")),
+ MPP_MODE(36,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "a1"),
+ MPP_FUNCTION(0x2, "spi0", "miso")),
+ MPP_MODE(37,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "a0"),
+ MPP_FUNCTION(0x2, "sata0", "prsnt")),
+ MPP_MODE(38,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ready"),
+ MPP_FUNCTION(0x2, "uart1", "cts"),
+ MPP_FUNCTION(0x3, "uart0", "cts")),
+ MPP_MODE(39,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad0"),
+ MPP_FUNCTION(0x2, "audio", "spdifo")),
+ MPP_MODE(40,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad1"),
+ MPP_FUNCTION(0x2, "uart1", "rts"),
+ MPP_FUNCTION(0x3, "uart0", "rts")),
+ MPP_MODE(41,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad2"),
+ MPP_FUNCTION(0x2, "uart1", "rxd")),
+ MPP_MODE(42,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad3"),
+ MPP_FUNCTION(0x2, "uart1", "txd")),
+ MPP_MODE(43,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad4"),
+ MPP_FUNCTION(0x2, "audio", "bclk")),
+ MPP_MODE(44,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad5"),
+ MPP_FUNCTION(0x2, "audio", "mclk")),
+ MPP_MODE(45,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad6"),
+ MPP_FUNCTION(0x2, "audio", "lrclk")),
+ MPP_MODE(46,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad7"),
+ MPP_FUNCTION(0x2, "audio", "sdo")),
+ MPP_MODE(47,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad8"),
+ MPP_FUNCTION(0x3, "sd0", "clk"),
+ MPP_FUNCTION(0x5, "audio", "spdifo")),
+ MPP_MODE(48,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad9"),
+ MPP_FUNCTION(0x2, "uart0", "rts"),
+ MPP_FUNCTION(0x3, "sd0", "cmd"),
+ MPP_FUNCTION(0x4, "sata1", "prsnt"),
+ MPP_FUNCTION(0x5, "spi0", "cs1")),
+ MPP_MODE(49,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad10"),
+ MPP_FUNCTION(0x2, "pcie", "clkreq1"),
+ MPP_FUNCTION(0x3, "sd0", "d0"),
+ MPP_FUNCTION(0x4, "spi1", "cs0"),
+ MPP_FUNCTION(0x5, "audio", "spdifi")),
+ MPP_MODE(50,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad11"),
+ MPP_FUNCTION(0x2, "uart0", "cts"),
+ MPP_FUNCTION(0x3, "sd0", "d1"),
+ MPP_FUNCTION(0x4, "spi1", "miso"),
+ MPP_FUNCTION(0x5, "audio", "rmclk")),
+ MPP_MODE(51,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad12"),
+ MPP_FUNCTION(0x2, "i2c1", "sda"),
+ MPP_FUNCTION(0x3, "sd0", "d2"),
+ MPP_FUNCTION(0x4, "spi1", "mosi")),
+ MPP_MODE(52,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad13"),
+ MPP_FUNCTION(0x2, "i2c1", "sck"),
+ MPP_FUNCTION(0x3, "sd0", "d3"),
+ MPP_FUNCTION(0x4, "spi1", "sck")),
+ MPP_MODE(53,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad14"),
+ MPP_FUNCTION(0x2, "sd0", "clk"),
+ MPP_FUNCTION(0x3, "tdm", "pclk"),
+ MPP_FUNCTION(0x4, "spi0", "cs2"),
+ MPP_FUNCTION(0x5, "pcie", "clkreq1")),
+ MPP_MODE(54,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad15"),
+ MPP_FUNCTION(0x3, "tdm", "dtx")),
+ MPP_MODE(55,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "cs1"),
+ MPP_FUNCTION(0x2, "uart1", "txd"),
+ MPP_FUNCTION(0x3, "tdm", "rst"),
+ MPP_FUNCTION(0x4, "sata1", "prsnt"),
+ MPP_FUNCTION(0x5, "sata0", "prsnt")),
+ MPP_MODE(56,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "cs2"),
+ MPP_FUNCTION(0x2, "uart1", "cts"),
+ MPP_FUNCTION(0x3, "uart0", "cts"),
+ MPP_FUNCTION(0x4, "spi0", "cs3"),
+ MPP_FUNCTION(0x5, "pcie", "clkreq0"),
+ MPP_FUNCTION(0x6, "spi1", "cs1")),
+ MPP_MODE(57,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "cs3"),
+ MPP_FUNCTION(0x2, "uart1", "rxd"),
+ MPP_FUNCTION(0x3, "tdm", "fsync"),
+ MPP_FUNCTION(0x4, "sata0", "prsnt"),
+ MPP_FUNCTION(0x5, "audio", "sdo")),
+ MPP_MODE(58,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "cs0"),
+ MPP_FUNCTION(0x2, "uart1", "rts"),
+ MPP_FUNCTION(0x3, "tdm", "int"),
+ MPP_FUNCTION(0x5, "audio", "extclk"),
+ MPP_FUNCTION(0x6, "uart0", "rts")),
+ MPP_MODE(59,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "ale0"),
+ MPP_FUNCTION(0x2, "uart1", "rts"),
+ MPP_FUNCTION(0x3, "uart0", "rts"),
+ MPP_FUNCTION(0x5, "audio", "bclk")),
+ MPP_MODE(60,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ale1"),
+ MPP_FUNCTION(0x2, "uart1", "rxd"),
+ MPP_FUNCTION(0x3, "sata0", "prsnt"),
+ MPP_FUNCTION(0x4, "pcie", "rst-out"),
+ MPP_FUNCTION(0x5, "audio", "sdi")),
+ MPP_MODE(61,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "wen1"),
+ MPP_FUNCTION(0x2, "uart1", "txd"),
+ MPP_FUNCTION(0x5, "audio", "rclk")),
+ MPP_MODE(62,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "a2"),
+ MPP_FUNCTION(0x2, "uart1", "cts"),
+ MPP_FUNCTION(0x3, "tdm", "drx"),
+ MPP_FUNCTION(0x4, "pcie", "clkreq0"),
+ MPP_FUNCTION(0x5, "audio", "mclk"),
+ MPP_FUNCTION(0x6, "uart0", "cts")),
+ MPP_MODE(63,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "spi0", "sck"),
+ MPP_FUNCTION(0x2, "tclk", NULL)),
+ MPP_MODE(64,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "spi0", "miso"),
+ MPP_FUNCTION(0x2, "spi0-1", "cs1")),
+ MPP_MODE(65,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "spi0", "mosi"),
+ MPP_FUNCTION(0x2, "spi0-1", "cs2")),
+};
+
+static struct mvebu_pinctrl_soc_info armada_370_pinctrl_info;
+
+static struct of_device_id armada_370_pinctrl_of_match[] __devinitdata = {
+ { .compatible = "marvell,mv88f6710-pinctrl" },
+ { },
+};
+
+static struct mvebu_mpp_ctrl mv88f6710_mpp_controls[] = {
+ MPP_REG_CTRL(0, 65),
+};
+
+static struct pinctrl_gpio_range mv88f6710_mpp_gpio_ranges[] = {
+ MPP_GPIO_RANGE(0, 0, 0, 32),
+ MPP_GPIO_RANGE(1, 32, 32, 32),
+ MPP_GPIO_RANGE(2, 64, 64, 2),
+};
+
+static int __devinit armada_370_pinctrl_probe(struct platform_device *pdev)
+{
+ struct mvebu_pinctrl_soc_info *soc = &armada_370_pinctrl_info;
+
+ soc->variant = 0; /* no variants for Armada 370 */
+ soc->controls = mv88f6710_mpp_controls;
+ soc->ncontrols = ARRAY_SIZE(mv88f6710_mpp_controls);
+ soc->modes = mv88f6710_mpp_modes;
+ soc->nmodes = ARRAY_SIZE(mv88f6710_mpp_modes);
+ soc->gpioranges = mv88f6710_mpp_gpio_ranges;
+ soc->ngpioranges = ARRAY_SIZE(mv88f6710_mpp_gpio_ranges);
+
+ pdev->dev.platform_data = soc;
+
+ return mvebu_pinctrl_probe(pdev);
+}
+
+static int __devexit armada_370_pinctrl_remove(struct platform_device *pdev)
+{
+ return mvebu_pinctrl_remove(pdev);
+}
+
+static struct platform_driver armada_370_pinctrl_driver = {
+ .driver = {
+ .name = "armada-370-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(armada_370_pinctrl_of_match),
+ },
+ .probe = armada_370_pinctrl_probe,
+ .remove = __devexit_p(armada_370_pinctrl_remove),
+};
+
+module_platform_driver(armada_370_pinctrl_driver);
+
+MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
+MODULE_DESCRIPTION("Marvell Armada 370 pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-armada-xp.c b/drivers/pinctrl/pinctrl-armada-xp.c
new file mode 100644
index 000000000000..40bd52a46b4e
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-armada-xp.c
@@ -0,0 +1,468 @@
+/*
+ * Marvell Armada XP pinctrl driver based on mvebu pinctrl core
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.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.
+ *
+ * This file supports the three variants of Armada XP SoCs that are
+ * available: mv78230, mv78260 and mv78460. From a pin muxing
+ * perspective, the mv78230 has 49 MPP pins. The mv78260 and mv78460
+ * both have 67 MPP pins (more GPIOs and address lines for the memory
+ * bus mainly). The only difference between the mv78260 and the
+ * mv78460 in terms of pin muxing is the addition of two functions on
+ * pins 43 and 56 to access the VDD of the CPU2 and 3 (mv78260 has two
+ * cores, mv78460 has four cores).
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/bitops.h>
+
+#include "pinctrl-mvebu.h"
+
+enum armada_xp_variant {
+ V_MV78230 = BIT(0),
+ V_MV78260 = BIT(1),
+ V_MV78460 = BIT(2),
+ V_MV78230_PLUS = (V_MV78230 | V_MV78260 | V_MV78460),
+ V_MV78260_PLUS = (V_MV78260 | V_MV78460),
+};
+
+static struct mvebu_mpp_mode armada_xp_mpp_modes[] = {
+ MPP_MODE(0,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txclko", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d0", V_MV78230_PLUS)),
+ MPP_MODE(1,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txd0", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d1", V_MV78230_PLUS)),
+ MPP_MODE(2,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txd1", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d2", V_MV78230_PLUS)),
+ MPP_MODE(3,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txd2", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d3", V_MV78230_PLUS)),
+ MPP_MODE(4,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txd3", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d4", V_MV78230_PLUS)),
+ MPP_MODE(5,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txctl", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d5", V_MV78230_PLUS)),
+ MPP_MODE(6,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxd0", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d6", V_MV78230_PLUS)),
+ MPP_MODE(7,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxd1", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d7", V_MV78230_PLUS)),
+ MPP_MODE(8,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxd2", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d8", V_MV78230_PLUS)),
+ MPP_MODE(9,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxd3", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d9", V_MV78230_PLUS)),
+ MPP_MODE(10,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxctl", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d10", V_MV78230_PLUS)),
+ MPP_MODE(11,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxclk", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d11", V_MV78230_PLUS)),
+ MPP_MODE(12,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txd4", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "clkout", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d12", V_MV78230_PLUS)),
+ MPP_MODE(13,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txd5", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "txd0", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d13", V_MV78230_PLUS)),
+ MPP_MODE(14,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txd6", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "txd1", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d14", V_MV78230_PLUS)),
+ MPP_MODE(15,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txd7", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "txd2", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d15", V_MV78230_PLUS)),
+ MPP_MODE(16,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txclk", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "txd3", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d16", V_MV78230_PLUS)),
+ MPP_MODE(17,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "col", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "txctl", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d17", V_MV78230_PLUS)),
+ MPP_MODE(18,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxerr", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "rxd0", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "ptp", "trig", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d18", V_MV78230_PLUS)),
+ MPP_MODE(19,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "crs", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "rxd1", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "ptp", "evreq", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d19", V_MV78230_PLUS)),
+ MPP_MODE(20,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxd4", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "rxd2", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "ptp", "clk", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d20", V_MV78230_PLUS)),
+ MPP_MODE(21,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxd5", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "rxd3", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "mem", "bat", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d21", V_MV78230_PLUS)),
+ MPP_MODE(22,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxd6", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "rxctl", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "sata0", "prsnt", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d22", V_MV78230_PLUS)),
+ MPP_MODE(23,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxd7", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "rxclk", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "sata1", "prsnt", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d23", V_MV78230_PLUS)),
+ MPP_MODE(24,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "sata1", "prsnt", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "nf", "bootcs-re", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "rst", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "hsync", V_MV78230_PLUS)),
+ MPP_MODE(25,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "sata0", "prsnt", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "nf", "bootcs-we", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "pclk", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "vsync", V_MV78230_PLUS)),
+ MPP_MODE(26,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "fsync", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "clk", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "vdd", "cpu1-pd", V_MV78230_PLUS)),
+ MPP_MODE(27,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ptp", "trig", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "dtx", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "e", V_MV78230_PLUS)),
+ MPP_MODE(28,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ptp", "evreq", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "drx", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "pwm", V_MV78230_PLUS)),
+ MPP_MODE(29,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ptp", "clk", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "int0", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "ref-clk", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd", V_MV78230_PLUS)),
+ MPP_MODE(30,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "sd0", "clk", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "int1", V_MV78230_PLUS)),
+ MPP_MODE(31,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "sd0", "cmd", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "int2", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd", V_MV78230_PLUS)),
+ MPP_MODE(32,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "sd0", "d0", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "int3", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "vdd", "cpu1-pd", V_MV78230_PLUS)),
+ MPP_MODE(33,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "sd0", "d1", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "int4", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "mem", "bat", V_MV78230_PLUS)),
+ MPP_MODE(34,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "sd0", "d2", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "sata0", "prsnt", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "int5", V_MV78230_PLUS)),
+ MPP_MODE(35,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "sd0", "d3", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "sata1", "prsnt", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "int6", V_MV78230_PLUS)),
+ MPP_MODE(36,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "spi", "mosi", V_MV78230_PLUS)),
+ MPP_MODE(37,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "spi", "miso", V_MV78230_PLUS)),
+ MPP_MODE(38,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "spi", "sck", V_MV78230_PLUS)),
+ MPP_MODE(39,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "spi", "cs0", V_MV78230_PLUS)),
+ MPP_MODE(40,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "spi", "cs1", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "uart2", "cts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "vdd", "cpu1-pd", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "vga-hsync", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "pcie", "clkreq0", V_MV78230_PLUS)),
+ MPP_MODE(41,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "spi", "cs2", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "uart2", "rts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "sata1", "prsnt", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "vga-vsync", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "pcie", "clkreq1", V_MV78230_PLUS)),
+ MPP_MODE(42,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "uart2", "rxd", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "uart0", "cts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "int7", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "tdm-1", "timer", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd", V_MV78230_PLUS)),
+ MPP_MODE(43,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "uart2", "txd", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "uart0", "rts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "spi", "cs3", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "pcie", "rstout", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "vdd", "cpu2-3-pd", V_MV78460)),
+ MPP_MODE(44,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "uart2", "cts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "uart3", "rxd", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "spi", "cs4", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "mem", "bat", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "pcie", "clkreq2", V_MV78230_PLUS)),
+ MPP_MODE(45,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "uart2", "rts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "uart3", "txd", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "spi", "cs5", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "sata1", "prsnt", V_MV78230_PLUS)),
+ MPP_MODE(46,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "uart3", "rts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "uart1", "rts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "spi", "cs6", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "sata0", "prsnt", V_MV78230_PLUS)),
+ MPP_MODE(47,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "uart3", "cts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "uart1", "cts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "spi", "cs7", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "ref", "clkout", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "pcie", "clkreq3", V_MV78230_PLUS)),
+ MPP_MODE(48,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "tclk", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "dev", "burst/last", V_MV78230_PLUS)),
+ MPP_MODE(49,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "we3", V_MV78260_PLUS)),
+ MPP_MODE(50,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "we2", V_MV78260_PLUS)),
+ MPP_MODE(51,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad16", V_MV78260_PLUS)),
+ MPP_MODE(52,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad17", V_MV78260_PLUS)),
+ MPP_MODE(53,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad18", V_MV78260_PLUS)),
+ MPP_MODE(54,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad19", V_MV78260_PLUS)),
+ MPP_MODE(55,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad20", V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x2, "vdd", "cpu0-pd", V_MV78260_PLUS)),
+ MPP_MODE(56,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad21", V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x2, "vdd", "cpu1-pd", V_MV78260_PLUS)),
+ MPP_MODE(57,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad22", V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x2, "vdd", "cpu2-3-pd", V_MV78460)),
+ MPP_MODE(58,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad23", V_MV78260_PLUS)),
+ MPP_MODE(59,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad24", V_MV78260_PLUS)),
+ MPP_MODE(60,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad25", V_MV78260_PLUS)),
+ MPP_MODE(61,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad26", V_MV78260_PLUS)),
+ MPP_MODE(62,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad27", V_MV78260_PLUS)),
+ MPP_MODE(63,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad28", V_MV78260_PLUS)),
+ MPP_MODE(64,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad29", V_MV78260_PLUS)),
+ MPP_MODE(65,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad30", V_MV78260_PLUS)),
+ MPP_MODE(66,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad31", V_MV78260_PLUS)),
+};
+
+static struct mvebu_pinctrl_soc_info armada_xp_pinctrl_info;
+
+static struct of_device_id armada_xp_pinctrl_of_match[] __devinitdata = {
+ {
+ .compatible = "marvell,mv78230-pinctrl",
+ .data = (void *) V_MV78230,
+ },
+ {
+ .compatible = "marvell,mv78260-pinctrl",
+ .data = (void *) V_MV78260,
+ },
+ {
+ .compatible = "marvell,mv78460-pinctrl",
+ .data = (void *) V_MV78460,
+ },
+ { },
+};
+
+static struct mvebu_mpp_ctrl mv78230_mpp_controls[] = {
+ MPP_REG_CTRL(0, 48),
+};
+
+static struct pinctrl_gpio_range mv78230_mpp_gpio_ranges[] = {
+ MPP_GPIO_RANGE(0, 0, 0, 32),
+ MPP_GPIO_RANGE(1, 32, 32, 17),
+};
+
+static struct mvebu_mpp_ctrl mv78260_mpp_controls[] = {
+ MPP_REG_CTRL(0, 66),
+};
+
+static struct pinctrl_gpio_range mv78260_mpp_gpio_ranges[] = {
+ MPP_GPIO_RANGE(0, 0, 0, 32),
+ MPP_GPIO_RANGE(1, 32, 32, 32),
+ MPP_GPIO_RANGE(2, 64, 64, 3),
+};
+
+static struct mvebu_mpp_ctrl mv78460_mpp_controls[] = {
+ MPP_REG_CTRL(0, 66),
+};
+
+static struct pinctrl_gpio_range mv78460_mpp_gpio_ranges[] = {
+ MPP_GPIO_RANGE(0, 0, 0, 32),
+ MPP_GPIO_RANGE(1, 32, 32, 32),
+ MPP_GPIO_RANGE(2, 64, 64, 3),
+};
+
+static int __devinit armada_xp_pinctrl_probe(struct platform_device *pdev)
+{
+ struct mvebu_pinctrl_soc_info *soc = &armada_xp_pinctrl_info;
+ const struct of_device_id *match =
+ of_match_device(armada_xp_pinctrl_of_match, &pdev->dev);
+
+ if (!match)
+ return -ENODEV;
+
+ soc->variant = (unsigned) match->data & 0xff;
+
+ switch (soc->variant) {
+ case V_MV78230:
+ soc->controls = mv78230_mpp_controls;
+ soc->ncontrols = ARRAY_SIZE(mv78230_mpp_controls);
+ soc->modes = armada_xp_mpp_modes;
+ /* We don't necessarily want the full list of the
+ * armada_xp_mpp_modes, but only the first 'n' ones
+ * that are available on this SoC */
+ soc->nmodes = mv78230_mpp_controls[0].npins;
+ soc->gpioranges = mv78230_mpp_gpio_ranges;
+ soc->ngpioranges = ARRAY_SIZE(mv78230_mpp_gpio_ranges);
+ break;
+ case V_MV78260:
+ soc->controls = mv78260_mpp_controls;
+ soc->ncontrols = ARRAY_SIZE(mv78260_mpp_controls);
+ soc->modes = armada_xp_mpp_modes;
+ /* We don't necessarily want the full list of the
+ * armada_xp_mpp_modes, but only the first 'n' ones
+ * that are available on this SoC */
+ soc->nmodes = mv78260_mpp_controls[0].npins;
+ soc->gpioranges = mv78260_mpp_gpio_ranges;
+ soc->ngpioranges = ARRAY_SIZE(mv78260_mpp_gpio_ranges);
+ break;
+ case V_MV78460:
+ soc->controls = mv78460_mpp_controls;
+ soc->ncontrols = ARRAY_SIZE(mv78460_mpp_controls);
+ soc->modes = armada_xp_mpp_modes;
+ /* We don't necessarily want the full list of the
+ * armada_xp_mpp_modes, but only the first 'n' ones
+ * that are available on this SoC */
+ soc->nmodes = mv78460_mpp_controls[0].npins;
+ soc->gpioranges = mv78460_mpp_gpio_ranges;
+ soc->ngpioranges = ARRAY_SIZE(mv78460_mpp_gpio_ranges);
+ break;
+ }
+
+ pdev->dev.platform_data = soc;
+
+ return mvebu_pinctrl_probe(pdev);
+}
+
+static int __devexit armada_xp_pinctrl_remove(struct platform_device *pdev)
+{
+ return mvebu_pinctrl_remove(pdev);
+}
+
+static struct platform_driver armada_xp_pinctrl_driver = {
+ .driver = {
+ .name = "armada-xp-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(armada_xp_pinctrl_of_match),
+ },
+ .probe = armada_xp_pinctrl_probe,
+ .remove = __devexit_p(armada_xp_pinctrl_remove),
+};
+
+module_platform_driver(armada_xp_pinctrl_driver);
+
+MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
+MODULE_DESCRIPTION("Marvell Armada XP pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c
index cc0f00d73d15..b446c9641212 100644
--- a/drivers/pinctrl/pinctrl-coh901.c
+++ b/drivers/pinctrl/pinctrl-coh901.c
@@ -1,11 +1,8 @@
/*
* U300 GPIO module.
*
- * Copyright (C) 2007-2011 ST-Ericsson AB
+ * Copyright (C) 2007-2012 ST-Ericsson AB
* License terms: GNU General Public License (GPL) version 2
- * This can driver either of the two basic GPIO cores
- * available in the U300 platforms:
- * COH 901 335 - Used in DB3150 (U300 1.0) and DB3200 (U330 1.0)
* COH 901 571/3 - Used in DB3210 (U365 2.0) and DB3350 (U335 1.0)
* Author: Linus Walleij <linus.walleij@linaro.org>
* Author: Jonas Aaberg <jonas.aberg@stericsson.com>
@@ -24,19 +21,22 @@
#include <linux/slab.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/pinconf-generic.h>
-#include <mach/gpio-u300.h>
+#include <linux/platform_data/pinctrl-coh901.h>
#include "pinctrl-coh901.h"
+#define U300_GPIO_PORT_STRIDE (0x30)
/*
- * Register definitions for COH 901 335 variant
+ * Control Register 32bit (R/W)
+ * bit 15-9 (mask 0x0000FE00) contains the number of cores. 8*cores
+ * gives the number of GPIO pins.
+ * bit 8-2 (mask 0x000001FC) contains the core version ID.
*/
-#define U300_335_PORT_STRIDE (0x1C)
-/* Port X Pin Data Register 32bit, this is both input and output (R/W) */
-#define U300_335_PXPDIR (0x00)
-#define U300_335_PXPDOR (0x00)
-/* Port X Pin Config Register 32bit (R/W) */
-#define U300_335_PXPCR (0x04)
-/* This register layout is the same in both blocks */
+#define U300_GPIO_CR (0x00)
+#define U300_GPIO_CR_SYNC_SEL_ENABLE (0x00000002UL)
+#define U300_GPIO_CR_BLOCK_CLKRQ_ENABLE (0x00000001UL)
+#define U300_GPIO_PXPDIR (0x04)
+#define U300_GPIO_PXPDOR (0x08)
+#define U300_GPIO_PXPCR (0x0C)
#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL)
#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL)
#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL)
@@ -44,53 +44,17 @@
#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL)
#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL)
#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL)
-/* Port X Interrupt Event Register 32bit (R/W) */
-#define U300_335_PXIEV (0x08)
-/* Port X Interrupt Enable Register 32bit (R/W) */
-#define U300_335_PXIEN (0x0C)
-/* Port X Interrupt Force Register 32bit (R/W) */
-#define U300_335_PXIFR (0x10)
-/* Port X Interrupt Config Register 32bit (R/W) */
-#define U300_335_PXICR (0x14)
-/* This register layout is the same in both blocks */
+#define U300_GPIO_PXPER (0x10)
+#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL)
+#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL)
+#define U300_GPIO_PXIEV (0x14)
+#define U300_GPIO_PXIEN (0x18)
+#define U300_GPIO_PXIFR (0x1C)
+#define U300_GPIO_PXICR (0x20)
#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL)
#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL)
#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL)
#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL)
-/* Port X Pull-up Enable Register 32bit (R/W) */
-#define U300_335_PXPER (0x18)
-/* This register layout is the same in both blocks */
-#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL)
-#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL)
-/* Control Register 32bit (R/W) */
-#define U300_335_CR (0x54)
-#define U300_335_CR_BLOCK_CLOCK_ENABLE (0x00000001UL)
-
-/*
- * Register definitions for COH 901 571 / 3 variant
- */
-#define U300_571_PORT_STRIDE (0x30)
-/*
- * Control Register 32bit (R/W)
- * bit 15-9 (mask 0x0000FE00) contains the number of cores. 8*cores
- * gives the number of GPIO pins.
- * bit 8-2 (mask 0x000001FC) contains the core version ID.
- */
-#define U300_571_CR (0x00)
-#define U300_571_CR_SYNC_SEL_ENABLE (0x00000002UL)
-#define U300_571_CR_BLOCK_CLKRQ_ENABLE (0x00000001UL)
-/*
- * These registers have the same layout and function as the corresponding
- * COH 901 335 registers, just at different offset.
- */
-#define U300_571_PXPDIR (0x04)
-#define U300_571_PXPDOR (0x08)
-#define U300_571_PXPCR (0x0C)
-#define U300_571_PXPER (0x10)
-#define U300_571_PXIEV (0x14)
-#define U300_571_PXIEN (0x18)
-#define U300_571_PXIFR (0x1C)
-#define U300_571_PXICR (0x20)
/* 8 bits per port, no version has more than 7 ports */
#define U300_GPIO_PINS_PER_PORT 8
@@ -149,8 +113,6 @@ struct u300_gpio_confdata {
/* BS335 has seven ports of 8 bits each = GPIO pins 0..55 */
#define BS335_GPIO_NUM_PORTS 7
-/* BS365 has five ports of 8 bits each = GPIO pins 0..39 */
-#define BS365_GPIO_NUM_PORTS 5
#define U300_FLOATING_INPUT { \
.bias_mode = PIN_CONFIG_BIAS_HIGH_IMPEDANCE, \
@@ -172,7 +134,6 @@ struct u300_gpio_confdata {
.outval = 1, \
}
-
/* Initial configuration */
static const struct __initconst u300_gpio_confdata
bs335_gpio_config[BS335_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
@@ -255,66 +216,6 @@ bs335_gpio_config[BS335_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
}
};
-static const struct __initconst u300_gpio_confdata
-bs365_gpio_config[BS365_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
- /* Port 0, pins 0-7 */
- {
- U300_FLOATING_INPUT,
- U300_OUTPUT_LOW,
- U300_FLOATING_INPUT,
- U300_OUTPUT_LOW,
- U300_OUTPUT_LOW,
- U300_OUTPUT_LOW,
- U300_PULL_UP_INPUT,
- U300_FLOATING_INPUT,
- },
- /* Port 1, pins 0-7 */
- {
- U300_OUTPUT_LOW,
- U300_FLOATING_INPUT,
- U300_OUTPUT_LOW,
- U300_FLOATING_INPUT,
- U300_FLOATING_INPUT,
- U300_OUTPUT_HIGH,
- U300_OUTPUT_LOW,
- U300_OUTPUT_LOW,
- },
- /* Port 2, pins 0-7 */
- {
- U300_FLOATING_INPUT,
- U300_PULL_UP_INPUT,
- U300_OUTPUT_LOW,
- U300_OUTPUT_LOW,
- U300_PULL_UP_INPUT,
- U300_PULL_UP_INPUT,
- U300_PULL_UP_INPUT,
- U300_PULL_UP_INPUT,
- },
- /* Port 3, pins 0-7 */
- {
- U300_PULL_UP_INPUT,
- U300_PULL_UP_INPUT,
- U300_PULL_UP_INPUT,
- U300_PULL_UP_INPUT,
- U300_PULL_UP_INPUT,
- U300_PULL_UP_INPUT,
- U300_PULL_UP_INPUT,
- U300_PULL_UP_INPUT,
- },
- /* Port 4, pins 0-7 */
- {
- U300_PULL_UP_INPUT,
- U300_PULL_UP_INPUT,
- U300_PULL_UP_INPUT,
- U300_PULL_UP_INPUT,
- /* These 4 pins doesn't exist on DB3210 */
- U300_OUTPUT_LOW,
- U300_OUTPUT_LOW,
- U300_OUTPUT_LOW,
- U300_OUTPUT_LOW,
- }
-};
-
/**
* to_u300_gpio() - get the pointer to u300_gpio
* @chip: the gpio chip member of the structure u300_gpio
@@ -716,13 +617,7 @@ static void __init u300_gpio_init_coh901571(struct u300_gpio *gpio,
const struct u300_gpio_confdata *conf;
int offset = (i*8) + j;
- if (plat->variant == U300_GPIO_COH901571_3_BS335)
- conf = &bs335_gpio_config[i][j];
- else if (plat->variant == U300_GPIO_COH901571_3_BS365)
- conf = &bs365_gpio_config[i][j];
- else
- break;
-
+ conf = &bs335_gpio_config[i][j];
u300_gpio_init_pin(gpio, offset, conf);
}
}
@@ -796,50 +691,27 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
goto err_no_ioremap;
}
- if (plat->variant == U300_GPIO_COH901335) {
- dev_info(gpio->dev,
- "initializing GPIO Controller COH 901 335\n");
- gpio->stride = U300_335_PORT_STRIDE;
- gpio->pcr = U300_335_PXPCR;
- gpio->dor = U300_335_PXPDOR;
- gpio->dir = U300_335_PXPDIR;
- gpio->per = U300_335_PXPER;
- gpio->icr = U300_335_PXICR;
- gpio->ien = U300_335_PXIEN;
- gpio->iev = U300_335_PXIEV;
- ifr = U300_335_PXIFR;
-
- /* Turn on the GPIO block */
- writel(U300_335_CR_BLOCK_CLOCK_ENABLE,
- gpio->base + U300_335_CR);
- } else if (plat->variant == U300_GPIO_COH901571_3_BS335 ||
- plat->variant == U300_GPIO_COH901571_3_BS365) {
- dev_info(gpio->dev,
- "initializing GPIO Controller COH 901 571/3\n");
- gpio->stride = U300_571_PORT_STRIDE;
- gpio->pcr = U300_571_PXPCR;
- gpio->dor = U300_571_PXPDOR;
- gpio->dir = U300_571_PXPDIR;
- gpio->per = U300_571_PXPER;
- gpio->icr = U300_571_PXICR;
- gpio->ien = U300_571_PXIEN;
- gpio->iev = U300_571_PXIEV;
- ifr = U300_571_PXIFR;
-
- val = readl(gpio->base + U300_571_CR);
- dev_info(gpio->dev, "COH901571/3 block version: %d, " \
- "number of cores: %d totalling %d pins\n",
- ((val & 0x000001FC) >> 2),
- ((val & 0x0000FE00) >> 9),
- ((val & 0x0000FE00) >> 9) * 8);
- writel(U300_571_CR_BLOCK_CLKRQ_ENABLE,
- gpio->base + U300_571_CR);
- u300_gpio_init_coh901571(gpio, plat);
- } else {
- dev_err(gpio->dev, "unknown block variant\n");
- err = -ENODEV;
- goto err_unknown_variant;
- }
+ dev_info(gpio->dev,
+ "initializing GPIO Controller COH 901 571/3\n");
+ gpio->stride = U300_GPIO_PORT_STRIDE;
+ gpio->pcr = U300_GPIO_PXPCR;
+ gpio->dor = U300_GPIO_PXPDOR;
+ gpio->dir = U300_GPIO_PXPDIR;
+ gpio->per = U300_GPIO_PXPER;
+ gpio->icr = U300_GPIO_PXICR;
+ gpio->ien = U300_GPIO_PXIEN;
+ gpio->iev = U300_GPIO_PXIEV;
+ ifr = U300_GPIO_PXIFR;
+
+ val = readl(gpio->base + U300_GPIO_CR);
+ dev_info(gpio->dev, "COH901571/3 block version: %d, " \
+ "number of cores: %d totalling %d pins\n",
+ ((val & 0x000001FC) >> 2),
+ ((val & 0x0000FE00) >> 9),
+ ((val & 0x0000FE00) >> 9) * 8);
+ writel(U300_GPIO_CR_BLOCK_CLKRQ_ENABLE,
+ gpio->base + U300_GPIO_CR);
+ u300_gpio_init_coh901571(gpio, plat);
/* Add each port with its IRQ separately */
INIT_LIST_HEAD(&gpio->port_list);
@@ -906,7 +778,6 @@ err_no_pinctrl:
err_no_chip:
err_no_port:
u300_gpio_free_ports(gpio);
-err_unknown_variant:
iounmap(gpio->base);
err_no_ioremap:
release_mem_region(gpio->memres->start, resource_size(gpio->memres));
@@ -923,16 +794,11 @@ err_no_clk:
static int __exit u300_gpio_remove(struct platform_device *pdev)
{
- struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev);
struct u300_gpio *gpio = platform_get_drvdata(pdev);
int err;
/* Turn off the GPIO block */
- if (plat->variant == U300_GPIO_COH901335)
- writel(0x00000000U, gpio->base + U300_335_CR);
- if (plat->variant == U300_GPIO_COH901571_3_BS335 ||
- plat->variant == U300_GPIO_COH901571_3_BS365)
- writel(0x00000000U, gpio->base + U300_571_CR);
+ writel(0x00000000U, gpio->base + U300_GPIO_CR);
err = gpiochip_remove(&gpio->chip);
if (err < 0) {
diff --git a/drivers/pinctrl/pinctrl-dove.c b/drivers/pinctrl/pinctrl-dove.c
new file mode 100644
index 000000000000..ffe74b27d66d
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-dove.c
@@ -0,0 +1,620 @@
+/*
+ * Marvell Dove pinctrl driver based on mvebu pinctrl core
+ *
+ * Author: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.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/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-mvebu.h"
+
+#define DOVE_SB_REGS_VIRT_BASE 0xfde00000
+#define DOVE_MPP_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE | 0xd0200)
+#define DOVE_PMU_MPP_GENERAL_CTRL (DOVE_MPP_VIRT_BASE + 0x10)
+#define DOVE_AU0_AC97_SEL BIT(16)
+#define DOVE_GLOBAL_CONFIG_1 (DOVE_SB_REGS_VIRT_BASE | 0xe802C)
+#define DOVE_TWSI_ENABLE_OPTION1 BIT(7)
+#define DOVE_GLOBAL_CONFIG_2 (DOVE_SB_REGS_VIRT_BASE | 0xe8030)
+#define DOVE_TWSI_ENABLE_OPTION2 BIT(20)
+#define DOVE_TWSI_ENABLE_OPTION3 BIT(21)
+#define DOVE_TWSI_OPTION3_GPIO BIT(22)
+#define DOVE_SSP_CTRL_STATUS_1 (DOVE_SB_REGS_VIRT_BASE | 0xe8034)
+#define DOVE_SSP_ON_AU1 BIT(0)
+#define DOVE_MPP_GENERAL_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE | 0xe803c)
+#define DOVE_AU1_SPDIFO_GPIO_EN BIT(1)
+#define DOVE_NAND_GPIO_EN BIT(0)
+#define DOVE_GPIO_LO_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE | 0xd0400)
+#define DOVE_MPP_CTRL4_VIRT_BASE (DOVE_GPIO_LO_VIRT_BASE + 0x40)
+#define DOVE_SPI_GPIO_SEL BIT(5)
+#define DOVE_UART1_GPIO_SEL BIT(4)
+#define DOVE_AU1_GPIO_SEL BIT(3)
+#define DOVE_CAM_GPIO_SEL BIT(2)
+#define DOVE_SD1_GPIO_SEL BIT(1)
+#define DOVE_SD0_GPIO_SEL BIT(0)
+
+#define MPPS_PER_REG 8
+#define MPP_BITS 4
+#define MPP_MASK 0xf
+
+#define CONFIG_PMU BIT(4)
+
+static int dove_pmu_mpp_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
+ unsigned long *config)
+{
+ unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS;
+ unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS;
+ unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
+ unsigned long mpp = readl(DOVE_MPP_VIRT_BASE + off);
+
+ if (pmu & (1 << ctrl->pid))
+ *config = CONFIG_PMU;
+ else
+ *config = (mpp >> shift) & MPP_MASK;
+ return 0;
+}
+
+static int dove_pmu_mpp_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
+ unsigned long config)
+{
+ unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS;
+ unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS;
+ unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
+ unsigned long mpp = readl(DOVE_MPP_VIRT_BASE + off);
+
+ if (config == CONFIG_PMU)
+ writel(pmu | (1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL);
+ else {
+ writel(pmu & ~(1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL);
+ mpp &= ~(MPP_MASK << shift);
+ mpp |= config << shift;
+ writel(mpp, DOVE_MPP_VIRT_BASE + off);
+ }
+ return 0;
+}
+
+static int dove_mpp4_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
+ unsigned long *config)
+{
+ unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
+ unsigned long mask;
+
+ switch (ctrl->pid) {
+ case 24: /* mpp_camera */
+ mask = DOVE_CAM_GPIO_SEL;
+ break;
+ case 40: /* mpp_sdio0 */
+ mask = DOVE_SD0_GPIO_SEL;
+ break;
+ case 46: /* mpp_sdio1 */
+ mask = DOVE_SD1_GPIO_SEL;
+ break;
+ case 58: /* mpp_spi0 */
+ mask = DOVE_SPI_GPIO_SEL;
+ break;
+ case 62: /* mpp_uart1 */
+ mask = DOVE_UART1_GPIO_SEL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *config = ((mpp4 & mask) != 0);
+
+ return 0;
+}
+
+static int dove_mpp4_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
+ unsigned long config)
+{
+ unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
+ unsigned long mask;
+
+ switch (ctrl->pid) {
+ case 24: /* mpp_camera */
+ mask = DOVE_CAM_GPIO_SEL;
+ break;
+ case 40: /* mpp_sdio0 */
+ mask = DOVE_SD0_GPIO_SEL;
+ break;
+ case 46: /* mpp_sdio1 */
+ mask = DOVE_SD1_GPIO_SEL;
+ break;
+ case 58: /* mpp_spi0 */
+ mask = DOVE_SPI_GPIO_SEL;
+ break;
+ case 62: /* mpp_uart1 */
+ mask = DOVE_UART1_GPIO_SEL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ mpp4 &= ~mask;
+ if (config)
+ mpp4 |= mask;
+
+ writel(mpp4, DOVE_MPP_CTRL4_VIRT_BASE);
+
+ return 0;
+}
+
+static int dove_nand_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
+ unsigned long *config)
+{
+ unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
+
+ *config = ((gmpp & DOVE_NAND_GPIO_EN) != 0);
+
+ return 0;
+}
+
+static int dove_nand_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
+ unsigned long config)
+{
+ unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
+
+ gmpp &= ~DOVE_NAND_GPIO_EN;
+ if (config)
+ gmpp |= DOVE_NAND_GPIO_EN;
+
+ writel(gmpp, DOVE_MPP_GENERAL_VIRT_BASE);
+
+ return 0;
+}
+
+static int dove_audio0_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
+ unsigned long *config)
+{
+ unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
+
+ *config = ((pmu & DOVE_AU0_AC97_SEL) != 0);
+
+ return 0;
+}
+
+static int dove_audio0_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
+ unsigned long config)
+{
+ unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL);
+
+ pmu &= ~DOVE_AU0_AC97_SEL;
+ if (config)
+ pmu |= DOVE_AU0_AC97_SEL;
+ writel(pmu, DOVE_PMU_MPP_GENERAL_CTRL);
+
+ return 0;
+}
+
+static int dove_audio1_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
+ unsigned long *config)
+{
+ unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
+ unsigned long sspc1 = readl(DOVE_SSP_CTRL_STATUS_1);
+ unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
+ unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
+
+ *config = 0;
+ if (mpp4 & DOVE_AU1_GPIO_SEL)
+ *config |= BIT(3);
+ if (sspc1 & DOVE_SSP_ON_AU1)
+ *config |= BIT(2);
+ if (gmpp & DOVE_AU1_SPDIFO_GPIO_EN)
+ *config |= BIT(1);
+ if (gcfg2 & DOVE_TWSI_OPTION3_GPIO)
+ *config |= BIT(0);
+
+ /* SSP/TWSI only if I2S1 not set*/
+ if ((*config & BIT(3)) == 0)
+ *config &= ~(BIT(2) | BIT(0));
+ /* TWSI only if SPDIFO not set*/
+ if ((*config & BIT(1)) == 0)
+ *config &= ~BIT(0);
+ return 0;
+}
+
+static int dove_audio1_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
+ unsigned long config)
+{
+ unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
+ unsigned long sspc1 = readl(DOVE_SSP_CTRL_STATUS_1);
+ unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE);
+ unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
+
+ if (config & BIT(0))
+ gcfg2 |= DOVE_TWSI_OPTION3_GPIO;
+ if (config & BIT(1))
+ gmpp |= DOVE_AU1_SPDIFO_GPIO_EN;
+ if (config & BIT(2))
+ sspc1 |= DOVE_SSP_ON_AU1;
+ if (config & BIT(3))
+ mpp4 |= DOVE_AU1_GPIO_SEL;
+
+ writel(mpp4, DOVE_MPP_CTRL4_VIRT_BASE);
+ writel(sspc1, DOVE_SSP_CTRL_STATUS_1);
+ writel(gmpp, DOVE_MPP_GENERAL_VIRT_BASE);
+ writel(gcfg2, DOVE_GLOBAL_CONFIG_2);
+
+ return 0;
+}
+
+/* mpp[52:57] gpio pins depend heavily on current config;
+ * gpio_req does not try to mux in gpio capabilities to not
+ * break other functions. If you require all mpps as gpio
+ * enforce gpio setting by pinctrl mapping.
+ */
+static int dove_audio1_ctrl_gpio_req(struct mvebu_mpp_ctrl *ctrl, u8 pid)
+{
+ unsigned long config;
+
+ dove_audio1_ctrl_get(ctrl, &config);
+
+ switch (config) {
+ case 0x02: /* i2s1 : gpio[56:57] */
+ case 0x0e: /* ssp : gpio[56:57] */
+ if (pid >= 56)
+ return 0;
+ return -ENOTSUPP;
+ case 0x08: /* spdifo : gpio[52:55] */
+ case 0x0b: /* twsi : gpio[52:55] */
+ if (pid <= 55)
+ return 0;
+ return -ENOTSUPP;
+ case 0x0a: /* all gpio */
+ return 0;
+ /* 0x00 : i2s1/spdifo : no gpio */
+ /* 0x0c : ssp/spdifo : no gpio */
+ /* 0x0f : ssp/twsi : no gpio */
+ }
+ return -ENOTSUPP;
+}
+
+/* mpp[52:57] has gpio pins capable of in and out */
+static int dove_audio1_ctrl_gpio_dir(struct mvebu_mpp_ctrl *ctrl, u8 pid,
+ bool input)
+{
+ if (pid < 52 || pid > 57)
+ return -ENOTSUPP;
+ return 0;
+}
+
+static int dove_twsi_ctrl_get(struct mvebu_mpp_ctrl *ctrl,
+ unsigned long *config)
+{
+ unsigned long gcfg1 = readl(DOVE_GLOBAL_CONFIG_1);
+ unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
+
+ *config = 0;
+ if (gcfg1 & DOVE_TWSI_ENABLE_OPTION1)
+ *config = 1;
+ else if (gcfg2 & DOVE_TWSI_ENABLE_OPTION2)
+ *config = 2;
+ else if (gcfg2 & DOVE_TWSI_ENABLE_OPTION3)
+ *config = 3;
+
+ return 0;
+}
+
+static int dove_twsi_ctrl_set(struct mvebu_mpp_ctrl *ctrl,
+ unsigned long config)
+{
+ unsigned long gcfg1 = readl(DOVE_GLOBAL_CONFIG_1);
+ unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
+
+ gcfg1 &= ~DOVE_TWSI_ENABLE_OPTION1;
+ gcfg2 &= ~(DOVE_TWSI_ENABLE_OPTION2 | DOVE_TWSI_ENABLE_OPTION2);
+
+ switch (config) {
+ case 1:
+ gcfg1 |= DOVE_TWSI_ENABLE_OPTION1;
+ break;
+ case 2:
+ gcfg2 |= DOVE_TWSI_ENABLE_OPTION2;
+ break;
+ case 3:
+ gcfg2 |= DOVE_TWSI_ENABLE_OPTION3;
+ break;
+ }
+
+ writel(gcfg1, DOVE_GLOBAL_CONFIG_1);
+ writel(gcfg2, DOVE_GLOBAL_CONFIG_2);
+
+ return 0;
+}
+
+static struct mvebu_mpp_ctrl dove_mpp_controls[] = {
+ MPP_FUNC_CTRL(0, 0, "mpp0", dove_pmu_mpp_ctrl),
+ MPP_FUNC_CTRL(1, 1, "mpp1", dove_pmu_mpp_ctrl),
+ MPP_FUNC_CTRL(2, 2, "mpp2", dove_pmu_mpp_ctrl),
+ MPP_FUNC_CTRL(3, 3, "mpp3", dove_pmu_mpp_ctrl),
+ MPP_FUNC_CTRL(4, 4, "mpp4", dove_pmu_mpp_ctrl),
+ MPP_FUNC_CTRL(5, 5, "mpp5", dove_pmu_mpp_ctrl),
+ MPP_FUNC_CTRL(6, 6, "mpp6", dove_pmu_mpp_ctrl),
+ MPP_FUNC_CTRL(7, 7, "mpp7", dove_pmu_mpp_ctrl),
+ MPP_FUNC_CTRL(8, 8, "mpp8", dove_pmu_mpp_ctrl),
+ MPP_FUNC_CTRL(9, 9, "mpp9", dove_pmu_mpp_ctrl),
+ MPP_FUNC_CTRL(10, 10, "mpp10", dove_pmu_mpp_ctrl),
+ MPP_FUNC_CTRL(11, 11, "mpp11", dove_pmu_mpp_ctrl),
+ MPP_FUNC_CTRL(12, 12, "mpp12", dove_pmu_mpp_ctrl),
+ MPP_FUNC_CTRL(13, 13, "mpp13", dove_pmu_mpp_ctrl),
+ MPP_FUNC_CTRL(14, 14, "mpp14", dove_pmu_mpp_ctrl),
+ MPP_FUNC_CTRL(15, 15, "mpp15", dove_pmu_mpp_ctrl),
+ MPP_REG_CTRL(16, 23),
+ MPP_FUNC_CTRL(24, 39, "mpp_camera", dove_mpp4_ctrl),
+ MPP_FUNC_CTRL(40, 45, "mpp_sdio0", dove_mpp4_ctrl),
+ MPP_FUNC_CTRL(46, 51, "mpp_sdio1", dove_mpp4_ctrl),
+ MPP_FUNC_GPIO_CTRL(52, 57, "mpp_audio1", dove_audio1_ctrl),
+ MPP_FUNC_CTRL(58, 61, "mpp_spi0", dove_mpp4_ctrl),
+ MPP_FUNC_CTRL(62, 63, "mpp_uart1", dove_mpp4_ctrl),
+ MPP_FUNC_CTRL(64, 71, "mpp_nand", dove_nand_ctrl),
+ MPP_FUNC_CTRL(72, 72, "audio0", dove_audio0_ctrl),
+ MPP_FUNC_CTRL(73, 73, "twsi", dove_twsi_ctrl),
+};
+
+static struct mvebu_mpp_mode dove_mpp_modes[] = {
+ MPP_MODE(0,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x02, "uart2", "rts"),
+ MPP_FUNCTION(0x03, "sdio0", "cd"),
+ MPP_FUNCTION(0x0f, "lcd0", "pwm"),
+ MPP_FUNCTION(0x10, "pmu", NULL)),
+ MPP_MODE(1,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x02, "uart2", "cts"),
+ MPP_FUNCTION(0x03, "sdio0", "wp"),
+ MPP_FUNCTION(0x0f, "lcd1", "pwm"),
+ MPP_FUNCTION(0x10, "pmu", NULL)),
+ MPP_MODE(2,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x01, "sata", "prsnt"),
+ MPP_FUNCTION(0x02, "uart2", "txd"),
+ MPP_FUNCTION(0x03, "sdio0", "buspwr"),
+ MPP_FUNCTION(0x04, "uart1", "rts"),
+ MPP_FUNCTION(0x10, "pmu", NULL)),
+ MPP_MODE(3,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x01, "sata", "act"),
+ MPP_FUNCTION(0x02, "uart2", "rxd"),
+ MPP_FUNCTION(0x03, "sdio0", "ledctrl"),
+ MPP_FUNCTION(0x04, "uart1", "cts"),
+ MPP_FUNCTION(0x0f, "lcd-spi", "cs1"),
+ MPP_FUNCTION(0x10, "pmu", NULL)),
+ MPP_MODE(4,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x02, "uart3", "rts"),
+ MPP_FUNCTION(0x03, "sdio1", "cd"),
+ MPP_FUNCTION(0x04, "spi1", "miso"),
+ MPP_FUNCTION(0x10, "pmu", NULL)),
+ MPP_MODE(5,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x02, "uart3", "cts"),
+ MPP_FUNCTION(0x03, "sdio1", "wp"),
+ MPP_FUNCTION(0x04, "spi1", "cs"),
+ MPP_FUNCTION(0x10, "pmu", NULL)),
+ MPP_MODE(6,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x02, "uart3", "txd"),
+ MPP_FUNCTION(0x03, "sdio1", "buspwr"),
+ MPP_FUNCTION(0x04, "spi1", "mosi"),
+ MPP_FUNCTION(0x10, "pmu", NULL)),
+ MPP_MODE(7,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x02, "uart3", "rxd"),
+ MPP_FUNCTION(0x03, "sdio1", "ledctrl"),
+ MPP_FUNCTION(0x04, "spi1", "sck"),
+ MPP_FUNCTION(0x10, "pmu", NULL)),
+ MPP_MODE(8,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x01, "watchdog", "rstout"),
+ MPP_FUNCTION(0x10, "pmu", NULL)),
+ MPP_MODE(9,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x05, "pex1", "clkreq"),
+ MPP_FUNCTION(0x10, "pmu", NULL)),
+ MPP_MODE(10,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x05, "ssp", "sclk"),
+ MPP_FUNCTION(0x10, "pmu", NULL)),
+ MPP_MODE(11,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x01, "sata", "prsnt"),
+ MPP_FUNCTION(0x02, "sata-1", "act"),
+ MPP_FUNCTION(0x03, "sdio0", "ledctrl"),
+ MPP_FUNCTION(0x04, "sdio1", "ledctrl"),
+ MPP_FUNCTION(0x05, "pex0", "clkreq"),
+ MPP_FUNCTION(0x10, "pmu", NULL)),
+ MPP_MODE(12,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x01, "sata", "act"),
+ MPP_FUNCTION(0x02, "uart2", "rts"),
+ MPP_FUNCTION(0x03, "audio0", "extclk"),
+ MPP_FUNCTION(0x04, "sdio1", "cd"),
+ MPP_FUNCTION(0x10, "pmu", NULL)),
+ MPP_MODE(13,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x02, "uart2", "cts"),
+ MPP_FUNCTION(0x03, "audio1", "extclk"),
+ MPP_FUNCTION(0x04, "sdio1", "wp"),
+ MPP_FUNCTION(0x05, "ssp", "extclk"),
+ MPP_FUNCTION(0x10, "pmu", NULL)),
+ MPP_MODE(14,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x02, "uart2", "txd"),
+ MPP_FUNCTION(0x04, "sdio1", "buspwr"),
+ MPP_FUNCTION(0x05, "ssp", "rxd"),
+ MPP_FUNCTION(0x10, "pmu", NULL)),
+ MPP_MODE(15,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x02, "uart2", "rxd"),
+ MPP_FUNCTION(0x04, "sdio1", "ledctrl"),
+ MPP_FUNCTION(0x05, "ssp", "sfrm"),
+ MPP_FUNCTION(0x10, "pmu", NULL)),
+ MPP_MODE(16,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x02, "uart3", "rts"),
+ MPP_FUNCTION(0x03, "sdio0", "cd"),
+ MPP_FUNCTION(0x04, "lcd-spi", "cs1"),
+ MPP_FUNCTION(0x05, "ac97", "sdi1")),
+ MPP_MODE(17,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x01, "ac97-1", "sysclko"),
+ MPP_FUNCTION(0x02, "uart3", "cts"),
+ MPP_FUNCTION(0x03, "sdio0", "wp"),
+ MPP_FUNCTION(0x04, "twsi", "sda"),
+ MPP_FUNCTION(0x05, "ac97", "sdi2")),
+ MPP_MODE(18,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x02, "uart3", "txd"),
+ MPP_FUNCTION(0x03, "sdio0", "buspwr"),
+ MPP_FUNCTION(0x04, "lcd0", "pwm"),
+ MPP_FUNCTION(0x05, "ac97", "sdi3")),
+ MPP_MODE(19,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x02, "uart3", "rxd"),
+ MPP_FUNCTION(0x03, "sdio0", "ledctrl"),
+ MPP_FUNCTION(0x04, "twsi", "sck")),
+ MPP_MODE(20,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x01, "ac97", "sysclko"),
+ MPP_FUNCTION(0x02, "lcd-spi", "miso"),
+ MPP_FUNCTION(0x03, "sdio1", "cd"),
+ MPP_FUNCTION(0x05, "sdio0", "cd"),
+ MPP_FUNCTION(0x06, "spi1", "miso")),
+ MPP_MODE(21,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x01, "uart1", "rts"),
+ MPP_FUNCTION(0x02, "lcd-spi", "cs0"),
+ MPP_FUNCTION(0x03, "sdio1", "wp"),
+ MPP_FUNCTION(0x04, "ssp", "sfrm"),
+ MPP_FUNCTION(0x05, "sdio0", "wp"),
+ MPP_FUNCTION(0x06, "spi1", "cs")),
+ MPP_MODE(22,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x01, "uart1", "cts"),
+ MPP_FUNCTION(0x02, "lcd-spi", "mosi"),
+ MPP_FUNCTION(0x03, "sdio1", "buspwr"),
+ MPP_FUNCTION(0x04, "ssp", "txd"),
+ MPP_FUNCTION(0x05, "sdio0", "buspwr"),
+ MPP_FUNCTION(0x06, "spi1", "mosi")),
+ MPP_MODE(23,
+ MPP_FUNCTION(0x00, "gpio", NULL),
+ MPP_FUNCTION(0x02, "lcd-spi", "sck"),
+ MPP_FUNCTION(0x03, "sdio1", "ledctrl"),
+ MPP_FUNCTION(0x04, "ssp", "sclk"),
+ MPP_FUNCTION(0x05, "sdio0", "ledctrl"),
+ MPP_FUNCTION(0x06, "spi1", "sck")),
+ MPP_MODE(24,
+ MPP_FUNCTION(0x00, "camera", NULL),
+ MPP_FUNCTION(0x01, "gpio", NULL)),
+ MPP_MODE(40,
+ MPP_FUNCTION(0x00, "sdio0", NULL),
+ MPP_FUNCTION(0x01, "gpio", NULL)),
+ MPP_MODE(46,
+ MPP_FUNCTION(0x00, "sdio1", NULL),
+ MPP_FUNCTION(0x01, "gpio", NULL)),
+ MPP_MODE(52,
+ MPP_FUNCTION(0x00, "i2s1/spdifo", NULL),
+ MPP_FUNCTION(0x02, "i2s1", NULL),
+ MPP_FUNCTION(0x08, "spdifo", NULL),
+ MPP_FUNCTION(0x0a, "gpio", NULL),
+ MPP_FUNCTION(0x0b, "twsi", NULL),
+ MPP_FUNCTION(0x0c, "ssp/spdifo", NULL),
+ MPP_FUNCTION(0x0e, "ssp", NULL),
+ MPP_FUNCTION(0x0f, "ssp/twsi", NULL)),
+ MPP_MODE(58,
+ MPP_FUNCTION(0x00, "spi0", NULL),
+ MPP_FUNCTION(0x01, "gpio", NULL)),
+ MPP_MODE(62,
+ MPP_FUNCTION(0x00, "uart1", NULL),
+ MPP_FUNCTION(0x01, "gpio", NULL)),
+ MPP_MODE(64,
+ MPP_FUNCTION(0x00, "nand", NULL),
+ MPP_FUNCTION(0x01, "gpo", NULL)),
+ MPP_MODE(72,
+ MPP_FUNCTION(0x00, "i2s", NULL),
+ MPP_FUNCTION(0x01, "ac97", NULL)),
+ MPP_MODE(73,
+ MPP_FUNCTION(0x00, "twsi-none", NULL),
+ MPP_FUNCTION(0x01, "twsi-opt1", NULL),
+ MPP_FUNCTION(0x02, "twsi-opt2", NULL),
+ MPP_FUNCTION(0x03, "twsi-opt3", NULL)),
+};
+
+static struct pinctrl_gpio_range dove_mpp_gpio_ranges[] = {
+ MPP_GPIO_RANGE(0, 0, 0, 32),
+ MPP_GPIO_RANGE(1, 32, 32, 32),
+ MPP_GPIO_RANGE(2, 64, 64, 8),
+};
+
+static struct mvebu_pinctrl_soc_info dove_pinctrl_info = {
+ .controls = dove_mpp_controls,
+ .ncontrols = ARRAY_SIZE(dove_mpp_controls),
+ .modes = dove_mpp_modes,
+ .nmodes = ARRAY_SIZE(dove_mpp_modes),
+ .gpioranges = dove_mpp_gpio_ranges,
+ .ngpioranges = ARRAY_SIZE(dove_mpp_gpio_ranges),
+ .variant = 0,
+};
+
+static struct clk *clk;
+
+static struct of_device_id dove_pinctrl_of_match[] __devinitdata = {
+ { .compatible = "marvell,dove-pinctrl", .data = &dove_pinctrl_info },
+ { }
+};
+
+static int __devinit dove_pinctrl_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match =
+ of_match_device(dove_pinctrl_of_match, &pdev->dev);
+ pdev->dev.platform_data = match->data;
+
+ /*
+ * General MPP Configuration Register is part of pdma registers.
+ * grab clk to make sure it is ticking.
+ */
+ clk = devm_clk_get(&pdev->dev, NULL);
+ if (!IS_ERR(clk))
+ clk_prepare_enable(clk);
+
+ return mvebu_pinctrl_probe(pdev);
+}
+
+static int __devexit dove_pinctrl_remove(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = mvebu_pinctrl_remove(pdev);
+ if (!IS_ERR(clk))
+ clk_disable_unprepare(clk);
+ return ret;
+}
+
+static struct platform_driver dove_pinctrl_driver = {
+ .driver = {
+ .name = "dove-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(dove_pinctrl_of_match),
+ },
+ .probe = dove_pinctrl_probe,
+ .remove = __devexit_p(dove_pinctrl_remove),
+};
+
+module_platform_driver(dove_pinctrl_driver);
+
+MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>");
+MODULE_DESCRIPTION("Marvell Dove pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-kirkwood.c b/drivers/pinctrl/pinctrl-kirkwood.c
new file mode 100644
index 000000000000..9a74ef674a0e
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-kirkwood.c
@@ -0,0 +1,472 @@
+/*
+ * Marvell Kirkwood pinctrl driver based on mvebu pinctrl core
+ *
+ * Author: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.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/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-mvebu.h"
+
+#define V(f6180, f6190, f6192, f6281, f6282) \
+ ((f6180 << 0) | (f6190 << 1) | (f6192 << 2) | \
+ (f6281 << 3) | (f6282 << 4))
+
+enum kirkwood_variant {
+ VARIANT_MV88F6180 = V(1, 0, 0, 0, 0),
+ VARIANT_MV88F6190 = V(0, 1, 0, 0, 0),
+ VARIANT_MV88F6192 = V(0, 0, 1, 0, 0),
+ VARIANT_MV88F6281 = V(0, 0, 0, 1, 0),
+ VARIANT_MV88F6282 = V(0, 0, 0, 0, 1),
+};
+
+static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = {
+ MPP_MODE(0,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io2", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "cs", V(1, 1, 1, 1, 1))),
+ MPP_MODE(1,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io3", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "mosi", V(1, 1, 1, 1, 1))),
+ MPP_MODE(2,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io4", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "sck", V(1, 1, 1, 1, 1))),
+ MPP_MODE(3,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io5", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "miso", V(1, 1, 1, 1, 1))),
+ MPP_MODE(4,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io6", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "rxd", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "hsync", V(0, 0, 0, 0, 1)),
+ MPP_VAR_FUNCTION(0xd, "ptp", "clk", V(1, 1, 1, 1, 0))),
+ MPP_MODE(5,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io7", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "txd", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "ptp", "trig", V(1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1))),
+ MPP_MODE(6,
+ MPP_VAR_FUNCTION(0x0, "sysrst", "out", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "spi", "mosi", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "ptp", "trig", V(1, 1, 1, 1, 0))),
+ MPP_MODE(7,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "pex", "rsto", V(1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "spi", "cs", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ptp", "trig", V(1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "pwm", V(0, 0, 0, 0, 1))),
+ MPP_MODE(8,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "twsi0", "sda", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "rts", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "rts", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "mii-1", "rxerr", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "prsnt", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xc, "ptp", "clk", V(1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xd, "mii", "col", V(1, 1, 1, 1, 1))),
+ MPP_MODE(9,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "twsi0", "sck", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "cts", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "cts", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "prsnt", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xc, "ptp", "evreq", V(1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xd, "mii", "crs", V(1, 1, 1, 1, 1))),
+ MPP_MODE(10,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "sck", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0X3, "uart0", "txd", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xc, "ptp", "trig", V(1, 1, 1, 1, 0))),
+ MPP_MODE(11,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "spi", "miso", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart0", "rxd", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "ptp-1", "evreq", V(1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xc, "ptp-2", "trig", V(1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0xd, "ptp", "clk", V(1, 1, 1, 1, 0)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1))),
+ MPP_MODE(12,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 0, 1)),
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "clk", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xa, "audio", "spdifo", V(0, 0, 0, 0, 1)),
+ MPP_VAR_FUNCTION(0xb, "spi", "mosi", V(0, 0, 0, 0, 1)),
+ MPP_VAR_FUNCTION(0xd, "twsi1", "sda", V(0, 0, 0, 0, 1))),
+ MPP_MODE(13,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "cmd", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "txd", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xa, "audio", "rmclk", V(0, 0, 0, 0, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "pwm", V(0, 0, 0, 0, 1))),
+ MPP_MODE(14,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "d0", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "rxd", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "sata1", "prsnt", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xa, "audio", "spdifi", V(0, 0, 0, 0, 1)),
+ MPP_VAR_FUNCTION(0xb, "audio-1", "sdi", V(0, 0, 0, 0, 1)),
+ MPP_VAR_FUNCTION(0xd, "mii", "col", V(1, 1, 1, 1, 1))),
+ MPP_MODE(15,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "d1", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "rts", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "txd", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "sata0", "act", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "spi", "cs", V(0, 0, 0, 0, 1))),
+ MPP_MODE(16,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "d2", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "uart0", "cts", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "uart1", "rxd", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "sata1", "act", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "extclk", V(0, 0, 0, 0, 1)),
+ MPP_VAR_FUNCTION(0xd, "mii", "crs", V(1, 1, 1, 1, 1))),
+ MPP_MODE(17,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "sdio", "d3", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "sata0", "prsnt", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xa, "sata1", "act", V(0, 0, 0, 0, 1)),
+ MPP_VAR_FUNCTION(0xd, "twsi1", "sck", V(0, 0, 0, 0, 1))),
+ MPP_MODE(18,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io0", V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "pex", "clkreq", V(0, 0, 0, 0, 1))),
+ MPP_MODE(19,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "nand", "io1", V(1, 1, 1, 1, 1))),
+ MPP_MODE(20,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp0", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txd0", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d0", V(0, 0, 0, 0, 1)),
+ MPP_VAR_FUNCTION(0xc, "mii", "rxerr", V(1, 0, 0, 0, 0))),
+ MPP_MODE(21,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp1", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txd1", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(1, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d1", V(0, 0, 0, 0, 1))),
+ MPP_MODE(22,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp2", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txd2", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(1, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "prsnt", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d2", V(0, 0, 0, 0, 1))),
+ MPP_MODE(23,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp3", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txd3", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(1, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "prsnt", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d3", V(0, 0, 0, 0, 1))),
+ MPP_MODE(24,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp4", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxd0", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(1, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d4", V(0, 0, 0, 0, 1))),
+ MPP_MODE(25,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp5", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxd1", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(1, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d5", V(0, 0, 0, 0, 1))),
+ MPP_MODE(26,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp6", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxd2", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(1, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d6", V(0, 0, 0, 0, 1))),
+ MPP_MODE(27,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp7", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxd3", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(1, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d7", V(0, 0, 0, 0, 1))),
+ MPP_MODE(28,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp8", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "int", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "col", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(1, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d8", V(0, 0, 0, 0, 1))),
+ MPP_MODE(29,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rst", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txclk", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(1, 0, 0, 0, 0)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d9", V(0, 0, 0, 0, 1))),
+ MPP_MODE(30,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp10", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "pclk", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxctl", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d10", V(0, 0, 0, 0, 1))),
+ MPP_MODE(31,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp11", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "fs", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxclk", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d11", V(0, 0, 0, 0, 1))),
+ MPP_MODE(32,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp12", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "drx", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txclko", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d12", V(0, 0, 0, 0, 1))),
+ MPP_MODE(33,
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "dtx", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txctl", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d13", V(0, 0, 0, 0, 1))),
+ MPP_MODE(34,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "txen", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d14", V(0, 0, 0, 0, 1))),
+ MPP_MODE(35,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql", V(0, 0, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x3, "ge1", "rxerr", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d15", V(0, 0, 0, 0, 1)),
+ MPP_VAR_FUNCTION(0xc, "mii", "rxerr", V(0, 1, 1, 1, 1))),
+ MPP_MODE(36,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp0", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "twsi1", "sda", V(0, 0, 0, 0, 1))),
+ MPP_MODE(37,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp1", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "twsi1", "sck", V(0, 0, 0, 0, 1))),
+ MPP_MODE(38,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp2", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d18", V(0, 0, 0, 0, 1))),
+ MPP_MODE(39,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp3", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d19", V(0, 0, 0, 0, 1))),
+ MPP_MODE(40,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp4", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d20", V(0, 0, 0, 0, 1))),
+ MPP_MODE(41,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp5", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d21", V(0, 0, 0, 0, 1))),
+ MPP_MODE(42,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp6", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d22", V(0, 0, 0, 0, 1))),
+ MPP_MODE(43,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp7", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "int", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d23", V(0, 0, 0, 0, 1))),
+ MPP_MODE(44,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp8", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rst", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "clk", V(0, 0, 0, 0, 1))),
+ MPP_MODE(45,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "pclk", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "e", V(0, 0, 0, 0, 1))),
+ MPP_MODE(46,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp10", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "fs", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "hsync", V(0, 0, 0, 0, 1))),
+ MPP_MODE(47,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp11", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "drx", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1))),
+ MPP_MODE(48,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp12", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "dtx", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d16", V(0, 0, 0, 0, 1))),
+ MPP_MODE(49,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(0, 0, 0, 0, 1)),
+ MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql", V(0, 0, 0, 1, 1)),
+ MPP_VAR_FUNCTION(0x5, "ptp", "clk", V(0, 0, 0, 1, 0)),
+ MPP_VAR_FUNCTION(0xa, "pex", "clkreq", V(0, 0, 0, 0, 1)),
+ MPP_VAR_FUNCTION(0xb, "lcd", "d17", V(0, 0, 0, 0, 1))),
+};
+
+static struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = {
+ MPP_REG_CTRL(0, 29),
+};
+
+static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
+ MPP_GPIO_RANGE(0, 0, 0, 30),
+};
+
+static struct mvebu_mpp_ctrl mv88f619x_mpp_controls[] = {
+ MPP_REG_CTRL(0, 35),
+};
+
+static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
+ MPP_GPIO_RANGE(0, 0, 0, 32),
+ MPP_GPIO_RANGE(1, 32, 32, 4),
+};
+
+static struct mvebu_mpp_ctrl mv88f628x_mpp_controls[] = {
+ MPP_REG_CTRL(0, 49),
+};
+
+static struct pinctrl_gpio_range mv88f628x_gpio_ranges[] = {
+ MPP_GPIO_RANGE(0, 0, 0, 32),
+ MPP_GPIO_RANGE(1, 32, 32, 18),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6180_info = {
+ .variant = VARIANT_MV88F6180,
+ .controls = mv88f6180_mpp_controls,
+ .ncontrols = ARRAY_SIZE(mv88f6180_mpp_controls),
+ .modes = mv88f6xxx_mpp_modes,
+ .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+ .gpioranges = mv88f6180_gpio_ranges,
+ .ngpioranges = ARRAY_SIZE(mv88f6180_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6190_info = {
+ .variant = VARIANT_MV88F6190,
+ .controls = mv88f619x_mpp_controls,
+ .ncontrols = ARRAY_SIZE(mv88f619x_mpp_controls),
+ .modes = mv88f6xxx_mpp_modes,
+ .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+ .gpioranges = mv88f619x_gpio_ranges,
+ .ngpioranges = ARRAY_SIZE(mv88f619x_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6192_info = {
+ .variant = VARIANT_MV88F6192,
+ .controls = mv88f619x_mpp_controls,
+ .ncontrols = ARRAY_SIZE(mv88f619x_mpp_controls),
+ .modes = mv88f6xxx_mpp_modes,
+ .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+ .gpioranges = mv88f619x_gpio_ranges,
+ .ngpioranges = ARRAY_SIZE(mv88f619x_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6281_info = {
+ .variant = VARIANT_MV88F6281,
+ .controls = mv88f628x_mpp_controls,
+ .ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
+ .modes = mv88f6xxx_mpp_modes,
+ .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+ .gpioranges = mv88f628x_gpio_ranges,
+ .ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6282_info = {
+ .variant = VARIANT_MV88F6282,
+ .controls = mv88f628x_mpp_controls,
+ .ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
+ .modes = mv88f6xxx_mpp_modes,
+ .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+ .gpioranges = mv88f628x_gpio_ranges,
+ .ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
+};
+
+static struct of_device_id kirkwood_pinctrl_of_match[] __devinitdata = {
+ { .compatible = "marvell,88f6180-pinctrl", .data = &mv88f6180_info },
+ { .compatible = "marvell,88f6190-pinctrl", .data = &mv88f6190_info },
+ { .compatible = "marvell,88f6192-pinctrl", .data = &mv88f6192_info },
+ { .compatible = "marvell,88f6281-pinctrl", .data = &mv88f6281_info },
+ { .compatible = "marvell,88f6282-pinctrl", .data = &mv88f6282_info },
+ { }
+};
+
+static int __devinit kirkwood_pinctrl_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match =
+ of_match_device(kirkwood_pinctrl_of_match, &pdev->dev);
+ pdev->dev.platform_data = match->data;
+ return mvebu_pinctrl_probe(pdev);
+}
+
+static int __devexit kirkwood_pinctrl_remove(struct platform_device *pdev)
+{
+ return mvebu_pinctrl_remove(pdev);
+}
+
+static struct platform_driver kirkwood_pinctrl_driver = {
+ .driver = {
+ .name = "kirkwood-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(kirkwood_pinctrl_of_match),
+ },
+ .probe = kirkwood_pinctrl_probe,
+ .remove = __devexit_p(kirkwood_pinctrl_remove),
+};
+
+module_platform_driver(kirkwood_pinctrl_driver);
+
+MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>");
+MODULE_DESCRIPTION("Marvell Kirkwood pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-mvebu.c b/drivers/pinctrl/pinctrl-mvebu.c
new file mode 100644
index 000000000000..8e6266c6249a
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-mvebu.c
@@ -0,0 +1,754 @@
+/*
+ * Marvell MVEBU pinctrl core driver
+ *
+ * Authors: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.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/platform_device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "core.h"
+#include "pinctrl-mvebu.h"
+
+#define MPPS_PER_REG 8
+#define MPP_BITS 4
+#define MPP_MASK 0xf
+
+struct mvebu_pinctrl_function {
+ const char *name;
+ const char **groups;
+ unsigned num_groups;
+};
+
+struct mvebu_pinctrl_group {
+ const char *name;
+ struct mvebu_mpp_ctrl *ctrl;
+ struct mvebu_mpp_ctrl_setting *settings;
+ unsigned num_settings;
+ unsigned gid;
+ unsigned *pins;
+ unsigned npins;
+};
+
+struct mvebu_pinctrl {
+ struct device *dev;
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_desc desc;
+ void __iomem *base;
+ struct mvebu_pinctrl_group *groups;
+ unsigned num_groups;
+ struct mvebu_pinctrl_function *functions;
+ unsigned num_functions;
+ u8 variant;
+};
+
+static struct mvebu_pinctrl_group *mvebu_pinctrl_find_group_by_pid(
+ struct mvebu_pinctrl *pctl, unsigned pid)
+{
+ unsigned n;
+ for (n = 0; n < pctl->num_groups; n++) {
+ if (pid >= pctl->groups[n].pins[0] &&
+ pid < pctl->groups[n].pins[0] +
+ pctl->groups[n].npins)
+ return &pctl->groups[n];
+ }
+ return NULL;
+}
+
+static struct mvebu_pinctrl_group *mvebu_pinctrl_find_group_by_name(
+ struct mvebu_pinctrl *pctl, const char *name)
+{
+ unsigned n;
+ for (n = 0; n < pctl->num_groups; n++) {
+ if (strcmp(name, pctl->groups[n].name) == 0)
+ return &pctl->groups[n];
+ }
+ return NULL;
+}
+
+static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_setting_by_val(
+ struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp,
+ unsigned long config)
+{
+ unsigned n;
+ for (n = 0; n < grp->num_settings; n++) {
+ if (config == grp->settings[n].val) {
+ if (!pctl->variant || (pctl->variant &
+ grp->settings[n].variant))
+ return &grp->settings[n];
+ }
+ }
+ return NULL;
+}
+
+static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_setting_by_name(
+ struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp,
+ const char *name)
+{
+ unsigned n;
+ for (n = 0; n < grp->num_settings; n++) {
+ if (strcmp(name, grp->settings[n].name) == 0) {
+ if (!pctl->variant || (pctl->variant &
+ grp->settings[n].variant))
+ return &grp->settings[n];
+ }
+ }
+ return NULL;
+}
+
+static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_gpio_setting(
+ struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp)
+{
+ unsigned n;
+ for (n = 0; n < grp->num_settings; n++) {
+ if (grp->settings[n].flags &
+ (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) {
+ if (!pctl->variant || (pctl->variant &
+ grp->settings[n].variant))
+ return &grp->settings[n];
+ }
+ }
+ return NULL;
+}
+
+static struct mvebu_pinctrl_function *mvebu_pinctrl_find_function_by_name(
+ struct mvebu_pinctrl *pctl, const char *name)
+{
+ unsigned n;
+ for (n = 0; n < pctl->num_functions; n++) {
+ if (strcmp(name, pctl->functions[n].name) == 0)
+ return &pctl->functions[n];
+ }
+ return NULL;
+}
+
+/*
+ * Common mpp pin configuration registers on MVEBU are
+ * registers of eight 4-bit values for each mpp setting.
+ * Register offset and bit mask are calculated accordingly below.
+ */
+static int mvebu_common_mpp_get(struct mvebu_pinctrl *pctl,
+ struct mvebu_pinctrl_group *grp,
+ unsigned long *config)
+{
+ unsigned pin = grp->gid;
+ unsigned off = (pin / MPPS_PER_REG) * MPP_BITS;
+ unsigned shift = (pin % MPPS_PER_REG) * MPP_BITS;
+
+ *config = readl(pctl->base + off);
+ *config >>= shift;
+ *config &= MPP_MASK;
+
+ return 0;
+}
+
+static int mvebu_common_mpp_set(struct mvebu_pinctrl *pctl,
+ struct mvebu_pinctrl_group *grp,
+ unsigned long config)
+{
+ unsigned pin = grp->gid;
+ unsigned off = (pin / MPPS_PER_REG) * MPP_BITS;
+ unsigned shift = (pin % MPPS_PER_REG) * MPP_BITS;
+ unsigned long reg;
+
+ reg = readl(pctl->base + off);
+ reg &= ~(MPP_MASK << shift);
+ reg |= (config << shift);
+ writel(reg, pctl->base + off);
+
+ return 0;
+}
+
+static int mvebu_pinconf_group_get(struct pinctrl_dev *pctldev,
+ unsigned gid, unsigned long *config)
+{
+ struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct mvebu_pinctrl_group *grp = &pctl->groups[gid];
+
+ if (!grp->ctrl)
+ return -EINVAL;
+
+ if (grp->ctrl->mpp_get)
+ return grp->ctrl->mpp_get(grp->ctrl, config);
+
+ return mvebu_common_mpp_get(pctl, grp, config);
+}
+
+static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev,
+ unsigned gid, unsigned long config)
+{
+ struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct mvebu_pinctrl_group *grp = &pctl->groups[gid];
+
+ if (!grp->ctrl)
+ return -EINVAL;
+
+ if (grp->ctrl->mpp_set)
+ return grp->ctrl->mpp_set(grp->ctrl, config);
+
+ return mvebu_common_mpp_set(pctl, grp, config);
+}
+
+static void mvebu_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned gid)
+{
+ struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct mvebu_pinctrl_group *grp = &pctl->groups[gid];
+ struct mvebu_mpp_ctrl_setting *curr;
+ unsigned long config;
+ unsigned n;
+
+ if (mvebu_pinconf_group_get(pctldev, gid, &config))
+ return;
+
+ curr = mvebu_pinctrl_find_setting_by_val(pctl, grp, config);
+
+ if (curr) {
+ seq_printf(s, "current: %s", curr->name);
+ if (curr->subname)
+ seq_printf(s, "(%s)", curr->subname);
+ if (curr->flags & (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) {
+ seq_printf(s, "(");
+ if (curr->flags & MVEBU_SETTING_GPI)
+ seq_printf(s, "i");
+ if (curr->flags & MVEBU_SETTING_GPO)
+ seq_printf(s, "o");
+ seq_printf(s, ")");
+ }
+ } else
+ seq_printf(s, "current: UNKNOWN");
+
+ if (grp->num_settings > 1) {
+ seq_printf(s, ", available = [");
+ for (n = 0; n < grp->num_settings; n++) {
+ if (curr == &grp->settings[n])
+ continue;
+
+ /* skip unsupported settings for this variant */
+ if (pctl->variant &&
+ !(pctl->variant & grp->settings[n].variant))
+ continue;
+
+ seq_printf(s, " %s", grp->settings[n].name);
+ if (grp->settings[n].subname)
+ seq_printf(s, "(%s)", grp->settings[n].subname);
+ if (grp->settings[n].flags &
+ (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) {
+ seq_printf(s, "(");
+ if (grp->settings[n].flags & MVEBU_SETTING_GPI)
+ seq_printf(s, "i");
+ if (grp->settings[n].flags & MVEBU_SETTING_GPO)
+ seq_printf(s, "o");
+ seq_printf(s, ")");
+ }
+ }
+ seq_printf(s, " ]");
+ }
+ return;
+}
+
+static struct pinconf_ops mvebu_pinconf_ops = {
+ .pin_config_group_get = mvebu_pinconf_group_get,
+ .pin_config_group_set = mvebu_pinconf_group_set,
+ .pin_config_group_dbg_show = mvebu_pinconf_group_dbg_show,
+};
+
+static int mvebu_pinmux_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+ struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ return pctl->num_functions;
+}
+
+static const char *mvebu_pinmux_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned fid)
+{
+ struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ return pctl->functions[fid].name;
+}
+
+static int mvebu_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned fid,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ *groups = pctl->functions[fid].groups;
+ *num_groups = pctl->functions[fid].num_groups;
+ return 0;
+}
+
+static int mvebu_pinmux_enable(struct pinctrl_dev *pctldev, unsigned fid,
+ unsigned gid)
+{
+ struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct mvebu_pinctrl_function *func = &pctl->functions[fid];
+ struct mvebu_pinctrl_group *grp = &pctl->groups[gid];
+ struct mvebu_mpp_ctrl_setting *setting;
+ int ret;
+
+ setting = mvebu_pinctrl_find_setting_by_name(pctl, grp,
+ func->name);
+ if (!setting) {
+ dev_err(pctl->dev,
+ "unable to find setting %s in group %s\n",
+ func->name, func->groups[gid]);
+ return -EINVAL;
+ }
+
+ ret = mvebu_pinconf_group_set(pctldev, grp->gid, setting->val);
+ if (ret) {
+ dev_err(pctl->dev, "cannot set group %s to %s\n",
+ func->groups[gid], func->name);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mvebu_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range, unsigned offset)
+{
+ struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct mvebu_pinctrl_group *grp;
+ struct mvebu_mpp_ctrl_setting *setting;
+
+ grp = mvebu_pinctrl_find_group_by_pid(pctl, offset);
+ if (!grp)
+ return -EINVAL;
+
+ if (grp->ctrl->mpp_gpio_req)
+ return grp->ctrl->mpp_gpio_req(grp->ctrl, offset);
+
+ setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);
+ if (!setting)
+ return -ENOTSUPP;
+
+ return mvebu_pinconf_group_set(pctldev, grp->gid, setting->val);
+}
+
+static int mvebu_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range, unsigned offset, bool input)
+{
+ struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct mvebu_pinctrl_group *grp;
+ struct mvebu_mpp_ctrl_setting *setting;
+
+ grp = mvebu_pinctrl_find_group_by_pid(pctl, offset);
+ if (!grp)
+ return -EINVAL;
+
+ if (grp->ctrl->mpp_gpio_dir)
+ return grp->ctrl->mpp_gpio_dir(grp->ctrl, offset, input);
+
+ setting = mvebu_pinctrl_find_gpio_setting(pctl, grp);
+ if (!setting)
+ return -ENOTSUPP;
+
+ if ((input && (setting->flags & MVEBU_SETTING_GPI)) ||
+ (!input && (setting->flags & MVEBU_SETTING_GPO)))
+ return 0;
+
+ return -ENOTSUPP;
+}
+
+static struct pinmux_ops mvebu_pinmux_ops = {
+ .get_functions_count = mvebu_pinmux_get_funcs_count,
+ .get_function_name = mvebu_pinmux_get_func_name,
+ .get_function_groups = mvebu_pinmux_get_groups,
+ .gpio_request_enable = mvebu_pinmux_gpio_request_enable,
+ .gpio_set_direction = mvebu_pinmux_gpio_set_direction,
+ .enable = mvebu_pinmux_enable,
+};
+
+static int mvebu_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ return pctl->num_groups;
+}
+
+static const char *mvebu_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned gid)
+{
+ struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ return pctl->groups[gid].name;
+}
+
+static int mvebu_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned gid, const unsigned **pins,
+ unsigned *num_pins)
+{
+ struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ *pins = pctl->groups[gid].pins;
+ *num_pins = pctl->groups[gid].npins;
+ return 0;
+}
+
+static int mvebu_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **map,
+ unsigned *num_maps)
+{
+ struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct property *prop;
+ const char *function;
+ const char *group;
+ int ret, nmaps, n;
+
+ *map = NULL;
+ *num_maps = 0;
+
+ ret = of_property_read_string(np, "marvell,function", &function);
+ if (ret) {
+ dev_err(pctl->dev,
+ "missing marvell,function in node %s\n", np->name);
+ return 0;
+ }
+
+ nmaps = of_property_count_strings(np, "marvell,pins");
+ if (nmaps < 0) {
+ dev_err(pctl->dev,
+ "missing marvell,pins in node %s\n", np->name);
+ return 0;
+ }
+
+ *map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL);
+ if (map == NULL) {
+ dev_err(pctl->dev,
+ "cannot allocate pinctrl_map memory for %s\n",
+ np->name);
+ return -ENOMEM;
+ }
+
+ n = 0;
+ of_property_for_each_string(np, "marvell,pins", prop, group) {
+ struct mvebu_pinctrl_group *grp =
+ mvebu_pinctrl_find_group_by_name(pctl, group);
+
+ if (!grp) {
+ dev_err(pctl->dev, "unknown pin %s", group);
+ continue;
+ }
+
+ if (!mvebu_pinctrl_find_setting_by_name(pctl, grp, function)) {
+ dev_err(pctl->dev, "unsupported function %s on pin %s",
+ function, group);
+ continue;
+ }
+
+ (*map)[n].type = PIN_MAP_TYPE_MUX_GROUP;
+ (*map)[n].data.mux.group = group;
+ (*map)[n].data.mux.function = function;
+ n++;
+ }
+
+ *num_maps = nmaps;
+
+ return 0;
+}
+
+static void mvebu_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+ kfree(map);
+}
+
+static struct pinctrl_ops mvebu_pinctrl_ops = {
+ .get_groups_count = mvebu_pinctrl_get_groups_count,
+ .get_group_name = mvebu_pinctrl_get_group_name,
+ .get_group_pins = mvebu_pinctrl_get_group_pins,
+ .dt_node_to_map = mvebu_pinctrl_dt_node_to_map,
+ .dt_free_map = mvebu_pinctrl_dt_free_map,
+};
+
+static int __devinit _add_function(struct mvebu_pinctrl_function *funcs,
+ const char *name)
+{
+ while (funcs->num_groups) {
+ /* function already there */
+ if (strcmp(funcs->name, name) == 0) {
+ funcs->num_groups++;
+ return -EEXIST;
+ }
+ funcs++;
+ }
+ funcs->name = name;
+ funcs->num_groups = 1;
+ return 0;
+}
+
+static int __devinit mvebu_pinctrl_build_functions(struct platform_device *pdev,
+ struct mvebu_pinctrl *pctl)
+{
+ struct mvebu_pinctrl_function *funcs;
+ int num = 0;
+ int n, s;
+
+ /* we allocate functions for number of pins and hope
+ * there are less unique functions than pins available */
+ funcs = devm_kzalloc(&pdev->dev, pctl->desc.npins *
+ sizeof(struct mvebu_pinctrl_function), GFP_KERNEL);
+ if (!funcs)
+ return -ENOMEM;
+
+ for (n = 0; n < pctl->num_groups; n++) {
+ struct mvebu_pinctrl_group *grp = &pctl->groups[n];
+ for (s = 0; s < grp->num_settings; s++) {
+ /* skip unsupported settings on this variant */
+ if (pctl->variant &&
+ !(pctl->variant & grp->settings[s].variant))
+ continue;
+
+ /* check for unique functions and count groups */
+ if (_add_function(funcs, grp->settings[s].name))
+ continue;
+
+ num++;
+ }
+ }
+
+ /* with the number of unique functions and it's groups known,
+ reallocate functions and assign group names */
+ funcs = krealloc(funcs, num * sizeof(struct mvebu_pinctrl_function),
+ GFP_KERNEL);
+ if (!funcs)
+ return -ENOMEM;
+
+ pctl->num_functions = num;
+ pctl->functions = funcs;
+
+ for (n = 0; n < pctl->num_groups; n++) {
+ struct mvebu_pinctrl_group *grp = &pctl->groups[n];
+ for (s = 0; s < grp->num_settings; s++) {
+ struct mvebu_pinctrl_function *f;
+ const char **groups;
+
+ /* skip unsupported settings on this variant */
+ if (pctl->variant &&
+ !(pctl->variant & grp->settings[s].variant))
+ continue;
+
+ f = mvebu_pinctrl_find_function_by_name(pctl,
+ grp->settings[s].name);
+
+ /* allocate group name array if not done already */
+ if (!f->groups) {
+ f->groups = devm_kzalloc(&pdev->dev,
+ f->num_groups * sizeof(char *),
+ GFP_KERNEL);
+ if (!f->groups)
+ return -ENOMEM;
+ }
+
+ /* find next free group name and assign current name */
+ groups = f->groups;
+ while (*groups)
+ groups++;
+ *groups = grp->name;
+ }
+ }
+
+ return 0;
+}
+
+int __devinit mvebu_pinctrl_probe(struct platform_device *pdev)
+{
+ struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(&pdev->dev);
+ struct device_node *np = pdev->dev.of_node;
+ struct mvebu_pinctrl *pctl;
+ void __iomem *base;
+ struct pinctrl_pin_desc *pdesc;
+ unsigned gid, n, k;
+ int ret;
+
+ if (!soc || !soc->controls || !soc->modes) {
+ dev_err(&pdev->dev, "wrong pinctrl soc info\n");
+ return -EINVAL;
+ }
+
+ base = of_iomap(np, 0);
+ if (!base) {
+ dev_err(&pdev->dev, "unable to get base address\n");
+ return -ENODEV;
+ }
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_pinctrl),
+ GFP_KERNEL);
+ if (!pctl) {
+ dev_err(&pdev->dev, "unable to alloc driver\n");
+ return -ENOMEM;
+ }
+
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+ pctl->desc.pctlops = &mvebu_pinctrl_ops;
+ pctl->desc.pmxops = &mvebu_pinmux_ops;
+ pctl->desc.confops = &mvebu_pinconf_ops;
+ pctl->variant = soc->variant;
+ pctl->base = base;
+ pctl->dev = &pdev->dev;
+ platform_set_drvdata(pdev, pctl);
+
+ /* count controls and create names for mvebu generic
+ register controls; also does sanity checks */
+ pctl->num_groups = 0;
+ pctl->desc.npins = 0;
+ for (n = 0; n < soc->ncontrols; n++) {
+ struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
+ char *names;
+
+ pctl->desc.npins += ctrl->npins;
+ /* initial control pins */
+ for (k = 0; k < ctrl->npins; k++)
+ ctrl->pins[k] = ctrl->pid + k;
+
+ /* special soc specific control */
+ if (ctrl->mpp_get || ctrl->mpp_set) {
+ if (!ctrl->name || !ctrl->mpp_set || !ctrl->mpp_set) {
+ dev_err(&pdev->dev, "wrong soc control info\n");
+ return -EINVAL;
+ }
+ pctl->num_groups += 1;
+ continue;
+ }
+
+ /* generic mvebu register control */
+ names = devm_kzalloc(&pdev->dev, ctrl->npins * 8, GFP_KERNEL);
+ if (!names) {
+ dev_err(&pdev->dev, "failed to alloc mpp names\n");
+ return -ENOMEM;
+ }
+ for (k = 0; k < ctrl->npins; k++)
+ sprintf(names + 8*k, "mpp%d", ctrl->pid+k);
+ ctrl->name = names;
+ pctl->num_groups += ctrl->npins;
+ }
+
+ pdesc = devm_kzalloc(&pdev->dev, pctl->desc.npins *
+ sizeof(struct pinctrl_pin_desc), GFP_KERNEL);
+ if (!pdesc) {
+ dev_err(&pdev->dev, "failed to alloc pinctrl pins\n");
+ return -ENOMEM;
+ }
+
+ for (n = 0; n < pctl->desc.npins; n++)
+ pdesc[n].number = n;
+ pctl->desc.pins = pdesc;
+
+ pctl->groups = devm_kzalloc(&pdev->dev, pctl->num_groups *
+ sizeof(struct mvebu_pinctrl_group), GFP_KERNEL);
+ if (!pctl->groups) {
+ dev_err(&pdev->dev, "failed to alloc pinctrl groups\n");
+ return -ENOMEM;
+ }
+
+ /* assign mpp controls to groups */
+ gid = 0;
+ for (n = 0; n < soc->ncontrols; n++) {
+ struct mvebu_mpp_ctrl *ctrl = &soc->controls[n];
+ pctl->groups[gid].gid = gid;
+ pctl->groups[gid].ctrl = ctrl;
+ pctl->groups[gid].name = ctrl->name;
+ pctl->groups[gid].pins = ctrl->pins;
+ pctl->groups[gid].npins = ctrl->npins;
+
+ /* generic mvebu register control maps to a number of groups */
+ if (!ctrl->mpp_get && !ctrl->mpp_set) {
+ pctl->groups[gid].npins = 1;
+
+ for (k = 1; k < ctrl->npins; k++) {
+ gid++;
+ pctl->groups[gid].gid = gid;
+ pctl->groups[gid].ctrl = ctrl;
+ pctl->groups[gid].name = &ctrl->name[8*k];
+ pctl->groups[gid].pins = &ctrl->pins[k];
+ pctl->groups[gid].npins = 1;
+ }
+ }
+ gid++;
+ }
+
+ /* assign mpp modes to groups */
+ for (n = 0; n < soc->nmodes; n++) {
+ struct mvebu_mpp_mode *mode = &soc->modes[n];
+ struct mvebu_pinctrl_group *grp =
+ mvebu_pinctrl_find_group_by_pid(pctl, mode->pid);
+ unsigned num_settings;
+
+ if (!grp) {
+ dev_warn(&pdev->dev, "unknown pinctrl group %d\n",
+ mode->pid);
+ continue;
+ }
+
+ for (num_settings = 0; ;) {
+ struct mvebu_mpp_ctrl_setting *set =
+ &mode->settings[num_settings];
+
+ if (!set->name)
+ break;
+ num_settings++;
+
+ /* skip unsupported settings for this variant */
+ if (pctl->variant && !(pctl->variant & set->variant))
+ continue;
+
+ /* find gpio/gpo/gpi settings */
+ if (strcmp(set->name, "gpio") == 0)
+ set->flags = MVEBU_SETTING_GPI |
+ MVEBU_SETTING_GPO;
+ else if (strcmp(set->name, "gpo") == 0)
+ set->flags = MVEBU_SETTING_GPO;
+ else if (strcmp(set->name, "gpi") == 0)
+ set->flags = MVEBU_SETTING_GPI;
+ }
+
+ grp->settings = mode->settings;
+ grp->num_settings = num_settings;
+ }
+
+ ret = mvebu_pinctrl_build_functions(pdev, pctl);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to build functions\n");
+ return ret;
+ }
+
+ pctl->pctldev = pinctrl_register(&pctl->desc, &pdev->dev, pctl);
+ if (!pctl->pctldev) {
+ dev_err(&pdev->dev, "unable to register pinctrl driver\n");
+ return -EINVAL;
+ }
+
+ dev_info(&pdev->dev, "registered pinctrl driver\n");
+
+ /* register gpio ranges */
+ for (n = 0; n < soc->ngpioranges; n++)
+ pinctrl_add_gpio_range(pctl->pctldev, &soc->gpioranges[n]);
+
+ return 0;
+}
+
+int __devexit mvebu_pinctrl_remove(struct platform_device *pdev)
+{
+ struct mvebu_pinctrl *pctl = platform_get_drvdata(pdev);
+ pinctrl_unregister(pctl->pctldev);
+ return 0;
+}
diff --git a/drivers/pinctrl/pinctrl-mvebu.h b/drivers/pinctrl/pinctrl-mvebu.h
new file mode 100644
index 000000000000..90bd3beee860
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-mvebu.h
@@ -0,0 +1,192 @@
+/*
+ * Marvell MVEBU pinctrl driver
+ *
+ * Authors: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.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.
+ */
+
+#ifndef __PINCTRL_MVEBU_H__
+#define __PINCTRL_MVEBU_H__
+
+/**
+ * struct mvebu_mpp_ctrl - describe a mpp control
+ * @name: name of the control group
+ * @pid: first pin id handled by this control
+ * @npins: number of pins controlled by this control
+ * @mpp_get: (optional) special function to get mpp setting
+ * @mpp_set: (optional) special function to set mpp setting
+ * @mpp_gpio_req: (optional) special function to request gpio
+ * @mpp_gpio_dir: (optional) special function to set gpio direction
+ *
+ * A mpp_ctrl describes a muxable unit, e.g. pin, group of pins, or
+ * internal function, inside the SoC. Each muxable unit can be switched
+ * between two or more different settings, e.g. assign mpp pin 13 to
+ * uart1 or sata.
+ *
+ * If optional mpp_get/_set functions are set these are used to get/set
+ * a specific mode. Otherwise it is assumed that the mpp control is based
+ * on 4-bit groups in subsequent registers. The optional mpp_gpio_req/_dir
+ * functions can be used to allow pin settings with varying gpio pins.
+ */
+struct mvebu_mpp_ctrl {
+ const char *name;
+ u8 pid;
+ u8 npins;
+ unsigned *pins;
+ int (*mpp_get)(struct mvebu_mpp_ctrl *ctrl, unsigned long *config);
+ int (*mpp_set)(struct mvebu_mpp_ctrl *ctrl, unsigned long config);
+ int (*mpp_gpio_req)(struct mvebu_mpp_ctrl *ctrl, u8 pid);
+ int (*mpp_gpio_dir)(struct mvebu_mpp_ctrl *ctrl, u8 pid, bool input);
+};
+
+/**
+ * struct mvebu_mpp_ctrl_setting - describe a mpp ctrl setting
+ * @val: ctrl setting value
+ * @name: ctrl setting name, e.g. uart2, spi0 - unique per mpp_mode
+ * @subname: (optional) additional ctrl setting name, e.g. rts, cts
+ * @variant: (optional) variant identifier mask
+ * @flags: (private) flags to store gpi/gpo/gpio capabilities
+ *
+ * A ctrl_setting describes a specific internal mux function that a mpp pin
+ * can be switched to. The value (val) will be written in the corresponding
+ * register for common mpp pin configuration registers on MVEBU. SoC specific
+ * mpp_get/_set function may use val to distinguish between different settings.
+ *
+ * The name will be used to switch to this setting in DT description, e.g.
+ * marvell,function = "uart2". subname is only for debugging purposes.
+ *
+ * If name is one of "gpi", "gpo", "gpio" gpio capabilities are
+ * parsed during initialization and stored in flags.
+ *
+ * The variant can be used to combine different revisions of one SoC to a
+ * common pinctrl driver. It is matched (AND) with variant of soc_info to
+ * determine if a setting is available on the current SoC revision.
+ */
+struct mvebu_mpp_ctrl_setting {
+ u8 val;
+ const char *name;
+ const char *subname;
+ u8 variant;
+ u8 flags;
+#define MVEBU_SETTING_GPO (1 << 0)
+#define MVEBU_SETTING_GPI (1 << 1)
+};
+
+/**
+ * struct mvebu_mpp_mode - link ctrl and settings
+ * @pid: first pin id handled by this mode
+ * @settings: list of settings available for this mode
+ *
+ * A mode connects all available settings with the corresponding mpp_ctrl
+ * given by pid.
+ */
+struct mvebu_mpp_mode {
+ u8 pid;
+ struct mvebu_mpp_ctrl_setting *settings;
+};
+
+/**
+ * struct mvebu_pinctrl_soc_info - SoC specific info passed to pinctrl-mvebu
+ * @variant: variant mask of soc_info
+ * @controls: list of available mvebu_mpp_ctrls
+ * @ncontrols: number of available mvebu_mpp_ctrls
+ * @modes: list of available mvebu_mpp_modes
+ * @nmodes: number of available mvebu_mpp_modes
+ * @gpioranges: list of pinctrl_gpio_ranges
+ * @ngpioranges: number of available pinctrl_gpio_ranges
+ *
+ * This struct describes all pinctrl related information for a specific SoC.
+ * If variant is unequal 0 it will be matched (AND) with variant of each
+ * setting and allows to distinguish between different revisions of one SoC.
+ */
+struct mvebu_pinctrl_soc_info {
+ u8 variant;
+ struct mvebu_mpp_ctrl *controls;
+ int ncontrols;
+ struct mvebu_mpp_mode *modes;
+ int nmodes;
+ struct pinctrl_gpio_range *gpioranges;
+ int ngpioranges;
+};
+
+#define MPP_REG_CTRL(_idl, _idh) \
+ { \
+ .name = NULL, \
+ .pid = _idl, \
+ .npins = _idh - _idl + 1, \
+ .pins = (unsigned[_idh - _idl + 1]) { }, \
+ .mpp_get = NULL, \
+ .mpp_set = NULL, \
+ .mpp_gpio_req = NULL, \
+ .mpp_gpio_dir = NULL, \
+ }
+
+#define MPP_FUNC_CTRL(_idl, _idh, _name, _func) \
+ { \
+ .name = _name, \
+ .pid = _idl, \
+ .npins = _idh - _idl + 1, \
+ .pins = (unsigned[_idh - _idl + 1]) { }, \
+ .mpp_get = _func ## _get, \
+ .mpp_set = _func ## _set, \
+ .mpp_gpio_req = NULL, \
+ .mpp_gpio_dir = NULL, \
+ }
+
+#define MPP_FUNC_GPIO_CTRL(_idl, _idh, _name, _func) \
+ { \
+ .name = _name, \
+ .pid = _idl, \
+ .npins = _idh - _idl + 1, \
+ .pins = (unsigned[_idh - _idl + 1]) { }, \
+ .mpp_get = _func ## _get, \
+ .mpp_set = _func ## _set, \
+ .mpp_gpio_req = _func ## _gpio_req, \
+ .mpp_gpio_dir = _func ## _gpio_dir, \
+ }
+
+#define _MPP_VAR_FUNCTION(_val, _name, _subname, _mask) \
+ { \
+ .val = _val, \
+ .name = _name, \
+ .subname = _subname, \
+ .variant = _mask, \
+ .flags = 0, \
+ }
+
+#if defined(CONFIG_DEBUG_FS)
+#define MPP_VAR_FUNCTION(_val, _name, _subname, _mask) \
+ _MPP_VAR_FUNCTION(_val, _name, _subname, _mask)
+#else
+#define MPP_VAR_FUNCTION(_val, _name, _subname, _mask) \
+ _MPP_VAR_FUNCTION(_val, _name, NULL, _mask)
+#endif
+
+#define MPP_FUNCTION(_val, _name, _subname) \
+ MPP_VAR_FUNCTION(_val, _name, _subname, (u8)-1)
+
+#define MPP_MODE(_id, ...) \
+ { \
+ .pid = _id, \
+ .settings = (struct mvebu_mpp_ctrl_setting[]){ \
+ __VA_ARGS__, { } }, \
+ }
+
+#define MPP_GPIO_RANGE(_id, _pinbase, _gpiobase, _npins) \
+ { \
+ .name = "mvebu-gpio", \
+ .id = _id, \
+ .pin_base = _pinbase, \
+ .base = _gpiobase, \
+ .npins = _npins, \
+ }
+
+int mvebu_pinctrl_probe(struct platform_device *pdev);
+int mvebu_pinctrl_remove(struct platform_device *pdev);
+
+#endif
diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c
index 7fca6ce5952b..304360cd213e 100644
--- a/drivers/pinctrl/pinctrl-sirf.c
+++ b/drivers/pinctrl/pinctrl-sirf.c
@@ -17,6 +17,7 @@
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/machine.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
@@ -916,11 +917,66 @@ static void sirfsoc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s
seq_printf(s, " " DRIVER_NAME);
}
+static int sirfsoc_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np_config,
+ struct pinctrl_map **map, unsigned *num_maps)
+{
+ struct sirfsoc_pmx *spmx = pinctrl_dev_get_drvdata(pctldev);
+ struct device_node *np;
+ struct property *prop;
+ const char *function, *group;
+ int ret, index = 0, count = 0;
+
+ /* calculate number of maps required */
+ for_each_child_of_node(np_config, np) {
+ ret = of_property_read_string(np, "sirf,function", &function);
+ if (ret < 0)
+ return ret;
+
+ ret = of_property_count_strings(np, "sirf,pins");
+ if (ret < 0)
+ return ret;
+
+ count += ret;
+ }
+
+ if (!count) {
+ dev_err(spmx->dev, "No child nodes passed via DT\n");
+ return -ENODEV;
+ }
+
+ *map = kzalloc(sizeof(**map) * count, GFP_KERNEL);
+ if (!*map)
+ return -ENOMEM;
+
+ for_each_child_of_node(np_config, np) {
+ of_property_read_string(np, "sirf,function", &function);
+ of_property_for_each_string(np, "sirf,pins", prop, group) {
+ (*map)[index].type = PIN_MAP_TYPE_MUX_GROUP;
+ (*map)[index].data.mux.group = group;
+ (*map)[index].data.mux.function = function;
+ index++;
+ }
+ }
+
+ *num_maps = count;
+
+ return 0;
+}
+
+static void sirfsoc_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+ kfree(map);
+}
+
static struct pinctrl_ops sirfsoc_pctrl_ops = {
.get_groups_count = sirfsoc_get_groups_count,
.get_group_name = sirfsoc_get_group_name,
.get_group_pins = sirfsoc_get_group_pins,
.pin_dbg_show = sirfsoc_pin_dbg_show,
+ .dt_node_to_map = sirfsoc_dt_node_to_map,
+ .dt_free_map = sirfsoc_dt_free_map,
};
struct sirfsoc_pmx_func {
@@ -1221,7 +1277,7 @@ out_no_gpio_remap:
}
static const struct of_device_id pinmux_ids[] __devinitconst = {
- { .compatible = "sirf,prima2-gpio-pinmux" },
+ { .compatible = "sirf,prima2-pinctrl" },
{}
};
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
index 19241fc30050..82125269b667 100644
--- a/drivers/regulator/tps6586x-regulator.c
+++ b/drivers/regulator/tps6586x-regulator.c
@@ -162,6 +162,9 @@ static struct regulator_ops tps6586x_regulator_ops = {
.disable = tps6586x_regulator_disable,
};
+static struct regulator_ops tps6586x_sys_regulator_ops = {
+};
+
static const unsigned int tps6586x_ldo0_voltages[] = {
1200000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
};
@@ -230,15 +233,28 @@ static const unsigned int tps6586x_dvm_voltages[] = {
TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit) \
}
+#define TPS6586X_SYS_REGULATOR() \
+{ \
+ .desc = { \
+ .supply_name = "sys", \
+ .name = "REG-SYS", \
+ .ops = &tps6586x_sys_regulator_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = TPS6586X_ID_SYS, \
+ .owner = THIS_MODULE, \
+ }, \
+}
+
static struct tps6586x_regulator tps6586x_regulator[] = {
+ TPS6586X_SYS_REGULATOR(),
TPS6586X_LDO(LDO_0, "vinldo01", ldo0, SUPPLYV1, 5, 3, ENC, 0, END, 0),
TPS6586X_LDO(LDO_3, "vinldo23", ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2),
- TPS6586X_LDO(LDO_5, NULL, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6),
+ TPS6586X_LDO(LDO_5, "REG-SYS", ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6),
TPS6586X_LDO(LDO_6, "vinldo678", ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4),
TPS6586X_LDO(LDO_7, "vinldo678", ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5),
TPS6586X_LDO(LDO_8, "vinldo678", ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6),
TPS6586X_LDO(LDO_9, "vinldo9", ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7),
- TPS6586X_LDO(LDO_RTC, NULL, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),
+ TPS6586X_LDO(LDO_RTC, "REG-SYS", ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),
TPS6586X_LDO(LDO_1, "vinldo01", dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1),
TPS6586X_LDO(SM_2, "vin-sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),
diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c
index a1f7ac1f8cf6..b54504ee61f1 100644
--- a/drivers/remoteproc/omap_remoteproc.c
+++ b/drivers/remoteproc/omap_remoteproc.c
@@ -29,7 +29,7 @@
#include <linux/remoteproc.h>
#include <plat/mailbox.h>
-#include <plat/remoteproc.h>
+#include <linux/platform_data/remoteproc-omap.h>
#include "omap_remoteproc.h"
#include "remoteproc_internal.h"
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c
index 0075c8fd93d8..f771b2ee4b18 100644
--- a/drivers/rtc/rtc-pxa.c
+++ b/drivers/rtc/rtc-pxa.c
@@ -27,6 +27,8 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <mach/hardware.h>
@@ -396,6 +398,14 @@ static int __exit pxa_rtc_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_OF
+static struct of_device_id pxa_rtc_dt_ids[] = {
+ { .compatible = "marvell,pxa-rtc" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, pxa_rtc_dt_ids);
+#endif
+
#ifdef CONFIG_PM
static int pxa_rtc_suspend(struct device *dev)
{
@@ -425,6 +435,7 @@ static struct platform_driver pxa_rtc_driver = {
.remove = __exit_p(pxa_rtc_remove),
.driver = {
.name = "pxa-rtc",
+ .of_match_table = of_match_ptr(pxa_rtc_dt_ids),
#ifdef CONFIG_PM
.pm = &pxa_rtc_pm_ops,
#endif
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
index edfd12b48c28..968d08358d20 100644
--- a/drivers/scsi/arm/eesox.c
+++ b/drivers/scsi/arm/eesox.c
@@ -273,7 +273,7 @@ static void eesoxscsi_buffer_out(void *buf, int length, void __iomem *base)
{
const void __iomem *reg_fas = base + EESOX_FAS216_OFFSET;
const void __iomem *reg_dmastat = base + EESOX_DMASTAT;
- const void __iomem *reg_dmadata = base + EESOX_DMADATA;
+ void __iomem *reg_dmadata = base + EESOX_DMADATA;
do {
unsigned int status;
diff --git a/drivers/sh/pfc/gpio.c b/drivers/sh/pfc/gpio.c
index 62bca98474a9..038fa071382a 100644
--- a/drivers/sh/pfc/gpio.c
+++ b/drivers/sh/pfc/gpio.c
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/consumer.h>
+#include <linux/sh_pfc.h>
struct sh_pfc_chip {
struct sh_pfc *pfc;
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 5f84b5563c2d..2d198a01a410 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -366,7 +366,7 @@ config SPI_STMP3XXX
config SPI_TEGRA
tristate "Nvidia Tegra SPI controller"
- depends on ARCH_TEGRA && (TEGRA_SYSTEM_DMA || TEGRA20_APB_DMA)
+ depends on ARCH_TEGRA && TEGRA20_APB_DMA
help
SPI driver for NVidia Tegra SoCs
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index 9b2901feaf78..3afe2f4f5b8e 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -30,7 +30,7 @@
#include <linux/spi/spi_bitbang.h>
#include <linux/slab.h>
-#include <mach/spi.h>
+#include <linux/platform_data/spi-davinci.h>
#include <mach/edma.h>
#define SPI_NO_RESOURCE ((resource_size_t)-1)
diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c
index f97f1d248800..3a219599612a 100644
--- a/drivers/spi/spi-ep93xx.c
+++ b/drivers/spi/spi-ep93xx.c
@@ -31,8 +31,8 @@
#include <linux/scatterlist.h>
#include <linux/spi/spi.h>
-#include <mach/dma.h>
-#include <mach/ep93xx_spi.h>
+#include <linux/platform_data/dma-ep93xx.h>
+#include <linux/platform_data/spi-ep93xx.h>
#define SSPCR0 0x0000
#define SSPCR0_MODE_SHIFT 6
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index e834ff8c0188..63e7fc9801cd 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -39,7 +39,7 @@
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h>
-#include <mach/spi.h>
+#include <linux/platform_data/spi-imx.h>
#define DRIVER_NAME "spi_imx"
diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c
index dae8be229c5d..a6eca6ffdabe 100644
--- a/drivers/spi/spi-nuc900.c
+++ b/drivers/spi/spi-nuc900.c
@@ -26,7 +26,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
-#include <mach/nuc900_spi.h>
+#include <linux/platform_data/spi-nuc900.h>
/* usi registers offset */
#define USI_CNT 0x00
diff --git a/drivers/spi/spi-omap-uwire.c b/drivers/spi/spi-omap-uwire.c
index a3996a1c6345..0a94d9dc9c31 100644
--- a/drivers/spi/spi-omap-uwire.c
+++ b/drivers/spi/spi-omap-uwire.c
@@ -52,7 +52,7 @@
#include <asm/io.h>
#include <asm/mach-types.h>
-#include <plat/mux.h>
+#include <mach/mux.h>
#include <mach/omap7xx.h> /* OMAP7XX_IO_CONF registers */
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index b5d6994c8ba3..d3d62f1e894c 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -41,7 +41,7 @@
#include <linux/spi/spi.h>
-#include <plat/mcspi.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
#define OMAP2_MCSPI_MAX_FREQ 48000000
#define SPI_AUTOSUSPEND_TIMEOUT 2000
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index d1c8441f638c..0e2a02228d5e 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -32,7 +32,7 @@
#include <linux/of_gpio.h>
#include <mach/dma.h>
-#include <plat/s3c64xx-spi.h>
+#include <linux/platform_data/spi-s3c64xx.h>
#define MAX_SPI_PORTS 3
diff --git a/drivers/spi/spi-tegra.c b/drivers/spi/spi-tegra.c
index ef52c1c6f5c5..488d9b6e9cbe 100644
--- a/drivers/spi/spi-tegra.c
+++ b/drivers/spi/spi-tegra.c
@@ -164,23 +164,15 @@ struct spi_tegra_data {
* for the generic case.
*/
int dma_req_len;
-#if defined(CONFIG_TEGRA_SYSTEM_DMA)
- struct tegra_dma_req rx_dma_req;
- struct tegra_dma_channel *rx_dma;
-#else
struct dma_chan *rx_dma;
struct dma_slave_config sconfig;
struct dma_async_tx_descriptor *rx_dma_desc;
dma_cookie_t rx_cookie;
-#endif
u32 *rx_bb;
dma_addr_t rx_bb_phys;
};
-#if !defined(CONFIG_TEGRA_SYSTEM_DMA)
static void tegra_spi_rx_dma_complete(void *args);
-#endif
-
static inline unsigned long spi_tegra_readl(struct spi_tegra_data *tspi,
unsigned long reg)
{
@@ -204,10 +196,6 @@ static void spi_tegra_go(struct spi_tegra_data *tspi)
val &= ~SLINK_DMA_BLOCK_SIZE(~0) & ~SLINK_DMA_EN;
val |= SLINK_DMA_BLOCK_SIZE(tspi->dma_req_len / 4 - 1);
spi_tegra_writel(tspi, val, SLINK_DMA_CTL);
-#if defined(CONFIG_TEGRA_SYSTEM_DMA)
- tspi->rx_dma_req.size = tspi->dma_req_len;
- tegra_dma_enqueue_req(tspi->rx_dma, &tspi->rx_dma_req);
-#else
tspi->rx_dma_desc = dmaengine_prep_slave_single(tspi->rx_dma,
tspi->rx_bb_phys, tspi->dma_req_len,
DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
@@ -219,7 +207,6 @@ static void spi_tegra_go(struct spi_tegra_data *tspi)
tspi->rx_dma_desc->callback_param = tspi;
tspi->rx_cookie = dmaengine_submit(tspi->rx_dma_desc);
dma_async_issue_pending(tspi->rx_dma);
-#endif
val |= SLINK_DMA_EN;
spi_tegra_writel(tspi, val, SLINK_DMA_CTL);
@@ -405,19 +392,12 @@ static void handle_spi_rx_dma_complete(struct spi_tegra_data *tspi)
spin_unlock_irqrestore(&tspi->lock, flags);
}
-#if defined(CONFIG_TEGRA_SYSTEM_DMA)
-static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req)
-{
- struct spi_tegra_data *tspi = req->dev;
- handle_spi_rx_dma_complete(tspi);
-}
-#else
+
static void tegra_spi_rx_dma_complete(void *args)
{
struct spi_tegra_data *tspi = args;
handle_spi_rx_dma_complete(tspi);
}
-#endif
static int spi_tegra_setup(struct spi_device *spi)
{
@@ -509,9 +489,7 @@ static int __devinit spi_tegra_probe(struct platform_device *pdev)
struct spi_tegra_data *tspi;
struct resource *r;
int ret;
-#if !defined(CONFIG_TEGRA_SYSTEM_DMA)
dma_cap_mask_t mask;
-#endif
master = spi_alloc_master(&pdev->dev, sizeof *tspi);
if (master == NULL) {
@@ -563,14 +541,6 @@ static int __devinit spi_tegra_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&tspi->queue);
-#if defined(CONFIG_TEGRA_SYSTEM_DMA)
- tspi->rx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT);
- if (!tspi->rx_dma) {
- dev_err(&pdev->dev, "can not allocate rx dma channel\n");
- ret = -ENODEV;
- goto err3;
- }
-#else
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
tspi->rx_dma = dma_request_channel(mask, NULL, NULL);
@@ -580,8 +550,6 @@ static int __devinit spi_tegra_probe(struct platform_device *pdev)
goto err3;
}
-#endif
-
tspi->rx_bb = dma_alloc_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
&tspi->rx_bb_phys, GFP_KERNEL);
if (!tspi->rx_bb) {
@@ -590,17 +558,6 @@ static int __devinit spi_tegra_probe(struct platform_device *pdev)
goto err4;
}
-#if defined(CONFIG_TEGRA_SYSTEM_DMA)
- tspi->rx_dma_req.complete = tegra_spi_rx_dma_complete;
- tspi->rx_dma_req.to_memory = 1;
- tspi->rx_dma_req.dest_addr = tspi->rx_bb_phys;
- tspi->rx_dma_req.dest_bus_width = 32;
- tspi->rx_dma_req.source_addr = tspi->phys + SLINK_RX_FIFO;
- tspi->rx_dma_req.source_bus_width = 32;
- tspi->rx_dma_req.source_wrap = 4;
- tspi->rx_dma_req.req_sel = spi_tegra_req_sels[pdev->id];
- tspi->rx_dma_req.dev = tspi;
-#else
/* Dmaengine Dma slave config */
tspi->sconfig.src_addr = tspi->phys + SLINK_RX_FIFO;
tspi->sconfig.dst_addr = tspi->phys + SLINK_RX_FIFO;
@@ -616,7 +573,6 @@ static int __devinit spi_tegra_probe(struct platform_device *pdev)
ret);
goto err4;
}
-#endif
master->dev.of_node = pdev->dev.of_node;
ret = spi_register_master(master);
@@ -630,11 +586,7 @@ err5:
dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
tspi->rx_bb, tspi->rx_bb_phys);
err4:
-#if defined(CONFIG_TEGRA_SYSTEM_DMA)
- tegra_dma_free_channel(tspi->rx_dma);
-#else
dma_release_channel(tspi->rx_dma);
-#endif
err3:
clk_put(tspi->clk);
err2:
@@ -656,12 +608,7 @@ static int __devexit spi_tegra_remove(struct platform_device *pdev)
tspi = spi_master_get_devdata(master);
spi_unregister_master(master);
-#if defined(CONFIG_TEGRA_SYSTEM_DMA)
- tegra_dma_free_channel(tspi->rx_dma);
-#else
dma_release_channel(tspi->rx_dma);
-#endif
-
dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
tspi->rx_bb, tspi->rx_bb_phys);
diff --git a/drivers/staging/ste_rmi4/board-mop500-u8500uib-rmi4.c b/drivers/staging/ste_rmi4/board-mop500-u8500uib-rmi4.c
index a272e488e5b9..47439c3f7258 100644
--- a/drivers/staging/ste_rmi4/board-mop500-u8500uib-rmi4.c
+++ b/drivers/staging/ste_rmi4/board-mop500-u8500uib-rmi4.c
@@ -5,7 +5,6 @@
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
-#include <mach/gpio.h>
#include <mach/irqs.h>
#include "synaptics_i2c_rmi4.h"
diff --git a/drivers/staging/tidspbridge/core/dsp-clock.c b/drivers/staging/tidspbridge/core/dsp-clock.c
index c7df34e6b60b..7d056bd1eaad 100644
--- a/drivers/staging/tidspbridge/core/dsp-clock.c
+++ b/drivers/staging/tidspbridge/core/dsp-clock.c
@@ -21,7 +21,7 @@
/* ----------------------------------- Host OS */
#include <dspbridge/host_os.h>
#include <plat/dmtimer.h>
-#include <plat/mcbsp.h>
+#include <linux/platform_data/asoc-ti-mcbsp.h>
/* ----------------------------------- DSP/BIOS Bridge */
#include <dspbridge/dbdefs.h>
diff --git a/drivers/staging/tidspbridge/core/tiomap3430.c b/drivers/staging/tidspbridge/core/tiomap3430.c
index f9609ce2c163..7bf55c40944e 100644
--- a/drivers/staging/tidspbridge/core/tiomap3430.c
+++ b/drivers/staging/tidspbridge/core/tiomap3430.c
@@ -16,7 +16,7 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include <plat/dsp.h>
+#include <linux/platform_data/dsp-omap.h>
#include <linux/types.h>
/* ----------------------------------- Host OS */
diff --git a/drivers/staging/tidspbridge/core/tiomap3430_pwr.c b/drivers/staging/tidspbridge/core/tiomap3430_pwr.c
index 16a4aafa86ae..55675b7b9b66 100644
--- a/drivers/staging/tidspbridge/core/tiomap3430_pwr.c
+++ b/drivers/staging/tidspbridge/core/tiomap3430_pwr.c
@@ -19,7 +19,7 @@
/* ----------------------------------- Host OS */
#include <dspbridge/host_os.h>
-#include <plat/dsp.h>
+#include <linux/platform_data/dsp-omap.h>
/* ----------------------------------- DSP/BIOS Bridge */
#include <dspbridge/dbdefs.h>
diff --git a/drivers/staging/tidspbridge/core/tiomap_io.c b/drivers/staging/tidspbridge/core/tiomap_io.c
index 7fda10c36862..f53ed98d18c1 100644
--- a/drivers/staging/tidspbridge/core/tiomap_io.c
+++ b/drivers/staging/tidspbridge/core/tiomap_io.c
@@ -16,7 +16,7 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include <plat/dsp.h>
+#include <linux/platform_data/dsp-omap.h>
/* ----------------------------------- DSP/BIOS Bridge */
#include <dspbridge/dbdefs.h>
diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c
index 3cac01492063..49c9b662392f 100644
--- a/drivers/staging/tidspbridge/rmgr/drv_interface.c
+++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c
@@ -16,7 +16,7 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include <plat/dsp.h>
+#include <linux/platform_data/dsp-omap.h>
#include <linux/types.h>
#include <linux/platform_device.h>
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 5952b25c288e..2a093a42512f 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -51,7 +51,7 @@
#include <asm/io.h>
#include <asm/irq.h>
-#include <mach/imx-uart.h>
+#include <linux/platform_data/serial-imx.h>
/* Register definitions */
#define URXD0 0x0 /* Receiver Register */
diff --git a/drivers/tty/serial/serial_ks8695.c b/drivers/tty/serial/serial_ks8695.c
index 7c13639c597e..9bd004f9da89 100644
--- a/drivers/tty/serial/serial_ks8695.c
+++ b/drivers/tty/serial/serial_ks8695.c
@@ -548,8 +548,8 @@ static struct uart_ops ks8695uart_pops = {
static struct uart_port ks8695uart_ports[SERIAL_KS8695_NR] = {
{
- .membase = (void *) KS8695_UART_VA,
- .mapbase = KS8695_UART_VA,
+ .membase = KS8695_UART_VA,
+ .mapbase = KS8695_UART_PA,
.iotype = SERIAL_IO_MEM,
.irq = KS8695_IRQ_UART_TX,
.uartclk = KS8695_CLOCK_RATE * 16,
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 7065df6036ca..7de2285d9fa9 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -13,7 +13,6 @@ config USB_ARCH_HAS_OHCI
default y if PXA3xx
default y if ARCH_EP93XX
default y if ARCH_AT91
- default y if ARCH_PNX4008
default y if MFD_TC6393XB
default y if ARCH_W90X900
default y if ARCH_DAVINCI_DA8XX
diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c
index dc5334856afe..a0eb85794fd4 100644
--- a/drivers/usb/gadget/imx_udc.c
+++ b/drivers/usb/gadget/imx_udc.c
@@ -35,7 +35,7 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
-#include <mach/usb.h>
+#include <linux/platform_data/usb-imx_udc.h>
#include <mach/hardware.h>
#include "imx_udc.h"
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index 644b4305cb99..7a8713cda945 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -2508,7 +2508,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
IRQF_SHARED, driver_name, udc);
if (retval != 0) {
dev_err(udc->dev, "%s: can't get irq %i, err %d\n",
- driver_name, IRQ_USB, retval);
+ driver_name, udc->irq, retval);
goto err_irq;
}
retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index f2e51f50e528..f006045fc44c 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -43,7 +43,7 @@
#include <mach/hardware.h>
#include <plat/regs-udc.h>
-#include <plat/udc.h>
+#include <linux/platform_data/usb-s3c2410_udc.h>
#include "s3c2410_udc.h"
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 075d2eca8108..276add2358a1 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -292,7 +292,7 @@ config USB_OHCI_HCD
depends on USB && USB_ARCH_HAS_OHCI
select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
select USB_OTG_UTILS if ARCH_OMAP
- select USB_ISP1301 if ARCH_LPC32XX || ARCH_PNX4008
+ select USB_ISP1301 if ARCH_LPC32XX
---help---
The Open Host Controller Interface (OHCI) is a standard for accessing
USB 1.1 host controller hardware. It does more in hardware than Intel's
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index 34201372c85f..a6e2ea4ef8fd 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -25,7 +25,7 @@
#include <linux/slab.h>
#include <mach/hardware.h>
-#include <mach/mxc_ehci.h>
+#include <linux/platform_data/usb-ehci-mxc.h>
#include <asm/mach-types.h>
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index 8892d3642cef..8e7eca62f169 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -13,7 +13,7 @@
#include <linux/platform_device.h>
#include <linux/mbus.h>
#include <linux/clk.h>
-#include <plat/ehci-orion.h>
+#include <linux/platform_data/usb-ehci-orion.h>
#define rdl(off) __raw_readl(hcd->regs + (off))
#define wrl(off, val) __raw_writel((val), hcd->regs + (off))
diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
index 9d8f1dd57cb3..dfb14c7a61e2 100644
--- a/drivers/usb/host/ehci-s5p.c
+++ b/drivers/usb/host/ehci-s5p.c
@@ -16,7 +16,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
-#include <plat/ehci.h>
+#include <linux/platform_data/usb-ehci-s5p.h>
#include <plat/usb-phy.h>
#define EHCI_INSNREG00(base) (base + 0x90)
diff --git a/drivers/usb/host/imx21-hcd.h b/drivers/usb/host/imx21-hcd.h
index 87b29fd971b4..c005770a73e9 100644
--- a/drivers/usb/host/imx21-hcd.h
+++ b/drivers/usb/host/imx21-hcd.h
@@ -24,7 +24,7 @@
#ifndef __LINUX_IMX21_HCD_H__
#define __LINUX_IMX21_HCD_H__
-#include <mach/mx21-usbhost.h>
+#include <linux/platform_data/usb-mx2.h>
#define NUM_ISO_ETDS 2
#define USB_NUM_ETD 32
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index 269b1e0f7691..0b815a856811 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -17,7 +17,7 @@
#include <linux/clk.h>
#include <mach/da8xx.h>
-#include <mach/usb.h>
+#include <linux/platform_data/usb-davinci.h>
#ifndef CONFIG_ARCH_DAVINCI_DA8XX
#error "This file is DA8xx bus glue. Define CONFIG_ARCH_DAVINCI_DA8XX."
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index fc3091bd2379..20a50081f922 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -14,7 +14,7 @@
#include <linux/clk.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <mach/ohci.h>
+#include <linux/platform_data/usb-exynos.h>
#include <plat/usb-phy.h>
struct exynos_ohci_hcd {
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 2b1e8d84c873..6780010e9c3c 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -1049,7 +1049,7 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ohci_hcd_at91_driver
#endif
-#if defined(CONFIG_ARCH_PNX4008) || defined(CONFIG_ARCH_LPC32XX)
+#ifdef CONFIG_ARCH_LPC32XX
#include "ohci-nxp.c"
#define PLATFORM_DRIVER usb_hcd_nxp_driver
#endif
diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c
index a446386bf779..119966603d8d 100644
--- a/drivers/usb/host/ohci-nxp.c
+++ b/drivers/usb/host/ohci-nxp.c
@@ -2,7 +2,6 @@
* driver for NXP USB Host devices
*
* Currently supported OHCI host devices:
- * - Philips PNX4008
* - NXP LPC32xx
*
* Authors: Dmitry Chigirev <source@mvista.com>
@@ -66,38 +65,6 @@ static struct clk *usb_pll_clk;
static struct clk *usb_dev_clk;
static struct clk *usb_otg_clk;
-static void isp1301_configure_pnx4008(void)
-{
- /* PNX4008 only supports DAT_SE0 USB mode */
- /* PNX4008 R2A requires setting the MAX603 to output 3.6V */
- /* Power up externel charge-pump */
-
- i2c_smbus_write_byte_data(isp1301_i2c_client,
- ISP1301_I2C_MODE_CONTROL_1, MC1_DAT_SE0 | MC1_SPEED_REG);
- i2c_smbus_write_byte_data(isp1301_i2c_client,
- ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR,
- ~(MC1_DAT_SE0 | MC1_SPEED_REG));
- i2c_smbus_write_byte_data(isp1301_i2c_client,
- ISP1301_I2C_MODE_CONTROL_2,
- MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL);
- i2c_smbus_write_byte_data(isp1301_i2c_client,
- ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR,
- ~(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL));
- i2c_smbus_write_byte_data(isp1301_i2c_client,
- ISP1301_I2C_OTG_CONTROL_1, OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN);
- i2c_smbus_write_byte_data(isp1301_i2c_client,
- ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR,
- ~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN));
- i2c_smbus_write_byte_data(isp1301_i2c_client,
- ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR, 0xFF);
- i2c_smbus_write_byte_data(isp1301_i2c_client,
- ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR,
- 0xFF);
- i2c_smbus_write_byte_data(isp1301_i2c_client,
- ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR,
- 0xFF);
-}
-
static void isp1301_configure_lpc32xx(void)
{
/* LPC32XX only supports DAT_SE0 USB mode */
@@ -149,10 +116,7 @@ static void isp1301_configure_lpc32xx(void)
static void isp1301_configure(void)
{
- if (machine_is_pnx4008())
- isp1301_configure_pnx4008();
- else
- isp1301_configure_lpc32xx();
+ isp1301_configure_lpc32xx();
}
static inline void isp1301_vbus_on(void)
@@ -241,47 +205,6 @@ static const struct hc_driver ohci_nxp_hc_driver = {
.start_port_reset = ohci_start_port_reset,
};
-static void nxp_set_usb_bits(void)
-{
- if (machine_is_pnx4008()) {
- start_int_set_falling_edge(SE_USB_OTG_ATX_INT_N);
- start_int_ack(SE_USB_OTG_ATX_INT_N);
- start_int_umask(SE_USB_OTG_ATX_INT_N);
-
- start_int_set_rising_edge(SE_USB_OTG_TIMER_INT);
- start_int_ack(SE_USB_OTG_TIMER_INT);
- start_int_umask(SE_USB_OTG_TIMER_INT);
-
- start_int_set_rising_edge(SE_USB_I2C_INT);
- start_int_ack(SE_USB_I2C_INT);
- start_int_umask(SE_USB_I2C_INT);
-
- start_int_set_rising_edge(SE_USB_INT);
- start_int_ack(SE_USB_INT);
- start_int_umask(SE_USB_INT);
-
- start_int_set_rising_edge(SE_USB_NEED_CLK_INT);
- start_int_ack(SE_USB_NEED_CLK_INT);
- start_int_umask(SE_USB_NEED_CLK_INT);
-
- start_int_set_rising_edge(SE_USB_AHB_NEED_CLK_INT);
- start_int_ack(SE_USB_AHB_NEED_CLK_INT);
- start_int_umask(SE_USB_AHB_NEED_CLK_INT);
- }
-}
-
-static void nxp_unset_usb_bits(void)
-{
- if (machine_is_pnx4008()) {
- start_int_mask(SE_USB_OTG_ATX_INT_N);
- start_int_mask(SE_USB_OTG_TIMER_INT);
- start_int_mask(SE_USB_I2C_INT);
- start_int_mask(SE_USB_INT);
- start_int_mask(SE_USB_NEED_CLK_INT);
- start_int_mask(SE_USB_AHB_NEED_CLK_INT);
- }
-}
-
static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd = 0;
@@ -376,9 +299,6 @@ static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev)
goto out8;
}
- /* Set all USB bits in the Start Enable register */
- nxp_set_usb_bits();
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "Failed to get MEM resource\n");
@@ -413,7 +333,6 @@ static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev)
nxp_stop_hc();
out8:
- nxp_unset_usb_bits();
usb_put_hcd(hcd);
out7:
clk_disable(usb_otg_clk);
@@ -441,7 +360,6 @@ static int usb_hcd_nxp_remove(struct platform_device *pdev)
nxp_stop_hc();
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
- nxp_unset_usb_bits();
clk_disable(usb_pll_clk);
clk_put(usb_pll_clk);
clk_disable(usb_dev_clk);
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index f8b2d91851f7..4531d03503c3 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -24,7 +24,7 @@
#include <asm/io.h>
#include <asm/mach-types.h>
-#include <plat/mux.h>
+#include <mach/mux.h>
#include <plat/fpga.h>
#include <mach/hardware.h>
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index e1a3cc6d28dc..955c410d59b6 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -24,8 +24,8 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <mach/hardware.h>
-#include <mach/ohci.h>
-#include <mach/pxa3xx-u2d.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
+#include <linux/platform_data/usb-pxa3xx-ulpi.h>
/*
* UHC: USB Host Controller (OHCI-like) register definitions
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 664c869eb096..0d2309ca471e 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -21,7 +21,7 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
-#include <plat/usb-control.h>
+#include <linux/platform_data/usb-ohci-s3c2410.h>
#define valid_port(idx) ((idx) == 1 || (idx) == 2)
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 0f9fcec4e1d3..15a262754150 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -35,7 +35,7 @@
#include <linux/dma-mapping.h>
#include <mach/da8xx.h>
-#include <mach/usb.h>
+#include <linux/platform_data/usb-davinci.h>
#include "musb_core.h"
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index b67b4bc596c1..89f0709f8935 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -17,7 +17,6 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <plat/dma.h>
-#include <plat/mux.h>
#include "musb_core.h"
#include "tusb6010.h"
diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c
index d05c7fbbb703..f82246d2fd16 100644
--- a/drivers/usb/musb/ux500_dma.c
+++ b/drivers/usb/musb/ux500_dma.c
@@ -30,7 +30,7 @@
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/pfn.h>
-#include <mach/usb.h>
+#include <linux/platform_data/usb-musb-ux500.h>
#include "musb_core.h"
struct ux500_dma_channel {
diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c
index 7a88667742b6..81f1f9a0be8f 100644
--- a/drivers/usb/otg/isp1301_omap.c
+++ b/drivers/usb/otg/isp1301_omap.c
@@ -36,7 +36,7 @@
#include <asm/irq.h>
#include <asm/mach-types.h>
-#include <plat/mux.h>
+#include <mach/mux.h>
#include <mach/usb.h>
diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c
index 92257ef19403..9a046a4c98f5 100644
--- a/drivers/video/backlight/omap1_bl.c
+++ b/drivers/video/backlight/omap1_bl.c
@@ -30,7 +30,7 @@
#include <linux/platform_data/omap1_bl.h>
#include <mach/hardware.h>
-#include <plat/mux.h>
+#include <mach/mux.h>
#define OMAPBL_MAX_INTENSITY 0xff
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 7ae9d53f2bf1..113d43a16f54 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -131,7 +131,7 @@
#define UPPER_MARGIN 32
#define LOWER_MARGIN 32
-static resource_size_t da8xx_fb_reg_base;
+static void __iomem *da8xx_fb_reg_base;
static struct resource *lcdc_regs;
static unsigned int lcd_revision;
static irq_handler_t lcdc_irq_handler;
@@ -951,7 +951,7 @@ static int __devexit fb_remove(struct platform_device *dev)
clk_disable(par->lcdc_clk);
clk_put(par->lcdc_clk);
framebuffer_release(info);
- iounmap((void __iomem *)da8xx_fb_reg_base);
+ iounmap(da8xx_fb_reg_base);
release_mem_region(lcdc_regs->start, resource_size(lcdc_regs));
}
@@ -1171,7 +1171,7 @@ static int __devinit fb_probe(struct platform_device *device)
if (!lcdc_regs)
return -EBUSY;
- da8xx_fb_reg_base = (resource_size_t)ioremap(lcdc_regs->start, len);
+ da8xx_fb_reg_base = ioremap(lcdc_regs->start, len);
if (!da8xx_fb_reg_base) {
ret = -EBUSY;
goto err_request_mem;
@@ -1392,7 +1392,7 @@ err_clk_put:
clk_put(fb_clk);
err_ioremap:
- iounmap((void __iomem *)da8xx_fb_reg_base);
+ iounmap(da8xx_fb_reg_base);
err_request_mem:
release_mem_region(lcdc_regs->start, len);
diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c
index 345d96230978..f2c092da84b0 100644
--- a/drivers/video/ep93xx-fb.c
+++ b/drivers/video/ep93xx-fb.c
@@ -24,7 +24,7 @@
#include <linux/clk.h>
#include <linux/fb.h>
-#include <mach/fb.h>
+#include <linux/platform_data/video-ep93xx.h>
/* Vertical Frame Timing Registers */
#define EP93XXFB_VLINES_TOTAL 0x0000 /* SW locked */
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index caad3689b4e6..53ffdfc82a75 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -32,7 +32,7 @@
#include <linux/io.h>
#include <linux/math64.h>
-#include <mach/imxfb.h>
+#include <linux/platform_data/video-imxfb.h>
#include <mach/hardware.h>
/*
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c
index b061d709bc44..bf73f0480061 100644
--- a/drivers/video/msm/mddi.c
+++ b/drivers/video/msm/mddi.c
@@ -29,7 +29,7 @@
#include <mach/msm_iomap.h>
#include <mach/irqs.h>
#include <mach/board.h>
-#include <mach/msm_fb.h>
+#include <linux/platform_data/video-msm_fb.h>
#include "mddi_hw.h"
#define FLAG_DISABLE_HIBERNATION 0x0001
diff --git a/drivers/video/msm/mddi_client_dummy.c b/drivers/video/msm/mddi_client_dummy.c
index d2a091cebe2c..f1b0dfcc9717 100644
--- a/drivers/video/msm/mddi_client_dummy.c
+++ b/drivers/video/msm/mddi_client_dummy.c
@@ -20,7 +20,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
-#include <mach/msm_fb.h>
+#include <linux/platform_data/video-msm_fb.h>
struct panel_info {
struct platform_device pdev;
diff --git a/drivers/video/msm/mddi_client_nt35399.c b/drivers/video/msm/mddi_client_nt35399.c
index 7fcd67e132bf..d7a5bf84fb2a 100644
--- a/drivers/video/msm/mddi_client_nt35399.c
+++ b/drivers/video/msm/mddi_client_nt35399.c
@@ -22,7 +22,7 @@
#include <linux/sched.h>
#include <linux/gpio.h>
#include <linux/slab.h>
-#include <mach/msm_fb.h>
+#include <linux/platform_data/video-msm_fb.h>
static DECLARE_WAIT_QUEUE_HEAD(nt35399_vsync_wait);
diff --git a/drivers/video/msm/mddi_client_toshiba.c b/drivers/video/msm/mddi_client_toshiba.c
index 053eb6877330..061d7dfebbf3 100644
--- a/drivers/video/msm/mddi_client_toshiba.c
+++ b/drivers/video/msm/mddi_client_toshiba.c
@@ -22,7 +22,7 @@
#include <linux/gpio.h>
#include <linux/sched.h>
#include <linux/slab.h>
-#include <mach/msm_fb.h>
+#include <linux/platform_data/video-msm_fb.h>
#define LCD_CONTROL_BLOCK_BASE 0x110000
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index cb2ddf164c98..d1f881e8030e 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -26,7 +26,7 @@
#include <linux/slab.h>
#include <mach/msm_iomap.h>
-#include <mach/msm_fb.h>
+#include <linux/platform_data/video-msm_fb.h>
#include <linux/platform_device.h>
#include <linux/export.h>
diff --git a/drivers/video/msm/mdp_hw.h b/drivers/video/msm/mdp_hw.h
index d80477415caa..a0bacf581b32 100644
--- a/drivers/video/msm/mdp_hw.h
+++ b/drivers/video/msm/mdp_hw.h
@@ -16,7 +16,7 @@
#define _MDP_HW_H_
#include <mach/msm_iomap.h>
-#include <mach/msm_fb.h>
+#include <linux/platform_data/video-msm_fb.h>
struct mdp_info {
struct mdp_device mdp_dev;
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
index 2b6564e8bfea..be6079cdfbb6 100644
--- a/drivers/video/msm/mdp_ppp.c
+++ b/drivers/video/msm/mdp_ppp.c
@@ -16,7 +16,7 @@
#include <linux/file.h>
#include <linux/delay.h>
#include <linux/msm_mdp.h>
-#include <mach/msm_fb.h>
+#include <linux/platform_data/video-msm_fb.h>
#include "mdp_hw.h"
#include "mdp_scale_tables.h"
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index c6e3b4fcdd68..ec08a9ec377d 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -25,7 +25,7 @@
#include <linux/msm_mdp.h>
#include <linux/io.h>
#include <linux/uaccess.h>
-#include <mach/msm_fb.h>
+#include <linux/platform_data/video-msm_fb.h>
#include <mach/board.h>
#include <linux/workqueue.h>
#include <linux/clk.h>
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index c89f8a8d36d2..d7381088a180 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -27,10 +27,10 @@
#include <linux/clk.h>
#include <linux/mutex.h>
-#include <mach/dma.h>
+#include <linux/platform_data/dma-imx.h>
#include <mach/hardware.h>
#include <mach/ipu.h>
-#include <mach/mx3fb.h>
+#include <linux/platform_data/video-mx3fb.h>
#include <asm/io.h>
#include <asm/uaccess.h>
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
index e10f551ade21..93387555337e 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/nuc900fb.c
@@ -38,7 +38,7 @@
#include <mach/map.h>
#include <mach/regs-clock.h>
#include <mach/regs-ldm.h>
-#include <mach/fb.h>
+#include <linux/platform_data/video-nuc900fb.h>
#include "nuc900fb.h"
diff --git a/drivers/video/nuc900fb.h b/drivers/video/nuc900fb.h
index bc7c9300f276..9a1ca6dbb6b2 100644
--- a/drivers/video/nuc900fb.h
+++ b/drivers/video/nuc900fb.h
@@ -16,7 +16,7 @@
#define __NUC900FB_H
#include <mach/map.h>
-#include <mach/fb.h>
+#include <linux/platform_data/video-nuc900fb.h>
enum nuc900_lcddrv_type {
LCDDRV_NUC910,
diff --git a/drivers/video/omap/lcd_ams_delta.c b/drivers/video/omap/lcd_ams_delta.c
index d3a311327227..ed4cad87fbcd 100644
--- a/drivers/video/omap/lcd_ams_delta.c
+++ b/drivers/video/omap/lcd_ams_delta.c
@@ -27,8 +27,7 @@
#include <linux/lcd.h>
#include <linux/gpio.h>
-#include <plat/board-ams-delta.h>
-#include <mach/hardware.h>
+#include <mach/board-ams-delta.h>
#include "omapfb.h"
diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c
index e3880c4a0bb1..b739600c51ac 100644
--- a/drivers/video/omap/lcd_mipid.c
+++ b/drivers/video/omap/lcd_mipid.c
@@ -25,7 +25,7 @@
#include <linux/spi/spi.h>
#include <linux/module.h>
-#include <plat/lcd_mipid.h>
+#include <linux/platform_data/lcd-mipid.h>
#include "omapfb.h"
diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c
index 5914220dfa9c..3aa62da89195 100644
--- a/drivers/video/omap/lcd_osk.c
+++ b/drivers/video/omap/lcd_osk.c
@@ -24,7 +24,7 @@
#include <linux/platform_device.h>
#include <asm/gpio.h>
-#include <plat/mux.h>
+#include <mach/mux.h>
#include "omapfb.h"
static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 3f902557690e..4fa2ad43fd97 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -61,7 +61,7 @@
#include <asm/irq.h>
#include <asm/div64.h>
#include <mach/bitfield.h>
-#include <mach/pxafb.h>
+#include <linux/platform_data/video-pxafb.h>
/*
* Complain if VAR is out of range.
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c
index 2a5fe6ede845..66a74f9073fb 100644
--- a/drivers/video/vt8500lcdfb.c
+++ b/drivers/video/vt8500lcdfb.c
@@ -30,7 +30,7 @@
#include <linux/platform_device.h>
#include <linux/wait.h>
-#include <mach/vt8500fb.h>
+#include <linux/platform_data/video-vt8500lcdfb.h>
#include "vt8500lcdfb.h"
#include "wmt_ge_rops.h"
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
index c8703bd61b74..ffeff4838120 100644
--- a/drivers/video/wm8505fb.c
+++ b/drivers/video/wm8505fb.c
@@ -29,7 +29,7 @@
#include <linux/platform_device.h>
#include <linux/wait.h>
-#include <mach/vt8500fb.h>
+#include <linux/platform_data/video-vt8500lcdfb.h>
#include "wm8505fb_regs.h"
#include "wmt_ge_rops.h"
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 53d75719078e..ad1bb9382a96 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -237,12 +237,12 @@ config OMAP_WATCHDOG
here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer.
config PNX4008_WATCHDOG
- tristate "PNX4008 and LPC32XX Watchdog"
- depends on ARCH_PNX4008 || ARCH_LPC32XX
+ tristate "LPC32XX Watchdog"
+ depends on ARCH_LPC32XX
select WATCHDOG_CORE
help
Say Y here if to include support for the watchdog timer
- in the PNX4008 or LPC32XX processor.
+ in the LPC32XX processor.
This driver can be built as a module by choosing M. The module
will be called pnx4008_wdt.
diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c
index 59e75d9a6b7f..c1a4d3bf581d 100644
--- a/drivers/watchdog/ks8695_wdt.c
+++ b/drivers/watchdog/ks8695_wdt.c
@@ -24,7 +24,19 @@
#include <linux/io.h>
#include <linux/uaccess.h>
#include <mach/hardware.h>
-#include <mach/regs-timer.h>
+
+#define KS8695_TMR_OFFSET (0xF0000 + 0xE400)
+#define KS8695_TMR_VA (KS8695_IO_VA + KS8695_TMR_OFFSET)
+
+/*
+ * Timer registers
+ */
+#define KS8695_TMCON (0x00) /* Timer Control Register */
+#define KS8695_T0TC (0x08) /* Timer 0 Timeout Count Register */
+#define TMCON_T0EN (1 << 0) /* Timer 0 Enable */
+
+/* Timer0 Timeout Counter Register */
+#define T0TC_WATCHDOG (0xff) /* Enable watchdog mode */
#define WDT_DEFAULT_TIME 5 /* seconds */
#define WDT_MAX_TIME 171 /* seconds */