summaryrefslogtreecommitdiff
path: root/arch/arm/mach-shmobile
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-shmobile')
-rw-r--r--arch/arm/mach-shmobile/Kconfig213
-rw-r--r--arch/arm/mach-shmobile/Makefile65
-rw-r--r--arch/arm/mach-shmobile/Makefile.boot15
-rw-r--r--arch/arm/mach-shmobile/board-armadillo800eva.c1365
-rw-r--r--arch/arm/mach-shmobile/board-bockw-reference.c86
-rw-r--r--arch/arm/mach-shmobile/board-bockw.c737
-rw-r--r--arch/arm/mach-shmobile/board-kzm9g.c916
-rw-r--r--arch/arm/mach-shmobile/board-marzen-reference.c56
-rw-r--r--arch/arm/mach-shmobile/board-marzen.c347
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7740.c675
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7778.c342
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7779.c271
-rw-r--r--arch/arm/mach-shmobile/clock-sh73a0.c752
-rw-r--r--arch/arm/mach-shmobile/clock.c47
-rw-r--r--arch/arm/mach-shmobile/clock.h42
-rw-r--r--arch/arm/mach-shmobile/common.h48
-rw-r--r--arch/arm/mach-shmobile/console.c27
-rw-r--r--arch/arm/mach-shmobile/cpufreq.c17
-rw-r--r--arch/arm/mach-shmobile/dma-register.h84
-rw-r--r--arch/arm/mach-shmobile/headsmp-scu.S46
-rw-r--r--arch/arm/mach-shmobile/headsmp.S98
-rw-r--r--arch/arm/mach-shmobile/include/mach/head-kzm9g.txt410
-rw-r--r--arch/arm/mach-shmobile/include/mach/irqs.h10
-rw-r--r--arch/arm/mach-shmobile/include/mach/zboot.h19
-rw-r--r--arch/arm/mach-shmobile/include/mach/zboot_macros.h108
-rw-r--r--arch/arm/mach-shmobile/intc-sh73a0.c337
-rw-r--r--arch/arm/mach-shmobile/intc.h295
-rw-r--r--arch/arm/mach-shmobile/irqs.h15
-rw-r--r--arch/arm/mach-shmobile/platsmp-apmu.c238
-rw-r--r--arch/arm/mach-shmobile/platsmp-apmu.h32
-rw-r--r--arch/arm/mach-shmobile/platsmp-scu.c97
-rw-r--r--arch/arm/mach-shmobile/platsmp.c38
-rw-r--r--arch/arm/mach-shmobile/pm-r8a7740.c129
-rw-r--r--arch/arm/mach-shmobile/pm-r8a7779.c143
-rw-r--r--arch/arm/mach-shmobile/pm-rcar-gen2.c115
-rw-r--r--arch/arm/mach-shmobile/pm-rcar.c137
-rw-r--r--arch/arm/mach-shmobile/pm-rcar.h15
-rw-r--r--arch/arm/mach-shmobile/pm-rmobile.c434
-rw-r--r--arch/arm/mach-shmobile/pm-rmobile.h64
-rw-r--r--arch/arm/mach-shmobile/pm-sh73a0.c32
-rw-r--r--arch/arm/mach-shmobile/r8a7740.h58
-rw-r--r--arch/arm/mach-shmobile/r8a7778.h78
-rw-r--r--arch/arm/mach-shmobile/r8a7779.h35
-rw-r--r--arch/arm/mach-shmobile/r8a7790.h6
-rw-r--r--arch/arm/mach-shmobile/r8a7791.h6
-rw-r--r--arch/arm/mach-shmobile/rcar-gen2.h10
-rw-r--r--arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c147
-rw-r--r--arch/arm/mach-shmobile/setup-emev2.c53
-rw-r--r--arch/arm/mach-shmobile/setup-r7s72100.c32
-rw-r--r--arch/arm/mach-shmobile/setup-r8a73a4.c32
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7740.c859
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7778.c633
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7779.c771
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7790.c37
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7791.c38
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7794.c33
-rw-r--r--arch/arm/mach-shmobile/setup-rcar-gen2.c203
-rw-r--r--arch/arm/mach-shmobile/setup-sh73a0.c810
-rw-r--r--arch/arm/mach-shmobile/sh-gpio.h29
-rw-r--r--arch/arm/mach-shmobile/sh73a0.h89
-rw-r--r--arch/arm/mach-shmobile/smp-emev2.c55
-rw-r--r--arch/arm/mach-shmobile/smp-r8a7779.c136
-rw-r--r--arch/arm/mach-shmobile/smp-r8a7790.c71
-rw-r--r--arch/arm/mach-shmobile/smp-r8a7791.c65
-rw-r--r--arch/arm/mach-shmobile/smp-sh73a0.c75
-rw-r--r--arch/arm/mach-shmobile/suspend.c48
-rw-r--r--arch/arm/mach-shmobile/timer.c112
67 files changed, 13438 insertions, 0 deletions
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
new file mode 100644
index 000000000..0fb484221
--- /dev/null
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -0,0 +1,213 @@
+config ARCH_SHMOBILE
+ bool
+ select ZONE_DMA if ARM_LPAE
+
+config PM_RCAR
+ bool
+
+config PM_RMOBILE
+ bool
+ select PM_GENERIC_DOMAINS
+
+config ARCH_RCAR_GEN1
+ bool
+ select PM_RCAR if PM || SMP
+ select RENESAS_INTC_IRQPIN
+ select SYS_SUPPORTS_SH_TMU
+
+config ARCH_RCAR_GEN2
+ bool
+ select PM_RCAR if PM || SMP
+ select RENESAS_IRQC
+ select SYS_SUPPORTS_SH_CMT
+ select PCI_DOMAINS if PCI
+
+config ARCH_RMOBILE
+ bool
+ select PM_RMOBILE if PM
+ select SYS_SUPPORTS_SH_CMT
+ select SYS_SUPPORTS_SH_TMU
+
+menuconfig ARCH_SHMOBILE_MULTI
+ bool "Renesas ARM SoCs" if ARCH_MULTI_V7
+ depends on MMU
+ select ARCH_SHMOBILE
+ select HAVE_ARM_SCU if SMP
+ select HAVE_ARM_TWD if SMP
+ select ARM_GIC
+ select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
+ select NO_IOPORT_MAP
+ select PINCTRL
+ select ARCH_REQUIRE_GPIOLIB
+
+if ARCH_SHMOBILE_MULTI
+
+#comment "Renesas ARM SoCs System Type"
+
+config ARCH_EMEV2
+ bool "Emma Mobile EV2"
+ select SYS_SUPPORTS_EM_STI
+
+config ARCH_R7S72100
+ bool "RZ/A1H (R7S72100)"
+ select SYS_SUPPORTS_SH_MTU2
+
+config ARCH_R8A73A4
+ bool "R-Mobile APE6 (R8A73A40)"
+ select ARCH_RMOBILE
+ select RENESAS_IRQC
+
+config ARCH_R8A7740
+ bool "R-Mobile A1 (R8A77400)"
+ select ARCH_RMOBILE
+ select RENESAS_INTC_IRQPIN
+
+config ARCH_R8A7778
+ bool "R-Car M1A (R8A77781)"
+ select ARCH_RCAR_GEN1
+
+config ARCH_R8A7779
+ bool "R-Car H1 (R8A77790)"
+ select ARCH_RCAR_GEN1
+
+config ARCH_R8A7790
+ bool "R-Car H2 (R8A77900)"
+ select ARCH_RCAR_GEN2
+ select I2C
+
+config ARCH_R8A7791
+ bool "R-Car M2-W (R8A77910)"
+ select ARCH_RCAR_GEN2
+ select I2C
+
+config ARCH_R8A7794
+ bool "R-Car E2 (R8A77940)"
+ select ARCH_RCAR_GEN2
+
+config ARCH_SH73A0
+ bool "SH-Mobile AG5 (R8A73A00)"
+ select ARCH_RMOBILE
+ select RENESAS_INTC_IRQPIN
+
+comment "Renesas ARM SoCs Board Type"
+
+config MACH_MARZEN
+ bool "MARZEN board"
+ depends on ARCH_R8A7779
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
+
+comment "Renesas ARM SoCs System Configuration"
+endif
+
+if ARCH_SHMOBILE_LEGACY
+
+comment "Renesas ARM SoCs System Type"
+
+config ARCH_SH73A0
+ bool "SH-Mobile AG5 (R8A73A00)"
+ select ARCH_RMOBILE
+ select ARCH_WANT_OPTIONAL_GPIOLIB
+ select ARM_GIC
+ select I2C
+ select SH_INTC
+ select RENESAS_INTC_IRQPIN
+
+config ARCH_R8A7740
+ bool "R-Mobile A1 (R8A77400)"
+ select ARCH_RMOBILE
+ select ARCH_WANT_OPTIONAL_GPIOLIB
+ select ARM_GIC
+ select RENESAS_INTC_IRQPIN
+
+config ARCH_R8A7778
+ bool "R-Car M1A (R8A77781)"
+ select ARCH_RCAR_GEN1
+ select ARCH_WANT_OPTIONAL_GPIOLIB
+ select ARM_GIC
+
+config ARCH_R8A7779
+ bool "R-Car H1 (R8A77790)"
+ select ARCH_RCAR_GEN1
+ select ARCH_WANT_OPTIONAL_GPIOLIB
+ select ARM_GIC
+
+comment "Renesas ARM SoCs Board Type"
+
+config MACH_ARMADILLO800EVA
+ bool "Armadillo-800 EVA board"
+ depends on ARCH_R8A7740
+ select ARCH_REQUIRE_GPIOLIB
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
+ select SMSC_PHY if SH_ETH
+ select SND_SOC_WM8978 if SND_SIMPLE_CARD
+ select USE_OF
+
+config MACH_BOCKW
+ bool "BOCK-W platform"
+ depends on ARCH_R8A7778
+ select ARCH_REQUIRE_GPIOLIB
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
+ select SND_SOC_AK4554 if SND_SIMPLE_CARD
+ select SND_SOC_AK4642 if SND_SIMPLE_CARD
+ select USE_OF
+
+config MACH_BOCKW_REFERENCE
+ bool "BOCK-W - Reference Device Tree Implementation"
+ depends on ARCH_R8A7778
+ select ARCH_REQUIRE_GPIOLIB
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
+ select USE_OF
+ ---help---
+ Use reference implementation of BockW board support
+ which makes use of device tree at the expense
+ of not supporting a number of devices.
+
+ This is intended to aid developers
+
+config MACH_MARZEN
+ bool "MARZEN board"
+ depends on ARCH_R8A7779
+ select ARCH_REQUIRE_GPIOLIB
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
+ select USE_OF
+
+config MACH_KZM9G
+ bool "KZM-A9-GT board"
+ depends on ARCH_SH73A0
+ select ARCH_REQUIRE_GPIOLIB
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
+ select SND_SOC_AK4642 if SND_SIMPLE_CARD
+ select USE_OF
+
+comment "Renesas ARM SoCs System Configuration"
+
+config CPU_HAS_INTEVT
+ bool
+ default y
+
+config SH_CLK_CPG
+ bool
+
+source "drivers/sh/Kconfig"
+
+endif
+
+if ARCH_SHMOBILE
+
+menu "Timer and clock configuration"
+
+config SHMOBILE_TIMER_HZ
+ int "Kernel HZ (jiffies per second)"
+ range 32 1024
+ default "128"
+ help
+ Allows the configuration of the timer frequency. It is customary
+ to have the timer interrupt run at 1000 Hz or 100 Hz, but in the
+ case of low timer frequencies other values may be more suitable.
+ Renesas ARM SoC systems using a 32768 Hz RCLK for clock events may
+ want to select a HZ value such as 128 that can evenly divide RCLK.
+ A HZ value that does not divide evenly may cause timer drift.
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
new file mode 100644
index 000000000..89e463de4
--- /dev/null
+++ b/arch/arm/mach-shmobile/Makefile
@@ -0,0 +1,65 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Common objects
+obj-y := timer.o console.o
+
+# CPU objects
+obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o pm-sh73a0.o
+obj-$(CONFIG_ARCH_R8A73A4) += setup-r8a73a4.o
+obj-$(CONFIG_ARCH_R8A7740) += setup-r8a7740.o pm-r8a7740.o
+obj-$(CONFIG_ARCH_R8A7778) += setup-r8a7778.o
+obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o pm-r8a7779.o
+obj-$(CONFIG_ARCH_R8A7790) += setup-r8a7790.o
+obj-$(CONFIG_ARCH_R8A7791) += setup-r8a7791.o
+obj-$(CONFIG_ARCH_R8A7794) += setup-r8a7794.o
+obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o
+obj-$(CONFIG_ARCH_R7S72100) += setup-r7s72100.o
+
+# Clock objects
+ifndef CONFIG_COMMON_CLK
+obj-y += clock.o
+obj-$(CONFIG_ARCH_SH73A0) += clock-sh73a0.o
+obj-$(CONFIG_ARCH_R8A7740) += clock-r8a7740.o
+obj-$(CONFIG_ARCH_R8A7778) += clock-r8a7778.o
+obj-$(CONFIG_ARCH_R8A7779) += clock-r8a7779.o
+endif
+
+# CPU reset vector handling objects
+cpu-y := platsmp.o headsmp.o
+
+# Shared SoC family objects
+obj-$(CONFIG_ARCH_RCAR_GEN2) += setup-rcar-gen2.o platsmp-apmu.o $(cpu-y)
+CFLAGS_setup-rcar-gen2.o += -march=armv7-a
+obj-$(CONFIG_ARCH_R8A7790) += regulator-quirk-rcar-gen2.o
+obj-$(CONFIG_ARCH_R8A7791) += regulator-quirk-rcar-gen2.o
+
+# SMP objects
+smp-y := $(cpu-y)
+smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-scu.o platsmp-scu.o
+smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o headsmp-scu.o platsmp-scu.o
+smp-$(CONFIG_ARCH_R8A7790) += smp-r8a7790.o
+smp-$(CONFIG_ARCH_R8A7791) += smp-r8a7791.o
+smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o platsmp-scu.o
+
+# PM objects
+obj-$(CONFIG_SUSPEND) += suspend.o
+obj-$(CONFIG_CPU_FREQ) += cpufreq.o
+obj-$(CONFIG_PM_RCAR) += pm-rcar.o
+obj-$(CONFIG_PM_RMOBILE) += pm-rmobile.o
+obj-$(CONFIG_ARCH_RCAR_GEN2) += pm-rcar-gen2.o
+
+# Board objects
+ifdef CONFIG_ARCH_SHMOBILE_MULTI
+obj-$(CONFIG_MACH_MARZEN) += board-marzen-reference.o
+else
+obj-$(CONFIG_MACH_BOCKW) += board-bockw.o
+obj-$(CONFIG_MACH_BOCKW_REFERENCE) += board-bockw-reference.o
+obj-$(CONFIG_MACH_MARZEN) += board-marzen.o
+obj-$(CONFIG_MACH_ARMADILLO800EVA) += board-armadillo800eva.o
+obj-$(CONFIG_MACH_KZM9G) += board-kzm9g.o intc-sh73a0.o
+endif
+
+# Framework support
+obj-$(CONFIG_SMP) += $(smp-y)
diff --git a/arch/arm/mach-shmobile/Makefile.boot b/arch/arm/mach-shmobile/Makefile.boot
new file mode 100644
index 000000000..e1ef19cef
--- /dev/null
+++ b/arch/arm/mach-shmobile/Makefile.boot
@@ -0,0 +1,15 @@
+# per-board load address for uImage
+loadaddr-y :=
+loadaddr-$(CONFIG_MACH_ARMADILLO800EVA) += 0x40008000
+loadaddr-$(CONFIG_MACH_BOCKW) += 0x60008000
+loadaddr-$(CONFIG_MACH_BOCKW_REFERENCE) += 0x60008000
+loadaddr-$(CONFIG_MACH_KZM9G) += 0x41008000
+loadaddr-$(CONFIG_MACH_MARZEN) += 0x60008000
+
+__ZRELADDR := $(sort $(loadaddr-y))
+ zreladdr-y += $(__ZRELADDR)
+
+# Unsupported legacy stuff
+#
+#params_phys-y (Instead: Pass atags pointer in r2)
+#initrd_phys-y (Instead: Use compiled-in initramfs)
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
new file mode 100644
index 000000000..bf37e3c53
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -0,0 +1,1365 @@
+/*
+ * armadillo 800 eva board support
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/i2c-gpio.h>
+#include <linux/input.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/mfd/tmio.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mmcif.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/platform_data/st1232_pdata.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/pwm_backlight.h>
+#include <linux/reboot.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/gpio-regulator.h>
+#include <linux/regulator/machine.h>
+#include <linux/sh_eth.h>
+#include <linux/usb/renesas_usbhs.h>
+#include <linux/videodev2.h>
+
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <asm/page.h>
+#include <media/mt9t112.h>
+#include <media/sh_mobile_ceu.h>
+#include <media/soc_camera.h>
+#include <sound/sh_fsi.h>
+#include <sound/simple_card.h>
+#include <video/sh_mobile_hdmi.h>
+#include <video/sh_mobile_lcdc.h>
+
+#include "common.h"
+#include "irqs.h"
+#include "pm-rmobile.h"
+#include "r8a7740.h"
+#include "sh-gpio.h"
+
+/*
+ * CON1 Camera Module
+ * CON2 Extension Bus
+ * CON3 HDMI Output
+ * CON4 Composite Video Output
+ * CON5 H-UDI JTAG
+ * CON6 ARM JTAG
+ * CON7 SD1
+ * CON8 SD2
+ * CON9 RTC BackUp
+ * CON10 Monaural Mic Input
+ * CON11 Stereo Headphone Output
+ * CON12 Audio Line Output(L)
+ * CON13 Audio Line Output(R)
+ * CON14 AWL13 Module
+ * CON15 Extension
+ * CON16 LCD1
+ * CON17 LCD2
+ * CON19 Power Input
+ * CON20 USB1
+ * CON21 USB2
+ * CON22 Serial
+ * CON23 LAN
+ * CON24 USB3
+ * LED1 Camera LED(Yellow)
+ * LED2 Power LED (Green)
+ * ED3-LED6 User LED(Yellow)
+ * LED7 LAN link LED(Green)
+ * LED8 LAN activity LED(Yellow)
+ */
+
+/*
+ * DipSwitch
+ *
+ * SW1
+ *
+ * -12345678-+---------------+----------------------------
+ * 1 | boot | hermit
+ * 0 | boot | OS auto boot
+ * -12345678-+---------------+----------------------------
+ * 00 | boot device | eMMC
+ * 10 | boot device | SDHI0 (CON7)
+ * 01 | boot device | -
+ * 11 | boot device | Extension Buss (CS0)
+ * -12345678-+---------------+----------------------------
+ * 0 | Extension Bus | D8-D15 disable, eMMC enable
+ * 1 | Extension Bus | D8-D15 enable, eMMC disable
+ * -12345678-+---------------+----------------------------
+ * 0 | SDHI1 | COM8 disable, COM14 enable
+ * 1 | SDHI1 | COM8 enable, COM14 disable
+ * -12345678-+---------------+----------------------------
+ * 0 | USB0 | COM20 enable, COM24 disable
+ * 1 | USB0 | COM20 disable, COM24 enable
+ * -12345678-+---------------+----------------------------
+ * 00 | JTAG | SH-X2
+ * 10 | JTAG | ARM
+ * 01 | JTAG | -
+ * 11 | JTAG | Boundary Scan
+ *-----------+---------------+----------------------------
+ */
+
+/*
+ * FSI-WM8978
+ *
+ * this command is required when playback.
+ *
+ * # amixer set "Headphone" 50
+ *
+ * this command is required when capture.
+ *
+ * # amixer set "Input PGA" 15
+ * # amixer set "Left Input Mixer MicP" on
+ * # amixer set "Left Input Mixer MicN" on
+ * # amixer set "Right Input Mixer MicN" on
+ * # amixer set "Right Input Mixer MicP" on
+ */
+
+/*
+ * USB function
+ *
+ * When you use USB Function,
+ * set SW1.6 ON, and connect cable to CN24.
+ *
+ * USBF needs workaround on R8A7740 chip.
+ * These are a little bit complex.
+ * see
+ * usbhsf_power_ctrl()
+ */
+#define IRQ7 irq_pin(7)
+#define USBCR1 IOMEM(0xe605810a)
+#define USBH 0xC6700000
+#define USBH_USBCTR 0x10834
+
+struct usbhsf_private {
+ struct clk *phy;
+ struct clk *usb24;
+ struct clk *pci;
+ struct clk *func;
+ struct clk *host;
+ void __iomem *usbh_base;
+ struct renesas_usbhs_platform_info info;
+};
+
+#define usbhsf_get_priv(pdev) \
+ container_of(renesas_usbhs_get_info(pdev), \
+ struct usbhsf_private, info)
+
+static int usbhsf_get_id(struct platform_device *pdev)
+{
+ return USBHS_GADGET;
+}
+
+static int usbhsf_power_ctrl(struct platform_device *pdev,
+ void __iomem *base, int enable)
+{
+ struct usbhsf_private *priv = usbhsf_get_priv(pdev);
+
+ /*
+ * Work around for USB Function.
+ * It needs USB host clock, and settings
+ */
+ if (enable) {
+ /*
+ * enable all the related usb clocks
+ * for usb workaround
+ */
+ clk_enable(priv->usb24);
+ clk_enable(priv->pci);
+ clk_enable(priv->host);
+ clk_enable(priv->func);
+ clk_enable(priv->phy);
+
+ /*
+ * set USBCR1
+ *
+ * Port1 is driven by USB function,
+ * Port2 is driven by USB HOST
+ * One HOST (Port1 or Port2 is HOST)
+ * USB PLL input clock = 24MHz
+ */
+ __raw_writew(0xd750, USBCR1);
+ mdelay(1);
+
+ /*
+ * start USB Host
+ */
+ __raw_writel(0x0000000c, priv->usbh_base + USBH_USBCTR);
+ __raw_writel(0x00000008, priv->usbh_base + USBH_USBCTR);
+ mdelay(10);
+
+ /*
+ * USB PHY Power ON
+ */
+ __raw_writew(0xd770, USBCR1);
+ __raw_writew(0x4000, base + 0x102); /* USBF :: SUSPMODE */
+
+ } else {
+ __raw_writel(0x0000010f, priv->usbh_base + USBH_USBCTR);
+ __raw_writew(0xd7c0, USBCR1); /* GPIO */
+
+ clk_disable(priv->phy);
+ clk_disable(priv->func); /* usb work around */
+ clk_disable(priv->host); /* usb work around */
+ clk_disable(priv->pci); /* usb work around */
+ clk_disable(priv->usb24); /* usb work around */
+ }
+
+ return 0;
+}
+
+static int usbhsf_get_vbus(struct platform_device *pdev)
+{
+ return gpio_get_value(209);
+}
+
+static irqreturn_t usbhsf_interrupt(int irq, void *data)
+{
+ struct platform_device *pdev = data;
+
+ renesas_usbhs_call_notify_hotplug(pdev);
+
+ return IRQ_HANDLED;
+}
+
+static int usbhsf_hardware_exit(struct platform_device *pdev)
+{
+ struct usbhsf_private *priv = usbhsf_get_priv(pdev);
+
+ if (!IS_ERR(priv->phy))
+ clk_put(priv->phy);
+ if (!IS_ERR(priv->usb24))
+ clk_put(priv->usb24);
+ if (!IS_ERR(priv->pci))
+ clk_put(priv->pci);
+ if (!IS_ERR(priv->host))
+ clk_put(priv->host);
+ if (!IS_ERR(priv->func))
+ clk_put(priv->func);
+ if (priv->usbh_base)
+ iounmap(priv->usbh_base);
+
+ priv->phy = NULL;
+ priv->usb24 = NULL;
+ priv->pci = NULL;
+ priv->host = NULL;
+ priv->func = NULL;
+ priv->usbh_base = NULL;
+
+ free_irq(IRQ7, pdev);
+
+ return 0;
+}
+
+static int usbhsf_hardware_init(struct platform_device *pdev)
+{
+ struct usbhsf_private *priv = usbhsf_get_priv(pdev);
+ int ret;
+
+ priv->phy = clk_get(&pdev->dev, "phy");
+ priv->usb24 = clk_get(&pdev->dev, "usb24");
+ priv->pci = clk_get(&pdev->dev, "pci");
+ priv->func = clk_get(&pdev->dev, "func");
+ priv->host = clk_get(&pdev->dev, "host");
+ priv->usbh_base = ioremap_nocache(USBH, 0x20000);
+
+ if (IS_ERR(priv->phy) ||
+ IS_ERR(priv->usb24) ||
+ IS_ERR(priv->pci) ||
+ IS_ERR(priv->host) ||
+ IS_ERR(priv->func) ||
+ !priv->usbh_base) {
+ dev_err(&pdev->dev, "USB clock setting failed\n");
+ usbhsf_hardware_exit(pdev);
+ return -EIO;
+ }
+
+ ret = request_irq(IRQ7, usbhsf_interrupt, IRQF_TRIGGER_NONE,
+ dev_name(&pdev->dev), pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "request_irq err\n");
+ return ret;
+ }
+ irq_set_irq_type(IRQ7, IRQ_TYPE_EDGE_BOTH);
+
+ /* usb24 use 1/1 of parent clock (= usb24s = 24MHz) */
+ clk_set_rate(priv->usb24,
+ clk_get_rate(clk_get_parent(priv->usb24)));
+
+ return 0;
+}
+
+static struct usbhsf_private usbhsf_private = {
+ .info = {
+ .platform_callback = {
+ .get_id = usbhsf_get_id,
+ .get_vbus = usbhsf_get_vbus,
+ .hardware_init = usbhsf_hardware_init,
+ .hardware_exit = usbhsf_hardware_exit,
+ .power_ctrl = usbhsf_power_ctrl,
+ },
+ .driver_param = {
+ .buswait_bwait = 5,
+ .detection_delay = 5,
+ .d0_rx_id = SHDMA_SLAVE_USBHS_RX,
+ .d1_tx_id = SHDMA_SLAVE_USBHS_TX,
+ },
+ }
+};
+
+static struct resource usbhsf_resources[] = {
+ {
+ .name = "USBHS",
+ .start = 0xe6890000,
+ .end = 0xe6890104 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = gic_spi(51),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device usbhsf_device = {
+ .name = "renesas_usbhs",
+ .dev = {
+ .platform_data = &usbhsf_private.info,
+ },
+ .id = -1,
+ .num_resources = ARRAY_SIZE(usbhsf_resources),
+ .resource = usbhsf_resources,
+};
+
+/* Ether */
+static struct sh_eth_plat_data sh_eth_platdata = {
+ .phy = 0x00, /* LAN8710A */
+ .edmac_endian = EDMAC_LITTLE_ENDIAN,
+ .phy_interface = PHY_INTERFACE_MODE_MII,
+};
+
+static struct resource sh_eth_resources[] = {
+ {
+ .start = 0xe9a00000,
+ .end = 0xe9a00800 - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 0xe9a01800,
+ .end = 0xe9a02000 - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = gic_spi(110),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sh_eth_device = {
+ .name = "r8a7740-gether",
+ .id = -1,
+ .dev = {
+ .platform_data = &sh_eth_platdata,
+ .dma_mask = &sh_eth_device.dev.coherent_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .resource = sh_eth_resources,
+ .num_resources = ARRAY_SIZE(sh_eth_resources),
+};
+
+/* PWM */
+static struct resource pwm_resources[] = {
+ [0] = {
+ .start = 0xe6600000,
+ .end = 0xe66000ff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device pwm_device = {
+ .name = "renesas-tpu-pwm",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(pwm_resources),
+ .resource = pwm_resources,
+};
+
+static struct pwm_lookup pwm_lookup[] = {
+ PWM_LOOKUP("renesas-tpu-pwm", 2, "pwm-backlight.0", NULL,
+ 33333, PWM_POLARITY_INVERSED),
+};
+
+/* LCDC and backlight */
+static struct platform_pwm_backlight_data pwm_backlight_data = {
+ .lth_brightness = 50,
+ .max_brightness = 255,
+ .dft_brightness = 255,
+ .pwm_period_ns = 33333, /* 30kHz */
+ .enable_gpio = 61,
+};
+
+static struct platform_device pwm_backlight_device = {
+ .name = "pwm-backlight",
+ .dev = {
+ .platform_data = &pwm_backlight_data,
+ },
+};
+
+static struct fb_videomode lcdc0_mode = {
+ .name = "AMPIER/AM-800480",
+ .xres = 800,
+ .yres = 480,
+ .left_margin = 88,
+ .right_margin = 40,
+ .hsync_len = 128,
+ .upper_margin = 20,
+ .lower_margin = 5,
+ .vsync_len = 5,
+ .sync = 0,
+};
+
+static struct sh_mobile_lcdc_info lcdc0_info = {
+ .clock_source = LCDC_CLK_BUS,
+ .ch[0] = {
+ .chan = LCDC_CHAN_MAINLCD,
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .interface_type = RGB24,
+ .clock_divider = 5,
+ .flags = 0,
+ .lcd_modes = &lcdc0_mode,
+ .num_modes = 1,
+ .panel_cfg = {
+ .width = 111,
+ .height = 68,
+ },
+ },
+};
+
+static struct resource lcdc0_resources[] = {
+ [0] = {
+ .name = "LCD0",
+ .start = 0xfe940000,
+ .end = 0xfe943fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(177),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device lcdc0_device = {
+ .name = "sh_mobile_lcdc_fb",
+ .num_resources = ARRAY_SIZE(lcdc0_resources),
+ .resource = lcdc0_resources,
+ .id = 0,
+ .dev = {
+ .platform_data = &lcdc0_info,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+/*
+ * LCDC1/HDMI
+ */
+static struct sh_mobile_hdmi_info hdmi_info = {
+ .flags = HDMI_OUTPUT_PUSH_PULL |
+ HDMI_OUTPUT_POLARITY_HI |
+ HDMI_32BIT_REG |
+ HDMI_HAS_HTOP1 |
+ HDMI_SND_SRC_SPDIF,
+};
+
+static struct resource hdmi_resources[] = {
+ [0] = {
+ .name = "HDMI",
+ .start = 0xe6be0000,
+ .end = 0xe6be03ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(131),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .name = "HDMI emma3pf",
+ .start = 0xe6be4000,
+ .end = 0xe6be43ff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device hdmi_device = {
+ .name = "sh-mobile-hdmi",
+ .num_resources = ARRAY_SIZE(hdmi_resources),
+ .resource = hdmi_resources,
+ .id = -1,
+ .dev = {
+ .platform_data = &hdmi_info,
+ },
+};
+
+static const struct fb_videomode lcdc1_mode = {
+ .name = "HDMI 720p",
+ .xres = 1280,
+ .yres = 720,
+ .pixclock = 13468,
+ .left_margin = 220,
+ .right_margin = 110,
+ .hsync_len = 40,
+ .upper_margin = 20,
+ .lower_margin = 5,
+ .vsync_len = 5,
+ .refresh = 60,
+ .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
+};
+
+static struct sh_mobile_lcdc_info hdmi_lcdc_info = {
+ .clock_source = LCDC_CLK_PERIPHERAL, /* HDMI clock */
+ .ch[0] = {
+ .chan = LCDC_CHAN_MAINLCD,
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .interface_type = RGB24,
+ .clock_divider = 1,
+ .flags = LCDC_FLAGS_DWPOL,
+ .lcd_modes = &lcdc1_mode,
+ .num_modes = 1,
+ .tx_dev = &hdmi_device,
+ .panel_cfg = {
+ .width = 1280,
+ .height = 720,
+ },
+ },
+};
+
+static struct resource hdmi_lcdc_resources[] = {
+ [0] = {
+ .name = "LCDC1",
+ .start = 0xfe944000,
+ .end = 0xfe948000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(178),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device hdmi_lcdc_device = {
+ .name = "sh_mobile_lcdc_fb",
+ .num_resources = ARRAY_SIZE(hdmi_lcdc_resources),
+ .resource = hdmi_lcdc_resources,
+ .id = 1,
+ .dev = {
+ .platform_data = &hdmi_lcdc_info,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+/* LEDS */
+static struct gpio_led gpio_leds[] = {
+ {
+ .name = "LED3",
+ .gpio = 102,
+ .default_state = LEDS_GPIO_DEFSTATE_ON,
+ }, {
+ .name = "LED4",
+ .gpio = 111,
+ .default_state = LEDS_GPIO_DEFSTATE_ON,
+ }, {
+ .name = "LED5",
+ .gpio = 110,
+ .default_state = LEDS_GPIO_DEFSTATE_ON,
+ }, {
+ .name = "LED6",
+ .gpio = 177,
+ .default_state = LEDS_GPIO_DEFSTATE_ON,
+ },
+};
+
+static struct gpio_led_platform_data leds_gpio_info = {
+ .leds = gpio_leds,
+ .num_leds = ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device leds_gpio_device = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &leds_gpio_info,
+ },
+};
+
+/* GPIO KEY */
+#define GPIO_KEY(c, g, d, ...) \
+ { .code = c, .gpio = g, .desc = d, .active_low = 1, __VA_ARGS__ }
+
+static struct gpio_keys_button gpio_buttons[] = {
+ GPIO_KEY(KEY_POWER, 99, "SW3", .wakeup = 1),
+ GPIO_KEY(KEY_BACK, 100, "SW4"),
+ GPIO_KEY(KEY_MENU, 97, "SW5"),
+ GPIO_KEY(KEY_HOME, 98, "SW6"),
+};
+
+static struct gpio_keys_platform_data gpio_key_info = {
+ .buttons = gpio_buttons,
+ .nbuttons = ARRAY_SIZE(gpio_buttons),
+};
+
+static struct platform_device gpio_keys_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &gpio_key_info,
+ },
+};
+
+/* Fixed 3.3V regulator to be used by SDHI1, MMCIF */
+static struct regulator_consumer_supply fixed3v3_power_consumers[] = {
+ REGULATOR_SUPPLY("vmmc", "sh_mmcif"),
+ REGULATOR_SUPPLY("vqmmc", "sh_mmcif"),
+};
+
+/* Fixed 3.3V regulator used by LCD backlight */
+static struct regulator_consumer_supply fixed5v0_power_consumers[] = {
+ REGULATOR_SUPPLY("power", "pwm-backlight.0"),
+};
+
+/* Fixed 3.3V regulator to be used by SDHI0 */
+static struct regulator_consumer_supply vcc_sdhi0_consumers[] = {
+ REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
+};
+
+static struct regulator_init_data vcc_sdhi0_init_data = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vcc_sdhi0_consumers),
+ .consumer_supplies = vcc_sdhi0_consumers,
+};
+
+static struct fixed_voltage_config vcc_sdhi0_info = {
+ .supply_name = "SDHI0 Vcc",
+ .microvolts = 3300000,
+ .gpio = 75,
+ .enable_high = 1,
+ .init_data = &vcc_sdhi0_init_data,
+};
+
+static struct platform_device vcc_sdhi0 = {
+ .name = "reg-fixed-voltage",
+ .id = 1,
+ .dev = {
+ .platform_data = &vcc_sdhi0_info,
+ },
+};
+
+/* 1.8 / 3.3V SDHI0 VccQ regulator */
+static struct regulator_consumer_supply vccq_sdhi0_consumers[] = {
+ REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"),
+};
+
+static struct regulator_init_data vccq_sdhi0_init_data = {
+ .constraints = {
+ .input_uV = 3300000,
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vccq_sdhi0_consumers),
+ .consumer_supplies = vccq_sdhi0_consumers,
+};
+
+static struct gpio vccq_sdhi0_gpios[] = {
+ {17, GPIOF_OUT_INIT_LOW, "vccq-sdhi0" },
+};
+
+static struct gpio_regulator_state vccq_sdhi0_states[] = {
+ { .value = 3300000, .gpios = (0 << 0) },
+ { .value = 1800000, .gpios = (1 << 0) },
+};
+
+static struct gpio_regulator_config vccq_sdhi0_info = {
+ .supply_name = "vqmmc",
+
+ .enable_gpio = 74,
+ .enable_high = 1,
+ .enabled_at_boot = 0,
+
+ .gpios = vccq_sdhi0_gpios,
+ .nr_gpios = ARRAY_SIZE(vccq_sdhi0_gpios),
+
+ .states = vccq_sdhi0_states,
+ .nr_states = ARRAY_SIZE(vccq_sdhi0_states),
+
+ .type = REGULATOR_VOLTAGE,
+ .init_data = &vccq_sdhi0_init_data,
+};
+
+static struct platform_device vccq_sdhi0 = {
+ .name = "gpio-regulator",
+ .id = -1,
+ .dev = {
+ .platform_data = &vccq_sdhi0_info,
+ },
+};
+
+/* Fixed 3.3V regulator to be used by SDHI1 */
+static struct regulator_consumer_supply vcc_sdhi1_consumers[] = {
+ REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"),
+};
+
+static struct regulator_init_data vcc_sdhi1_init_data = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vcc_sdhi1_consumers),
+ .consumer_supplies = vcc_sdhi1_consumers,
+};
+
+static struct fixed_voltage_config vcc_sdhi1_info = {
+ .supply_name = "SDHI1 Vcc",
+ .microvolts = 3300000,
+ .gpio = 16,
+ .enable_high = 1,
+ .init_data = &vcc_sdhi1_init_data,
+};
+
+static struct platform_device vcc_sdhi1 = {
+ .name = "reg-fixed-voltage",
+ .id = 2,
+ .dev = {
+ .platform_data = &vcc_sdhi1_info,
+ },
+};
+
+/* SDHI0 */
+static struct tmio_mmc_data sdhi0_info = {
+ .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI0_TX,
+ .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI0_RX,
+ .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+ MMC_CAP_POWER_OFF_CARD,
+ .flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_USE_GPIO_CD,
+ .cd_gpio = 167,
+};
+
+static struct resource sdhi0_resources[] = {
+ {
+ .name = "SDHI0",
+ .start = 0xe6850000,
+ .end = 0xe6850100 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ /*
+ * no SH_MOBILE_SDHI_IRQ_CARD_DETECT here
+ */
+ {
+ .name = SH_MOBILE_SDHI_IRQ_SDCARD,
+ .start = gic_spi(118),
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = SH_MOBILE_SDHI_IRQ_SDIO,
+ .start = gic_spi(119),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sdhi0_device = {
+ .name = "sh_mobile_sdhi",
+ .id = 0,
+ .dev = {
+ .platform_data = &sdhi0_info,
+ },
+ .num_resources = ARRAY_SIZE(sdhi0_resources),
+ .resource = sdhi0_resources,
+};
+
+/* SDHI1 */
+static struct tmio_mmc_data sdhi1_info = {
+ .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI1_TX,
+ .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI1_RX,
+ .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+ MMC_CAP_POWER_OFF_CARD,
+ .flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_USE_GPIO_CD,
+ /* Port72 cannot generate IRQs, will be used in polling mode. */
+ .cd_gpio = 72,
+};
+
+static struct resource sdhi1_resources[] = {
+ [0] = {
+ .name = "SDHI1",
+ .start = 0xe6860000,
+ .end = 0xe6860100 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(121),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = gic_spi(122),
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = gic_spi(123),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sdhi1_device = {
+ .name = "sh_mobile_sdhi",
+ .id = 1,
+ .dev = {
+ .platform_data = &sdhi1_info,
+ },
+ .num_resources = ARRAY_SIZE(sdhi1_resources),
+ .resource = sdhi1_resources,
+};
+
+static const struct pinctrl_map eva_sdhi1_pinctrl_map[] = {
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7740",
+ "sdhi1_data4", "sdhi1"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7740",
+ "sdhi1_ctrl", "sdhi1"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7740",
+ "sdhi1_cd", "sdhi1"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7740",
+ "sdhi1_wp", "sdhi1"),
+};
+
+/* MMCIF */
+static struct sh_mmcif_plat_data sh_mmcif_plat = {
+ .sup_pclk = 0,
+ .caps = MMC_CAP_4_BIT_DATA |
+ MMC_CAP_8_BIT_DATA |
+ MMC_CAP_NONREMOVABLE,
+ .ccs_unsupported = true,
+ .slave_id_tx = SHDMA_SLAVE_MMCIF_TX,
+ .slave_id_rx = SHDMA_SLAVE_MMCIF_RX,
+};
+
+static struct resource sh_mmcif_resources[] = {
+ [0] = {
+ .name = "MMCIF",
+ .start = 0xe6bd0000,
+ .end = 0xe6bd0100 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* MMC ERR */
+ .start = gic_spi(56),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ /* MMC NOR */
+ .start = gic_spi(57),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sh_mmcif_device = {
+ .name = "sh_mmcif",
+ .id = -1,
+ .dev = {
+ .platform_data = &sh_mmcif_plat,
+ },
+ .num_resources = ARRAY_SIZE(sh_mmcif_resources),
+ .resource = sh_mmcif_resources,
+};
+
+/* Camera */
+static int mt9t111_power(struct device *dev, int mode)
+{
+ struct clk *mclk = clk_get(NULL, "video1");
+
+ if (IS_ERR(mclk)) {
+ dev_err(dev, "can't get video1 clock\n");
+ return -EINVAL;
+ }
+
+ if (mode) {
+ /* video1 (= CON1 camera) expect 24MHz */
+ clk_set_rate(mclk, clk_round_rate(mclk, 24000000));
+ clk_enable(mclk);
+ gpio_set_value(158, 1);
+ } else {
+ gpio_set_value(158, 0);
+ clk_disable(mclk);
+ }
+
+ clk_put(mclk);
+
+ return 0;
+}
+
+static struct i2c_board_info i2c_camera_mt9t111 = {
+ I2C_BOARD_INFO("mt9t112", 0x3d),
+};
+
+static struct mt9t112_camera_info mt9t111_info = {
+ .divider = { 16, 0, 0, 7, 0, 10, 14, 7, 7 },
+};
+
+static struct soc_camera_link mt9t111_link = {
+ .i2c_adapter_id = 0,
+ .bus_id = 0,
+ .board_info = &i2c_camera_mt9t111,
+ .power = mt9t111_power,
+ .priv = &mt9t111_info,
+};
+
+static struct platform_device camera_device = {
+ .name = "soc-camera-pdrv",
+ .id = 0,
+ .dev = {
+ .platform_data = &mt9t111_link,
+ },
+};
+
+/* CEU0 */
+static struct sh_mobile_ceu_info sh_mobile_ceu0_info = {
+ .flags = SH_CEU_FLAG_LOWER_8BIT,
+};
+
+static struct resource ceu0_resources[] = {
+ [0] = {
+ .name = "CEU",
+ .start = 0xfe910000,
+ .end = 0xfe91009f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(160),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ /* place holder for contiguous memory */
+ },
+};
+
+static struct platform_device ceu0_device = {
+ .name = "sh_mobile_ceu",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(ceu0_resources),
+ .resource = ceu0_resources,
+ .dev = {
+ .platform_data = &sh_mobile_ceu0_info,
+ .coherent_dma_mask = 0xffffffff,
+ },
+};
+
+/* FSI */
+static struct sh_fsi_platform_info fsi_info = {
+ /* FSI-WM8978 */
+ .port_a = {
+ .tx_id = SHDMA_SLAVE_FSIA_TX,
+ },
+ /* FSI-HDMI */
+ .port_b = {
+ .flags = SH_FSI_FMT_SPDIF |
+ SH_FSI_ENABLE_STREAM_MODE |
+ SH_FSI_CLK_CPG,
+ .tx_id = SHDMA_SLAVE_FSIB_TX,
+ }
+};
+
+static struct resource fsi_resources[] = {
+ [0] = {
+ .name = "FSI",
+ .start = 0xfe1f0000,
+ .end = 0xfe1f0400 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(9),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device fsi_device = {
+ .name = "sh_fsi2",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(fsi_resources),
+ .resource = fsi_resources,
+ .dev = {
+ .platform_data = &fsi_info,
+ },
+};
+
+/* FSI-WM8978 */
+static struct asoc_simple_card_info fsi_wm8978_info = {
+ .name = "wm8978",
+ .card = "FSI2A-WM8978",
+ .codec = "wm8978.0-001a",
+ .platform = "sh_fsi2",
+ .daifmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM,
+ .cpu_dai = {
+ .name = "fsia-dai",
+ },
+ .codec_dai = {
+ .name = "wm8978-hifi",
+ .sysclk = 12288000,
+ },
+};
+
+static struct platform_device fsi_wm8978_device = {
+ .name = "asoc-simple-card",
+ .id = 0,
+ .dev = {
+ .platform_data = &fsi_wm8978_info,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .dma_mask = &fsi_wm8978_device.dev.coherent_dma_mask,
+ },
+};
+
+/* FSI-HDMI */
+static struct asoc_simple_card_info fsi2_hdmi_info = {
+ .name = "HDMI",
+ .card = "FSI2B-HDMI",
+ .codec = "sh-mobile-hdmi",
+ .platform = "sh_fsi2",
+ .daifmt = SND_SOC_DAIFMT_CBS_CFS,
+ .cpu_dai = {
+ .name = "fsib-dai",
+ },
+ .codec_dai = {
+ .name = "sh_mobile_hdmi-hifi",
+ },
+};
+
+static struct platform_device fsi_hdmi_device = {
+ .name = "asoc-simple-card",
+ .id = 1,
+ .dev = {
+ .platform_data = &fsi2_hdmi_info,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .dma_mask = &fsi_hdmi_device.dev.coherent_dma_mask,
+ },
+};
+
+/* RTC: RTC connects i2c-gpio. */
+static struct i2c_gpio_platform_data i2c_gpio_data = {
+ .sda_pin = 208,
+ .scl_pin = 91,
+ .udelay = 5, /* 100 kHz */
+};
+
+static struct platform_device i2c_gpio_device = {
+ .name = "i2c-gpio",
+ .id = 2,
+ .dev = {
+ .platform_data = &i2c_gpio_data,
+ },
+};
+
+/* I2C */
+static struct st1232_pdata st1232_i2c0_pdata = {
+ .reset_gpio = 166,
+};
+
+static struct i2c_board_info i2c0_devices[] = {
+ {
+ I2C_BOARD_INFO("st1232-ts", 0x55),
+ .irq = irq_pin(10),
+ .platform_data = &st1232_i2c0_pdata,
+ },
+ {
+ I2C_BOARD_INFO("wm8978", 0x1a),
+ },
+};
+
+static struct i2c_board_info i2c2_devices[] = {
+ {
+ I2C_BOARD_INFO("s35390a", 0x30),
+ .type = "s35390a",
+ },
+};
+
+/*
+ * board devices
+ */
+static struct platform_device *eva_devices[] __initdata = {
+ &lcdc0_device,
+ &pwm_device,
+ &pwm_backlight_device,
+ &leds_gpio_device,
+ &gpio_keys_device,
+ &sh_eth_device,
+ &vcc_sdhi0,
+ &vccq_sdhi0,
+ &sdhi0_device,
+ &sh_mmcif_device,
+ &hdmi_device,
+ &hdmi_lcdc_device,
+ &camera_device,
+ &ceu0_device,
+ &fsi_device,
+ &fsi_wm8978_device,
+ &fsi_hdmi_device,
+ &i2c_gpio_device,
+};
+
+static const struct pinctrl_map eva_pinctrl_map[] = {
+ /* CEU0 */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_ceu.0", "pfc-r8a7740",
+ "ceu0_data_0_7", "ceu0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_ceu.0", "pfc-r8a7740",
+ "ceu0_clk_0", "ceu0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_ceu.0", "pfc-r8a7740",
+ "ceu0_sync", "ceu0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_ceu.0", "pfc-r8a7740",
+ "ceu0_field", "ceu0"),
+ /* FSIA */
+ PIN_MAP_MUX_GROUP_DEFAULT("asoc-simple-card.0", "pfc-r8a7740",
+ "fsia_sclk_in", "fsia"),
+ PIN_MAP_MUX_GROUP_DEFAULT("asoc-simple-card.0", "pfc-r8a7740",
+ "fsia_mclk_out", "fsia"),
+ PIN_MAP_MUX_GROUP_DEFAULT("asoc-simple-card.0", "pfc-r8a7740",
+ "fsia_data_in_1", "fsia"),
+ PIN_MAP_MUX_GROUP_DEFAULT("asoc-simple-card.0", "pfc-r8a7740",
+ "fsia_data_out_0", "fsia"),
+ /* FSIB */
+ PIN_MAP_MUX_GROUP_DEFAULT("asoc-simple-card.1", "pfc-r8a7740",
+ "fsib_mclk_in", "fsib"),
+ /* GETHER */
+ PIN_MAP_MUX_GROUP_DEFAULT("r8a7740-gether", "pfc-r8a7740",
+ "gether_mii", "gether"),
+ PIN_MAP_MUX_GROUP_DEFAULT("r8a7740-gether", "pfc-r8a7740",
+ "gether_int", "gether"),
+ /* HDMI */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh-mobile-hdmi", "pfc-r8a7740",
+ "hdmi", "hdmi"),
+ /* LCD0 */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-r8a7740",
+ "lcd0_data24_0", "lcd0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-r8a7740",
+ "lcd0_lclk_1", "lcd0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-r8a7740",
+ "lcd0_sync", "lcd0"),
+ /* MMCIF */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-r8a7740",
+ "mmc0_data8_1", "mmc0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-r8a7740",
+ "mmc0_ctrl_1", "mmc0"),
+ /* SCIFA1 */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.1", "pfc-r8a7740",
+ "scifa1_data", "scifa1"),
+ /* SDHI0 */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7740",
+ "sdhi0_data4", "sdhi0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7740",
+ "sdhi0_ctrl", "sdhi0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7740",
+ "sdhi0_wp", "sdhi0"),
+ /* ST1232 */
+ PIN_MAP_MUX_GROUP_DEFAULT("0-0055", "pfc-r8a7740",
+ "intc_irq10", "intc"),
+ /* TPU0 */
+ PIN_MAP_MUX_GROUP_DEFAULT("renesas-tpu-pwm", "pfc-r8a7740",
+ "tpu0_to2_1", "tpu0"),
+ /* USBHS */
+ PIN_MAP_MUX_GROUP_DEFAULT("renesas_usbhs", "pfc-r8a7740",
+ "intc_irq7_1", "intc"),
+};
+
+static void __init eva_clock_init(void)
+{
+ struct clk *system = clk_get(NULL, "system_clk");
+ struct clk *xtal1 = clk_get(NULL, "extal1");
+ struct clk *usb24s = clk_get(NULL, "usb24s");
+ struct clk *fsibck = clk_get(NULL, "fsibck");
+
+ if (IS_ERR(system) ||
+ IS_ERR(xtal1) ||
+ IS_ERR(usb24s) ||
+ IS_ERR(fsibck)) {
+ pr_err("armadillo800eva board clock init failed\n");
+ goto clock_error;
+ }
+
+ /* armadillo 800 eva extal1 is 24MHz */
+ clk_set_rate(xtal1, 24000000);
+
+ /* usb24s use extal1 (= system) clock (= 24MHz) */
+ clk_set_parent(usb24s, system);
+
+ /* FSIBCK is 12.288MHz, and it is parent of FSI-B */
+ clk_set_rate(fsibck, 12288000);
+
+clock_error:
+ if (!IS_ERR(system))
+ clk_put(system);
+ if (!IS_ERR(xtal1))
+ clk_put(xtal1);
+ if (!IS_ERR(usb24s))
+ clk_put(usb24s);
+ if (!IS_ERR(fsibck))
+ clk_put(fsibck);
+}
+
+/*
+ * board init
+ */
+#define GPIO_PORT7CR IOMEM(0xe6050007)
+#define GPIO_PORT8CR IOMEM(0xe6050008)
+static void __init eva_init(void)
+{
+ static struct pm_domain_device domain_devices[] __initdata = {
+ { "A4LC", &lcdc0_device },
+ { "A4LC", &hdmi_lcdc_device },
+ { "A4MP", &hdmi_device },
+ { "A4MP", &fsi_device },
+ { "A4R", &ceu0_device },
+ { "A4S", &sh_eth_device },
+ { "A3SP", &pwm_device },
+ { "A3SP", &sdhi0_device },
+ { "A3SP", &sh_mmcif_device },
+ };
+ struct platform_device *usb = NULL, *sdhi1 = NULL;
+
+ regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
+ ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
+ regulator_register_always_on(3, "fixed-5.0V", fixed5v0_power_consumers,
+ ARRAY_SIZE(fixed5v0_power_consumers), 5000000);
+
+ pinctrl_register_mappings(eva_pinctrl_map, ARRAY_SIZE(eva_pinctrl_map));
+ pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
+
+ r8a7740_pinmux_init();
+ r8a7740_meram_workaround();
+
+ /* GETHER */
+ gpio_request_one(18, GPIOF_OUT_INIT_HIGH, NULL); /* PHY_RST */
+
+ /* USB */
+ gpio_request_one(159, GPIOF_IN, NULL); /* USB_DEVICE_MODE */
+
+ if (gpio_get_value(159)) {
+ /* USB Host */
+ } else {
+ /* USB Func */
+ /*
+ * The USBHS interrupt handlers needs to read the IRQ pin value
+ * (HI/LOW) to diffentiate USB connection and disconnection
+ * events (usbhsf_get_vbus()). We thus need to select both the
+ * intc_irq7_1 pin group and GPIO 209 here.
+ */
+ gpio_request_one(209, GPIOF_IN, NULL);
+
+ platform_device_register(&usbhsf_device);
+ usb = &usbhsf_device;
+ }
+
+ /* CON1/CON15 Camera */
+ gpio_request_one(173, GPIOF_OUT_INIT_LOW, NULL); /* STANDBY */
+ gpio_request_one(172, GPIOF_OUT_INIT_HIGH, NULL); /* RST */
+ /* see mt9t111_power() */
+ gpio_request_one(158, GPIOF_OUT_INIT_LOW, NULL); /* CAM_PON */
+
+ /* FSI-WM8978 */
+ gpio_request(7, NULL);
+ gpio_request(8, NULL);
+ gpio_direction_none(GPIO_PORT7CR); /* FSIAOBT needs no direction */
+ gpio_direction_none(GPIO_PORT8CR); /* FSIAOLR needs no direction */
+
+ /*
+ * CAUTION
+ *
+ * DBGMD/LCDC0/FSIA MUX
+ * DBGMD_SELECT_B should be set after setting PFC Function.
+ */
+ gpio_request_one(176, GPIOF_OUT_INIT_HIGH, NULL);
+
+ /*
+ * We can switch CON8/CON14 by SW1.5,
+ * but it needs after DBGMD_SELECT_B
+ */
+ gpio_request_one(6, GPIOF_IN, NULL);
+ if (gpio_get_value(6)) {
+ /* CON14 enable */
+ } else {
+ /* CON8 (SDHI1) enable */
+ pinctrl_register_mappings(eva_sdhi1_pinctrl_map,
+ ARRAY_SIZE(eva_sdhi1_pinctrl_map));
+
+ platform_device_register(&vcc_sdhi1);
+ platform_device_register(&sdhi1_device);
+ sdhi1 = &sdhi1_device;
+ }
+
+
+#ifdef CONFIG_CACHE_L2X0
+ /* Shared attribute override enable, 32K*8way */
+ l2x0_init(IOMEM(0xf0002000), 0x00400000, 0xc20f0fff);
+#endif
+
+ i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices));
+ i2c_register_board_info(2, i2c2_devices, ARRAY_SIZE(i2c2_devices));
+
+ r8a7740_add_standard_devices();
+
+ platform_add_devices(eva_devices,
+ ARRAY_SIZE(eva_devices));
+
+ rmobile_add_devices_to_domains(domain_devices,
+ ARRAY_SIZE(domain_devices));
+ if (usb)
+ rmobile_add_device_to_domain("A3SP", usb);
+ if (sdhi1)
+ rmobile_add_device_to_domain("A3SP", sdhi1);
+
+ r8a7740_pm_init();
+}
+
+static void __init eva_earlytimer_init(void)
+{
+ r8a7740_clock_init(MD_CK0 | MD_CK2);
+ shmobile_earlytimer_init();
+
+ /* the rate of extal1 clock must be set before late_time_init */
+ eva_clock_init();
+}
+
+#define RESCNT2 IOMEM(0xe6188020)
+static void eva_restart(enum reboot_mode mode, const char *cmd)
+{
+ /* Do soft power on reset */
+ writel((1 << 31), RESCNT2);
+}
+
+static const char *eva_boards_compat_dt[] __initdata = {
+ "renesas,armadillo800eva",
+ NULL,
+};
+
+DT_MACHINE_START(ARMADILLO800EVA_DT, "armadillo800eva")
+ .map_io = r8a7740_map_io,
+ .init_early = r8a7740_add_early_devices,
+ .init_irq = r8a7740_init_irq_of,
+ .init_machine = eva_init,
+ .init_late = shmobile_init_late,
+ .init_time = eva_earlytimer_init,
+ .dt_compat = eva_boards_compat_dt,
+ .restart = eva_restart,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-bockw-reference.c b/arch/arm/mach-shmobile/board-bockw-reference.c
new file mode 100644
index 000000000..9a74efda3
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-bockw-reference.c
@@ -0,0 +1,86 @@
+/*
+ * Bock-W board support
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+
+#include "common.h"
+#include "r8a7778.h"
+
+/*
+ * see board-bock.c for checking detail of dip-switch
+ */
+
+#define FPGA 0x18200000
+#define IRQ0MR 0x30
+#define COMCTLR 0x101c
+
+#define PFC 0xfffc0000
+#define PUPR4 0x110
+static void __init bockw_init(void)
+{
+ void __iomem *fpga;
+ void __iomem *pfc;
+
+#ifndef CONFIG_COMMON_CLK
+ r8a7778_clock_init();
+#endif
+ r8a7778_init_irq_extpin_dt(1);
+ r8a7778_add_dt_devices();
+
+ fpga = ioremap_nocache(FPGA, SZ_1M);
+ if (fpga) {
+ /*
+ * CAUTION
+ *
+ * IRQ0/1 is cascaded interrupt from FPGA.
+ * it should be cared in the future
+ * Now, it is assuming IRQ0 was used only from SMSC.
+ */
+ u16 val = ioread16(fpga + IRQ0MR);
+ val &= ~(1 << 4); /* enable SMSC911x */
+ iowrite16(val, fpga + IRQ0MR);
+
+ iounmap(fpga);
+ }
+
+ pfc = ioremap_nocache(PFC, 0x200);
+ if (pfc) {
+ /*
+ * FIXME
+ *
+ * SDHI CD/WP pin needs pull-up
+ */
+ iowrite32(ioread32(pfc + PUPR4) | (3 << 26), pfc + PUPR4);
+ iounmap(pfc);
+ }
+
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *bockw_boards_compat_dt[] __initdata = {
+ "renesas,bockw-reference",
+ NULL,
+};
+
+DT_MACHINE_START(BOCKW_DT, "bockw")
+ .init_early = shmobile_init_delay,
+ .init_irq = r8a7778_init_irq_dt,
+ .init_machine = bockw_init,
+ .init_late = shmobile_init_late,
+ .dt_compat = bockw_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c
new file mode 100644
index 000000000..25558d1f4
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-bockw.c
@@ -0,0 +1,737 @@
+/*
+ * Bock-W board support
+ *
+ * Copyright (C) 2013-2014 Renesas Solutions Corp.
+ * Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ * Copyright (C) 2013-2014 Cogent Embedded, Inc.
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mfd/tmio.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
+#include <linux/mmc/sh_mmcif.h>
+#include <linux/mtd/partitions.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/platform_data/camera-rcar.h>
+#include <linux/platform_data/usb-rcar-phy.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
+#include <linux/smsc911x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/usb/renesas_usbhs.h>
+
+#include <media/soc_camera.h>
+#include <asm/mach/arch.h>
+#include <sound/rcar_snd.h>
+#include <sound/simple_card.h>
+
+#include "common.h"
+#include "irqs.h"
+#include "r8a7778.h"
+
+#define FPGA 0x18200000
+#define IRQ0MR 0x30
+#define COMCTLR 0x101c
+static void __iomem *fpga;
+
+/*
+ * CN9(Upper side) SCIF/RCAN selection
+ *
+ * 1,4 3,6
+ * SW40 SCIF RCAN
+ * SW41 SCIF RCAN
+ */
+
+/*
+ * MMC (CN26) pin
+ *
+ * SW6 (D2) 3 pin
+ * SW7 (D5) ON
+ * SW8 (D3) 3 pin
+ * SW10 (D4) 1 pin
+ * SW12 (CLK) 1 pin
+ * SW13 (D6) 3 pin
+ * SW14 (CMD) ON
+ * SW15 (D6) 1 pin
+ * SW16 (D0) ON
+ * SW17 (D1) ON
+ * SW18 (D7) 3 pin
+ * SW19 (MMC) 1 pin
+ */
+
+/*
+ * SSI settings
+ *
+ * SW45: 1-4 side (SSI5 out, ROUT/LOUT CN19 Mid)
+ * SW46: 1101 (SSI6 Recorde)
+ * SW47: 1110 (SSI5 Playback)
+ * SW48: 11 (Recorde power)
+ * SW49: 1 (SSI slave mode)
+ * SW50: 1111 (SSI7, SSI8)
+ * SW51: 1111 (SSI3, SSI4)
+ * SW54: 1pin (ak4554 FPGA control)
+ * SW55: 1 (CLKB is 24.5760MHz)
+ * SW60: 1pin (ak4554 FPGA control)
+ * SW61: 3pin (use X11 clock)
+ * SW78: 3-6 (ak4642 connects I2C0)
+ *
+ * You can use sound as
+ *
+ * hw0: CN19: SSI56-AK4643
+ * hw1: CN21: SSI3-AK4554(playback)
+ * hw2: CN21: SSI4-AK4554(capture)
+ * hw3: CN20: SSI7-AK4554(playback)
+ * hw4: CN20: SSI8-AK4554(capture)
+ *
+ * this command is required when playback on hw0.
+ *
+ * # amixer set "LINEOUT Mixer DACL" on
+ */
+
+/*
+ * USB
+ *
+ * USB1 (CN29) can be Host/Function
+ *
+ * Host Func
+ * SW98 1 2
+ * SW99 1 3
+ */
+
+/* Dummy supplies, where voltage doesn't matter */
+static struct regulator_consumer_supply dummy_supplies[] = {
+ REGULATOR_SUPPLY("vddvario", "smsc911x"),
+ REGULATOR_SUPPLY("vdd33a", "smsc911x"),
+};
+
+static struct regulator_consumer_supply fixed3v3_power_consumers[] = {
+ REGULATOR_SUPPLY("vmmc", "sh_mmcif"),
+ REGULATOR_SUPPLY("vqmmc", "sh_mmcif"),
+};
+
+static struct smsc911x_platform_config smsc911x_data __initdata = {
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+ .flags = SMSC911X_USE_32BIT,
+ .phy_interface = PHY_INTERFACE_MODE_MII,
+};
+
+static struct resource smsc911x_resources[] __initdata = {
+ DEFINE_RES_MEM(0x18300000, 0x1000),
+ DEFINE_RES_IRQ(irq_pin(0)), /* IRQ 0 */
+};
+
+#if IS_ENABLED(CONFIG_USB_RENESAS_USBHS_UDC)
+/*
+ * When USB1 is Func
+ */
+static int usbhsf_get_id(struct platform_device *pdev)
+{
+ return USBHS_GADGET;
+}
+
+#define SUSPMODE 0x102
+static int usbhsf_power_ctrl(struct platform_device *pdev,
+ void __iomem *base, int enable)
+{
+ enable = !!enable;
+
+ r8a7778_usb_phy_power(enable);
+
+ iowrite16(enable << 14, base + SUSPMODE);
+
+ return 0;
+}
+
+static struct resource usbhsf_resources[] __initdata = {
+ DEFINE_RES_MEM(0xffe60000, 0x110),
+ DEFINE_RES_IRQ(gic_iid(0x4f)),
+};
+
+static struct renesas_usbhs_platform_info usbhs_info __initdata = {
+ .platform_callback = {
+ .get_id = usbhsf_get_id,
+ .power_ctrl = usbhsf_power_ctrl,
+ },
+ .driver_param = {
+ .buswait_bwait = 4,
+ .d0_tx_id = HPBDMA_SLAVE_USBFUNC_TX,
+ .d1_rx_id = HPBDMA_SLAVE_USBFUNC_RX,
+ },
+};
+
+#define USB_PHY_SETTING {.port1_func = 1, .ovc_pin[1].active_high = 1,}
+#define USB1_DEVICE "renesas_usbhs"
+#define ADD_USB_FUNC_DEVICE_IF_POSSIBLE() \
+ platform_device_register_resndata( \
+ NULL, "renesas_usbhs", -1, \
+ usbhsf_resources, \
+ ARRAY_SIZE(usbhsf_resources), \
+ &usbhs_info, sizeof(struct renesas_usbhs_platform_info))
+
+#else
+/*
+ * When USB1 is Host
+ */
+#define USB_PHY_SETTING { }
+#define USB1_DEVICE "ehci-platform"
+#define ADD_USB_FUNC_DEVICE_IF_POSSIBLE()
+
+#endif
+
+/* USB */
+static struct resource usb_phy_resources[] __initdata = {
+ DEFINE_RES_MEM(0xffe70800, 0x100),
+ DEFINE_RES_MEM(0xffe76000, 0x100),
+};
+
+static struct rcar_phy_platform_data usb_phy_platform_data __initdata =
+ USB_PHY_SETTING;
+
+
+/* SDHI */
+static struct tmio_mmc_data sdhi0_info __initdata = {
+ .chan_priv_tx = (void *)HPBDMA_SLAVE_SDHI0_TX,
+ .chan_priv_rx = (void *)HPBDMA_SLAVE_SDHI0_RX,
+ .capabilities = MMC_CAP_SD_HIGHSPEED,
+ .ocr_mask = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
+ .flags = TMIO_MMC_HAS_IDLE_WAIT,
+};
+
+static struct resource sdhi0_resources[] __initdata = {
+ DEFINE_RES_MEM(0xFFE4C000, 0x100),
+ DEFINE_RES_IRQ(gic_iid(0x77)),
+};
+
+/* Ether */
+static struct resource ether_resources[] __initdata = {
+ DEFINE_RES_MEM(0xfde00000, 0x400),
+ DEFINE_RES_IRQ(gic_iid(0x89)),
+};
+
+static struct sh_eth_plat_data ether_platform_data __initdata = {
+ .phy = 0x01,
+ .edmac_endian = EDMAC_LITTLE_ENDIAN,
+ .phy_interface = PHY_INTERFACE_MODE_RMII,
+ /*
+ * Although the LINK signal is available on the board, it's connected to
+ * the link/activity LED output of the PHY, thus the link disappears and
+ * reappears after each packet. We'd be better off ignoring such signal
+ * and getting the link state from the PHY indirectly.
+ */
+ .no_ether_link = 1,
+};
+
+static struct platform_device_info ether_info __initdata = {
+ .name = "r8a777x-ether",
+ .id = -1,
+ .res = ether_resources,
+ .num_res = ARRAY_SIZE(ether_resources),
+ .data = &ether_platform_data,
+ .size_data = sizeof(ether_platform_data),
+ .dma_mask = DMA_BIT_MASK(32),
+};
+
+/* I2C */
+static struct i2c_board_info i2c0_devices[] = {
+ {
+ I2C_BOARD_INFO("rx8581", 0x51),
+ }, {
+ I2C_BOARD_INFO("ak4643", 0x12),
+ }
+};
+
+/* HSPI*/
+static struct mtd_partition m25p80_spi_flash_partitions[] = {
+ {
+ .name = "data(spi)",
+ .size = 0x0100000,
+ .offset = 0,
+ },
+};
+
+static struct flash_platform_data spi_flash_data = {
+ .name = "m25p80",
+ .type = "s25fl008k",
+ .parts = m25p80_spi_flash_partitions,
+ .nr_parts = ARRAY_SIZE(m25p80_spi_flash_partitions),
+};
+
+static struct spi_board_info spi_board_info[] __initdata = {
+ {
+ .modalias = "m25p80",
+ .max_speed_hz = 104000000,
+ .chip_select = 0,
+ .bus_num = 0,
+ .mode = SPI_MODE_0,
+ .platform_data = &spi_flash_data,
+ },
+};
+
+/* MMC */
+static struct resource mmc_resources[] __initdata = {
+ DEFINE_RES_MEM(0xffe4e000, 0x100),
+ DEFINE_RES_IRQ(gic_iid(0x5d)),
+};
+
+static struct sh_mmcif_plat_data sh_mmcif_plat __initdata = {
+ .sup_pclk = 0,
+ .caps = MMC_CAP_4_BIT_DATA |
+ MMC_CAP_8_BIT_DATA |
+ MMC_CAP_NEEDS_POLL,
+};
+
+/* In the default configuration both decoders reside on I2C bus 0 */
+#define BOCKW_CAMERA(idx) \
+static struct i2c_board_info camera##idx##_info = { \
+ I2C_BOARD_INFO("ml86v7667", 0x41 + 2 * (idx)), \
+}; \
+ \
+static struct soc_camera_link iclink##idx##_ml86v7667 __initdata = { \
+ .bus_id = idx, \
+ .i2c_adapter_id = 0, \
+ .board_info = &camera##idx##_info, \
+}
+
+BOCKW_CAMERA(0);
+BOCKW_CAMERA(1);
+
+/* VIN */
+static struct rcar_vin_platform_data vin_platform_data __initdata = {
+ .flags = RCAR_VIN_BT656,
+};
+
+#define R8A7778_VIN(idx) \
+static struct resource vin##idx##_resources[] __initdata = { \
+ DEFINE_RES_MEM(0xffc50000 + 0x1000 * (idx), 0x1000), \
+ DEFINE_RES_IRQ(gic_iid(0x5a)), \
+}; \
+ \
+static struct platform_device_info vin##idx##_info __initdata = { \
+ .name = "r8a7778-vin", \
+ .id = idx, \
+ .res = vin##idx##_resources, \
+ .num_res = ARRAY_SIZE(vin##idx##_resources), \
+ .dma_mask = DMA_BIT_MASK(32), \
+ .data = &vin_platform_data, \
+ .size_data = sizeof(vin_platform_data), \
+}
+R8A7778_VIN(0);
+R8A7778_VIN(1);
+
+/* Sound */
+static struct resource rsnd_resources[] __initdata = {
+ [RSND_GEN1_SRU] = DEFINE_RES_MEM(0xffd90000, 0x1000),
+ [RSND_GEN1_SSI] = DEFINE_RES_MEM(0xffd91000, 0x1240),
+ [RSND_GEN1_ADG] = DEFINE_RES_MEM(0xfffe0000, 0x24),
+};
+
+static struct rsnd_ssi_platform_info rsnd_ssi[] = {
+ RSND_SSI_UNUSED, /* SSI 0 */
+ RSND_SSI_UNUSED, /* SSI 1 */
+ RSND_SSI_UNUSED, /* SSI 2 */
+ RSND_SSI(HPBDMA_SLAVE_HPBIF3_TX, gic_iid(0x85), 0),
+ RSND_SSI(HPBDMA_SLAVE_HPBIF4_RX, gic_iid(0x85), RSND_SSI_CLK_PIN_SHARE),
+ RSND_SSI(HPBDMA_SLAVE_HPBIF5_TX, gic_iid(0x86), 0),
+ RSND_SSI(HPBDMA_SLAVE_HPBIF6_RX, gic_iid(0x86), 0),
+ RSND_SSI(HPBDMA_SLAVE_HPBIF7_TX, gic_iid(0x86), 0),
+ RSND_SSI(HPBDMA_SLAVE_HPBIF8_RX, gic_iid(0x86), RSND_SSI_CLK_PIN_SHARE),
+};
+
+static struct rsnd_src_platform_info rsnd_src[9] = {
+ RSND_SRC_UNUSED, /* SRU 0 */
+ RSND_SRC_UNUSED, /* SRU 1 */
+ RSND_SRC_UNUSED, /* SRU 2 */
+ RSND_SRC(0, 0),
+ RSND_SRC(0, 0),
+ RSND_SRC(0, 0),
+ RSND_SRC(0, 0),
+ RSND_SRC(0, 0),
+ RSND_SRC(0, 0),
+};
+
+static struct rsnd_dai_platform_info rsnd_dai[] = {
+ {
+ .playback = { .ssi = &rsnd_ssi[5], .src = &rsnd_src[5] },
+ .capture = { .ssi = &rsnd_ssi[6], .src = &rsnd_src[6] },
+ }, {
+ .playback = { .ssi = &rsnd_ssi[3], .src = &rsnd_src[3] },
+ }, {
+ .capture = { .ssi = &rsnd_ssi[4], .src = &rsnd_src[4] },
+ }, {
+ .playback = { .ssi = &rsnd_ssi[7], .src = &rsnd_src[7] },
+ }, {
+ .capture = { .ssi = &rsnd_ssi[8], .src = &rsnd_src[8] },
+ },
+};
+
+enum {
+ AK4554_34 = 0,
+ AK4643_56,
+ AK4554_78,
+ SOUND_MAX,
+};
+
+static int rsnd_codec_power(int id, int enable)
+{
+ static int sound_user[SOUND_MAX] = {0, 0, 0};
+ int *usr = NULL;
+ u32 bit;
+
+ switch (id) {
+ case 3:
+ case 4:
+ usr = sound_user + AK4554_34;
+ bit = (1 << 10);
+ break;
+ case 5:
+ case 6:
+ usr = sound_user + AK4643_56;
+ bit = (1 << 6);
+ break;
+ case 7:
+ case 8:
+ usr = sound_user + AK4554_78;
+ bit = (1 << 7);
+ break;
+ }
+
+ if (!usr)
+ return -EIO;
+
+ if (enable) {
+ if (*usr == 0) {
+ u32 val = ioread16(fpga + COMCTLR);
+ val &= ~bit;
+ iowrite16(val, fpga + COMCTLR);
+ }
+
+ (*usr)++;
+ } else {
+ if (*usr == 0)
+ return 0;
+
+ (*usr)--;
+
+ if (*usr == 0) {
+ u32 val = ioread16(fpga + COMCTLR);
+ val |= bit;
+ iowrite16(val, fpga + COMCTLR);
+ }
+ }
+
+ return 0;
+}
+
+static int rsnd_start(int id)
+{
+ return rsnd_codec_power(id, 1);
+}
+
+static int rsnd_stop(int id)
+{
+ return rsnd_codec_power(id, 0);
+}
+
+static struct rcar_snd_info rsnd_info = {
+ .flags = RSND_GEN1,
+ .ssi_info = rsnd_ssi,
+ .ssi_info_nr = ARRAY_SIZE(rsnd_ssi),
+ .src_info = rsnd_src,
+ .src_info_nr = ARRAY_SIZE(rsnd_src),
+ .dai_info = rsnd_dai,
+ .dai_info_nr = ARRAY_SIZE(rsnd_dai),
+ .start = rsnd_start,
+ .stop = rsnd_stop,
+};
+
+static struct asoc_simple_card_info rsnd_card_info[] = {
+ /* SSI5, SSI6 */
+ {
+ .name = "AK4643",
+ .card = "SSI56-AK4643",
+ .codec = "ak4642-codec.0-0012",
+ .platform = "rcar_sound",
+ .daifmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM,
+ .cpu_dai = {
+ .name = "rsnd-dai.0",
+ },
+ .codec_dai = {
+ .name = "ak4642-hifi",
+ .sysclk = 11289600,
+ },
+ },
+ /* SSI3 */
+ {
+ .name = "AK4554",
+ .card = "SSI3-AK4554(playback)",
+ .codec = "ak4554-adc-dac.0",
+ .platform = "rcar_sound",
+ .daifmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_RIGHT_J,
+ .cpu_dai = {
+ .name = "rsnd-dai.1",
+ },
+ .codec_dai = {
+ .name = "ak4554-hifi",
+ },
+ },
+ /* SSI4 */
+ {
+ .name = "AK4554",
+ .card = "SSI4-AK4554(capture)",
+ .codec = "ak4554-adc-dac.0",
+ .platform = "rcar_sound",
+ .daifmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_LEFT_J,
+ .cpu_dai = {
+ .name = "rsnd-dai.2",
+ },
+ .codec_dai = {
+ .name = "ak4554-hifi",
+ },
+ },
+ /* SSI7 */
+ {
+ .name = "AK4554",
+ .card = "SSI7-AK4554(playback)",
+ .codec = "ak4554-adc-dac.1",
+ .platform = "rcar_sound",
+ .daifmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_RIGHT_J,
+ .cpu_dai = {
+ .name = "rsnd-dai.3",
+ },
+ .codec_dai = {
+ .name = "ak4554-hifi",
+ },
+ },
+ /* SSI8 */
+ {
+ .name = "AK4554",
+ .card = "SSI8-AK4554(capture)",
+ .codec = "ak4554-adc-dac.1",
+ .platform = "rcar_sound",
+ .daifmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_LEFT_J,
+ .cpu_dai = {
+ .name = "rsnd-dai.4",
+ },
+ .codec_dai = {
+ .name = "ak4554-hifi",
+ },
+ }
+};
+
+static const struct pinctrl_map bockw_pinctrl_map[] = {
+ /* AUDIO */
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "audio_clk_a", "audio_clk"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "audio_clk_b", "audio_clk"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi34_ctrl", "ssi"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi3_data", "ssi"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi4_data", "ssi"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi5_ctrl", "ssi"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi5_data", "ssi"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi6_ctrl", "ssi"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi6_data", "ssi"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi78_ctrl", "ssi"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi7_data", "ssi"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi8_data", "ssi"),
+ /* Ether */
+ PIN_MAP_MUX_GROUP_DEFAULT("r8a777x-ether", "pfc-r8a7778",
+ "ether_rmii", "ether"),
+ /* HSPI0 */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh-hspi.0", "pfc-r8a7778",
+ "hspi0_a", "hspi0"),
+ /* MMC */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif", "pfc-r8a7778",
+ "mmc_data8", "mmc"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif", "pfc-r8a7778",
+ "mmc_ctrl", "mmc"),
+ /* SCIF0 */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.0", "pfc-r8a7778",
+ "scif0_data_a", "scif0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.0", "pfc-r8a7778",
+ "scif0_ctrl", "scif0"),
+ /* USB */
+ PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform", "pfc-r8a7778",
+ "usb0", "usb0"),
+ PIN_MAP_MUX_GROUP_DEFAULT(USB1_DEVICE, "pfc-r8a7778",
+ "usb1", "usb1"),
+ /* SDHI0 */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778",
+ "sdhi0_data4", "sdhi0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778",
+ "sdhi0_ctrl", "sdhi0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778",
+ "sdhi0_cd", "sdhi0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778",
+ "sdhi0_wp", "sdhi0"),
+ /* VIN0 */
+ PIN_MAP_MUX_GROUP_DEFAULT("r8a7778-vin.0", "pfc-r8a7778",
+ "vin0_clk", "vin0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("r8a7778-vin.0", "pfc-r8a7778",
+ "vin0_data8", "vin0"),
+ /* VIN1 */
+ PIN_MAP_MUX_GROUP_DEFAULT("r8a7778-vin.1", "pfc-r8a7778",
+ "vin1_clk", "vin1"),
+ PIN_MAP_MUX_GROUP_DEFAULT("r8a7778-vin.1", "pfc-r8a7778",
+ "vin1_data8", "vin1"),
+};
+
+#define PFC 0xfffc0000
+#define PUPR4 0x110
+static void __init bockw_init(void)
+{
+ void __iomem *base;
+ struct clk *clk;
+ struct platform_device *pdev;
+ int i;
+
+ r8a7778_clock_init();
+ r8a7778_init_irq_extpin(1);
+ r8a7778_add_standard_devices();
+
+ platform_device_register_full(&ether_info);
+
+ platform_device_register_full(&vin0_info);
+ /* VIN1 has a pin conflict with Ether */
+ if (!IS_ENABLED(CONFIG_SH_ETH))
+ platform_device_register_full(&vin1_info);
+ platform_device_register_data(NULL, "soc-camera-pdrv", 0,
+ &iclink0_ml86v7667,
+ sizeof(iclink0_ml86v7667));
+ platform_device_register_data(NULL, "soc-camera-pdrv", 1,
+ &iclink1_ml86v7667,
+ sizeof(iclink1_ml86v7667));
+
+ i2c_register_board_info(0, i2c0_devices,
+ ARRAY_SIZE(i2c0_devices));
+ spi_register_board_info(spi_board_info,
+ ARRAY_SIZE(spi_board_info));
+ pinctrl_register_mappings(bockw_pinctrl_map,
+ ARRAY_SIZE(bockw_pinctrl_map));
+ r8a7778_pinmux_init();
+
+ platform_device_register_resndata(
+ NULL, "sh_mmcif", -1,
+ mmc_resources, ARRAY_SIZE(mmc_resources),
+ &sh_mmcif_plat, sizeof(struct sh_mmcif_plat_data));
+
+ platform_device_register_resndata(
+ NULL, "rcar_usb_phy", -1,
+ usb_phy_resources,
+ ARRAY_SIZE(usb_phy_resources),
+ &usb_phy_platform_data,
+ sizeof(struct rcar_phy_platform_data));
+
+ regulator_register_fixed(0, dummy_supplies,
+ ARRAY_SIZE(dummy_supplies));
+ regulator_register_always_on(1, "fixed-3.3V", fixed3v3_power_consumers,
+ ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
+
+ /* for SMSC */
+ fpga = ioremap_nocache(FPGA, SZ_1M);
+ if (fpga) {
+ /*
+ * CAUTION
+ *
+ * IRQ0/1 is cascaded interrupt from FPGA.
+ * it should be cared in the future
+ * Now, it is assuming IRQ0 was used only from SMSC.
+ */
+ u16 val = ioread16(fpga + IRQ0MR);
+ val &= ~(1 << 4); /* enable SMSC911x */
+ iowrite16(val, fpga + IRQ0MR);
+
+ platform_device_register_resndata(
+ NULL, "smsc911x", -1,
+ smsc911x_resources, ARRAY_SIZE(smsc911x_resources),
+ &smsc911x_data, sizeof(smsc911x_data));
+ }
+
+ /* for SDHI */
+ base = ioremap_nocache(PFC, 0x200);
+ if (base) {
+ /*
+ * FIXME
+ *
+ * SDHI CD/WP pin needs pull-up
+ */
+ iowrite32(ioread32(base + PUPR4) | (3 << 26), base + PUPR4);
+ iounmap(base);
+
+ platform_device_register_resndata(
+ NULL, "sh_mobile_sdhi", 0,
+ sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
+ &sdhi0_info, sizeof(struct tmio_mmc_data));
+ }
+
+ /* for Audio */
+ rsnd_codec_power(5, 1); /* enable ak4642 */
+
+ platform_device_register_simple(
+ "ak4554-adc-dac", 0, NULL, 0);
+
+ platform_device_register_simple(
+ "ak4554-adc-dac", 1, NULL, 0);
+
+ pdev = platform_device_register_resndata(
+ NULL, "rcar_sound", -1,
+ rsnd_resources, ARRAY_SIZE(rsnd_resources),
+ &rsnd_info, sizeof(rsnd_info));
+
+ clk = clk_get(&pdev->dev, "clk_b");
+ clk_set_rate(clk, 24576000);
+ clk_put(clk);
+
+ for (i = 0; i < ARRAY_SIZE(rsnd_card_info); i++) {
+ struct platform_device_info cardinfo = {
+ .name = "asoc-simple-card",
+ .id = i,
+ .data = &rsnd_card_info[i],
+ .size_data = sizeof(struct asoc_simple_card_info),
+ .dma_mask = DMA_BIT_MASK(32),
+ };
+
+ platform_device_register_full(&cardinfo);
+ }
+}
+
+static void __init bockw_init_late(void)
+{
+ r8a7778_init_late();
+ ADD_USB_FUNC_DEVICE_IF_POSSIBLE();
+}
+
+static const char *bockw_boards_compat_dt[] __initdata = {
+ "renesas,bockw",
+ NULL,
+};
+
+DT_MACHINE_START(BOCKW_DT, "bockw")
+ .init_early = shmobile_init_delay,
+ .init_irq = r8a7778_init_irq_dt,
+ .init_machine = bockw_init,
+ .dt_compat = bockw_boards_compat_dt,
+ .init_late = bockw_init_late,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
new file mode 100644
index 000000000..260d8319f
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-kzm9g.c
@@ -0,0 +1,916 @@
+/*
+ * KZM-A9-GT board support
+ *
+ * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pcf857x.h>
+#include <linux/input.h>
+#include <linux/irqchip/arm-gic.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mmcif.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
+#include <linux/mfd/as3711.h>
+#include <linux/mfd/tmio.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
+#include <linux/smsc911x.h>
+#include <linux/usb/r8a66597.h>
+#include <linux/usb/renesas_usbhs.h>
+#include <linux/videodev2.h>
+
+#include <sound/sh_fsi.h>
+#include <sound/simple_card.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <video/sh_mobile_lcdc.h>
+
+#include "common.h"
+#include "intc.h"
+#include "irqs.h"
+#include "sh73a0.h"
+
+/*
+ * external GPIO
+ */
+#define GPIO_PCF8575_BASE (310)
+#define GPIO_PCF8575_PORT10 (GPIO_PCF8575_BASE + 8)
+#define GPIO_PCF8575_PORT11 (GPIO_PCF8575_BASE + 9)
+#define GPIO_PCF8575_PORT12 (GPIO_PCF8575_BASE + 10)
+#define GPIO_PCF8575_PORT13 (GPIO_PCF8575_BASE + 11)
+#define GPIO_PCF8575_PORT14 (GPIO_PCF8575_BASE + 12)
+#define GPIO_PCF8575_PORT15 (GPIO_PCF8575_BASE + 13)
+#define GPIO_PCF8575_PORT16 (GPIO_PCF8575_BASE + 14)
+
+/* Dummy supplies, where voltage doesn't matter */
+static struct regulator_consumer_supply dummy_supplies[] = {
+ REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
+ REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
+};
+
+/*
+ * FSI-AK4648
+ *
+ * this command is required when playback.
+ *
+ * # amixer set "LINEOUT Mixer DACL" on
+ */
+
+/* SMSC 9221 */
+static struct resource smsc9221_resources[] = {
+ [0] = {
+ .start = 0x10000000, /* CS4 */
+ .end = 0x100000ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = irq_pin(3), /* IRQ3 */
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct smsc911x_platform_config smsc9221_platdata = {
+ .flags = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS,
+ .phy_interface = PHY_INTERFACE_MODE_MII,
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+};
+
+static struct platform_device smsc_device = {
+ .name = "smsc911x",
+ .dev = {
+ .platform_data = &smsc9221_platdata,
+ },
+ .resource = smsc9221_resources,
+ .num_resources = ARRAY_SIZE(smsc9221_resources),
+};
+
+/* USB external chip */
+static struct r8a66597_platdata usb_host_data = {
+ .on_chip = 0,
+ .xtal = R8A66597_PLATDATA_XTAL_48MHZ,
+};
+
+static struct resource usb_resources[] = {
+ [0] = {
+ .start = 0x10010000,
+ .end = 0x1001ffff - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = irq_pin(1), /* IRQ1 */
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device usb_host_device = {
+ .name = "r8a66597_hcd",
+ .dev = {
+ .platform_data = &usb_host_data,
+ .dma_mask = NULL,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(usb_resources),
+ .resource = usb_resources,
+};
+
+/* USB Func CN17 */
+struct usbhs_private {
+ void __iomem *phy;
+ void __iomem *cr2;
+ struct renesas_usbhs_platform_info info;
+};
+
+#define IRQ15 irq_pin(15)
+#define USB_PHY_MODE (1 << 4)
+#define USB_PHY_INT_EN ((1 << 3) | (1 << 2))
+#define USB_PHY_ON (1 << 1)
+#define USB_PHY_OFF (1 << 0)
+#define USB_PHY_INT_CLR (USB_PHY_ON | USB_PHY_OFF)
+
+#define usbhs_get_priv(pdev) \
+ container_of(renesas_usbhs_get_info(pdev), struct usbhs_private, info)
+
+static int usbhs_get_vbus(struct platform_device *pdev)
+{
+ struct usbhs_private *priv = usbhs_get_priv(pdev);
+
+ return !((1 << 7) & __raw_readw(priv->cr2));
+}
+
+static int usbhs_phy_reset(struct platform_device *pdev)
+{
+ struct usbhs_private *priv = usbhs_get_priv(pdev);
+
+ /* init phy */
+ __raw_writew(0x8a0a, priv->cr2);
+
+ return 0;
+}
+
+static int usbhs_get_id(struct platform_device *pdev)
+{
+ return USBHS_GADGET;
+}
+
+static irqreturn_t usbhs_interrupt(int irq, void *data)
+{
+ struct platform_device *pdev = data;
+ struct usbhs_private *priv = usbhs_get_priv(pdev);
+
+ renesas_usbhs_call_notify_hotplug(pdev);
+
+ /* clear status */
+ __raw_writew(__raw_readw(priv->phy) | USB_PHY_INT_CLR, priv->phy);
+
+ return IRQ_HANDLED;
+}
+
+static int usbhs_hardware_init(struct platform_device *pdev)
+{
+ struct usbhs_private *priv = usbhs_get_priv(pdev);
+ int ret;
+
+ /* clear interrupt status */
+ __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->phy);
+
+ ret = request_irq(IRQ15, usbhs_interrupt, IRQF_TRIGGER_HIGH,
+ dev_name(&pdev->dev), pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "request_irq err\n");
+ return ret;
+ }
+
+ /* enable USB phy interrupt */
+ __raw_writew(USB_PHY_MODE | USB_PHY_INT_EN, priv->phy);
+
+ return 0;
+}
+
+static int usbhs_hardware_exit(struct platform_device *pdev)
+{
+ struct usbhs_private *priv = usbhs_get_priv(pdev);
+
+ /* clear interrupt status */
+ __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->phy);
+
+ free_irq(IRQ15, pdev);
+
+ return 0;
+}
+
+static u32 usbhs_pipe_cfg[] = {
+ USB_ENDPOINT_XFER_CONTROL,
+ USB_ENDPOINT_XFER_ISOC,
+ USB_ENDPOINT_XFER_ISOC,
+ USB_ENDPOINT_XFER_BULK,
+ USB_ENDPOINT_XFER_BULK,
+ USB_ENDPOINT_XFER_BULK,
+ USB_ENDPOINT_XFER_INT,
+ USB_ENDPOINT_XFER_INT,
+ USB_ENDPOINT_XFER_INT,
+ USB_ENDPOINT_XFER_BULK,
+ USB_ENDPOINT_XFER_BULK,
+ USB_ENDPOINT_XFER_BULK,
+ USB_ENDPOINT_XFER_BULK,
+ USB_ENDPOINT_XFER_BULK,
+ USB_ENDPOINT_XFER_BULK,
+ USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usbhs_private usbhs_private = {
+ .phy = IOMEM(0xe60781e0), /* USBPHYINT */
+ .cr2 = IOMEM(0xe605810c), /* USBCR2 */
+ .info = {
+ .platform_callback = {
+ .hardware_init = usbhs_hardware_init,
+ .hardware_exit = usbhs_hardware_exit,
+ .get_id = usbhs_get_id,
+ .phy_reset = usbhs_phy_reset,
+ .get_vbus = usbhs_get_vbus,
+ },
+ .driver_param = {
+ .buswait_bwait = 4,
+ .has_otg = 1,
+ .pipe_type = usbhs_pipe_cfg,
+ .pipe_size = ARRAY_SIZE(usbhs_pipe_cfg),
+ },
+ },
+};
+
+static struct resource usbhs_resources[] = {
+ [0] = {
+ .start = 0xE6890000,
+ .end = 0xE68900e6 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(62),
+ .end = gic_spi(62),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device usbhs_device = {
+ .name = "renesas_usbhs",
+ .id = -1,
+ .dev = {
+ .dma_mask = NULL,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &usbhs_private.info,
+ },
+ .num_resources = ARRAY_SIZE(usbhs_resources),
+ .resource = usbhs_resources,
+};
+
+/* LCDC */
+static struct fb_videomode kzm_lcdc_mode = {
+ .name = "WVGA Panel",
+ .xres = 800,
+ .yres = 480,
+ .left_margin = 220,
+ .right_margin = 110,
+ .hsync_len = 70,
+ .upper_margin = 20,
+ .lower_margin = 5,
+ .vsync_len = 5,
+ .sync = 0,
+};
+
+static struct sh_mobile_lcdc_info lcdc_info = {
+ .clock_source = LCDC_CLK_BUS,
+ .ch[0] = {
+ .chan = LCDC_CHAN_MAINLCD,
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .interface_type = RGB24,
+ .lcd_modes = &kzm_lcdc_mode,
+ .num_modes = 1,
+ .clock_divider = 5,
+ .flags = 0,
+ .panel_cfg = {
+ .width = 152,
+ .height = 91,
+ },
+ }
+};
+
+static struct resource lcdc_resources[] = {
+ [0] = {
+ .name = "LCDC",
+ .start = 0xfe940000,
+ .end = 0xfe943fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = intcs_evt2irq(0x580),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device lcdc_device = {
+ .name = "sh_mobile_lcdc_fb",
+ .num_resources = ARRAY_SIZE(lcdc_resources),
+ .resource = lcdc_resources,
+ .dev = {
+ .platform_data = &lcdc_info,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+/* Fixed 1.8V regulator to be used by MMCIF */
+static struct regulator_consumer_supply fixed1v8_power_consumers[] =
+{
+ REGULATOR_SUPPLY("vmmc", "sh_mmcif.0"),
+ REGULATOR_SUPPLY("vqmmc", "sh_mmcif.0"),
+};
+
+/* MMCIF */
+static struct resource sh_mmcif_resources[] = {
+ [0] = {
+ .name = "MMCIF",
+ .start = 0xe6bd0000,
+ .end = 0xe6bd00ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(140),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = gic_spi(141),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct sh_mmcif_plat_data sh_mmcif_platdata = {
+ .ocr = MMC_VDD_165_195,
+ .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
+ .ccs_unsupported = true,
+ .slave_id_tx = SHDMA_SLAVE_MMCIF_TX,
+ .slave_id_rx = SHDMA_SLAVE_MMCIF_RX,
+};
+
+static struct platform_device mmc_device = {
+ .name = "sh_mmcif",
+ .dev = {
+ .dma_mask = NULL,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &sh_mmcif_platdata,
+ },
+ .num_resources = ARRAY_SIZE(sh_mmcif_resources),
+ .resource = sh_mmcif_resources,
+};
+
+/* Fixed 3.3V regulators to be used by SDHI0 */
+static struct regulator_consumer_supply vcc_sdhi0_consumers[] =
+{
+ REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
+};
+
+static struct regulator_init_data vcc_sdhi0_init_data = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vcc_sdhi0_consumers),
+ .consumer_supplies = vcc_sdhi0_consumers,
+};
+
+static struct fixed_voltage_config vcc_sdhi0_info = {
+ .supply_name = "SDHI0 Vcc",
+ .microvolts = 3300000,
+ .gpio = 15,
+ .enable_high = 1,
+ .init_data = &vcc_sdhi0_init_data,
+};
+
+static struct platform_device vcc_sdhi0 = {
+ .name = "reg-fixed-voltage",
+ .id = 0,
+ .dev = {
+ .platform_data = &vcc_sdhi0_info,
+ },
+};
+
+/* Fixed 3.3V regulators to be used by SDHI2 */
+static struct regulator_consumer_supply vcc_sdhi2_consumers[] =
+{
+ REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.2"),
+};
+
+static struct regulator_init_data vcc_sdhi2_init_data = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vcc_sdhi2_consumers),
+ .consumer_supplies = vcc_sdhi2_consumers,
+};
+
+static struct fixed_voltage_config vcc_sdhi2_info = {
+ .supply_name = "SDHI2 Vcc",
+ .microvolts = 3300000,
+ .gpio = 14,
+ .enable_high = 1,
+ .init_data = &vcc_sdhi2_init_data,
+};
+
+static struct platform_device vcc_sdhi2 = {
+ .name = "reg-fixed-voltage",
+ .id = 1,
+ .dev = {
+ .platform_data = &vcc_sdhi2_info,
+ },
+};
+
+/* SDHI */
+static struct tmio_mmc_data sdhi0_info = {
+ .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI0_TX,
+ .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI0_RX,
+ .flags = TMIO_MMC_HAS_IDLE_WAIT,
+ .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+ MMC_CAP_POWER_OFF_CARD,
+};
+
+static struct resource sdhi0_resources[] = {
+ [0] = {
+ .name = "SDHI0",
+ .start = 0xee100000,
+ .end = 0xee1000ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT,
+ .start = gic_spi(83),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .name = SH_MOBILE_SDHI_IRQ_SDCARD,
+ .start = gic_spi(84),
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .name = SH_MOBILE_SDHI_IRQ_SDIO,
+ .start = gic_spi(85),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sdhi0_device = {
+ .name = "sh_mobile_sdhi",
+ .num_resources = ARRAY_SIZE(sdhi0_resources),
+ .resource = sdhi0_resources,
+ .dev = {
+ .platform_data = &sdhi0_info,
+ },
+};
+
+/* Micro SD */
+static struct tmio_mmc_data sdhi2_info = {
+ .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI2_TX,
+ .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI2_RX,
+ .flags = TMIO_MMC_HAS_IDLE_WAIT |
+ TMIO_MMC_USE_GPIO_CD |
+ TMIO_MMC_WRPROTECT_DISABLE,
+ .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_POWER_OFF_CARD,
+ .cd_gpio = 13,
+};
+
+static struct resource sdhi2_resources[] = {
+ [0] = {
+ .name = "SDHI2",
+ .start = 0xee140000,
+ .end = 0xee1400ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT,
+ .start = gic_spi(103),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .name = SH_MOBILE_SDHI_IRQ_SDCARD,
+ .start = gic_spi(104),
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .name = SH_MOBILE_SDHI_IRQ_SDIO,
+ .start = gic_spi(105),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sdhi2_device = {
+ .name = "sh_mobile_sdhi",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(sdhi2_resources),
+ .resource = sdhi2_resources,
+ .dev = {
+ .platform_data = &sdhi2_info,
+ },
+};
+
+/* KEY */
+#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
+
+static struct gpio_keys_button gpio_buttons[] = {
+ GPIO_KEY(KEY_BACK, GPIO_PCF8575_PORT10, "SW3"),
+ GPIO_KEY(KEY_RIGHT, GPIO_PCF8575_PORT11, "SW2-R"),
+ GPIO_KEY(KEY_LEFT, GPIO_PCF8575_PORT12, "SW2-L"),
+ GPIO_KEY(KEY_ENTER, GPIO_PCF8575_PORT13, "SW2-P"),
+ GPIO_KEY(KEY_UP, GPIO_PCF8575_PORT14, "SW2-U"),
+ GPIO_KEY(KEY_DOWN, GPIO_PCF8575_PORT15, "SW2-D"),
+ GPIO_KEY(KEY_HOME, GPIO_PCF8575_PORT16, "SW1"),
+};
+
+static struct gpio_keys_platform_data gpio_key_info = {
+ .buttons = gpio_buttons,
+ .nbuttons = ARRAY_SIZE(gpio_buttons),
+};
+
+static struct platform_device gpio_keys_device = {
+ .name = "gpio-keys",
+ .dev = {
+ .platform_data = &gpio_key_info,
+ },
+};
+
+/* FSI-AK4648 */
+static struct sh_fsi_platform_info fsi_info = {
+ .port_a = {
+ .tx_id = SHDMA_SLAVE_FSI2A_TX,
+ },
+};
+
+static struct resource fsi_resources[] = {
+ [0] = {
+ .name = "FSI",
+ .start = 0xEC230000,
+ .end = 0xEC230400 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(146),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device fsi_device = {
+ .name = "sh_fsi2",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(fsi_resources),
+ .resource = fsi_resources,
+ .dev = {
+ .platform_data = &fsi_info,
+ },
+};
+
+static struct asoc_simple_card_info fsi2_ak4648_info = {
+ .name = "AK4648",
+ .card = "FSI2A-AK4648",
+ .codec = "ak4642-codec.0-0012",
+ .platform = "sh_fsi2",
+ .daifmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM,
+ .cpu_dai = {
+ .name = "fsia-dai",
+ },
+ .codec_dai = {
+ .name = "ak4642-hifi",
+ .sysclk = 11289600,
+ },
+};
+
+static struct platform_device fsi_ak4648_device = {
+ .name = "asoc-simple-card",
+ .dev = {
+ .platform_data = &fsi2_ak4648_info,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .dma_mask = &fsi_ak4648_device.dev.coherent_dma_mask,
+ },
+};
+
+/* I2C */
+
+/* StepDown1 is used to supply 1.315V to the CPU */
+static struct regulator_init_data as3711_sd1 = {
+ .constraints = {
+ .name = "1.315V CPU",
+ .boot_on = 1,
+ .always_on = 1,
+ .min_uV = 1315000,
+ .max_uV = 1335000,
+ },
+};
+
+/* StepDown2 is used to supply 1.8V to the CPU and to the board */
+static struct regulator_init_data as3711_sd2 = {
+ .constraints = {
+ .name = "1.8V",
+ .boot_on = 1,
+ .always_on = 1,
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ },
+};
+
+/*
+ * StepDown3 is switched in parallel with StepDown2, seems to be off,
+ * according to read-back pre-set register values
+ */
+
+/* StepDown4 is used to supply 1.215V to the CPU and to the board */
+static struct regulator_init_data as3711_sd4 = {
+ .constraints = {
+ .name = "1.215V",
+ .boot_on = 1,
+ .always_on = 1,
+ .min_uV = 1215000,
+ .max_uV = 1235000,
+ },
+};
+
+/* LDO1 is unused and unconnected */
+
+/* LDO2 is used to supply 2.8V to the CPU */
+static struct regulator_init_data as3711_ldo2 = {
+ .constraints = {
+ .name = "2.8V CPU",
+ .boot_on = 1,
+ .always_on = 1,
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ },
+};
+
+/* LDO3 is used to supply 3.0V to the CPU */
+static struct regulator_init_data as3711_ldo3 = {
+ .constraints = {
+ .name = "3.0V CPU",
+ .boot_on = 1,
+ .always_on = 1,
+ .min_uV = 3000000,
+ .max_uV = 3000000,
+ },
+};
+
+/* LDO4 is used to supply 2.8V to the board */
+static struct regulator_init_data as3711_ldo4 = {
+ .constraints = {
+ .name = "2.8V",
+ .boot_on = 1,
+ .always_on = 1,
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ },
+};
+
+/* LDO5 is switched parallel to LDO4, also set to 2.8V */
+static struct regulator_init_data as3711_ldo5 = {
+ .constraints = {
+ .name = "2.8V #2",
+ .boot_on = 1,
+ .always_on = 1,
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ },
+};
+
+/* LDO6 is unused and unconnected */
+
+/* LDO7 is used to supply 1.15V to the CPU */
+static struct regulator_init_data as3711_ldo7 = {
+ .constraints = {
+ .name = "1.15V CPU",
+ .boot_on = 1,
+ .always_on = 1,
+ .min_uV = 1150000,
+ .max_uV = 1150000,
+ },
+};
+
+/* LDO8 is switched parallel to LDO7, also set to 1.15V */
+static struct regulator_init_data as3711_ldo8 = {
+ .constraints = {
+ .name = "1.15V CPU #2",
+ .boot_on = 1,
+ .always_on = 1,
+ .min_uV = 1150000,
+ .max_uV = 1150000,
+ },
+};
+
+static struct as3711_platform_data as3711_pdata = {
+ .regulator = {
+ .init_data = {
+ [AS3711_REGULATOR_SD_1] = &as3711_sd1,
+ [AS3711_REGULATOR_SD_2] = &as3711_sd2,
+ [AS3711_REGULATOR_SD_4] = &as3711_sd4,
+ [AS3711_REGULATOR_LDO_2] = &as3711_ldo2,
+ [AS3711_REGULATOR_LDO_3] = &as3711_ldo3,
+ [AS3711_REGULATOR_LDO_4] = &as3711_ldo4,
+ [AS3711_REGULATOR_LDO_5] = &as3711_ldo5,
+ [AS3711_REGULATOR_LDO_7] = &as3711_ldo7,
+ [AS3711_REGULATOR_LDO_8] = &as3711_ldo8,
+ },
+ },
+ .backlight = {
+ .su2_fb = "sh_mobile_lcdc_fb.0",
+ .su2_max_uA = 36000,
+ .su2_feedback = AS3711_SU2_CURR_AUTO,
+ .su2_fbprot = AS3711_SU2_GPIO4,
+ .su2_auto_curr1 = true,
+ .su2_auto_curr2 = true,
+ .su2_auto_curr3 = true,
+ },
+};
+
+static struct pcf857x_platform_data pcf8575_pdata = {
+ .gpio_base = GPIO_PCF8575_BASE,
+};
+
+static struct i2c_board_info i2c0_devices[] = {
+ {
+ I2C_BOARD_INFO("ak4648", 0x12),
+ },
+ {
+ I2C_BOARD_INFO("r2025sd", 0x32),
+ },
+ {
+ I2C_BOARD_INFO("ak8975", 0x0c),
+ .irq = irq_pin(28), /* IRQ28 */
+ },
+ {
+ I2C_BOARD_INFO("adxl34x", 0x1d),
+ .irq = irq_pin(26), /* IRQ26 */
+ },
+ {
+ I2C_BOARD_INFO("as3711", 0x40),
+ .irq = intcs_evt2irq(0x3300), /* IRQ24 */
+ .platform_data = &as3711_pdata,
+ },
+};
+
+static struct i2c_board_info i2c1_devices[] = {
+ {
+ I2C_BOARD_INFO("st1232-ts", 0x55),
+ .irq = irq_pin(8), /* IRQ8 */
+ },
+};
+
+static struct i2c_board_info i2c3_devices[] = {
+ {
+ I2C_BOARD_INFO("pcf8575", 0x20),
+ .irq = irq_pin(19), /* IRQ19 */
+ .platform_data = &pcf8575_pdata,
+ },
+};
+
+static struct platform_device *kzm_devices[] __initdata = {
+ &smsc_device,
+ &usb_host_device,
+ &usbhs_device,
+ &lcdc_device,
+ &mmc_device,
+ &vcc_sdhi0,
+ &vcc_sdhi2,
+ &sdhi0_device,
+ &sdhi2_device,
+ &gpio_keys_device,
+ &fsi_device,
+ &fsi_ak4648_device,
+};
+
+static unsigned long pin_pullup_conf[] = {
+ PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_UP, 0),
+};
+
+static const struct pinctrl_map kzm_pinctrl_map[] = {
+ /* FSIA (AK4648) */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2", "pfc-sh73a0",
+ "fsia_mclk_in", "fsia"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2", "pfc-sh73a0",
+ "fsia_sclk_in", "fsia"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2", "pfc-sh73a0",
+ "fsia_data_in", "fsia"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_fsi2", "pfc-sh73a0",
+ "fsia_data_out", "fsia"),
+ /* I2C3 */
+ PIN_MAP_MUX_GROUP_DEFAULT("i2c-sh_mobile.3", "pfc-sh73a0",
+ "i2c3_1", "i2c3"),
+ /* LCD */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-sh73a0",
+ "lcd_data24", "lcd"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-sh73a0",
+ "lcd_sync", "lcd"),
+ /* MMCIF */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
+ "mmc0_data8_0", "mmc0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
+ "mmc0_ctrl_0", "mmc0"),
+ PIN_MAP_CONFIGS_PIN_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
+ "PORT279", pin_pullup_conf),
+ PIN_MAP_CONFIGS_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh73a0",
+ "mmc0_data8_0", pin_pullup_conf),
+ /* SCIFA4 */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-sh73a0",
+ "scifa4_data", "scifa4"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-sh73a0",
+ "scifa4_ctrl", "scifa4"),
+ /* SDHI0 */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
+ "sdhi0_data4", "sdhi0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
+ "sdhi0_ctrl", "sdhi0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
+ "sdhi0_cd", "sdhi0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh73a0",
+ "sdhi0_wp", "sdhi0"),
+ /* SDHI2 */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-sh73a0",
+ "sdhi2_data4", "sdhi2"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-sh73a0",
+ "sdhi2_ctrl", "sdhi2"),
+ /* SMSC */
+ PIN_MAP_MUX_GROUP_DEFAULT("smsc911x.0", "pfc-sh73a0",
+ "bsc_cs4", "bsc"),
+ /* USB */
+ PIN_MAP_MUX_GROUP_DEFAULT("renesas_usbhs", "pfc-sh73a0",
+ "usb_vbus", "usb"),
+};
+
+static void __init kzm_init(void)
+{
+ regulator_register_always_on(2, "fixed-1.8V", fixed1v8_power_consumers,
+ ARRAY_SIZE(fixed1v8_power_consumers), 1800000);
+ regulator_register_fixed(3, dummy_supplies, ARRAY_SIZE(dummy_supplies));
+
+ pinctrl_register_mappings(kzm_pinctrl_map, ARRAY_SIZE(kzm_pinctrl_map));
+
+ sh73a0_pinmux_init();
+
+ /* SMSC */
+ gpio_request_one(224, GPIOF_IN, NULL); /* IRQ3 */
+
+ /* LCDC */
+ gpio_request_one(222, GPIOF_OUT_INIT_HIGH, NULL); /* LCDCDON */
+ gpio_request_one(226, GPIOF_OUT_INIT_HIGH, NULL); /* SC */
+
+ /* Touchscreen */
+ gpio_request_one(223, GPIOF_IN, NULL); /* IRQ8 */
+
+#ifdef CONFIG_CACHE_L2X0
+ /* Shared attribute override enable, 64K*8way */
+ l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff);
+#endif
+
+ i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices));
+ i2c_register_board_info(1, i2c1_devices, ARRAY_SIZE(i2c1_devices));
+ i2c_register_board_info(3, i2c3_devices, ARRAY_SIZE(i2c3_devices));
+
+ sh73a0_add_standard_devices();
+ platform_add_devices(kzm_devices, ARRAY_SIZE(kzm_devices));
+
+ sh73a0_pm_init();
+}
+
+static void kzm9g_restart(enum reboot_mode mode, const char *cmd)
+{
+#define RESCNT2 IOMEM(0xe6188020)
+ /* Do soft power on reset */
+ writel((1 << 31), RESCNT2);
+}
+
+static const char *kzm9g_boards_compat_dt[] __initdata = {
+ "renesas,kzm9g",
+ NULL,
+};
+
+DT_MACHINE_START(KZM9G_DT, "kzm9g")
+ .smp = smp_ops(sh73a0_smp_ops),
+ .map_io = sh73a0_map_io,
+ .init_early = sh73a0_add_early_devices,
+ .init_irq = sh73a0_init_irq,
+ .init_machine = kzm_init,
+ .init_late = shmobile_init_late,
+ .init_time = sh73a0_earlytimer_init,
+ .restart = kzm9g_restart,
+ .dt_compat = kzm9g_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-marzen-reference.c b/arch/arm/mach-shmobile/board-marzen-reference.c
new file mode 100644
index 000000000..b15eb9232
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-marzen-reference.c
@@ -0,0 +1,56 @@
+/*
+ * marzen board support - Reference DT implementation
+ *
+ * Copyright (C) 2011 Renesas Solutions Corp.
+ * Copyright (C) 2011 Magnus Damm
+ * Copyright (C) 2013 Simon Horman
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk/shmobile.h>
+#include <linux/clocksource.h>
+#include <linux/of_platform.h>
+
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+
+#include "common.h"
+#include "irqs.h"
+#include "r8a7779.h"
+
+static void __init marzen_init_timer(void)
+{
+ r8a7779_clocks_init(r8a7779_read_mode_pins());
+ clocksource_of_init();
+}
+
+static void __init marzen_init(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+ r8a7779_init_irq_extpin_dt(1); /* IRQ1 as individual interrupt */
+}
+
+static const char *marzen_boards_compat_dt[] __initdata = {
+ "renesas,marzen",
+ "renesas,marzen-reference",
+ NULL,
+};
+
+DT_MACHINE_START(MARZEN, "marzen")
+ .smp = smp_ops(r8a7779_smp_ops),
+ .map_io = r8a7779_map_io,
+ .init_early = shmobile_init_delay,
+ .init_time = marzen_init_timer,
+ .init_irq = r8a7779_init_irq_dt,
+ .init_machine = marzen_init,
+ .init_late = shmobile_init_late,
+ .dt_compat = marzen_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
new file mode 100644
index 000000000..51db288f1
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-marzen.c
@@ -0,0 +1,347 @@
+/*
+ * marzen board support
+ *
+ * Copyright (C) 2011, 2013 Renesas Solutions Corp.
+ * Copyright (C) 2011 Magnus Damm
+ * Copyright (C) 2013 Cogent Embedded, Inc.
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/leds.h>
+#include <linux/dma-mapping.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/platform_data/camera-rcar.h>
+#include <linux/platform_data/gpio-rcar.h>
+#include <linux/platform_data/usb-rcar-phy.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
+#include <linux/smsc911x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/sh_hspi.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
+#include <linux/mfd/tmio.h>
+
+#include <media/soc_camera.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/traps.h>
+
+#include "common.h"
+#include "irqs.h"
+#include "r8a7779.h"
+
+/* Fixed 3.3V regulator to be used by SDHI0 */
+static struct regulator_consumer_supply fixed3v3_power_consumers[] = {
+ REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
+ REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"),
+};
+
+/* Dummy supplies, where voltage doesn't matter */
+static struct regulator_consumer_supply dummy_supplies[] = {
+ REGULATOR_SUPPLY("vddvario", "smsc911x"),
+ REGULATOR_SUPPLY("vdd33a", "smsc911x"),
+};
+
+/* USB PHY */
+static struct resource usb_phy_resources[] = {
+ [0] = {
+ .start = 0xffe70800,
+ .end = 0xffe70900 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct rcar_phy_platform_data usb_phy_platform_data;
+
+static struct platform_device usb_phy = {
+ .name = "rcar_usb_phy",
+ .id = -1,
+ .dev = {
+ .platform_data = &usb_phy_platform_data,
+ },
+ .resource = usb_phy_resources,
+ .num_resources = ARRAY_SIZE(usb_phy_resources),
+};
+
+/* SMSC LAN89218 */
+static struct resource smsc911x_resources[] = {
+ [0] = {
+ .start = 0x18000000, /* ExCS0 */
+ .end = 0x180000ff, /* A1->A7 */
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = irq_pin(1), /* IRQ 1 */
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct smsc911x_platform_config smsc911x_platdata = {
+ .flags = SMSC911X_USE_32BIT, /* 32-bit SW on 16-bit HW bus */
+ .phy_interface = PHY_INTERFACE_MODE_MII,
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+};
+
+static struct platform_device eth_device = {
+ .name = "smsc911x",
+ .id = -1,
+ .dev = {
+ .platform_data = &smsc911x_platdata,
+ },
+ .resource = smsc911x_resources,
+ .num_resources = ARRAY_SIZE(smsc911x_resources),
+};
+
+static struct resource sdhi0_resources[] = {
+ [0] = {
+ .name = "sdhi0",
+ .start = 0xffe4c000,
+ .end = 0xffe4c0ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_iid(0x88),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct tmio_mmc_data sdhi0_platform_data = {
+ .chan_priv_tx = (void *)HPBDMA_SLAVE_SDHI0_TX,
+ .chan_priv_rx = (void *)HPBDMA_SLAVE_SDHI0_RX,
+ .flags = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
+ .capabilities = MMC_CAP_SD_HIGHSPEED,
+};
+
+static struct platform_device sdhi0_device = {
+ .name = "sh_mobile_sdhi",
+ .num_resources = ARRAY_SIZE(sdhi0_resources),
+ .resource = sdhi0_resources,
+ .id = 0,
+ .dev = {
+ .platform_data = &sdhi0_platform_data,
+ }
+};
+
+/* Thermal */
+static struct resource thermal_resources[] = {
+ [0] = {
+ .start = 0xFFC48000,
+ .end = 0xFFC48038 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device thermal_device = {
+ .name = "rcar_thermal",
+ .resource = thermal_resources,
+ .num_resources = ARRAY_SIZE(thermal_resources),
+};
+
+/* HSPI */
+static struct resource hspi_resources[] = {
+ [0] = {
+ .start = 0xFFFC7000,
+ .end = 0xFFFC7018 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device hspi_device = {
+ .name = "sh-hspi",
+ .id = 0,
+ .resource = hspi_resources,
+ .num_resources = ARRAY_SIZE(hspi_resources),
+};
+
+/* LEDS */
+static struct gpio_led marzen_leds[] = {
+ {
+ .name = "led2",
+ .gpio = RCAR_GP_PIN(4, 29),
+ .default_state = LEDS_GPIO_DEFSTATE_ON,
+ }, {
+ .name = "led3",
+ .gpio = RCAR_GP_PIN(4, 30),
+ .default_state = LEDS_GPIO_DEFSTATE_ON,
+ }, {
+ .name = "led4",
+ .gpio = RCAR_GP_PIN(4, 31),
+ .default_state = LEDS_GPIO_DEFSTATE_ON,
+ },
+};
+
+static struct gpio_led_platform_data marzen_leds_pdata = {
+ .leds = marzen_leds,
+ .num_leds = ARRAY_SIZE(marzen_leds),
+};
+
+static struct platform_device leds_device = {
+ .name = "leds-gpio",
+ .id = 0,
+ .dev = {
+ .platform_data = &marzen_leds_pdata,
+ },
+};
+
+/* VIN */
+static struct rcar_vin_platform_data vin_platform_data __initdata = {
+ .flags = RCAR_VIN_BT656,
+};
+
+#define MARZEN_VIN(idx) \
+static struct resource vin##idx##_resources[] __initdata = { \
+ DEFINE_RES_MEM(0xffc50000 + 0x1000 * (idx), 0x1000), \
+ DEFINE_RES_IRQ(gic_iid(0x5f + (idx))), \
+}; \
+ \
+static struct platform_device_info vin##idx##_info __initdata = { \
+ .name = "r8a7779-vin", \
+ .id = idx, \
+ .res = vin##idx##_resources, \
+ .num_res = ARRAY_SIZE(vin##idx##_resources), \
+ .dma_mask = DMA_BIT_MASK(32), \
+ .data = &vin_platform_data, \
+ .size_data = sizeof(vin_platform_data), \
+}
+MARZEN_VIN(1);
+MARZEN_VIN(3);
+
+#define MARZEN_CAMERA(idx) \
+static struct i2c_board_info camera##idx##_info = { \
+ I2C_BOARD_INFO("adv7180", 0x20 + (idx)), \
+}; \
+ \
+static struct soc_camera_link iclink##idx##_adv7180 = { \
+ .bus_id = 1 + 2 * (idx), \
+ .i2c_adapter_id = 0, \
+ .board_info = &camera##idx##_info, \
+}; \
+ \
+static struct platform_device camera##idx##_device = { \
+ .name = "soc-camera-pdrv", \
+ .id = idx, \
+ .dev = { \
+ .platform_data = &iclink##idx##_adv7180, \
+ }, \
+};
+
+MARZEN_CAMERA(0);
+MARZEN_CAMERA(1);
+
+static struct platform_device *marzen_devices[] __initdata = {
+ &eth_device,
+ &sdhi0_device,
+ &thermal_device,
+ &hspi_device,
+ &leds_device,
+ &usb_phy,
+ &camera0_device,
+ &camera1_device,
+};
+
+static const struct pinctrl_map marzen_pinctrl_map[] = {
+ /* DU (CN10: ARGB0, CN13: LVDS) */
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779",
+ "du0_rgb888", "du0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779",
+ "du0_sync_1", "du0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779",
+ "du0_clk_out_0", "du0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779",
+ "du1_rgb666", "du1"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779",
+ "du1_sync_1", "du1"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779",
+ "du1_clk_out", "du1"),
+ /* HSPI0 */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh-hspi.0", "pfc-r8a7779",
+ "hspi0", "hspi0"),
+ /* SCIF2 (CN18: DEBUG0) */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.2", "pfc-r8a7779",
+ "scif2_data_c", "scif2"),
+ /* SCIF4 (CN19: DEBUG1) */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.4", "pfc-r8a7779",
+ "scif4_data", "scif4"),
+ /* SDHI0 */
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779",
+ "sdhi0_data4", "sdhi0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779",
+ "sdhi0_ctrl", "sdhi0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779",
+ "sdhi0_cd", "sdhi0"),
+ /* SMSC */
+ PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-r8a7779",
+ "intc_irq1_b", "intc"),
+ PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-r8a7779",
+ "lbsc_ex_cs0", "lbsc"),
+ /* USB0 */
+ PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform.0", "pfc-r8a7779",
+ "usb0", "usb0"),
+ /* USB1 */
+ PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform.0", "pfc-r8a7779",
+ "usb1", "usb1"),
+ /* USB2 */
+ PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform.1", "pfc-r8a7779",
+ "usb2", "usb2"),
+ /* VIN1 */
+ PIN_MAP_MUX_GROUP_DEFAULT("r8a7779-vin.1", "pfc-r8a7779",
+ "vin1_clk", "vin1"),
+ PIN_MAP_MUX_GROUP_DEFAULT("r8a7779-vin.1", "pfc-r8a7779",
+ "vin1_data8", "vin1"),
+ /* VIN3 */
+ PIN_MAP_MUX_GROUP_DEFAULT("r8a7779-vin.3", "pfc-r8a7779",
+ "vin3_clk", "vin3"),
+ PIN_MAP_MUX_GROUP_DEFAULT("r8a7779-vin.3", "pfc-r8a7779",
+ "vin3_data8", "vin3"),
+};
+
+static void __init marzen_init(void)
+{
+ regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
+ ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
+ regulator_register_fixed(1, dummy_supplies,
+ ARRAY_SIZE(dummy_supplies));
+
+ pinctrl_register_mappings(marzen_pinctrl_map,
+ ARRAY_SIZE(marzen_pinctrl_map));
+ r8a7779_pinmux_init();
+ r8a7779_init_irq_extpin(1); /* IRQ1 as individual interrupt */
+
+ r8a7779_add_standard_devices();
+ platform_device_register_full(&vin1_info);
+ platform_device_register_full(&vin3_info);
+ platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices));
+}
+
+static const char *marzen_boards_compat_dt[] __initdata = {
+ "renesas,marzen",
+ NULL,
+};
+
+DT_MACHINE_START(MARZEN, "marzen")
+ .smp = smp_ops(r8a7779_smp_ops),
+ .map_io = r8a7779_map_io,
+ .init_early = r8a7779_add_early_devices,
+ .init_irq = r8a7779_init_irq_dt,
+ .init_machine = marzen_init,
+ .init_late = r8a7779_init_late,
+ .dt_compat = marzen_boards_compat_dt,
+ .init_time = r8a7779_earlytimer_init,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
new file mode 100644
index 000000000..9cac8247c
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
@@ -0,0 +1,675 @@
+/*
+ * R8A7740 processor support
+ *
+ * Copyright (C) 2011 Renesas Solutions Corp.
+ * Copyright (C) 2011 Kuninori Morimoto <kuninori.morimoto.gx@renesas.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
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/sh_clk.h>
+#include <linux/clkdev.h>
+
+#include "clock.h"
+#include "common.h"
+#include "r8a7740.h"
+
+/*
+ * | MDx | XTAL1/EXTAL1 | System | EXTALR |
+ * Clock |-------+-----------------+ clock | 32.768 | RCLK
+ * Mode | 2/1/0 | src MHz | source | KHz | source
+ * -------+-------+-----------------+-----------+--------+----------
+ * 0 | 0 0 0 | External 20~50 | XTAL1 | O | EXTALR
+ * 1 | 0 0 1 | Crystal 20~30 | XTAL1 | O | EXTALR
+ * 2 | 0 1 0 | External 40~50 | XTAL1 / 2 | O | EXTALR
+ * 3 | 0 1 1 | Crystal 40~50 | XTAL1 / 2 | O | EXTALR
+ * 4 | 1 0 0 | External 20~50 | XTAL1 | x | XTAL1 / 1024
+ * 5 | 1 0 1 | Crystal 20~30 | XTAL1 | x | XTAL1 / 1024
+ * 6 | 1 1 0 | External 40~50 | XTAL1 / 2 | x | XTAL1 / 2048
+ * 7 | 1 1 1 | Crystal 40~50 | XTAL1 / 2 | x | XTAL1 / 2048
+ */
+
+/* CPG registers */
+#define FRQCRA IOMEM(0xe6150000)
+#define FRQCRB IOMEM(0xe6150004)
+#define VCLKCR1 IOMEM(0xE6150008)
+#define VCLKCR2 IOMEM(0xE615000c)
+#define FRQCRC IOMEM(0xe61500e0)
+#define FSIACKCR IOMEM(0xe6150018)
+#define PLLC01CR IOMEM(0xe6150028)
+
+#define SUBCKCR IOMEM(0xe6150080)
+#define USBCKCR IOMEM(0xe615008c)
+
+#define MSTPSR0 IOMEM(0xe6150030)
+#define MSTPSR1 IOMEM(0xe6150038)
+#define MSTPSR2 IOMEM(0xe6150040)
+#define MSTPSR3 IOMEM(0xe6150048)
+#define MSTPSR4 IOMEM(0xe615004c)
+#define FSIBCKCR IOMEM(0xe6150090)
+#define HDMICKCR IOMEM(0xe6150094)
+#define SMSTPCR0 IOMEM(0xe6150130)
+#define SMSTPCR1 IOMEM(0xe6150134)
+#define SMSTPCR2 IOMEM(0xe6150138)
+#define SMSTPCR3 IOMEM(0xe615013c)
+#define SMSTPCR4 IOMEM(0xe6150140)
+
+#define FSIDIVA IOMEM(0xFE1F8000)
+#define FSIDIVB IOMEM(0xFE1F8008)
+
+/* Fixed 32 KHz root clock from EXTALR pin */
+static struct clk extalr_clk = {
+ .rate = 32768,
+};
+
+/*
+ * 25MHz default rate for the EXTAL1 root input clock.
+ * If needed, reset this with clk_set_rate() from the platform code.
+ */
+static struct clk extal1_clk = {
+ .rate = 25000000,
+};
+
+/*
+ * 48MHz default rate for the EXTAL2 root input clock.
+ * If needed, reset this with clk_set_rate() from the platform code.
+ */
+static struct clk extal2_clk = {
+ .rate = 48000000,
+};
+
+/*
+ * 27MHz default rate for the DV_CLKI root input clock.
+ * If needed, reset this with clk_set_rate() from the platform code.
+ */
+static struct clk dv_clk = {
+ .rate = 27000000,
+};
+
+SH_CLK_RATIO(div2, 1, 2);
+SH_CLK_RATIO(div1k, 1, 1024);
+
+SH_FIXED_RATIO_CLK(extal1_div2_clk, extal1_clk, div2);
+SH_FIXED_RATIO_CLK(extal1_div1024_clk, extal1_clk, div1k);
+SH_FIXED_RATIO_CLK(extal1_div2048_clk, extal1_div2_clk, div1k);
+SH_FIXED_RATIO_CLK(extal2_div2_clk, extal2_clk, div2);
+
+static struct sh_clk_ops followparent_clk_ops = {
+ .recalc = followparent_recalc,
+};
+
+/* Main clock */
+static struct clk system_clk = {
+ .ops = &followparent_clk_ops,
+};
+
+SH_FIXED_RATIO_CLK(system_div2_clk, system_clk, div2);
+
+/* r_clk */
+static struct clk r_clk = {
+ .ops = &followparent_clk_ops,
+};
+
+/* PLLC0/PLLC1 */
+static unsigned long pllc01_recalc(struct clk *clk)
+{
+ unsigned long mult = 1;
+
+ if (__raw_readl(PLLC01CR) & (1 << 14))
+ mult = ((__raw_readl(clk->enable_reg) >> 24) & 0x7f) + 1;
+
+ return clk->parent->rate * mult;
+}
+
+static struct sh_clk_ops pllc01_clk_ops = {
+ .recalc = pllc01_recalc,
+};
+
+static struct clk pllc0_clk = {
+ .ops = &pllc01_clk_ops,
+ .flags = CLK_ENABLE_ON_INIT,
+ .parent = &system_clk,
+ .enable_reg = (void __iomem *)FRQCRC,
+};
+
+static struct clk pllc1_clk = {
+ .ops = &pllc01_clk_ops,
+ .flags = CLK_ENABLE_ON_INIT,
+ .parent = &system_div2_clk,
+ .enable_reg = (void __iomem *)FRQCRA,
+};
+
+/* PLLC1 / 2 */
+SH_FIXED_RATIO_CLK(pllc1_div2_clk, pllc1_clk, div2);
+
+/* USB clock */
+/*
+ * USBCKCR is controlling usb24 clock
+ * bit[7] : parent clock
+ * bit[6] : clock divide rate
+ * And this bit[7] is used as a "usb24s" from other devices.
+ * (Video clock / Sub clock / SPU clock)
+ * You can controll this clock as a below.
+ *
+ * struct clk *usb24 = clk_get(dev, "usb24");
+ * struct clk *usb24s = clk_get(NULL, "usb24s");
+ * struct clk *system = clk_get(NULL, "system_clk");
+ * int rate = clk_get_rate(system);
+ *
+ * clk_set_parent(usb24s, system); // for bit[7]
+ * clk_set_rate(usb24, rate / 2); // for bit[6]
+ */
+static struct clk *usb24s_parents[] = {
+ [0] = &system_clk,
+ [1] = &extal2_clk
+};
+
+static int usb24s_enable(struct clk *clk)
+{
+ __raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR);
+
+ return 0;
+}
+
+static void usb24s_disable(struct clk *clk)
+{
+ __raw_writel(__raw_readl(USBCKCR) | (1 << 8), USBCKCR);
+}
+
+static int usb24s_set_parent(struct clk *clk, struct clk *parent)
+{
+ int i, ret;
+ u32 val;
+
+ if (!clk->parent_table || !clk->parent_num)
+ return -EINVAL;
+
+ /* Search the parent */
+ for (i = 0; i < clk->parent_num; i++)
+ if (clk->parent_table[i] == parent)
+ break;
+
+ if (i == clk->parent_num)
+ return -ENODEV;
+
+ ret = clk_reparent(clk, parent);
+ if (ret < 0)
+ return ret;
+
+ val = __raw_readl(USBCKCR);
+ val &= ~(1 << 7);
+ val |= i << 7;
+ __raw_writel(val, USBCKCR);
+
+ return 0;
+}
+
+static struct sh_clk_ops usb24s_clk_ops = {
+ .recalc = followparent_recalc,
+ .enable = usb24s_enable,
+ .disable = usb24s_disable,
+ .set_parent = usb24s_set_parent,
+};
+
+static struct clk usb24s_clk = {
+ .ops = &usb24s_clk_ops,
+ .parent_table = usb24s_parents,
+ .parent_num = ARRAY_SIZE(usb24s_parents),
+ .parent = &system_clk,
+};
+
+static unsigned long usb24_recalc(struct clk *clk)
+{
+ return clk->parent->rate /
+ ((__raw_readl(USBCKCR) & (1 << 6)) ? 1 : 2);
+};
+
+static int usb24_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 val;
+
+ /* closer to which ? parent->rate or parent->rate/2 */
+ val = __raw_readl(USBCKCR);
+ val &= ~(1 << 6);
+ val |= (rate > (clk->parent->rate / 4) * 3) << 6;
+ __raw_writel(val, USBCKCR);
+
+ return 0;
+}
+
+static struct sh_clk_ops usb24_clk_ops = {
+ .recalc = usb24_recalc,
+ .set_rate = usb24_set_rate,
+};
+
+static struct clk usb24_clk = {
+ .ops = &usb24_clk_ops,
+ .parent = &usb24s_clk,
+};
+
+/* External FSIACK/FSIBCK clock */
+static struct clk fsiack_clk = {
+};
+
+static struct clk fsibck_clk = {
+};
+
+static struct clk *main_clks[] = {
+ &extalr_clk,
+ &extal1_clk,
+ &extal2_clk,
+ &extal1_div2_clk,
+ &extal1_div1024_clk,
+ &extal1_div2048_clk,
+ &extal2_div2_clk,
+ &dv_clk,
+ &system_clk,
+ &system_div2_clk,
+ &r_clk,
+ &pllc0_clk,
+ &pllc1_clk,
+ &pllc1_div2_clk,
+ &usb24s_clk,
+ &usb24_clk,
+ &fsiack_clk,
+ &fsibck_clk,
+};
+
+/* DIV4 clocks */
+static void div4_kick(struct clk *clk)
+{
+ unsigned long value;
+
+ /* set KICK bit in FRQCRB to update hardware setting */
+ value = __raw_readl(FRQCRB);
+ value |= (1 << 31);
+ __raw_writel(value, FRQCRB);
+}
+
+static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
+ 24, 32, 36, 48, 0, 72, 96, 0 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+ .divisors = divisors,
+ .nr_divisors = ARRAY_SIZE(divisors),
+};
+
+static struct clk_div4_table div4_table = {
+ .div_mult_table = &div4_div_mult_table,
+ .kick = div4_kick,
+};
+
+enum {
+ DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP,
+ DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP,
+ DIV4_NR
+};
+
+static struct clk div4_clks[DIV4_NR] = {
+ [DIV4_I] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 20, 0x6fff, CLK_ENABLE_ON_INIT),
+ [DIV4_ZG] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 16, 0x6fff, CLK_ENABLE_ON_INIT),
+ [DIV4_B] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 8, 0x6fff, CLK_ENABLE_ON_INIT),
+ [DIV4_M1] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT),
+ [DIV4_HP] = SH_CLK_DIV4(&pllc1_clk, FRQCRB, 4, 0x6fff, 0),
+ [DIV4_HPP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0),
+ [DIV4_USBP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 16, 0x6fff, 0),
+ [DIV4_S] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0),
+ [DIV4_ZB] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 8, 0x6fff, 0),
+ [DIV4_M3] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 4, 0x6fff, 0),
+ [DIV4_CP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 0, 0x6fff, 0),
+};
+
+/* DIV6 reparent */
+enum {
+ DIV6_HDMI,
+ DIV6_VCLK1, DIV6_VCLK2,
+ DIV6_FSIA, DIV6_FSIB,
+ DIV6_REPARENT_NR,
+};
+
+static struct clk *hdmi_parent[] = {
+ [0] = &pllc1_div2_clk,
+ [1] = &system_clk,
+ [2] = &dv_clk
+};
+
+static struct clk *vclk_parents[8] = {
+ [0] = &pllc1_div2_clk,
+ [2] = &dv_clk,
+ [3] = &usb24s_clk,
+ [4] = &extal1_div2_clk,
+ [5] = &extalr_clk,
+};
+
+static struct clk *fsia_parents[] = {
+ [0] = &pllc1_div2_clk,
+ [1] = &fsiack_clk, /* external clock */
+};
+
+static struct clk *fsib_parents[] = {
+ [0] = &pllc1_div2_clk,
+ [1] = &fsibck_clk, /* external clock */
+};
+
+static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
+ [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0,
+ hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2),
+ [DIV6_VCLK1] = SH_CLK_DIV6_EXT(VCLKCR1, 0,
+ vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3),
+ [DIV6_VCLK2] = SH_CLK_DIV6_EXT(VCLKCR2, 0,
+ vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3),
+ [DIV6_FSIA] = SH_CLK_DIV6_EXT(FSIACKCR, 0,
+ fsia_parents, ARRAY_SIZE(fsia_parents), 6, 2),
+ [DIV6_FSIB] = SH_CLK_DIV6_EXT(FSIBCKCR, 0,
+ fsib_parents, ARRAY_SIZE(fsib_parents), 6, 2),
+};
+
+/* DIV6 clocks */
+enum {
+ DIV6_SUB,
+ DIV6_NR
+};
+
+static struct clk div6_clks[DIV6_NR] = {
+ [DIV6_SUB] = SH_CLK_DIV6(&pllc1_div2_clk, SUBCKCR, 0),
+};
+
+/* HDMI1/2 clock */
+static unsigned long hdmi12_recalc(struct clk *clk)
+{
+ u32 val = __raw_readl(HDMICKCR);
+ int shift = (int)clk->priv;
+
+ val >>= shift;
+ val &= 0x3;
+
+ return clk->parent->rate / (1 << val);
+};
+
+static int hdmi12_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 val, mask;
+ int i, shift;
+
+ for (i = 0; i < 3; i++)
+ if (rate == clk->parent->rate / (1 << i))
+ goto find;
+ return -ENODEV;
+
+find:
+ shift = (int)clk->priv;
+
+ val = __raw_readl(HDMICKCR);
+ mask = ~(0x3 << shift);
+ val = (val & mask) | i << shift;
+ __raw_writel(val, HDMICKCR);
+
+ return 0;
+};
+
+static struct sh_clk_ops hdmi12_clk_ops = {
+ .recalc = hdmi12_recalc,
+ .set_rate = hdmi12_set_rate,
+};
+
+static struct clk hdmi1_clk = {
+ .ops = &hdmi12_clk_ops,
+ .priv = (void *)9,
+ .parent = &div6_reparent_clks[DIV6_HDMI], /* late install */
+};
+
+static struct clk hdmi2_clk = {
+ .ops = &hdmi12_clk_ops,
+ .priv = (void *)11,
+ .parent = &div6_reparent_clks[DIV6_HDMI], /* late install */
+};
+
+static struct clk *late_main_clks[] = {
+ &hdmi1_clk,
+ &hdmi2_clk,
+};
+
+/* FSI DIV */
+enum { FSIDIV_A, FSIDIV_B, FSIDIV_REPARENT_NR };
+
+static struct clk fsidivs[] = {
+ [FSIDIV_A] = SH_CLK_FSIDIV(FSIDIVA, &div6_reparent_clks[DIV6_FSIA]),
+ [FSIDIV_B] = SH_CLK_FSIDIV(FSIDIVB, &div6_reparent_clks[DIV6_FSIB]),
+};
+
+/* MSTP */
+enum {
+ MSTP128, MSTP127, MSTP125,
+ MSTP116, MSTP111, MSTP100, MSTP117,
+
+ MSTP230, MSTP229,
+ MSTP222,
+ MSTP218, MSTP217, MSTP216, MSTP214,
+ MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
+
+ MSTP329, MSTP328, MSTP323, MSTP320,
+ MSTP314, MSTP313, MSTP312,
+ MSTP309, MSTP304,
+
+ MSTP416, MSTP415, MSTP407, MSTP406,
+
+ MSTP_NR
+};
+
+static struct clk mstp_clks[MSTP_NR] = {
+ [MSTP128] = SH_CLK_MSTP32(&div4_clks[DIV4_S], SMSTPCR1, 28, 0), /* CEU21 */
+ [MSTP127] = SH_CLK_MSTP32(&div4_clks[DIV4_S], SMSTPCR1, 27, 0), /* CEU20 */
+ [MSTP125] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */
+ [MSTP117] = SH_CLK_MSTP32(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */
+ [MSTP116] = SH_CLK_MSTP32(&div4_clks[DIV4_HPP], SMSTPCR1, 16, 0), /* IIC0 */
+ [MSTP111] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 11, 0), /* TMU1 */
+ [MSTP100] = SH_CLK_MSTP32(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */
+
+ [MSTP230] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 30, 0), /* SCIFA6 */
+ [MSTP229] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 29, 0), /* INTCA */
+ [MSTP222] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 22, 0), /* SCIFA7 */
+ [MSTP218] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* DMAC1 */
+ [MSTP217] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 17, 0), /* DMAC2 */
+ [MSTP216] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 16, 0), /* DMAC3 */
+ [MSTP214] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 14, 0), /* USBDMAC */
+ [MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */
+ [MSTP206] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */
+ [MSTP204] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */
+ [MSTP203] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 3, 0), /* SCIFA1 */
+ [MSTP202] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 2, 0), /* SCIFA2 */
+ [MSTP201] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */
+ [MSTP200] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */
+
+ [MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
+ [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /* FSI */
+ [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
+ [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */
+ [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */
+ [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */
+ [MSTP312] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMC */
+ [MSTP309] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 9, 0), /* GEther */
+ [MSTP304] = SH_CLK_MSTP32(&div4_clks[DIV4_CP], SMSTPCR3, 4, 0), /* TPU0 */
+
+ [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */
+ [MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 15, 0), /* SDHI2 */
+ [MSTP407] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 7, 0), /* USB-Func */
+ [MSTP406] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 6, 0), /* USB Phy */
+};
+
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("extalr", &extalr_clk),
+ CLKDEV_CON_ID("extal1", &extal1_clk),
+ CLKDEV_CON_ID("extal2", &extal2_clk),
+ CLKDEV_CON_ID("extal1_div2", &extal1_div2_clk),
+ CLKDEV_CON_ID("extal1_div1024", &extal1_div1024_clk),
+ CLKDEV_CON_ID("extal1_div2048", &extal1_div2048_clk),
+ CLKDEV_CON_ID("extal2_div2", &extal2_div2_clk),
+ CLKDEV_CON_ID("dv_clk", &dv_clk),
+ CLKDEV_CON_ID("system_clk", &system_clk),
+ CLKDEV_CON_ID("system_div2_clk", &system_div2_clk),
+ CLKDEV_CON_ID("r_clk", &r_clk),
+ CLKDEV_CON_ID("pllc0_clk", &pllc0_clk),
+ CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
+ CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
+ CLKDEV_CON_ID("usb24s", &usb24s_clk),
+ CLKDEV_CON_ID("hdmi1", &hdmi1_clk),
+ CLKDEV_CON_ID("hdmi2", &hdmi2_clk),
+ CLKDEV_CON_ID("video1", &div6_reparent_clks[DIV6_VCLK1]),
+ CLKDEV_CON_ID("video2", &div6_reparent_clks[DIV6_VCLK2]),
+ CLKDEV_CON_ID("fsiack", &fsiack_clk),
+ CLKDEV_CON_ID("fsibck", &fsibck_clk),
+
+ /* DIV4 clocks */
+ CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
+ CLKDEV_CON_ID("zg_clk", &div4_clks[DIV4_ZG]),
+ CLKDEV_CON_ID("b_clk", &div4_clks[DIV4_B]),
+ CLKDEV_CON_ID("m1_clk", &div4_clks[DIV4_M1]),
+ CLKDEV_CON_ID("hp_clk", &div4_clks[DIV4_HP]),
+ CLKDEV_CON_ID("hpp_clk", &div4_clks[DIV4_HPP]),
+ CLKDEV_CON_ID("s_clk", &div4_clks[DIV4_S]),
+ CLKDEV_CON_ID("zb_clk", &div4_clks[DIV4_ZB]),
+ CLKDEV_CON_ID("m3_clk", &div4_clks[DIV4_M3]),
+ CLKDEV_CON_ID("cp_clk", &div4_clks[DIV4_CP]),
+
+ /* DIV6 clocks */
+ CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]),
+
+ /* MSTP32 clocks */
+ CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]),
+ CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]),
+ CLKDEV_DEV_ID("fff20000.i2c", &mstp_clks[MSTP116]),
+ CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]),
+ CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]),
+ CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP128]),
+
+ CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]),
+ CLKDEV_DEV_ID("e6c80000.serial", &mstp_clks[MSTP200]),
+ CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]),
+ CLKDEV_DEV_ID("e6c70000.serial", &mstp_clks[MSTP201]),
+ CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]),
+ CLKDEV_DEV_ID("e6c60000.serial", &mstp_clks[MSTP202]),
+ CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]),
+ CLKDEV_DEV_ID("e6c50000.serial", &mstp_clks[MSTP203]),
+ CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]),
+ CLKDEV_DEV_ID("e6c40000.serial", &mstp_clks[MSTP204]),
+ CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]),
+ CLKDEV_DEV_ID("e6c30000.serial", &mstp_clks[MSTP206]),
+ CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]),
+ CLKDEV_DEV_ID("e6cb0000.serial", &mstp_clks[MSTP207]),
+ CLKDEV_DEV_ID("sh-dma-engine.3", &mstp_clks[MSTP214]),
+ CLKDEV_DEV_ID("sh-dma-engine.2", &mstp_clks[MSTP216]),
+ CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]),
+ CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]),
+ CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP222]),
+ CLKDEV_DEV_ID("e6cd0000.serial", &mstp_clks[MSTP222]),
+ CLKDEV_DEV_ID("renesas_intc_irqpin.0", &mstp_clks[MSTP229]),
+ CLKDEV_DEV_ID("renesas_intc_irqpin.1", &mstp_clks[MSTP229]),
+ CLKDEV_DEV_ID("renesas_intc_irqpin.2", &mstp_clks[MSTP229]),
+ CLKDEV_DEV_ID("renesas_intc_irqpin.3", &mstp_clks[MSTP229]),
+ CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP230]),
+ CLKDEV_DEV_ID("e6cc0000.serial", &mstp_clks[MSTP230]),
+
+ CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]),
+ CLKDEV_DEV_ID("fe1f0000.sound", &mstp_clks[MSTP328]),
+ CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]),
+ CLKDEV_DEV_ID("e6c20000.i2c", &mstp_clks[MSTP323]),
+ CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]),
+ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]),
+ CLKDEV_DEV_ID("e6850000.sd", &mstp_clks[MSTP314]),
+ CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]),
+ CLKDEV_DEV_ID("e6860000.sd", &mstp_clks[MSTP313]),
+ CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP312]),
+ CLKDEV_DEV_ID("e6bd0000.mmc", &mstp_clks[MSTP312]),
+ CLKDEV_DEV_ID("r8a7740-gether", &mstp_clks[MSTP309]),
+ CLKDEV_DEV_ID("e9a00000.ethernet", &mstp_clks[MSTP309]),
+ CLKDEV_DEV_ID("renesas-tpu-pwm", &mstp_clks[MSTP304]),
+ CLKDEV_DEV_ID("e6600000.pwm", &mstp_clks[MSTP304]),
+
+ CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]),
+ CLKDEV_DEV_ID("e6870000.sd", &mstp_clks[MSTP415]),
+
+ /* ICK */
+ CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP111]),
+ CLKDEV_ICK_ID("fck", "fff90000.timer", &mstp_clks[MSTP111]),
+ CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP125]),
+ CLKDEV_ICK_ID("fck", "fff80000.timer", &mstp_clks[MSTP125]),
+ CLKDEV_ICK_ID("fck", "sh-cmt-48.1", &mstp_clks[MSTP329]),
+ CLKDEV_ICK_ID("fck", "e6138000.timer", &mstp_clks[MSTP329]),
+ CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]),
+ CLKDEV_ICK_ID("func", "renesas_usbhs", &mstp_clks[MSTP407]),
+ CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]),
+ CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]),
+ CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk),
+ CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]),
+
+ CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]),
+ CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]),
+ CLKDEV_ICK_ID("diva", "sh_fsi2", &fsidivs[FSIDIV_A]),
+ CLKDEV_ICK_ID("divb", "sh_fsi2", &fsidivs[FSIDIV_B]),
+ CLKDEV_ICK_ID("xcka", "sh_fsi2", &fsiack_clk),
+ CLKDEV_ICK_ID("xckb", "sh_fsi2", &fsibck_clk),
+};
+
+void __init r8a7740_clock_init(u8 md_ck)
+{
+ int k, ret = 0;
+
+ /* detect system clock parent */
+ if (md_ck & MD_CK1)
+ system_clk.parent = &extal1_div2_clk;
+ else
+ system_clk.parent = &extal1_clk;
+
+ /* detect RCLK parent */
+ switch (md_ck & (MD_CK2 | MD_CK1)) {
+ case MD_CK2 | MD_CK1:
+ r_clk.parent = &extal1_div2048_clk;
+ break;
+ case MD_CK2:
+ r_clk.parent = &extal1_div1024_clk;
+ break;
+ case MD_CK1:
+ default:
+ r_clk.parent = &extalr_clk;
+ break;
+ }
+
+ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+ ret = clk_register(main_clks[k]);
+
+ if (!ret)
+ ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+
+ if (!ret)
+ ret = sh_clk_div6_register(div6_clks, DIV6_NR);
+
+ if (!ret)
+ ret = sh_clk_div6_reparent_register(div6_reparent_clks,
+ DIV6_REPARENT_NR);
+
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+ for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
+ ret = clk_register(late_main_clks[k]);
+
+ if (!ret)
+ ret = sh_clk_fsidiv_register(fsidivs, FSIDIV_REPARENT_NR);
+
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+ if (!ret)
+ shmobile_clk_init();
+ else
+ panic("failed to setup r8a7740 clocks\n");
+}
diff --git a/arch/arm/mach-shmobile/clock-r8a7778.c b/arch/arm/mach-shmobile/clock-r8a7778.c
new file mode 100644
index 000000000..e8510c355
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock-r8a7778.c
@@ -0,0 +1,342 @@
+/*
+ * r8a7778 clock framework support
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * based on r8a7779
+ *
+ * Copyright (C) 2011 Renesas Solutions Corp.
+ * Copyright (C) 2011 Magnus Damm
+ *
+ * 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
+ *
+ * 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.
+ */
+
+/*
+ * MD MD MD MD PLLA PLLB EXTAL clki clkz
+ * 19 18 12 11 (HMz) (MHz) (MHz)
+ *----------------------------------------------------------------------------
+ * 1 0 0 0 x21 x21 38.00 800 800
+ * 1 0 0 1 x24 x24 33.33 800 800
+ * 1 0 1 0 x28 x28 28.50 800 800
+ * 1 0 1 1 x32 x32 25.00 800 800
+ * 1 1 0 1 x24 x21 33.33 800 700
+ * 1 1 1 0 x28 x21 28.50 800 600
+ * 1 1 1 1 x32 x24 25.00 800 600
+ */
+
+#include <linux/io.h>
+#include <linux/sh_clk.h>
+#include <linux/clkdev.h>
+#include "clock.h"
+#include "common.h"
+
+#define MSTPCR0 IOMEM(0xffc80030)
+#define MSTPCR1 IOMEM(0xffc80034)
+#define MSTPCR3 IOMEM(0xffc8003c)
+#define MSTPSR1 IOMEM(0xffc80044)
+#define MSTPSR4 IOMEM(0xffc80048)
+#define MSTPSR6 IOMEM(0xffc8004c)
+#define MSTPCR4 IOMEM(0xffc80050)
+#define MSTPCR5 IOMEM(0xffc80054)
+#define MSTPCR6 IOMEM(0xffc80058)
+#define MODEMR 0xFFCC0020
+
+#define MD(nr) BIT(nr)
+
+/* ioremap() through clock mapping mandatory to avoid
+ * collision with ARM coherent DMA virtual memory range.
+ */
+
+static struct clk_mapping cpg_mapping = {
+ .phys = 0xffc80000,
+ .len = 0x80,
+};
+
+static struct clk extal_clk = {
+ /* .rate will be updated on r8a7778_clock_init() */
+ .mapping = &cpg_mapping,
+};
+
+static struct clk audio_clk_a = {
+};
+
+static struct clk audio_clk_b = {
+};
+
+static struct clk audio_clk_c = {
+};
+
+/*
+ * clock ratio of these clock will be updated
+ * on r8a7778_clock_init()
+ */
+SH_FIXED_RATIO_CLK_SET(plla_clk, extal_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(pllb_clk, extal_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(i_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(s_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(s1_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(s3_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(s4_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(b_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(out_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(p_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(g_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(z_clk, pllb_clk, 1, 1);
+
+static struct clk *main_clks[] = {
+ &extal_clk,
+ &plla_clk,
+ &pllb_clk,
+ &i_clk,
+ &s_clk,
+ &s1_clk,
+ &s3_clk,
+ &s4_clk,
+ &b_clk,
+ &out_clk,
+ &p_clk,
+ &g_clk,
+ &z_clk,
+ &audio_clk_a,
+ &audio_clk_b,
+ &audio_clk_c,
+};
+
+enum {
+ MSTP531, MSTP530,
+ MSTP529, MSTP528, MSTP527, MSTP526, MSTP525, MSTP524, MSTP523,
+ MSTP331,
+ MSTP323, MSTP322, MSTP321,
+ MSTP311, MSTP310,
+ MSTP309, MSTP308, MSTP307,
+ MSTP114,
+ MSTP110, MSTP109,
+ MSTP100,
+ MSTP030,
+ MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
+ MSTP016, MSTP015, MSTP012, MSTP011, MSTP010,
+ MSTP009, MSTP008, MSTP007,
+ MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+ [MSTP531] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 31, 0), /* SCU0 */
+ [MSTP530] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 30, 0), /* SCU1 */
+ [MSTP529] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 29, 0), /* SCU2 */
+ [MSTP528] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 28, 0), /* SCU3 */
+ [MSTP527] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 27, 0), /* SCU4 */
+ [MSTP526] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 26, 0), /* SCU5 */
+ [MSTP525] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 25, 0), /* SCU6 */
+ [MSTP524] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 24, 0), /* SCU7 */
+ [MSTP523] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 23, 0), /* SCU8 */
+ [MSTP331] = SH_CLK_MSTP32(&s4_clk, MSTPCR3, 31, 0), /* MMC */
+ [MSTP323] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 23, 0), /* SDHI0 */
+ [MSTP322] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 22, 0), /* SDHI1 */
+ [MSTP321] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 21, 0), /* SDHI2 */
+ [MSTP311] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 11, 0), /* SSI4 */
+ [MSTP310] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 10, 0), /* SSI5 */
+ [MSTP309] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 9, 0), /* SSI6 */
+ [MSTP308] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 8, 0), /* SSI7 */
+ [MSTP307] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 7, 0), /* SSI8 */
+ [MSTP114] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 14, 0), /* Ether */
+ [MSTP110] = SH_CLK_MSTP32(&s_clk, MSTPCR1, 10, 0), /* VIN0 */
+ [MSTP109] = SH_CLK_MSTP32(&s_clk, MSTPCR1, 9, 0), /* VIN1 */
+ [MSTP100] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 0, 0), /* USB0/1 */
+ [MSTP030] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 30, 0), /* I2C0 */
+ [MSTP029] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 29, 0), /* I2C1 */
+ [MSTP028] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 28, 0), /* I2C2 */
+ [MSTP027] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 27, 0), /* I2C3 */
+ [MSTP026] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 26, 0), /* SCIF0 */
+ [MSTP025] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 25, 0), /* SCIF1 */
+ [MSTP024] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 24, 0), /* SCIF2 */
+ [MSTP023] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 23, 0), /* SCIF3 */
+ [MSTP022] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 22, 0), /* SCIF4 */
+ [MSTP021] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 21, 0), /* SCIF5 */
+ [MSTP016] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 16, 0), /* TMU0 */
+ [MSTP015] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 15, 0), /* TMU1 */
+ [MSTP012] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 12, 0), /* SSI0 */
+ [MSTP011] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 11, 0), /* SSI1 */
+ [MSTP010] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 10, 0), /* SSI2 */
+ [MSTP009] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 9, 0), /* SSI3 */
+ [MSTP008] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 8, 0), /* SRU */
+ [MSTP007] = SH_CLK_MSTP32(&s_clk, MSTPCR0, 7, 0), /* HSPI */
+};
+
+static struct clk_lookup lookups[] = {
+ /* main */
+ CLKDEV_CON_ID("shyway_clk", &s_clk),
+ CLKDEV_CON_ID("peripheral_clk", &p_clk),
+
+ /* MSTP32 clocks */
+ CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP331]), /* MMC */
+ CLKDEV_DEV_ID("ffe4e000.mmc", &mstp_clks[MSTP331]), /* MMC */
+ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP323]), /* SDHI0 */
+ CLKDEV_DEV_ID("ffe4c000.sd", &mstp_clks[MSTP323]), /* SDHI0 */
+ CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
+ CLKDEV_DEV_ID("ffe4d000.sd", &mstp_clks[MSTP322]), /* SDHI1 */
+ CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
+ CLKDEV_DEV_ID("ffe4f000.sd", &mstp_clks[MSTP321]), /* SDHI2 */
+ CLKDEV_DEV_ID("r8a777x-ether", &mstp_clks[MSTP114]), /* Ether */
+ CLKDEV_DEV_ID("r8a7778-vin.0", &mstp_clks[MSTP110]), /* VIN0 */
+ CLKDEV_DEV_ID("r8a7778-vin.1", &mstp_clks[MSTP109]), /* VIN1 */
+ CLKDEV_DEV_ID("ehci-platform", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */
+ CLKDEV_DEV_ID("ohci-platform", &mstp_clks[MSTP100]), /* USB OHCI port0/1 */
+ CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP100]), /* USB FUNC */
+ CLKDEV_DEV_ID("i2c-rcar.0", &mstp_clks[MSTP030]), /* I2C0 */
+ CLKDEV_DEV_ID("ffc70000.i2c", &mstp_clks[MSTP030]), /* I2C0 */
+ CLKDEV_DEV_ID("i2c-rcar.1", &mstp_clks[MSTP029]), /* I2C1 */
+ CLKDEV_DEV_ID("ffc71000.i2c", &mstp_clks[MSTP029]), /* I2C1 */
+ CLKDEV_DEV_ID("i2c-rcar.2", &mstp_clks[MSTP028]), /* I2C2 */
+ CLKDEV_DEV_ID("ffc72000.i2c", &mstp_clks[MSTP028]), /* I2C2 */
+ CLKDEV_DEV_ID("i2c-rcar.3", &mstp_clks[MSTP027]), /* I2C3 */
+ CLKDEV_DEV_ID("ffc73000.i2c", &mstp_clks[MSTP027]), /* I2C3 */
+ CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */
+ CLKDEV_DEV_ID("ffe40000.serial", &mstp_clks[MSTP026]), /* SCIF0 */
+ CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */
+ CLKDEV_DEV_ID("ffe41000.serial", &mstp_clks[MSTP025]), /* SCIF1 */
+ CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */
+ CLKDEV_DEV_ID("ffe42000.serial", &mstp_clks[MSTP024]), /* SCIF2 */
+ CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP023]), /* SCIF3 */
+ CLKDEV_DEV_ID("ffe43000.serial", &mstp_clks[MSTP023]), /* SCIF3 */
+ CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP022]), /* SCIF4 */
+ CLKDEV_DEV_ID("ffe44000.serial", &mstp_clks[MSTP022]), /* SCIF4 */
+ CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP021]), /* SCIF6 */
+ CLKDEV_DEV_ID("ffe45000.serial", &mstp_clks[MSTP021]), /* SCIF5 */
+ CLKDEV_DEV_ID("sh-hspi.0", &mstp_clks[MSTP007]), /* HSPI0 */
+ CLKDEV_DEV_ID("fffc7000.spi", &mstp_clks[MSTP007]), /* HSPI0 */
+ CLKDEV_DEV_ID("sh-hspi.1", &mstp_clks[MSTP007]), /* HSPI1 */
+ CLKDEV_DEV_ID("fffc8000.spi", &mstp_clks[MSTP007]), /* HSPI1 */
+ CLKDEV_DEV_ID("sh-hspi.2", &mstp_clks[MSTP007]), /* HSPI2 */
+ CLKDEV_DEV_ID("fffc6000.spi", &mstp_clks[MSTP007]), /* HSPI2 */
+ CLKDEV_DEV_ID("rcar_sound", &mstp_clks[MSTP008]), /* SRU */
+
+ CLKDEV_ICK_ID("clk_a", "rcar_sound", &audio_clk_a),
+ CLKDEV_ICK_ID("clk_b", "rcar_sound", &audio_clk_b),
+ CLKDEV_ICK_ID("clk_c", "rcar_sound", &audio_clk_c),
+ CLKDEV_ICK_ID("clk_i", "rcar_sound", &s1_clk),
+ CLKDEV_ICK_ID("ssi.0", "rcar_sound", &mstp_clks[MSTP012]),
+ CLKDEV_ICK_ID("ssi.1", "rcar_sound", &mstp_clks[MSTP011]),
+ CLKDEV_ICK_ID("ssi.2", "rcar_sound", &mstp_clks[MSTP010]),
+ CLKDEV_ICK_ID("ssi.3", "rcar_sound", &mstp_clks[MSTP009]),
+ CLKDEV_ICK_ID("ssi.4", "rcar_sound", &mstp_clks[MSTP311]),
+ CLKDEV_ICK_ID("ssi.5", "rcar_sound", &mstp_clks[MSTP310]),
+ CLKDEV_ICK_ID("ssi.6", "rcar_sound", &mstp_clks[MSTP309]),
+ CLKDEV_ICK_ID("ssi.7", "rcar_sound", &mstp_clks[MSTP308]),
+ CLKDEV_ICK_ID("ssi.8", "rcar_sound", &mstp_clks[MSTP307]),
+ CLKDEV_ICK_ID("src.0", "rcar_sound", &mstp_clks[MSTP531]),
+ CLKDEV_ICK_ID("src.1", "rcar_sound", &mstp_clks[MSTP530]),
+ CLKDEV_ICK_ID("src.2", "rcar_sound", &mstp_clks[MSTP529]),
+ CLKDEV_ICK_ID("src.3", "rcar_sound", &mstp_clks[MSTP528]),
+ CLKDEV_ICK_ID("src.4", "rcar_sound", &mstp_clks[MSTP527]),
+ CLKDEV_ICK_ID("src.5", "rcar_sound", &mstp_clks[MSTP526]),
+ CLKDEV_ICK_ID("src.6", "rcar_sound", &mstp_clks[MSTP525]),
+ CLKDEV_ICK_ID("src.7", "rcar_sound", &mstp_clks[MSTP524]),
+ CLKDEV_ICK_ID("src.8", "rcar_sound", &mstp_clks[MSTP523]),
+ CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP016]),
+ CLKDEV_ICK_ID("fck", "ffd80000.timer", &mstp_clks[MSTP016]),
+ CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP015]),
+ CLKDEV_ICK_ID("fck", "ffd81000.timer", &mstp_clks[MSTP015]),
+};
+
+void __init r8a7778_clock_init(void)
+{
+ void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
+ u32 mode;
+ int k, ret = 0;
+
+ BUG_ON(!modemr);
+ mode = ioread32(modemr);
+ iounmap(modemr);
+
+ switch (mode & (MD(19) | MD(18) | MD(12) | MD(11))) {
+ case MD(19):
+ extal_clk.rate = 38000000;
+ SH_CLK_SET_RATIO(&plla_clk_ratio, 21, 1);
+ SH_CLK_SET_RATIO(&pllb_clk_ratio, 21, 1);
+ break;
+ case MD(19) | MD(11):
+ extal_clk.rate = 33333333;
+ SH_CLK_SET_RATIO(&plla_clk_ratio, 24, 1);
+ SH_CLK_SET_RATIO(&pllb_clk_ratio, 24, 1);
+ break;
+ case MD(19) | MD(12):
+ extal_clk.rate = 28500000;
+ SH_CLK_SET_RATIO(&plla_clk_ratio, 28, 1);
+ SH_CLK_SET_RATIO(&pllb_clk_ratio, 28, 1);
+ break;
+ case MD(19) | MD(12) | MD(11):
+ extal_clk.rate = 25000000;
+ SH_CLK_SET_RATIO(&plla_clk_ratio, 32, 1);
+ SH_CLK_SET_RATIO(&pllb_clk_ratio, 32, 1);
+ break;
+ case MD(19) | MD(18) | MD(11):
+ extal_clk.rate = 33333333;
+ SH_CLK_SET_RATIO(&plla_clk_ratio, 24, 1);
+ SH_CLK_SET_RATIO(&pllb_clk_ratio, 21, 1);
+ break;
+ case MD(19) | MD(18) | MD(12):
+ extal_clk.rate = 28500000;
+ SH_CLK_SET_RATIO(&plla_clk_ratio, 28, 1);
+ SH_CLK_SET_RATIO(&pllb_clk_ratio, 21, 1);
+ break;
+ case MD(19) | MD(18) | MD(12) | MD(11):
+ extal_clk.rate = 25000000;
+ SH_CLK_SET_RATIO(&plla_clk_ratio, 32, 1);
+ SH_CLK_SET_RATIO(&pllb_clk_ratio, 24, 1);
+ break;
+ default:
+ BUG();
+ }
+
+ if (mode & MD(1)) {
+ SH_CLK_SET_RATIO(&i_clk_ratio, 1, 1);
+ SH_CLK_SET_RATIO(&s_clk_ratio, 1, 3);
+ SH_CLK_SET_RATIO(&s1_clk_ratio, 1, 6);
+ SH_CLK_SET_RATIO(&s3_clk_ratio, 1, 4);
+ SH_CLK_SET_RATIO(&s4_clk_ratio, 1, 8);
+ SH_CLK_SET_RATIO(&p_clk_ratio, 1, 12);
+ SH_CLK_SET_RATIO(&g_clk_ratio, 1, 12);
+ if (mode & MD(2)) {
+ SH_CLK_SET_RATIO(&b_clk_ratio, 1, 18);
+ SH_CLK_SET_RATIO(&out_clk_ratio, 1, 18);
+ } else {
+ SH_CLK_SET_RATIO(&b_clk_ratio, 1, 12);
+ SH_CLK_SET_RATIO(&out_clk_ratio, 1, 12);
+ }
+ } else {
+ SH_CLK_SET_RATIO(&i_clk_ratio, 1, 1);
+ SH_CLK_SET_RATIO(&s_clk_ratio, 1, 4);
+ SH_CLK_SET_RATIO(&s1_clk_ratio, 1, 8);
+ SH_CLK_SET_RATIO(&s3_clk_ratio, 1, 4);
+ SH_CLK_SET_RATIO(&s4_clk_ratio, 1, 8);
+ SH_CLK_SET_RATIO(&p_clk_ratio, 1, 16);
+ SH_CLK_SET_RATIO(&g_clk_ratio, 1, 12);
+ if (mode & MD(2)) {
+ SH_CLK_SET_RATIO(&b_clk_ratio, 1, 16);
+ SH_CLK_SET_RATIO(&out_clk_ratio, 1, 16);
+ } else {
+ SH_CLK_SET_RATIO(&b_clk_ratio, 1, 12);
+ SH_CLK_SET_RATIO(&out_clk_ratio, 1, 12);
+ }
+ }
+
+ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+ ret = clk_register(main_clks[k]);
+
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+ if (!ret)
+ shmobile_clk_init();
+ else
+ panic("failed to setup r8a7778 clocks\n");
+}
diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c
new file mode 100644
index 000000000..fa8ab2cc9
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock-r8a7779.c
@@ -0,0 +1,271 @@
+/*
+ * r8a7779 clock framework support
+ *
+ * Copyright (C) 2011 Renesas Solutions Corp.
+ * Copyright (C) 2011 Magnus Damm
+ *
+ * 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
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/bitops.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/sh_clk.h>
+#include <linux/clkdev.h>
+#include <linux/sh_timer.h>
+
+#include "clock.h"
+#include "common.h"
+#include "r8a7779.h"
+
+/*
+ * MD1 = 1 MD1 = 0
+ * (PLLA = 1500) (PLLA = 1600)
+ * (MHz) (MHz)
+ *------------------------------------------------+--------------------
+ * clkz 1000 (2/3) 800 (1/2)
+ * clkzs 250 (1/6) 200 (1/8)
+ * clki 750 (1/2) 800 (1/2)
+ * clks 250 (1/6) 200 (1/8)
+ * clks1 125 (1/12) 100 (1/16)
+ * clks3 187.5 (1/8) 200 (1/8)
+ * clks4 93.7 (1/16) 100 (1/16)
+ * clkp 62.5 (1/24) 50 (1/32)
+ * clkg 62.5 (1/24) 66.6 (1/24)
+ * clkb, CLKOUT
+ * (MD2 = 0) 62.5 (1/24) 66.6 (1/24)
+ * (MD2 = 1) 41.6 (1/36) 50 (1/32)
+*/
+
+#define MD(nr) BIT(nr)
+
+#define MSTPCR0 IOMEM(0xffc80030)
+#define MSTPCR1 IOMEM(0xffc80034)
+#define MSTPCR3 IOMEM(0xffc8003c)
+#define MSTPSR1 IOMEM(0xffc80044)
+
+/* ioremap() through clock mapping mandatory to avoid
+ * collision with ARM coherent DMA virtual memory range.
+ */
+
+static struct clk_mapping cpg_mapping = {
+ .phys = 0xffc80000,
+ .len = 0x80,
+};
+
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk plla_clk = {
+ /* .rate will be updated on r8a7779_clock_init() */
+ .mapping = &cpg_mapping,
+};
+
+/*
+ * clock ratio of these clock will be updated
+ * on r8a7779_clock_init()
+ */
+SH_FIXED_RATIO_CLK_SET(clkz_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clkzs_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clki_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clks_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clks1_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clks3_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clks4_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clkb_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clkout_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clkp_clk, plla_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(clkg_clk, plla_clk, 1, 1);
+
+static struct clk *main_clks[] = {
+ &plla_clk,
+ &clkz_clk,
+ &clkzs_clk,
+ &clki_clk,
+ &clks_clk,
+ &clks1_clk,
+ &clks3_clk,
+ &clks4_clk,
+ &clkb_clk,
+ &clkout_clk,
+ &clkp_clk,
+ &clkg_clk,
+};
+
+enum { MSTP323, MSTP322, MSTP321, MSTP320,
+ MSTP120,
+ MSTP116, MSTP115, MSTP114,
+ MSTP110, MSTP109, MSTP108,
+ MSTP103, MSTP101, MSTP100,
+ MSTP030,
+ MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
+ MSTP016, MSTP015, MSTP014,
+ MSTP007,
+ MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+ [MSTP323] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 23, 0), /* SDHI0 */
+ [MSTP322] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 22, 0), /* SDHI1 */
+ [MSTP321] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 21, 0), /* SDHI2 */
+ [MSTP320] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 20, 0), /* SDHI3 */
+ [MSTP120] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1, 20, MSTPSR1, 0), /* VIN3 */
+ [MSTP116] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1, 16, MSTPSR1, 0), /* PCIe */
+ [MSTP115] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1, 15, MSTPSR1, 0), /* SATA */
+ [MSTP114] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1, 14, MSTPSR1, 0), /* Ether */
+ [MSTP110] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1, 10, MSTPSR1, 0), /* VIN0 */
+ [MSTP109] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1, 9, MSTPSR1, 0), /* VIN1 */
+ [MSTP108] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1, 8, MSTPSR1, 0), /* VIN2 */
+ [MSTP103] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1, 3, MSTPSR1, 0), /* DU */
+ [MSTP101] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1, 1, MSTPSR1, 0), /* USB2 */
+ [MSTP100] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1, 0, MSTPSR1, 0), /* USB0/1 */
+ [MSTP030] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 30, 0), /* I2C0 */
+ [MSTP029] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 29, 0), /* I2C1 */
+ [MSTP028] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 28, 0), /* I2C2 */
+ [MSTP027] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 27, 0), /* I2C3 */
+ [MSTP026] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 26, 0), /* SCIF0 */
+ [MSTP025] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 25, 0), /* SCIF1 */
+ [MSTP024] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 24, 0), /* SCIF2 */
+ [MSTP023] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 23, 0), /* SCIF3 */
+ [MSTP022] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 22, 0), /* SCIF4 */
+ [MSTP021] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 21, 0), /* SCIF5 */
+ [MSTP016] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 16, 0), /* TMU0 */
+ [MSTP015] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 15, 0), /* TMU1 */
+ [MSTP014] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 14, 0), /* TMU2 */
+ [MSTP007] = SH_CLK_MSTP32(&clks_clk, MSTPCR0, 7, 0), /* HSPI */
+};
+
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("plla_clk", &plla_clk),
+ CLKDEV_CON_ID("clkz_clk", &clkz_clk),
+ CLKDEV_CON_ID("clkzs_clk", &clkzs_clk),
+
+ /* DIV4 clocks */
+ CLKDEV_CON_ID("shyway_clk", &clks_clk),
+ CLKDEV_CON_ID("bus_clk", &clkout_clk),
+ CLKDEV_CON_ID("shyway4_clk", &clks4_clk),
+ CLKDEV_CON_ID("shyway3_clk", &clks3_clk),
+ CLKDEV_CON_ID("shyway1_clk", &clks1_clk),
+ CLKDEV_CON_ID("peripheral_clk", &clkp_clk),
+
+ /* MSTP32 clocks */
+ CLKDEV_DEV_ID("r8a7779-vin.3", &mstp_clks[MSTP120]), /* VIN3 */
+ CLKDEV_DEV_ID("rcar-pcie", &mstp_clks[MSTP116]), /* PCIe */
+ CLKDEV_DEV_ID("sata_rcar", &mstp_clks[MSTP115]), /* SATA */
+ CLKDEV_DEV_ID("fc600000.sata", &mstp_clks[MSTP115]), /* SATA w/DT */
+ CLKDEV_DEV_ID("r8a777x-ether", &mstp_clks[MSTP114]), /* Ether */
+ CLKDEV_DEV_ID("r8a7779-vin.0", &mstp_clks[MSTP110]), /* VIN0 */
+ CLKDEV_DEV_ID("r8a7779-vin.1", &mstp_clks[MSTP109]), /* VIN1 */
+ CLKDEV_DEV_ID("r8a7779-vin.2", &mstp_clks[MSTP108]), /* VIN2 */
+ CLKDEV_DEV_ID("ehci-platform.1", &mstp_clks[MSTP101]), /* USB EHCI port2 */
+ CLKDEV_DEV_ID("ohci-platform.1", &mstp_clks[MSTP101]), /* USB OHCI port2 */
+ CLKDEV_DEV_ID("ehci-platform.0", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */
+ CLKDEV_DEV_ID("ohci-platform.0", &mstp_clks[MSTP100]), /* USB OHCI port0/1 */
+ CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP016]), /* TMU0 */
+ CLKDEV_DEV_ID("i2c-rcar.0", &mstp_clks[MSTP030]), /* I2C0 */
+ CLKDEV_DEV_ID("ffc70000.i2c", &mstp_clks[MSTP030]), /* I2C0 */
+ CLKDEV_DEV_ID("i2c-rcar.1", &mstp_clks[MSTP029]), /* I2C1 */
+ CLKDEV_DEV_ID("ffc71000.i2c", &mstp_clks[MSTP029]), /* I2C1 */
+ CLKDEV_DEV_ID("i2c-rcar.2", &mstp_clks[MSTP028]), /* I2C2 */
+ CLKDEV_DEV_ID("ffc72000.i2c", &mstp_clks[MSTP028]), /* I2C2 */
+ CLKDEV_DEV_ID("i2c-rcar.3", &mstp_clks[MSTP027]), /* I2C3 */
+ CLKDEV_DEV_ID("ffc73000.i2c", &mstp_clks[MSTP027]), /* I2C3 */
+ CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */
+ CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */
+ CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */
+ CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP023]), /* SCIF3 */
+ CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP022]), /* SCIF4 */
+ CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP021]), /* SCIF6 */
+ CLKDEV_DEV_ID("sh-hspi.0", &mstp_clks[MSTP007]), /* HSPI0 */
+ CLKDEV_DEV_ID("fffc7000.spi", &mstp_clks[MSTP007]), /* HSPI0 */
+ CLKDEV_DEV_ID("sh-hspi.1", &mstp_clks[MSTP007]), /* HSPI1 */
+ CLKDEV_DEV_ID("fffc8000.spi", &mstp_clks[MSTP007]), /* HSPI1 */
+ CLKDEV_DEV_ID("sh-hspi.2", &mstp_clks[MSTP007]), /* HSPI2 */
+ CLKDEV_DEV_ID("fffc6000.spi", &mstp_clks[MSTP007]), /* HSPI2 */
+ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP323]), /* SDHI0 */
+ CLKDEV_DEV_ID("ffe4c000.sd", &mstp_clks[MSTP323]), /* SDHI0 */
+ CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
+ CLKDEV_DEV_ID("ffe4d000.sd", &mstp_clks[MSTP322]), /* SDHI1 */
+ CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
+ CLKDEV_DEV_ID("ffe4e000.sd", &mstp_clks[MSTP321]), /* SDHI2 */
+ CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP320]), /* SDHI3 */
+ CLKDEV_DEV_ID("ffe4f000.sd", &mstp_clks[MSTP320]), /* SDHI3 */
+ CLKDEV_DEV_ID("rcar-du-r8a7779", &mstp_clks[MSTP103]), /* DU */
+};
+
+void __init r8a7779_clock_init(void)
+{
+ u32 mode = r8a7779_read_mode_pins();
+ int k, ret = 0;
+
+ if (mode & MD(1)) {
+ plla_clk.rate = 1500000000;
+
+ SH_CLK_SET_RATIO(&clkz_clk_ratio, 2, 3);
+ SH_CLK_SET_RATIO(&clkzs_clk_ratio, 1, 6);
+ SH_CLK_SET_RATIO(&clki_clk_ratio, 1, 2);
+ SH_CLK_SET_RATIO(&clks_clk_ratio, 1, 6);
+ SH_CLK_SET_RATIO(&clks1_clk_ratio, 1, 12);
+ SH_CLK_SET_RATIO(&clks3_clk_ratio, 1, 8);
+ SH_CLK_SET_RATIO(&clks4_clk_ratio, 1, 16);
+ SH_CLK_SET_RATIO(&clkp_clk_ratio, 1, 24);
+ SH_CLK_SET_RATIO(&clkg_clk_ratio, 1, 24);
+ if (mode & MD(2)) {
+ SH_CLK_SET_RATIO(&clkb_clk_ratio, 1, 36);
+ SH_CLK_SET_RATIO(&clkout_clk_ratio, 1, 36);
+ } else {
+ SH_CLK_SET_RATIO(&clkb_clk_ratio, 1, 24);
+ SH_CLK_SET_RATIO(&clkout_clk_ratio, 1, 24);
+ }
+ } else {
+ plla_clk.rate = 1600000000;
+
+ SH_CLK_SET_RATIO(&clkz_clk_ratio, 1, 2);
+ SH_CLK_SET_RATIO(&clkzs_clk_ratio, 1, 8);
+ SH_CLK_SET_RATIO(&clki_clk_ratio, 1, 2);
+ SH_CLK_SET_RATIO(&clks_clk_ratio, 1, 8);
+ SH_CLK_SET_RATIO(&clks1_clk_ratio, 1, 16);
+ SH_CLK_SET_RATIO(&clks3_clk_ratio, 1, 8);
+ SH_CLK_SET_RATIO(&clks4_clk_ratio, 1, 16);
+ SH_CLK_SET_RATIO(&clkp_clk_ratio, 1, 32);
+ SH_CLK_SET_RATIO(&clkg_clk_ratio, 1, 24);
+ if (mode & MD(2)) {
+ SH_CLK_SET_RATIO(&clkb_clk_ratio, 1, 32);
+ SH_CLK_SET_RATIO(&clkout_clk_ratio, 1, 32);
+ } else {
+ SH_CLK_SET_RATIO(&clkb_clk_ratio, 1, 24);
+ SH_CLK_SET_RATIO(&clkout_clk_ratio, 1, 24);
+ }
+ }
+
+ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+ ret = clk_register(main_clks[k]);
+
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+ if (!ret)
+ shmobile_clk_init();
+ else
+ panic("failed to setup r8a7779 clocks\n");
+}
+
+/* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
+void __init __weak r8a7779_register_twd(void) { }
+
+void __init r8a7779_earlytimer_init(void)
+{
+ r8a7779_clock_init();
+ r8a7779_register_twd();
+ shmobile_earlytimer_init();
+}
diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
new file mode 100644
index 000000000..3855fb024
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
@@ -0,0 +1,752 @@
+/*
+ * sh73a0 clock framework support
+ *
+ * Copyright (C) 2010 Magnus Damm
+ *
+ * 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
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/sh_clk.h>
+#include <linux/clkdev.h>
+#include <asm/processor.h>
+#include "clock.h"
+#include "common.h"
+
+#define FRQCRA IOMEM(0xe6150000)
+#define FRQCRB IOMEM(0xe6150004)
+#define FRQCRD IOMEM(0xe61500e4)
+#define VCLKCR1 IOMEM(0xe6150008)
+#define VCLKCR2 IOMEM(0xe615000C)
+#define VCLKCR3 IOMEM(0xe615001C)
+#define ZBCKCR IOMEM(0xe6150010)
+#define FLCKCR IOMEM(0xe6150014)
+#define SD0CKCR IOMEM(0xe6150074)
+#define SD1CKCR IOMEM(0xe6150078)
+#define SD2CKCR IOMEM(0xe615007C)
+#define FSIACKCR IOMEM(0xe6150018)
+#define FSIBCKCR IOMEM(0xe6150090)
+#define SUBCKCR IOMEM(0xe6150080)
+#define SPUACKCR IOMEM(0xe6150084)
+#define SPUVCKCR IOMEM(0xe6150094)
+#define MSUCKCR IOMEM(0xe6150088)
+#define HSICKCR IOMEM(0xe615008C)
+#define MFCK1CR IOMEM(0xe6150098)
+#define MFCK2CR IOMEM(0xe615009C)
+#define DSITCKCR IOMEM(0xe6150060)
+#define DSI0PCKCR IOMEM(0xe6150064)
+#define DSI1PCKCR IOMEM(0xe6150068)
+#define DSI0PHYCR 0xe615006C
+#define DSI1PHYCR 0xe6150070
+#define PLLECR IOMEM(0xe61500d0)
+#define PLL0CR IOMEM(0xe61500d8)
+#define PLL1CR IOMEM(0xe6150028)
+#define PLL2CR IOMEM(0xe615002c)
+#define PLL3CR IOMEM(0xe61500dc)
+#define SMSTPCR0 IOMEM(0xe6150130)
+#define SMSTPCR1 IOMEM(0xe6150134)
+#define SMSTPCR2 IOMEM(0xe6150138)
+#define SMSTPCR3 IOMEM(0xe615013c)
+#define SMSTPCR4 IOMEM(0xe6150140)
+#define SMSTPCR5 IOMEM(0xe6150144)
+#define CKSCR IOMEM(0xe61500c0)
+
+/* Fixed 32 KHz root clock from EXTALR pin */
+static struct clk r_clk = {
+ .rate = 32768,
+};
+
+/*
+ * 26MHz default rate for the EXTAL1 root input clock.
+ * If needed, reset this with clk_set_rate() from the platform code.
+ */
+struct clk sh73a0_extal1_clk = {
+ .rate = 26000000,
+};
+
+/*
+ * 48MHz default rate for the EXTAL2 root input clock.
+ * If needed, reset this with clk_set_rate() from the platform code.
+ */
+struct clk sh73a0_extal2_clk = {
+ .rate = 48000000,
+};
+
+static struct sh_clk_ops main_clk_ops = {
+ .recalc = followparent_recalc,
+};
+
+/* Main clock */
+static struct clk main_clk = {
+ /* .parent wll be set on sh73a0_clock_init() */
+ .ops = &main_clk_ops,
+};
+
+/* PLL0, PLL1, PLL2, PLL3 */
+static unsigned long pll_recalc(struct clk *clk)
+{
+ unsigned long mult = 1;
+
+ if (__raw_readl(PLLECR) & (1 << clk->enable_bit)) {
+ mult = (((__raw_readl(clk->enable_reg) >> 24) & 0x3f) + 1);
+ /* handle CFG bit for PLL1 and PLL2 */
+ switch (clk->enable_bit) {
+ case 1:
+ case 2:
+ if (__raw_readl(clk->enable_reg) & (1 << 20))
+ mult *= 2;
+ }
+ }
+
+ return clk->parent->rate * mult;
+}
+
+static struct sh_clk_ops pll_clk_ops = {
+ .recalc = pll_recalc,
+};
+
+static struct clk pll0_clk = {
+ .ops = &pll_clk_ops,
+ .flags = CLK_ENABLE_ON_INIT,
+ .parent = &main_clk,
+ .enable_reg = (void __iomem *)PLL0CR,
+ .enable_bit = 0,
+};
+
+static struct clk pll1_clk = {
+ .ops = &pll_clk_ops,
+ .flags = CLK_ENABLE_ON_INIT,
+ .parent = &main_clk,
+ .enable_reg = (void __iomem *)PLL1CR,
+ .enable_bit = 1,
+};
+
+static struct clk pll2_clk = {
+ .ops = &pll_clk_ops,
+ .flags = CLK_ENABLE_ON_INIT,
+ .parent = &main_clk,
+ .enable_reg = (void __iomem *)PLL2CR,
+ .enable_bit = 2,
+};
+
+static struct clk pll3_clk = {
+ .ops = &pll_clk_ops,
+ .flags = CLK_ENABLE_ON_INIT,
+ .parent = &main_clk,
+ .enable_reg = (void __iomem *)PLL3CR,
+ .enable_bit = 3,
+};
+
+/* A fixed divide block */
+SH_CLK_RATIO(div2, 1, 2);
+SH_CLK_RATIO(div7, 1, 7);
+SH_CLK_RATIO(div13, 1, 13);
+
+SH_FIXED_RATIO_CLK(extal1_div2_clk, sh73a0_extal1_clk, div2);
+SH_FIXED_RATIO_CLK(extal2_div2_clk, sh73a0_extal2_clk, div2);
+SH_FIXED_RATIO_CLK(main_div2_clk, main_clk, div2);
+SH_FIXED_RATIO_CLK(pll1_div2_clk, pll1_clk, div2);
+SH_FIXED_RATIO_CLK(pll1_div7_clk, pll1_clk, div7);
+SH_FIXED_RATIO_CLK(pll1_div13_clk, pll1_clk, div13);
+
+/* External input clock */
+struct clk sh73a0_extcki_clk = {
+};
+
+struct clk sh73a0_extalr_clk = {
+};
+
+static struct clk *main_clks[] = {
+ &r_clk,
+ &sh73a0_extal1_clk,
+ &sh73a0_extal2_clk,
+ &extal1_div2_clk,
+ &extal2_div2_clk,
+ &main_clk,
+ &main_div2_clk,
+ &pll0_clk,
+ &pll1_clk,
+ &pll2_clk,
+ &pll3_clk,
+ &pll1_div2_clk,
+ &pll1_div7_clk,
+ &pll1_div13_clk,
+ &sh73a0_extcki_clk,
+ &sh73a0_extalr_clk,
+};
+
+static int frqcr_kick(void)
+{
+ int i;
+
+ /* set KICK bit in FRQCRB to update hardware setting, check success */
+ __raw_writel(__raw_readl(FRQCRB) | (1 << 31), FRQCRB);
+ for (i = 1000; i; i--)
+ if (__raw_readl(FRQCRB) & (1 << 31))
+ cpu_relax();
+ else
+ return i;
+
+ return -ETIMEDOUT;
+}
+
+static void div4_kick(struct clk *clk)
+{
+ frqcr_kick();
+}
+
+static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
+ 24, 0, 36, 48, 7 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+ .divisors = divisors,
+ .nr_divisors = ARRAY_SIZE(divisors),
+};
+
+static struct clk_div4_table div4_table = {
+ .div_mult_table = &div4_div_mult_table,
+ .kick = div4_kick,
+};
+
+enum { DIV4_I, DIV4_ZG, DIV4_M3, DIV4_B, DIV4_M1, DIV4_M2,
+ DIV4_Z, DIV4_ZX, DIV4_HP, DIV4_NR };
+
+#define DIV4(_reg, _bit, _mask, _flags) \
+ SH_CLK_DIV4(&pll1_clk, _reg, _bit, _mask, _flags)
+
+static struct clk div4_clks[DIV4_NR] = {
+ [DIV4_I] = DIV4(FRQCRA, 20, 0xdff, CLK_ENABLE_ON_INIT),
+ /*
+ * ZG clock is dividing PLL0 frequency to supply SGX. Make sure not to
+ * exceed maximum frequencies of 201.5MHz for VDD_DVFS=1.175 and
+ * 239.2MHz for VDD_DVFS=1.315V.
+ */
+ [DIV4_ZG] = SH_CLK_DIV4(&pll0_clk, FRQCRA, 16, 0xd7f, CLK_ENABLE_ON_INIT),
+ [DIV4_M3] = DIV4(FRQCRA, 12, 0x1dff, CLK_ENABLE_ON_INIT),
+ [DIV4_B] = DIV4(FRQCRA, 8, 0xdff, CLK_ENABLE_ON_INIT),
+ [DIV4_M1] = DIV4(FRQCRA, 4, 0x1dff, 0),
+ [DIV4_M2] = DIV4(FRQCRA, 0, 0x1dff, 0),
+ [DIV4_Z] = SH_CLK_DIV4(&pll0_clk, FRQCRB, 24, 0x97f, 0),
+ [DIV4_ZX] = DIV4(FRQCRB, 12, 0xdff, 0),
+ [DIV4_HP] = DIV4(FRQCRB, 4, 0xdff, 0),
+};
+
+static unsigned long twd_recalc(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 4;
+}
+
+static struct sh_clk_ops twd_clk_ops = {
+ .recalc = twd_recalc,
+};
+
+static struct clk twd_clk = {
+ .parent = &div4_clks[DIV4_Z],
+ .ops = &twd_clk_ops,
+};
+
+static struct sh_clk_ops zclk_ops, kicker_ops;
+static const struct sh_clk_ops *div4_clk_ops;
+
+static int zclk_set_rate(struct clk *clk, unsigned long rate)
+{
+ int ret;
+
+ if (!clk->parent || !__clk_get(clk->parent))
+ return -ENODEV;
+
+ if (readl(FRQCRB) & (1 << 31))
+ return -EBUSY;
+
+ if (rate == clk_get_rate(clk->parent)) {
+ /* 1:1 - switch off divider */
+ __raw_writel(__raw_readl(FRQCRB) & ~(1 << 28), FRQCRB);
+ /* nullify the divider to prepare for the next time */
+ ret = div4_clk_ops->set_rate(clk, rate / 2);
+ if (!ret)
+ ret = frqcr_kick();
+ if (ret > 0)
+ ret = 0;
+ } else {
+ /* Enable the divider */
+ __raw_writel(__raw_readl(FRQCRB) | (1 << 28), FRQCRB);
+
+ ret = frqcr_kick();
+ if (ret >= 0)
+ /*
+ * set the divider - call the DIV4 method, it will kick
+ * FRQCRB too
+ */
+ ret = div4_clk_ops->set_rate(clk, rate);
+ if (ret < 0)
+ goto esetrate;
+ }
+
+esetrate:
+ __clk_put(clk->parent);
+ return ret;
+}
+
+static long zclk_round_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long div_freq = div4_clk_ops->round_rate(clk, rate),
+ parent_freq = clk_get_rate(clk->parent);
+
+ if (rate > div_freq && abs(parent_freq - rate) < rate - div_freq)
+ return parent_freq;
+
+ return div_freq;
+}
+
+static unsigned long zclk_recalc(struct clk *clk)
+{
+ /*
+ * Must recalculate frequencies in case PLL0 has been changed, even if
+ * the divisor is unused ATM!
+ */
+ unsigned long div_freq = div4_clk_ops->recalc(clk);
+
+ if (__raw_readl(FRQCRB) & (1 << 28))
+ return div_freq;
+
+ return clk_get_rate(clk->parent);
+}
+
+static int kicker_set_rate(struct clk *clk, unsigned long rate)
+{
+ if (__raw_readl(FRQCRB) & (1 << 31))
+ return -EBUSY;
+
+ return div4_clk_ops->set_rate(clk, rate);
+}
+
+static void div4_clk_extend(void)
+{
+ int i;
+
+ div4_clk_ops = div4_clks[0].ops;
+
+ /* Add a kicker-busy check before changing the rate */
+ kicker_ops = *div4_clk_ops;
+ /* We extend the DIV4 clock with a 1:1 pass-through case */
+ zclk_ops = *div4_clk_ops;
+
+ kicker_ops.set_rate = kicker_set_rate;
+ zclk_ops.set_rate = zclk_set_rate;
+ zclk_ops.round_rate = zclk_round_rate;
+ zclk_ops.recalc = zclk_recalc;
+
+ for (i = 0; i < DIV4_NR; i++)
+ div4_clks[i].ops = i == DIV4_Z ? &zclk_ops : &kicker_ops;
+}
+
+enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_ZB1,
+ DIV6_FLCTL, DIV6_SDHI0, DIV6_SDHI1, DIV6_SDHI2,
+ DIV6_FSIA, DIV6_FSIB, DIV6_SUB,
+ DIV6_SPUA, DIV6_SPUV, DIV6_MSU,
+ DIV6_HSI, DIV6_MFG1, DIV6_MFG2,
+ DIV6_DSIT, DIV6_DSI0P, DIV6_DSI1P,
+ DIV6_NR };
+
+static struct clk *vck_parent[8] = {
+ [0] = &pll1_div2_clk,
+ [1] = &pll2_clk,
+ [2] = &sh73a0_extcki_clk,
+ [3] = &sh73a0_extal2_clk,
+ [4] = &main_div2_clk,
+ [5] = &sh73a0_extalr_clk,
+ [6] = &main_clk,
+};
+
+static struct clk *pll_parent[4] = {
+ [0] = &pll1_div2_clk,
+ [1] = &pll2_clk,
+ [2] = &pll1_div13_clk,
+};
+
+static struct clk *hsi_parent[4] = {
+ [0] = &pll1_div2_clk,
+ [1] = &pll2_clk,
+ [2] = &pll1_div7_clk,
+};
+
+static struct clk *pll_extal2_parent[] = {
+ [0] = &pll1_div2_clk,
+ [1] = &pll2_clk,
+ [2] = &sh73a0_extal2_clk,
+ [3] = &sh73a0_extal2_clk,
+};
+
+static struct clk *dsi_parent[8] = {
+ [0] = &pll1_div2_clk,
+ [1] = &pll2_clk,
+ [2] = &main_clk,
+ [3] = &sh73a0_extal2_clk,
+ [4] = &sh73a0_extcki_clk,
+};
+
+static struct clk div6_clks[DIV6_NR] = {
+ [DIV6_VCK1] = SH_CLK_DIV6_EXT(VCLKCR1, 0,
+ vck_parent, ARRAY_SIZE(vck_parent), 12, 3),
+ [DIV6_VCK2] = SH_CLK_DIV6_EXT(VCLKCR2, 0,
+ vck_parent, ARRAY_SIZE(vck_parent), 12, 3),
+ [DIV6_VCK3] = SH_CLK_DIV6_EXT(VCLKCR3, 0,
+ vck_parent, ARRAY_SIZE(vck_parent), 12, 3),
+ [DIV6_ZB1] = SH_CLK_DIV6_EXT(ZBCKCR, CLK_ENABLE_ON_INIT,
+ pll_parent, ARRAY_SIZE(pll_parent), 7, 1),
+ [DIV6_FLCTL] = SH_CLK_DIV6_EXT(FLCKCR, 0,
+ pll_parent, ARRAY_SIZE(pll_parent), 7, 1),
+ [DIV6_SDHI0] = SH_CLK_DIV6_EXT(SD0CKCR, 0,
+ pll_parent, ARRAY_SIZE(pll_parent), 6, 2),
+ [DIV6_SDHI1] = SH_CLK_DIV6_EXT(SD1CKCR, 0,
+ pll_parent, ARRAY_SIZE(pll_parent), 6, 2),
+ [DIV6_SDHI2] = SH_CLK_DIV6_EXT(SD2CKCR, 0,
+ pll_parent, ARRAY_SIZE(pll_parent), 6, 2),
+ [DIV6_FSIA] = SH_CLK_DIV6_EXT(FSIACKCR, 0,
+ pll_parent, ARRAY_SIZE(pll_parent), 6, 1),
+ [DIV6_FSIB] = SH_CLK_DIV6_EXT(FSIBCKCR, 0,
+ pll_parent, ARRAY_SIZE(pll_parent), 6, 1),
+ [DIV6_SUB] = SH_CLK_DIV6_EXT(SUBCKCR, 0,
+ pll_extal2_parent, ARRAY_SIZE(pll_extal2_parent), 6, 2),
+ [DIV6_SPUA] = SH_CLK_DIV6_EXT(SPUACKCR, 0,
+ pll_extal2_parent, ARRAY_SIZE(pll_extal2_parent), 6, 2),
+ [DIV6_SPUV] = SH_CLK_DIV6_EXT(SPUVCKCR, 0,
+ pll_extal2_parent, ARRAY_SIZE(pll_extal2_parent), 6, 2),
+ [DIV6_MSU] = SH_CLK_DIV6_EXT(MSUCKCR, 0,
+ pll_parent, ARRAY_SIZE(pll_parent), 7, 1),
+ [DIV6_HSI] = SH_CLK_DIV6_EXT(HSICKCR, 0,
+ hsi_parent, ARRAY_SIZE(hsi_parent), 6, 2),
+ [DIV6_MFG1] = SH_CLK_DIV6_EXT(MFCK1CR, 0,
+ pll_parent, ARRAY_SIZE(pll_parent), 7, 1),
+ [DIV6_MFG2] = SH_CLK_DIV6_EXT(MFCK2CR, 0,
+ pll_parent, ARRAY_SIZE(pll_parent), 7, 1),
+ [DIV6_DSIT] = SH_CLK_DIV6_EXT(DSITCKCR, 0,
+ pll_parent, ARRAY_SIZE(pll_parent), 7, 1),
+ [DIV6_DSI0P] = SH_CLK_DIV6_EXT(DSI0PCKCR, 0,
+ dsi_parent, ARRAY_SIZE(dsi_parent), 12, 3),
+ [DIV6_DSI1P] = SH_CLK_DIV6_EXT(DSI1PCKCR, 0,
+ dsi_parent, ARRAY_SIZE(dsi_parent), 12, 3),
+};
+
+/* DSI DIV */
+static unsigned long dsiphy_recalc(struct clk *clk)
+{
+ u32 value;
+
+ value = __raw_readl(clk->mapping->base);
+
+ /* FIXME */
+ if (!(value & 0x000B8000))
+ return clk->parent->rate;
+
+ value &= 0x3f;
+ value += 1;
+
+ if ((value < 12) ||
+ (value > 33)) {
+ pr_err("DSIPHY has wrong value (%d)", value);
+ return 0;
+ }
+
+ return clk->parent->rate / value;
+}
+
+static long dsiphy_round_rate(struct clk *clk, unsigned long rate)
+{
+ return clk_rate_mult_range_round(clk, 12, 33, rate);
+}
+
+static void dsiphy_disable(struct clk *clk)
+{
+ u32 value;
+
+ value = __raw_readl(clk->mapping->base);
+ value &= ~0x000B8000;
+
+ __raw_writel(value , clk->mapping->base);
+}
+
+static int dsiphy_enable(struct clk *clk)
+{
+ u32 value;
+ int multi;
+
+ value = __raw_readl(clk->mapping->base);
+ multi = (value & 0x3f) + 1;
+
+ if ((multi < 12) || (multi > 33))
+ return -EIO;
+
+ __raw_writel(value | 0x000B8000, clk->mapping->base);
+
+ return 0;
+}
+
+static int dsiphy_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 value;
+ int idx;
+
+ idx = rate / clk->parent->rate;
+ if ((idx < 12) || (idx > 33))
+ return -EINVAL;
+
+ idx += -1;
+
+ value = __raw_readl(clk->mapping->base);
+ value = (value & ~0x3f) + idx;
+
+ __raw_writel(value, clk->mapping->base);
+
+ return 0;
+}
+
+static struct sh_clk_ops dsiphy_clk_ops = {
+ .recalc = dsiphy_recalc,
+ .round_rate = dsiphy_round_rate,
+ .set_rate = dsiphy_set_rate,
+ .enable = dsiphy_enable,
+ .disable = dsiphy_disable,
+};
+
+static struct clk_mapping dsi0phy_clk_mapping = {
+ .phys = DSI0PHYCR,
+ .len = 4,
+};
+
+static struct clk_mapping dsi1phy_clk_mapping = {
+ .phys = DSI1PHYCR,
+ .len = 4,
+};
+
+static struct clk dsi0phy_clk = {
+ .ops = &dsiphy_clk_ops,
+ .parent = &div6_clks[DIV6_DSI0P], /* late install */
+ .mapping = &dsi0phy_clk_mapping,
+};
+
+static struct clk dsi1phy_clk = {
+ .ops = &dsiphy_clk_ops,
+ .parent = &div6_clks[DIV6_DSI1P], /* late install */
+ .mapping = &dsi1phy_clk_mapping,
+};
+
+static struct clk *late_main_clks[] = {
+ &dsi0phy_clk,
+ &dsi1phy_clk,
+ &twd_clk,
+};
+
+enum { MSTP001,
+ MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, MSTP118, MSTP116, MSTP112, MSTP100,
+ MSTP219, MSTP218, MSTP217,
+ MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
+ MSTP331, MSTP329, MSTP328, MSTP325, MSTP323, MSTP322,
+ MSTP314, MSTP313, MSTP312, MSTP311,
+ MSTP304, MSTP303, MSTP302, MSTP301, MSTP300,
+ MSTP411, MSTP410, MSTP403,
+ MSTP508,
+ MSTP_NR };
+
+#define MSTP(_parent, _reg, _bit, _flags) \
+ SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
+
+static struct clk mstp_clks[MSTP_NR] = {
+ [MSTP001] = MSTP(&div4_clks[DIV4_HP], SMSTPCR0, 1, 0), /* IIC2 */
+ [MSTP129] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 29, 0), /* CEU1 */
+ [MSTP128] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 28, 0), /* CSI2-RX1 */
+ [MSTP127] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 27, 0), /* CEU0 */
+ [MSTP126] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 26, 0), /* CSI2-RX0 */
+ [MSTP125] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */
+ [MSTP118] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 18, 0), /* DSITX0 */
+ [MSTP116] = MSTP(&div4_clks[DIV4_HP], SMSTPCR1, 16, 0), /* IIC0 */
+ [MSTP112] = MSTP(&div4_clks[DIV4_ZG], SMSTPCR1, 12, 0), /* SGX */
+ [MSTP100] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */
+ [MSTP219] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 19, 0), /* SCIFA7 */
+ [MSTP218] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* SY-DMAC */
+ [MSTP217] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 17, 0), /* MP-DMAC */
+ [MSTP207] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */
+ [MSTP206] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */
+ [MSTP204] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */
+ [MSTP203] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 3, 0), /* SCIFA1 */
+ [MSTP202] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 2, 0), /* SCIFA2 */
+ [MSTP201] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */
+ [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */
+ [MSTP331] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 31, 0), /* SCIFA6 */
+ [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
+ [MSTP328] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /*FSI*/
+ [MSTP325] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 25, 0), /* IrDA */
+ [MSTP323] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 23, 0), /* IIC1 */
+ [MSTP322] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 22, 0), /* USB */
+ [MSTP314] = MSTP(&div6_clks[DIV6_SDHI0], SMSTPCR3, 14, 0), /* SDHI0 */
+ [MSTP313] = MSTP(&div6_clks[DIV6_SDHI1], SMSTPCR3, 13, 0), /* SDHI1 */
+ [MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMCIF0 */
+ [MSTP311] = MSTP(&div6_clks[DIV6_SDHI2], SMSTPCR3, 11, 0), /* SDHI2 */
+ [MSTP304] = MSTP(&main_div2_clk, SMSTPCR3, 4, 0), /* TPU0 */
+ [MSTP303] = MSTP(&main_div2_clk, SMSTPCR3, 3, 0), /* TPU1 */
+ [MSTP302] = MSTP(&main_div2_clk, SMSTPCR3, 2, 0), /* TPU2 */
+ [MSTP301] = MSTP(&main_div2_clk, SMSTPCR3, 1, 0), /* TPU3 */
+ [MSTP300] = MSTP(&main_div2_clk, SMSTPCR3, 0, 0), /* TPU4 */
+ [MSTP411] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 11, 0), /* IIC3 */
+ [MSTP410] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 10, 0), /* IIC4 */
+ [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */
+ [MSTP508] = MSTP(&div4_clks[DIV4_HP], SMSTPCR5, 8, 0), /* INTCA0 */
+};
+
+/* The lookups structure below includes duplicate entries for some clocks
+ * with alternate names.
+ * - The traditional name used when a device is initialised with platform data
+ * - The name used when a device is initialised using device tree
+ * The longer-term aim is to remove these duplicates, and indeed the
+ * lookups table entirely, by describing clocks using device tree.
+ */
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("r_clk", &r_clk),
+ CLKDEV_DEV_ID("smp_twd", &twd_clk), /* smp_twd */
+
+ /* DIV4 clocks */
+ CLKDEV_DEV_ID("cpu0", &div4_clks[DIV4_Z]),
+
+ /* DIV6 clocks */
+ CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]),
+ CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]),
+ CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]),
+ CLKDEV_CON_ID("sdhi0_clk", &div6_clks[DIV6_SDHI0]),
+ CLKDEV_CON_ID("sdhi1_clk", &div6_clks[DIV6_SDHI1]),
+ CLKDEV_CON_ID("sdhi2_clk", &div6_clks[DIV6_SDHI2]),
+
+ /* MSTP32 clocks */
+ CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* I2C2 */
+ CLKDEV_DEV_ID("e6824000.i2c", &mstp_clks[MSTP001]), /* I2C2 */
+ CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP129]), /* CEU1 */
+ CLKDEV_DEV_ID("sh-mobile-csi2.1", &mstp_clks[MSTP128]), /* CSI2-RX1 */
+ CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), /* CEU0 */
+ CLKDEV_DEV_ID("sh-mobile-csi2.0", &mstp_clks[MSTP126]), /* CSI2-RX0 */
+ CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */
+ CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* I2C0 */
+ CLKDEV_DEV_ID("e6820000.i2c", &mstp_clks[MSTP116]), /* I2C0 */
+ CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */
+ CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP219]), /* SCIFA7 */
+ CLKDEV_DEV_ID("e6cd0000.serial", &mstp_clks[MSTP219]), /* SCIFA7 */
+ CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), /* SY-DMAC */
+ CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]), /* MP-DMAC */
+ CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */
+ CLKDEV_DEV_ID("e6cb0000.serial", &mstp_clks[MSTP207]), /* SCIFA5 */
+ CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]), /* SCIFB */
+ CLKDEV_DEV_ID("e6c3000.serial", &mstp_clks[MSTP206]), /* SCIFB */
+ CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */
+ CLKDEV_DEV_ID("e6c40000.serial", &mstp_clks[MSTP204]), /* SCIFA0 */
+ CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), /* SCIFA1 */
+ CLKDEV_DEV_ID("e6c50000.serial", &mstp_clks[MSTP203]), /* SCIFA1 */
+ CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */
+ CLKDEV_DEV_ID("e6c60000.serial", &mstp_clks[MSTP202]), /* SCIFA2 */
+ CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */
+ CLKDEV_DEV_ID("e6c70000.serial", &mstp_clks[MSTP201]), /* SCIFA3 */
+ CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
+ CLKDEV_DEV_ID("e6c80000.serial", &mstp_clks[MSTP200]), /* SCIFA4 */
+ CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */
+ CLKDEV_DEV_ID("e6cc0000.serial", &mstp_clks[MSTP331]), /* SCIFA6 */
+ CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI */
+ CLKDEV_DEV_ID("ec230000.sound", &mstp_clks[MSTP328]), /* FSI */
+ CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */
+ CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */
+ CLKDEV_DEV_ID("e6822000.i2c", &mstp_clks[MSTP323]), /* I2C1 */
+ CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP322]), /* USB */
+ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
+ CLKDEV_DEV_ID("ee100000.sd", &mstp_clks[MSTP314]), /* SDHI0 */
+ CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
+ CLKDEV_DEV_ID("ee120000.sd", &mstp_clks[MSTP313]), /* SDHI1 */
+ CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */
+ CLKDEV_DEV_ID("e6bd0000.mmc", &mstp_clks[MSTP312]), /* MMCIF0 */
+ CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]), /* SDHI2 */
+ CLKDEV_DEV_ID("ee140000.sd", &mstp_clks[MSTP311]), /* SDHI2 */
+ CLKDEV_DEV_ID("renesas-tpu-pwm.0", &mstp_clks[MSTP304]), /* TPU0 */
+ CLKDEV_DEV_ID("renesas-tpu-pwm.1", &mstp_clks[MSTP303]), /* TPU1 */
+ CLKDEV_DEV_ID("renesas-tpu-pwm.2", &mstp_clks[MSTP302]), /* TPU2 */
+ CLKDEV_DEV_ID("renesas-tpu-pwm.3", &mstp_clks[MSTP301]), /* TPU3 */
+ CLKDEV_DEV_ID("renesas-tpu-pwm.4", &mstp_clks[MSTP300]), /* TPU4 */
+ CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* I2C3 */
+ CLKDEV_DEV_ID("e6826000.i2c", &mstp_clks[MSTP411]), /* I2C3 */
+ CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */
+ CLKDEV_DEV_ID("e6828000.i2c", &mstp_clks[MSTP410]), /* I2C4 */
+ CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
+ CLKDEV_DEV_ID("renesas_intc_irqpin.0", &mstp_clks[MSTP508]), /* INTCA0 */
+ CLKDEV_DEV_ID("e6900000.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */
+ CLKDEV_DEV_ID("renesas_intc_irqpin.1", &mstp_clks[MSTP508]), /* INTCA0 */
+ CLKDEV_DEV_ID("e6900004.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */
+ CLKDEV_DEV_ID("renesas_intc_irqpin.2", &mstp_clks[MSTP508]), /* INTCA0 */
+ CLKDEV_DEV_ID("e6900008.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */
+ CLKDEV_DEV_ID("renesas_intc_irqpin.3", &mstp_clks[MSTP508]), /* INTCA0 */
+ CLKDEV_DEV_ID("e690000c.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */
+
+ /* ICK */
+ CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]),
+ CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]),
+ CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]),
+ CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]),
+ CLKDEV_ICK_ID("dsiphy_clk", "sh-mipi-dsi.0", &dsi0phy_clk),
+ CLKDEV_ICK_ID("dsiphy_clk", "sh-mipi-dsi.1", &dsi1phy_clk),
+ CLKDEV_ICK_ID("fck", "sh-cmt-48.1", &mstp_clks[MSTP329]), /* CMT1 */
+ CLKDEV_ICK_ID("fck", "e6138000.timer", &mstp_clks[MSTP329]), /* CMT1 */
+ CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP125]), /* TMU0 */
+};
+
+void __init sh73a0_clock_init(void)
+{
+ int k, ret = 0;
+
+ /* Set SDHI clocks to a known state */
+ __raw_writel(0x108, SD0CKCR);
+ __raw_writel(0x108, SD1CKCR);
+ __raw_writel(0x108, SD2CKCR);
+
+ /* detect main clock parent */
+ switch ((__raw_readl(CKSCR) >> 28) & 0x03) {
+ case 0:
+ main_clk.parent = &sh73a0_extal1_clk;
+ break;
+ case 1:
+ main_clk.parent = &extal1_div2_clk;
+ break;
+ case 2:
+ main_clk.parent = &sh73a0_extal2_clk;
+ break;
+ case 3:
+ main_clk.parent = &extal2_div2_clk;
+ break;
+ }
+
+ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+ ret = clk_register(main_clks[k]);
+
+ if (!ret) {
+ ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+ if (!ret)
+ div4_clk_extend();
+ }
+
+ if (!ret)
+ ret = sh_clk_div6_reparent_register(div6_clks, DIV6_NR);
+
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+ for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
+ ret = clk_register(late_main_clks[k]);
+
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+ if (!ret)
+ shmobile_clk_init();
+ else
+ panic("failed to setup sh73a0 clocks\n");
+}
diff --git a/arch/arm/mach-shmobile/clock.c b/arch/arm/mach-shmobile/clock.c
new file mode 100644
index 000000000..68c2d06d0
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock.c
@@ -0,0 +1,47 @@
+/*
+ * SH-Mobile Clock Framework
+ *
+ * Copyright (C) 2010 Magnus Damm
+ *
+ * Used together with arch/arm/common/clkdev.c and drivers/sh/clk.c.
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sh_clk.h>
+
+#include "clock.h"
+#include "common.h"
+
+unsigned long shmobile_fixed_ratio_clk_recalc(struct clk *clk)
+{
+ struct clk_ratio *p = clk->priv;
+
+ return clk->parent->rate / p->div * p->mul;
+};
+
+struct sh_clk_ops shmobile_fixed_ratio_clk_ops = {
+ .recalc = shmobile_fixed_ratio_clk_recalc,
+};
+
+int __init shmobile_clk_init(void)
+{
+ /* Kick the child clocks.. */
+ recalculate_root_clocks();
+
+ /* Enable the necessary init clocks */
+ clk_enable_init_clocks();
+
+ return 0;
+}
diff --git a/arch/arm/mach-shmobile/clock.h b/arch/arm/mach-shmobile/clock.h
new file mode 100644
index 000000000..cf3552ea1
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock.h
@@ -0,0 +1,42 @@
+#ifndef CLOCK_H
+#define CLOCK_H
+
+/* legacy clock implementation */
+
+struct clk;
+unsigned long shmobile_fixed_ratio_clk_recalc(struct clk *clk);
+extern struct sh_clk_ops shmobile_fixed_ratio_clk_ops;
+
+/* clock ratio */
+struct clk_ratio {
+ int mul;
+ int div;
+};
+
+#define SH_CLK_RATIO(name, m, d) \
+static struct clk_ratio name ##_ratio = { \
+ .mul = m, \
+ .div = d, \
+}
+
+#define SH_FIXED_RATIO_CLKg(name, p, r) \
+struct clk name = { \
+ .parent = &p, \
+ .ops = &shmobile_fixed_ratio_clk_ops,\
+ .priv = &r ## _ratio, \
+}
+
+#define SH_FIXED_RATIO_CLK(name, p, r) \
+static SH_FIXED_RATIO_CLKg(name, p, r)
+
+#define SH_FIXED_RATIO_CLK_SET(name, p, m, d) \
+ SH_CLK_RATIO(name, m, d); \
+ SH_FIXED_RATIO_CLK(name, p, name)
+
+#define SH_CLK_SET_RATIO(p, m, d) \
+do { \
+ (p)->mul = m; \
+ (p)->div = d; \
+} while (0)
+
+#endif
diff --git a/arch/arm/mach-shmobile/common.h b/arch/arm/mach-shmobile/common.h
new file mode 100644
index 000000000..afc60bad6
--- /dev/null
+++ b/arch/arm/mach-shmobile/common.h
@@ -0,0 +1,48 @@
+#ifndef __ARCH_MACH_COMMON_H
+#define __ARCH_MACH_COMMON_H
+
+extern void shmobile_earlytimer_init(void);
+extern void shmobile_init_delay(void);
+struct twd_local_timer;
+extern void shmobile_setup_console(void);
+extern void shmobile_boot_vector(void);
+extern unsigned long shmobile_boot_fn;
+extern unsigned long shmobile_boot_arg;
+extern unsigned long shmobile_boot_size;
+extern void shmobile_smp_boot(void);
+extern void shmobile_smp_sleep(void);
+extern void shmobile_smp_hook(unsigned int cpu, unsigned long fn,
+ unsigned long arg);
+extern int shmobile_smp_cpu_disable(unsigned int cpu);
+extern void shmobile_invalidate_start(void);
+extern void shmobile_boot_scu(void);
+extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus);
+extern void shmobile_smp_scu_cpu_die(unsigned int cpu);
+extern int shmobile_smp_scu_cpu_kill(unsigned int cpu);
+struct clk;
+extern int shmobile_clk_init(void);
+extern struct platform_suspend_ops shmobile_suspend_ops;
+
+#ifdef CONFIG_SUSPEND
+int shmobile_suspend_init(void);
+void shmobile_smp_apmu_suspend_init(void);
+#else
+static inline int shmobile_suspend_init(void) { return 0; }
+static inline void shmobile_smp_apmu_suspend_init(void) { }
+#endif
+
+#ifdef CONFIG_CPU_FREQ
+int shmobile_cpufreq_init(void);
+#else
+static inline int shmobile_cpufreq_init(void) { return 0; }
+#endif
+
+extern void __iomem *shmobile_scu_base;
+
+static inline void __init shmobile_init_late(void)
+{
+ shmobile_suspend_init();
+ shmobile_cpufreq_init();
+}
+
+#endif /* __ARCH_MACH_COMMON_H */
diff --git a/arch/arm/mach-shmobile/console.c b/arch/arm/mach-shmobile/console.c
new file mode 100644
index 000000000..e329ccbd0
--- /dev/null
+++ b/arch/arm/mach-shmobile/console.c
@@ -0,0 +1,27 @@
+/*
+ * SH-Mobile Console
+ *
+ * Copyright (C) 2010 Magnus Damm
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <asm/mach/map.h>
+#include "common.h"
+
+void __init shmobile_setup_console(void)
+{
+ parse_early_param();
+
+ /* Let earlyprintk output early console messages */
+ early_platform_driver_probe("earlyprintk", 1, 1);
+}
diff --git a/arch/arm/mach-shmobile/cpufreq.c b/arch/arm/mach-shmobile/cpufreq.c
new file mode 100644
index 000000000..57fbff024
--- /dev/null
+++ b/arch/arm/mach-shmobile/cpufreq.c
@@ -0,0 +1,17 @@
+/*
+ * CPUFreq support code for SH-Mobile ARM
+ *
+ * Copyright (C) 2014 Gaku Inami
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/platform_device.h>
+
+int __init shmobile_cpufreq_init(void)
+{
+ platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
+ return 0;
+}
diff --git a/arch/arm/mach-shmobile/dma-register.h b/arch/arm/mach-shmobile/dma-register.h
new file mode 100644
index 000000000..52a2f66e6
--- /dev/null
+++ b/arch/arm/mach-shmobile/dma-register.h
@@ -0,0 +1,84 @@
+/*
+ * SH-ARM CPU-specific DMA definitions, used by both DMA drivers
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp
+ *
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * Based on arch/sh/include/cpu-sh4/cpu/dma-register.h
+ * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef DMA_REGISTER_H
+#define DMA_REGISTER_H
+
+/*
+ * Direct Memory Access Controller
+ */
+
+/* Transmit sizes and respective CHCR register values */
+enum {
+ XMIT_SZ_8BIT = 0,
+ XMIT_SZ_16BIT = 1,
+ XMIT_SZ_32BIT = 2,
+ XMIT_SZ_64BIT = 7,
+ XMIT_SZ_128BIT = 3,
+ XMIT_SZ_256BIT = 4,
+ XMIT_SZ_512BIT = 5,
+};
+
+/* log2(size / 8) - used to calculate number of transfers */
+static const unsigned int dma_ts_shift[] = {
+ [XMIT_SZ_8BIT] = 0,
+ [XMIT_SZ_16BIT] = 1,
+ [XMIT_SZ_32BIT] = 2,
+ [XMIT_SZ_64BIT] = 3,
+ [XMIT_SZ_128BIT] = 4,
+ [XMIT_SZ_256BIT] = 5,
+ [XMIT_SZ_512BIT] = 6,
+};
+
+#define TS_LOW_BIT 0x3 /* --xx */
+#define TS_HI_BIT 0xc /* xx-- */
+
+#define TS_LOW_SHIFT (3)
+#define TS_HI_SHIFT (20 - 2) /* 2 bits for shifted low TS */
+
+#define TS_INDEX2VAL(i) \
+ ((((i) & TS_LOW_BIT) << TS_LOW_SHIFT) |\
+ (((i) & TS_HI_BIT) << TS_HI_SHIFT))
+
+#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL((xmit_sz)))
+#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL((xmit_sz)))
+
+
+/*
+ * USB High-Speed DMAC
+ */
+/* Transmit sizes and respective CHCR register values */
+enum {
+ USBTS_XMIT_SZ_8BYTE = 0,
+ USBTS_XMIT_SZ_16BYTE = 1,
+ USBTS_XMIT_SZ_32BYTE = 2,
+};
+
+/* log2(size / 8) - used to calculate number of transfers */
+static const unsigned int dma_usbts_shift[] = {
+ [USBTS_XMIT_SZ_8BYTE] = 3,
+ [USBTS_XMIT_SZ_16BYTE] = 4,
+ [USBTS_XMIT_SZ_32BYTE] = 5,
+};
+
+#define USBTS_LOW_BIT 0x3 /* --xx */
+#define USBTS_HI_BIT 0x0 /* ---- */
+
+#define USBTS_LOW_SHIFT 6
+#define USBTS_HI_SHIFT 0
+
+#define USBTS_INDEX2VAL(i) (((i) & 3) << 6)
+
+#endif /* DMA_REGISTER_H */
diff --git a/arch/arm/mach-shmobile/headsmp-scu.S b/arch/arm/mach-shmobile/headsmp-scu.S
new file mode 100644
index 000000000..69df8bfac
--- /dev/null
+++ b/arch/arm/mach-shmobile/headsmp-scu.S
@@ -0,0 +1,46 @@
+/*
+ * Shared SCU setup for mach-shmobile
+ *
+ * Copyright (C) 2012 Bastian Hecht
+ *
+ * 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.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/memory.h>
+
+/*
+ * Boot code for secondary CPUs.
+ *
+ * First we turn on L1 cache coherency for our CPU. Then we jump to
+ * shmobile_invalidate_start that invalidates the cache and hands over control
+ * to the common ARM startup code.
+ */
+ENTRY(shmobile_boot_scu)
+ @ r0 = SCU base address
+ mrc p15, 0, r1, c0, c0, 5 @ read MIPDR
+ and r1, r1, #3 @ mask out cpu ID
+ lsl r1, r1, #3 @ we will shift by cpu_id * 8 bits
+ ldr r2, [r0, #8] @ SCU Power Status Register
+ mov r3, #3
+ lsl r3, r3, r1
+ bic r2, r2, r3 @ Clear bits of our CPU (Run Mode)
+ str r2, [r0, #8] @ write back
+
+ b shmobile_invalidate_start
+ENDPROC(shmobile_boot_scu)
+
+ .text
+ .align 2
+ .globl shmobile_scu_base
+shmobile_scu_base:
+ .space 4
diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S
new file mode 100644
index 000000000..50c491567
--- /dev/null
+++ b/arch/arm/mach-shmobile/headsmp.S
@@ -0,0 +1,98 @@
+/*
+ * SMP support for R-Mobile / SH-Mobile
+ *
+ * Copyright (C) 2010 Magnus Damm
+ * Copyright (C) 2010 Takashi Yoshii
+ *
+ * Based on vexpress, Copyright (c) 2003 ARM Limited, All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/threads.h>
+#include <asm/assembler.h>
+#include <asm/memory.h>
+
+#ifdef CONFIG_SMP
+ENTRY(shmobile_invalidate_start)
+ bl v7_invalidate_l1
+ b secondary_startup
+ENDPROC(shmobile_invalidate_start)
+#endif
+
+/*
+ * Reset vector for secondary CPUs.
+ * This will be mapped at address 0 by SBAR register.
+ * We need _long_ jump to the physical address.
+ */
+ .arm
+ .align 12
+ENTRY(shmobile_boot_vector)
+ ldr r0, 2f
+ ldr r1, 1f
+ bx r1
+
+ENDPROC(shmobile_boot_vector)
+
+ .align 2
+ .globl shmobile_boot_fn
+shmobile_boot_fn:
+1: .space 4
+ .globl shmobile_boot_arg
+shmobile_boot_arg:
+2: .space 4
+ .globl shmobile_boot_size
+shmobile_boot_size:
+ .long . - shmobile_boot_vector
+
+/*
+ * Per-CPU SMP boot function/argument selection code based on MPIDR
+ */
+
+ENTRY(shmobile_smp_boot)
+ @ r0 = MPIDR_HWID_BITMASK
+ mrc p15, 0, r1, c0, c0, 5 @ r1 = MPIDR
+ and r0, r1, r0 @ r0 = cpu_logical_map() value
+ mov r1, #0 @ r1 = CPU index
+ adr r5, 1f @ array of per-cpu mpidr values
+ adr r6, 2f @ array of per-cpu functions
+ adr r7, 3f @ array of per-cpu arguments
+
+shmobile_smp_boot_find_mpidr:
+ ldr r8, [r5, r1, lsl #2]
+ cmp r8, r0
+ bne shmobile_smp_boot_next
+
+ ldr r9, [r6, r1, lsl #2]
+ cmp r9, #0
+ bne shmobile_smp_boot_found
+
+shmobile_smp_boot_next:
+ add r1, r1, #1
+ cmp r1, #NR_CPUS
+ blo shmobile_smp_boot_find_mpidr
+
+ b shmobile_smp_sleep
+
+shmobile_smp_boot_found:
+ ldr r0, [r7, r1, lsl #2]
+ ret r9
+ENDPROC(shmobile_smp_boot)
+
+ENTRY(shmobile_smp_sleep)
+ wfi
+ b shmobile_smp_boot
+ENDPROC(shmobile_smp_sleep)
+
+ .globl shmobile_smp_mpidr
+shmobile_smp_mpidr:
+1: .space NR_CPUS * 4
+ .globl shmobile_smp_fn
+shmobile_smp_fn:
+2: .space NR_CPUS * 4
+ .globl shmobile_smp_arg
+shmobile_smp_arg:
+3: .space NR_CPUS * 4
diff --git a/arch/arm/mach-shmobile/include/mach/head-kzm9g.txt b/arch/arm/mach-shmobile/include/mach/head-kzm9g.txt
new file mode 100644
index 000000000..9531f46a8
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/head-kzm9g.txt
@@ -0,0 +1,410 @@
+LIST "KZM9G low-level initialization routine."
+LIST "Adapted from u-boot KZM9G support code."
+
+LIST "Copyright (C) 2013 Ulrich Hecht"
+
+LIST "This program is free software; you can redistribute it and/or modify"
+LIST "it under the terms of the GNU General Public License version 2 as"
+LIST "published by the Free Software Foundation."
+
+LIST "This program is distributed in the hope that it will be useful,"
+LIST "but WITHOUT ANY WARRANTY; without even the implied warranty of"
+LIST "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"
+LIST "GNU General Public License for more details."
+
+
+LIST "Register definitions:"
+
+LIST "Secure control register"
+#define LIFEC_SEC_SRC (0xE6110008)
+
+LIST "RWDT"
+#define RWDT_BASE (0xE6020000)
+#define RWTCSRA0 (RWDT_BASE + 0x04)
+
+LIST "HPB Semaphore Control Registers"
+#define HPBSCR_BASE (0xE6000000)
+#define HPBCTRL6 (HPBSCR_BASE + 0x1030)
+
+#define SBSC1_BASE (0xFE400000)
+#define SDCR0A (SBSC1_BASE + 0x0008)
+#define SDCR1A (SBSC1_BASE + 0x000C)
+#define SDPCRA (SBSC1_BASE + 0x0010)
+#define SDCR0SA (SBSC1_BASE + 0x0018)
+#define SDCR1SA (SBSC1_BASE + 0x001C)
+#define RTCSRA (SBSC1_BASE + 0x0020)
+#define RTCORA (SBSC1_BASE + 0x0028)
+#define RTCORHA (SBSC1_BASE + 0x002C)
+#define SDWCRC0A (SBSC1_BASE + 0x0040)
+#define SDWCRC1A (SBSC1_BASE + 0x0044)
+#define SDWCR00A (SBSC1_BASE + 0x0048)
+#define SDWCR01A (SBSC1_BASE + 0x004C)
+#define SDWCR10A (SBSC1_BASE + 0x0050)
+#define SDWCR11A (SBSC1_BASE + 0x0054)
+#define SDWCR2A (SBSC1_BASE + 0x0060)
+#define SDWCRC2A (SBSC1_BASE + 0x0064)
+#define ZQCCRA (SBSC1_BASE + 0x0068)
+#define SDMRACR0A (SBSC1_BASE + 0x0084)
+#define SDMRTMPCRA (SBSC1_BASE + 0x008C)
+#define SDMRTMPMSKA (SBSC1_BASE + 0x0094)
+#define SDGENCNTA (SBSC1_BASE + 0x009C)
+#define SDDRVCR0A (SBSC1_BASE + 0x00B4)
+#define DLLCNT0A (SBSC1_BASE + 0x0354)
+
+#define SDMRA1 (0xFE500000)
+#define SDMRA2 (0xFE5C0000)
+#define SDMRA3 (0xFE504000)
+
+#define SBSC2_BASE (0xFB400000)
+#define SDCR0B (SBSC2_BASE + 0x0008)
+#define SDCR1B (SBSC2_BASE + 0x000C)
+#define SDPCRB (SBSC2_BASE + 0x0010)
+#define SDCR0SB (SBSC2_BASE + 0x0018)
+#define SDCR1SB (SBSC2_BASE + 0x001C)
+#define RTCSRB (SBSC2_BASE + 0x0020)
+#define RTCORB (SBSC2_BASE + 0x0028)
+#define RTCORHB (SBSC2_BASE + 0x002C)
+#define SDWCRC0B (SBSC2_BASE + 0x0040)
+#define SDWCRC1B (SBSC2_BASE + 0x0044)
+#define SDWCR00B (SBSC2_BASE + 0x0048)
+#define SDWCR01B (SBSC2_BASE + 0x004C)
+#define SDWCR10B (SBSC2_BASE + 0x0050)
+#define SDWCR11B (SBSC2_BASE + 0x0054)
+#define SDPDCR0B (SBSC2_BASE + 0x0058)
+#define SDWCR2B (SBSC2_BASE + 0x0060)
+#define SDWCRC2B (SBSC2_BASE + 0x0064)
+#define ZQCCRB (SBSC2_BASE + 0x0068)
+#define SDMRACR0B (SBSC2_BASE + 0x0084)
+#define SDMRTMPCRB (SBSC2_BASE + 0x008C)
+#define SDMRTMPMSKB (SBSC2_BASE + 0x0094)
+#define SDGENCNTB (SBSC2_BASE + 0x009C)
+#define DPHYCNT0B (SBSC2_BASE + 0x00A0)
+#define DPHYCNT1B (SBSC2_BASE + 0x00A4)
+#define DPHYCNT2B (SBSC2_BASE + 0x00A8)
+#define SDDRVCR0B (SBSC2_BASE + 0x00B4)
+#define DLLCNT0B (SBSC2_BASE + 0x0354)
+
+#define SDMRB1 (0xFB500000)
+#define SDMRB2 (0xFB5C0000)
+#define SDMRB3 (0xFB504000)
+
+#define CPG_BASE (0xE6150000)
+#define FRQCRA (CPG_BASE + 0x0000)
+#define FRQCRB (CPG_BASE + 0x0004)
+#define FRQCRD (CPG_BASE + 0x00E4)
+#define VCLKCR1 (CPG_BASE + 0x0008)
+#define VCLKCR2 (CPG_BASE + 0x000C)
+#define VCLKCR3 (CPG_BASE + 0x001C)
+#define ZBCKCR (CPG_BASE + 0x0010)
+#define FLCKCR (CPG_BASE + 0x0014)
+#define SD0CKCR (CPG_BASE + 0x0074)
+#define SD1CKCR (CPG_BASE + 0x0078)
+#define SD2CKCR (CPG_BASE + 0x007C)
+#define FSIACKCR (CPG_BASE + 0x0018)
+#define SUBCKCR (CPG_BASE + 0x0080)
+#define SPUACKCR (CPG_BASE + 0x0084)
+#define SPUVCKCR (CPG_BASE + 0x0094)
+#define MSUCKCR (CPG_BASE + 0x0088)
+#define HSICKCR (CPG_BASE + 0x008C)
+#define FSIBCKCR (CPG_BASE + 0x0090)
+#define MFCK1CR (CPG_BASE + 0x0098)
+#define MFCK2CR (CPG_BASE + 0x009C)
+#define DSITCKCR (CPG_BASE + 0x0060)
+#define DSI0PCKCR (CPG_BASE + 0x0064)
+#define DSI1PCKCR (CPG_BASE + 0x0068)
+#define DSI0PHYCR (CPG_BASE + 0x006C)
+#define DVFSCR3 (CPG_BASE + 0x0174)
+#define DVFSCR4 (CPG_BASE + 0x0178)
+#define DVFSCR5 (CPG_BASE + 0x017C)
+#define MPMODE (CPG_BASE + 0x00CC)
+
+#define PLLECR (CPG_BASE + 0x00D0)
+#define PLL0CR (CPG_BASE + 0x00D8)
+#define PLL1CR (CPG_BASE + 0x0028)
+#define PLL2CR (CPG_BASE + 0x002C)
+#define PLL3CR (CPG_BASE + 0x00DC)
+#define PLL0STPCR (CPG_BASE + 0x00F0)
+#define PLL1STPCR (CPG_BASE + 0x00C8)
+#define PLL2STPCR (CPG_BASE + 0x00F8)
+#define PLL3STPCR (CPG_BASE + 0x00FC)
+#define RMSTPCR0 (CPG_BASE + 0x0110)
+#define RMSTPCR1 (CPG_BASE + 0x0114)
+#define RMSTPCR2 (CPG_BASE + 0x0118)
+#define RMSTPCR3 (CPG_BASE + 0x011C)
+#define RMSTPCR4 (CPG_BASE + 0x0120)
+#define RMSTPCR5 (CPG_BASE + 0x0124)
+#define SMSTPCR0 (CPG_BASE + 0x0130)
+#define SMSTPCR2 (CPG_BASE + 0x0138)
+#define SMSTPCR3 (CPG_BASE + 0x013C)
+#define CPGXXCR4 (CPG_BASE + 0x0150)
+#define SRCR0 (CPG_BASE + 0x80A0)
+#define SRCR2 (CPG_BASE + 0x80B0)
+#define SRCR3 (CPG_BASE + 0x80A8)
+#define VREFCR (CPG_BASE + 0x00EC)
+#define PCLKCR (CPG_BASE + 0x1020)
+
+#define PORT32CR (0xE6051020)
+#define PORT33CR (0xE6051021)
+#define PORT34CR (0xE6051022)
+#define PORT35CR (0xE6051023)
+
+LIST "DRAM initialization code:"
+
+EW RWTCSRA0, 0xA507
+
+ED_AND LIFEC_SEC_SRC, 0xFFFF7FFF
+
+ED_AND SMSTPCR3,0xFFFF7FFF
+ED_AND SRCR3, 0xFFFF7FFF
+ED_AND SMSTPCR2,0xFFFBFFFF
+ED_AND SRCR2, 0xFFFBFFFF
+ED PLLECR, 0x00000000
+
+WAIT_MASK PLLECR, 0x00000F00, 0x00000000
+WAIT_MASK FRQCRB, 0x80000000, 0x00000000
+
+ED PLL0CR, 0x2D000000
+ED PLL1CR, 0x17100000
+ED FRQCRB, 0x96235880
+WAIT_MASK FRQCRB, 0x80000000, 0x00000000
+
+ED FLCKCR, 0x0000000B
+ED_AND SMSTPCR0, 0xFFFFFFFD
+
+ED_AND SRCR0, 0xFFFFFFFD
+ED 0xE6001628, 0x514
+ED 0xE6001648, 0x514
+ED 0xE6001658, 0x514
+ED 0xE6001678, 0x514
+
+ED DVFSCR4, 0x00092000
+ED DVFSCR5, 0x000000DC
+ED PLLECR, 0x00000000
+WAIT_MASK PLLECR, 0x00000F00, 0x00000000
+
+ED FRQCRA, 0x0012453C
+ED FRQCRB, 0x80431350
+WAIT_MASK FRQCRB, 0x80000000, 0x00000000
+ED FRQCRD, 0x00000B0B
+WAIT_MASK FRQCRD, 0x80000000, 0x00000000
+
+ED PCLKCR, 0x00000003
+ED VCLKCR1, 0x0000012F
+ED VCLKCR2, 0x00000119
+ED VCLKCR3, 0x00000119
+ED ZBCKCR, 0x00000002
+ED FLCKCR, 0x00000005
+ED SD0CKCR, 0x00000080
+ED SD1CKCR, 0x00000080
+ED SD2CKCR, 0x00000080
+ED FSIACKCR, 0x0000003F
+ED FSIBCKCR, 0x0000003F
+ED SUBCKCR, 0x00000080
+ED SPUACKCR, 0x0000000B
+ED SPUVCKCR, 0x0000000B
+ED MSUCKCR, 0x0000013F
+ED HSICKCR, 0x00000080
+ED MFCK1CR, 0x0000003F
+ED MFCK2CR, 0x0000003F
+ED DSITCKCR, 0x00000107
+ED DSI0PCKCR, 0x00000313
+ED DSI1PCKCR, 0x0000130D
+ED DSI0PHYCR, 0x2A800E0E
+ED PLL0CR, 0x1E000000
+ED PLL0CR, 0x2D000000
+ED PLL1CR, 0x17100000
+ED PLL2CR, 0x27000080
+ED PLL3CR, 0x1D000000
+ED PLL0STPCR, 0x00080000
+ED PLL1STPCR, 0x000120C0
+ED PLL2STPCR, 0x00012000
+ED PLL3STPCR, 0x00000030
+ED PLLECR, 0x0000000B
+WAIT_MASK PLLECR, 0x00000B00, 0x00000B00
+
+ED DVFSCR3, 0x000120F0
+ED MPMODE, 0x00000020
+ED VREFCR, 0x0000028A
+ED RMSTPCR0, 0xE4628087
+ED RMSTPCR1, 0xFFFFFFFF
+ED RMSTPCR2, 0x53FFFFFF
+ED RMSTPCR3, 0xFFFFFFFF
+ED RMSTPCR4, 0x00800D3D
+ED RMSTPCR5, 0xFFFFF3FF
+ED SMSTPCR2, 0x00000000
+ED SRCR2, 0x00040000
+ED_AND PLLECR, 0xFFFFFFF7
+WAIT_MASK PLLECR, 0x00000800, 0x00000000
+
+LIST "set SBSC operational"
+ED HPBCTRL6, 0x00000001
+WAIT_MASK HPBCTRL6, 0x00000001, 0x00000001
+
+LIST "set SBSC operating frequency"
+ED FRQCRD, 0x00001414
+WAIT_MASK FRQCRD, 0x80000000, 0x00000000
+ED PLL3CR, 0x1D000000
+ED_OR PLLECR, 0x00000008
+WAIT_MASK PLLECR, 0x00000800, 0x00000800
+
+LIST "enable DLL oscillation in DDRPHY"
+ED_OR DLLCNT0A, 0x00000002
+
+LIST "wait >= 100 ns"
+ED SDGENCNTA, 0x00000005
+WAIT_MASK SDGENCNTA, 0xFFFFFFFF, 0x00000000
+
+LIST "target LPDDR2 device settings"
+ED SDCR0A, 0xACC90159
+ED SDCR1A, 0x00010059
+ED SDWCRC0A, 0x50874114
+ED SDWCRC1A, 0x33199B37
+ED SDWCRC2A, 0x008F2313
+ED SDWCR00A, 0x31020707
+ED SDWCR01A, 0x0017040A
+ED SDWCR10A, 0x31020707
+ED SDWCR11A, 0x0017040A
+
+ED SDDRVCR0A, 0x055557ff
+
+ED SDWCR2A, 0x30000000
+
+LIST "drive CKE high"
+ED_OR SDPCRA, 0x00000080
+WAIT_MASK SDPCRA, 0x00000080, 0x00000080
+
+LIST "wait >= 200 us"
+ED SDGENCNTA, 0x00002710
+WAIT_MASK SDGENCNTA, 0xFFFFFFFF, 0x00000000
+
+LIST "issue reset command to LPDDR2 device"
+ED SDMRACR0A, 0x0000003F
+ED SDMRA1, 0x00000000
+
+LIST "wait >= 10 (or 1) us (docs inconsistent)"
+ED SDGENCNTA, 0x000001F4
+WAIT_MASK SDGENCNTA, 0xFFFFFFFF, 0x00000000
+
+LIST "MRW ZS initialization calibration command"
+ED SDMRACR0A, 0x0000FF0A
+ED SDMRA3, 0x00000000
+
+LIST "wait >= 1 us"
+ED SDGENCNTA, 0x00000032
+WAIT_MASK SDGENCNTA, 0xFFFFFFFF, 0x00000000
+
+LIST "specify operating mode in LPDDR2"
+ED SDMRACR0A, 0x00002201
+ED SDMRA1, 0x00000000
+ED SDMRACR0A, 0x00000402
+ED SDMRA1, 0x00000000
+ED SDMRACR0A, 0x00000203
+ED SDMRA1, 0x00000000
+
+LIST "initialize DDR interface"
+ED SDMRA2, 0x00000000
+
+LIST "temperature sensor control"
+ED SDMRTMPCRA, 0x88800004
+ED SDMRTMPMSKA,0x00000004
+
+LIST "auto-refreshing control"
+ED RTCORA, 0xA55A0032
+ED RTCORHA, 0xA55A000C
+ED RTCSRA, 0xA55A2048
+
+ED_OR SDCR0A, 0x00000800
+ED_OR SDCR1A, 0x00000400
+
+LIST "auto ZQ calibration control"
+ED ZQCCRA, 0xFFF20000
+
+ED_OR DLLCNT0B, 0x00000002
+ED SDGENCNTB, 0x00000005
+WAIT_MASK SDGENCNTB, 0xFFFFFFFF, 0x00000000
+
+ED SDCR0B, 0xACC90159
+ED SDCR1B, 0x00010059
+ED SDWCRC0B, 0x50874114
+ED SDWCRC1B, 0x33199B37
+ED SDWCRC2B, 0x008F2313
+ED SDWCR00B, 0x31020707
+ED SDWCR01B, 0x0017040A
+ED SDWCR10B, 0x31020707
+ED SDWCR11B, 0x0017040A
+ED SDDRVCR0B, 0x055557ff
+ED SDWCR2B, 0x30000000
+ED_OR SDPCRB, 0x00000080
+WAIT_MASK SDPCRB, 0x00000080, 0x00000080
+
+ED SDGENCNTB, 0x00002710
+WAIT_MASK SDGENCNTB, 0xFFFFFFFF, 0x00000000
+ED SDMRACR0B, 0x0000003F
+
+LIST "upstream u-boot writes to SDMRA1A for both SBSC 1 and 2, which does"
+LIST "not seem to make a lot of sense..."
+ED SDMRB1, 0x00000000
+
+ED SDGENCNTB, 0x000001F4
+WAIT_MASK SDGENCNTB, 0xFFFFFFFF, 0x00000000
+
+ED SDMRACR0B, 0x0000FF0A
+ED SDMRB3, 0x00000000
+ED SDGENCNTB, 0x00000032
+WAIT_MASK SDGENCNTB, 0xFFFFFFFF, 0x00000000
+
+ED SDMRACR0B, 0x00002201
+ED SDMRB1, 0x00000000
+ED SDMRACR0B, 0x00000402
+ED SDMRB1, 0x00000000
+ED SDMRACR0B, 0x00000203
+ED SDMRB1, 0x00000000
+ED SDMRB2, 0x00000000
+ED SDMRTMPCRB, 0x88800004
+ED SDMRTMPMSKB, 0x00000004
+ED RTCORB, 0xA55A0032
+ED RTCORHB, 0xA55A000C
+ED RTCSRB, 0xA55A2048
+ED_OR SDCR0B, 0x00000800
+ED_OR SDCR1B, 0x00000400
+ED ZQCCRB, 0xFFF20000
+ED_OR SDPDCR0B, 0x00030000
+ED DPHYCNT1B, 0xA5390000
+ED DPHYCNT0B, 0x00001200
+ED DPHYCNT1B, 0x07CE0000
+ED DPHYCNT0B, 0x00001247
+WAIT_MASK DPHYCNT2B, 0xFFFFFFFF, 0x07CE0000
+
+ED_AND SDPDCR0B, 0xFFFCFFFF
+
+ED FRQCRD, 0x00000B0B
+WAIT_MASK FRQCRD, 0x80000000, 0x00000000
+
+ED CPGXXCR4, 0xfffffffc
+
+LIST "Setup SCIF4 / workaround"
+EB PORT32CR, 0x12
+EB PORT33CR, 0x22
+EB PORT34CR, 0x12
+EB PORT35CR, 0x22
+
+EW 0xE6C80000, 0
+EB 0xE6C80004, 0x19
+EW 0xE6C80008, 0x0030
+EW 0xE6C80018, 0
+EW 0xE6C80030, 0x0014
+
+LIST "Magic to avoid hangs and corruption on DRAM writes."
+
+LIST "It has been observed that the system would most often hang while"
+LIST "decompressing the kernel, and if it didn't it would always write"
+LIST "a corrupt image to DRAM."
+LIST "This problem does not occur in u-boot, and the reason is that"
+LIST "u-boot performs an additional cache invalidation after setting up"
+LIST "the DRAM controller. Such an invalidation should not be necessary at"
+LIST "this point, and attempts at removing parts of the routine to arrive"
+LIST "at the minimal snippet of code necessary to avoid the DRAM stability"
+LIST "problem yielded the following:"
+
+MRC p15, 0, r0, c1, c0, 0
+MCR p15, 0, r0, c1, c0, 0
diff --git a/arch/arm/mach-shmobile/include/mach/irqs.h b/arch/arm/mach-shmobile/include/mach/irqs.h
new file mode 100644
index 000000000..5aee83f07
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/irqs.h
@@ -0,0 +1,10 @@
+#ifndef __ASM_MACH_IRQS_H
+#define __ASM_MACH_IRQS_H
+
+/* Stuck here until drivers/pinctl/sh-pfc gets rid of legacy code */
+
+/* External IRQ pins */
+#define IRQPIN_BASE 2000
+#define irq_pin(nr) ((nr) + IRQPIN_BASE)
+
+#endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-shmobile/include/mach/zboot.h b/arch/arm/mach-shmobile/include/mach/zboot.h
new file mode 100644
index 000000000..175ee0546
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/zboot.h
@@ -0,0 +1,19 @@
+#ifndef ZBOOT_H
+#define ZBOOT_H
+
+#include <mach/zboot_macros.h>
+
+/**************************************************
+ *
+ * board specific settings
+ *
+ **************************************************/
+
+#ifdef CONFIG_MACH_KZM9G
+#define MEMORY_START 0x43000000
+#include "mach/head-kzm9g.txt"
+#else
+#error "unsupported board."
+#endif
+
+#endif /* ZBOOT_H */
diff --git a/arch/arm/mach-shmobile/include/mach/zboot_macros.h b/arch/arm/mach-shmobile/include/mach/zboot_macros.h
new file mode 100644
index 000000000..14fd3d538
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/zboot_macros.h
@@ -0,0 +1,108 @@
+#ifndef __ZBOOT_MACRO_H
+#define __ZBOOT_MACRO_H
+
+/* The LIST command is used to include comments in the script */
+.macro LIST comment
+.endm
+
+/* The ED command is used to write a 32-bit word */
+.macro ED, addr, data
+ LDR r0, 1f
+ LDR r1, 2f
+ STR r1, [r0]
+ B 3f
+1 : .long \addr
+2 : .long \data
+3 :
+.endm
+
+/* The EW command is used to write a 16-bit word */
+.macro EW, addr, data
+ LDR r0, 1f
+ LDR r1, 2f
+ STRH r1, [r0]
+ B 3f
+1 : .long \addr
+2 : .long \data
+3 :
+.endm
+
+/* The EB command is used to write an 8-bit word */
+.macro EB, addr, data
+ LDR r0, 1f
+ LDR r1, 2f
+ STRB r1, [r0]
+ B 3f
+1 : .long \addr
+2 : .long \data
+3 :
+.endm
+
+/* The WAIT command is used to delay the execution */
+.macro WAIT, time, reg
+ LDR r1, 1f
+ LDR r0, 2f
+ STR r0, [r1]
+10 :
+ LDR r0, [r1]
+ CMP r0, #0x00000000
+ BNE 10b
+ NOP
+ B 3f
+1 : .long \reg
+2 : .long \time * 100
+3 :
+.endm
+
+/* The DD command is used to read a 32-bit word */
+.macro DD, start, end
+ LDR r1, 1f
+ B 2f
+1 : .long \start
+2 :
+.endm
+
+/* loop until a given value has been read (with mask) */
+.macro WAIT_MASK, addr, data, cmp
+ LDR r0, 2f
+ LDR r1, 3f
+ LDR r2, 4f
+1:
+ LDR r3, [r0, #0]
+ AND r3, r1, r3
+ CMP r2, r3
+ BNE 1b
+ B 5f
+2: .long \addr
+3: .long \data
+4: .long \cmp
+5:
+.endm
+
+/* read 32-bit value from addr, "or" an immediate and write back */
+.macro ED_OR, addr, data
+ LDR r4, 1f
+ LDR r5, 2f
+ LDR r6, [r4]
+ ORR r5, r6, r5
+ STR r5, [r4]
+ B 3f
+1: .long \addr
+2: .long \data
+3:
+.endm
+
+/* read 32-bit value from addr, "and" an immediate and write back */
+.macro ED_AND, addr, data
+ LDR r4, 1f
+ LDR r5, 2f
+ LDR r6, [r4]
+ AND r5, r6, r5
+ STR r5, [r4]
+ B 3f
+1: .long \addr
+2: .long \data
+3:
+.endm
+
+#endif /* __ZBOOT_MACRO_H */
diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c
new file mode 100644
index 000000000..fd63ae653
--- /dev/null
+++ b/arch/arm/mach-shmobile/intc-sh73a0.c
@@ -0,0 +1,337 @@
+/*
+ * sh73a0 processor support - INTC hardware block
+ *
+ * Copyright (C) 2010 Magnus Damm
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/arm-gic.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "intc.h"
+#include "irqs.h"
+#include "sh73a0.h"
+
+enum {
+ UNUSED = 0,
+
+ /* interrupt sources INTCS */
+ PINTCS_PINT1, PINTCS_PINT2,
+ RTDMAC_0_DEI0, RTDMAC_0_DEI1, RTDMAC_0_DEI2, RTDMAC_0_DEI3,
+ CEU, MFI, BBIF2, VPU, TSIF1, _3DG_SGX543, _2DDMAC_2DDM0,
+ RTDMAC_1_DEI4, RTDMAC_1_DEI5, RTDMAC_1_DADERR,
+ KEYSC_KEY, VINT, MSIOF,
+ TMU0_TUNI00, TMU0_TUNI01, TMU0_TUNI02,
+ CMT0, TSIF0, CMT2, LMB, MSUG, MSU_MSU, MSU_MSU2,
+ CTI, RWDT0, ICB, PEP, ASA, JPU_JPEG, LCDC, LCRC,
+ RTDMAC_2_DEI6, RTDMAC_2_DEI7, RTDMAC_2_DEI8, RTDMAC_2_DEI9,
+ RTDMAC_3_DEI10, RTDMAC_3_DEI11,
+ FRC, GCU, LCDC1, CSIRX,
+ DSITX0_DSITX00, DSITX0_DSITX01,
+ SPU2_SPU0, SPU2_SPU1, FSI,
+ TMU1_TUNI10, TMU1_TUNI11, TMU1_TUNI12,
+ TSIF2, CMT4, MFIS2, CPORTS2R, TSG, DMASCH1, SCUW,
+ VIO60, VIO61, CEU21, CSI21, DSITX1_DSITX10, DSITX1_DSITX11,
+ DISP, DSRV, EMUX2_EMUX20I, EMUX2_EMUX21I,
+ MSTIF0_MST00I, MSTIF0_MST01I, MSTIF1_MST10I, MSTIF1_MST11I,
+ SPUV,
+
+ /* interrupt groups INTCS */
+ RTDMAC_0, RTDMAC_1, RTDMAC_2, RTDMAC_3,
+ DSITX0, SPU2, TMU1, MSU,
+};
+
+static struct intc_vect intcs_vectors[] = {
+ INTCS_VECT(PINTCS_PINT1, 0x0600), INTCS_VECT(PINTCS_PINT2, 0x0620),
+ INTCS_VECT(RTDMAC_0_DEI0, 0x0800), INTCS_VECT(RTDMAC_0_DEI1, 0x0820),
+ INTCS_VECT(RTDMAC_0_DEI2, 0x0840), INTCS_VECT(RTDMAC_0_DEI3, 0x0860),
+ INTCS_VECT(CEU, 0x0880), INTCS_VECT(MFI, 0x0900),
+ INTCS_VECT(BBIF2, 0x0960), INTCS_VECT(VPU, 0x0980),
+ INTCS_VECT(TSIF1, 0x09a0), INTCS_VECT(_3DG_SGX543, 0x09e0),
+ INTCS_VECT(_2DDMAC_2DDM0, 0x0a00),
+ INTCS_VECT(RTDMAC_1_DEI4, 0x0b80), INTCS_VECT(RTDMAC_1_DEI5, 0x0ba0),
+ INTCS_VECT(RTDMAC_1_DADERR, 0x0bc0),
+ INTCS_VECT(KEYSC_KEY, 0x0be0), INTCS_VECT(VINT, 0x0c80),
+ INTCS_VECT(MSIOF, 0x0d20),
+ INTCS_VECT(TMU0_TUNI00, 0x0e80), INTCS_VECT(TMU0_TUNI01, 0x0ea0),
+ INTCS_VECT(TMU0_TUNI02, 0x0ec0),
+ INTCS_VECT(CMT0, 0x0f00), INTCS_VECT(TSIF0, 0x0f20),
+ INTCS_VECT(CMT2, 0x0f40), INTCS_VECT(LMB, 0x0f60),
+ INTCS_VECT(MSUG, 0x0f80),
+ INTCS_VECT(MSU_MSU, 0x0fa0), INTCS_VECT(MSU_MSU2, 0x0fc0),
+ INTCS_VECT(CTI, 0x0400), INTCS_VECT(RWDT0, 0x0440),
+ INTCS_VECT(ICB, 0x0480), INTCS_VECT(PEP, 0x04a0),
+ INTCS_VECT(ASA, 0x04c0), INTCS_VECT(JPU_JPEG, 0x0560),
+ INTCS_VECT(LCDC, 0x0580), INTCS_VECT(LCRC, 0x05a0),
+ INTCS_VECT(RTDMAC_2_DEI6, 0x1300), INTCS_VECT(RTDMAC_2_DEI7, 0x1320),
+ INTCS_VECT(RTDMAC_2_DEI8, 0x1340), INTCS_VECT(RTDMAC_2_DEI9, 0x1360),
+ INTCS_VECT(RTDMAC_3_DEI10, 0x1380), INTCS_VECT(RTDMAC_3_DEI11, 0x13a0),
+ INTCS_VECT(FRC, 0x1700), INTCS_VECT(GCU, 0x1760),
+ INTCS_VECT(LCDC1, 0x1780), INTCS_VECT(CSIRX, 0x17a0),
+ INTCS_VECT(DSITX0_DSITX00, 0x17c0), INTCS_VECT(DSITX0_DSITX01, 0x17e0),
+ INTCS_VECT(SPU2_SPU0, 0x1800), INTCS_VECT(SPU2_SPU1, 0x1820),
+ INTCS_VECT(FSI, 0x1840),
+ INTCS_VECT(TMU1_TUNI10, 0x1900), INTCS_VECT(TMU1_TUNI11, 0x1920),
+ INTCS_VECT(TMU1_TUNI12, 0x1940),
+ INTCS_VECT(TSIF2, 0x1960), INTCS_VECT(CMT4, 0x1980),
+ INTCS_VECT(MFIS2, 0x1a00), INTCS_VECT(CPORTS2R, 0x1a20),
+ INTCS_VECT(TSG, 0x1ae0), INTCS_VECT(DMASCH1, 0x1b00),
+ INTCS_VECT(SCUW, 0x1b40),
+ INTCS_VECT(VIO60, 0x1b60), INTCS_VECT(VIO61, 0x1b80),
+ INTCS_VECT(CEU21, 0x1ba0), INTCS_VECT(CSI21, 0x1be0),
+ INTCS_VECT(DSITX1_DSITX10, 0x1c00), INTCS_VECT(DSITX1_DSITX11, 0x1c20),
+ INTCS_VECT(DISP, 0x1c40), INTCS_VECT(DSRV, 0x1c60),
+ INTCS_VECT(EMUX2_EMUX20I, 0x1c80), INTCS_VECT(EMUX2_EMUX21I, 0x1ca0),
+ INTCS_VECT(MSTIF0_MST00I, 0x1cc0), INTCS_VECT(MSTIF0_MST01I, 0x1ce0),
+ INTCS_VECT(MSTIF1_MST10I, 0x1d00), INTCS_VECT(MSTIF1_MST11I, 0x1d20),
+ INTCS_VECT(SPUV, 0x2300),
+};
+
+static struct intc_group intcs_groups[] __initdata = {
+ INTC_GROUP(RTDMAC_0, RTDMAC_0_DEI0, RTDMAC_0_DEI1,
+ RTDMAC_0_DEI2, RTDMAC_0_DEI3),
+ INTC_GROUP(RTDMAC_1, RTDMAC_1_DEI4, RTDMAC_1_DEI5, RTDMAC_1_DADERR),
+ INTC_GROUP(RTDMAC_2, RTDMAC_2_DEI6, RTDMAC_2_DEI7,
+ RTDMAC_2_DEI8, RTDMAC_2_DEI9),
+ INTC_GROUP(RTDMAC_3, RTDMAC_3_DEI10, RTDMAC_3_DEI11),
+ INTC_GROUP(TMU1, TMU1_TUNI12, TMU1_TUNI11, TMU1_TUNI10),
+ INTC_GROUP(DSITX0, DSITX0_DSITX00, DSITX0_DSITX01),
+ INTC_GROUP(SPU2, SPU2_SPU0, SPU2_SPU1),
+ INTC_GROUP(MSU, MSU_MSU, MSU_MSU2),
+};
+
+static struct intc_mask_reg intcs_mask_registers[] = {
+ { 0xffd20184, 0xffd201c4, 8, /* IMR1SA / IMCR1SA */
+ { 0, 0, 0, CEU,
+ 0, 0, 0, 0 } },
+ { 0xffd20188, 0xffd201c8, 8, /* IMR2SA / IMCR2SA */
+ { 0, 0, 0, VPU,
+ BBIF2, 0, 0, MFI } },
+ { 0xffd2018c, 0xffd201cc, 8, /* IMR3SA / IMCR3SA */
+ { 0, 0, 0, _2DDMAC_2DDM0,
+ 0, ASA, PEP, ICB } },
+ { 0xffd20190, 0xffd201d0, 8, /* IMR4SA / IMCR4SA */
+ { 0, 0, 0, CTI,
+ JPU_JPEG, 0, LCRC, LCDC } },
+ { 0xffd20194, 0xffd201d4, 8, /* IMR5SA / IMCR5SA */
+ { KEYSC_KEY, RTDMAC_1_DADERR, RTDMAC_1_DEI5, RTDMAC_1_DEI4,
+ RTDMAC_0_DEI3, RTDMAC_0_DEI2, RTDMAC_0_DEI1, RTDMAC_0_DEI0 } },
+ { 0xffd20198, 0xffd201d8, 8, /* IMR6SA / IMCR6SA */
+ { 0, 0, MSIOF, 0,
+ _3DG_SGX543, 0, 0, 0 } },
+ { 0xffd2019c, 0xffd201dc, 8, /* IMR7SA / IMCR7SA */
+ { 0, TMU0_TUNI02, TMU0_TUNI01, TMU0_TUNI00,
+ 0, 0, 0, 0 } },
+ { 0xffd201a0, 0xffd201e0, 8, /* IMR8SA / IMCR8SA */
+ { 0, 0, 0, 0,
+ 0, MSU_MSU, MSU_MSU2, MSUG } },
+ { 0xffd201a4, 0xffd201e4, 8, /* IMR9SA / IMCR9SA */
+ { 0, RWDT0, CMT2, CMT0,
+ 0, 0, 0, 0 } },
+ { 0xffd201ac, 0xffd201ec, 8, /* IMR11SA / IMCR11SA */
+ { 0, 0, 0, 0,
+ 0, TSIF1, LMB, TSIF0 } },
+ { 0xffd201b0, 0xffd201f0, 8, /* IMR12SA / IMCR12SA */
+ { 0, 0, 0, 0,
+ 0, 0, PINTCS_PINT2, PINTCS_PINT1 } },
+ { 0xffd50180, 0xffd501c0, 8, /* IMR0SA3 / IMCR0SA3 */
+ { RTDMAC_2_DEI6, RTDMAC_2_DEI7, RTDMAC_2_DEI8, RTDMAC_2_DEI9,
+ RTDMAC_3_DEI10, RTDMAC_3_DEI11, 0, 0 } },
+ { 0xffd50190, 0xffd501d0, 8, /* IMR4SA3 / IMCR4SA3 */
+ { FRC, 0, 0, GCU,
+ LCDC1, CSIRX, DSITX0_DSITX00, DSITX0_DSITX01 } },
+ { 0xffd50194, 0xffd501d4, 8, /* IMR5SA3 / IMCR5SA3 */
+ { SPU2_SPU0, SPU2_SPU1, FSI, 0,
+ 0, 0, 0, 0 } },
+ { 0xffd50198, 0xffd501d8, 8, /* IMR6SA3 / IMCR6SA3 */
+ { TMU1_TUNI10, TMU1_TUNI11, TMU1_TUNI12, 0,
+ TSIF2, CMT4, 0, 0 } },
+ { 0xffd5019c, 0xffd501dc, 8, /* IMR7SA3 / IMCR7SA3 */
+ { MFIS2, CPORTS2R, 0, 0,
+ 0, 0, 0, TSG } },
+ { 0xffd501a0, 0xffd501e0, 8, /* IMR8SA3 / IMCR8SA3 */
+ { DMASCH1, 0, SCUW, VIO60,
+ VIO61, CEU21, 0, CSI21 } },
+ { 0xffd501a4, 0xffd501e4, 8, /* IMR9SA3 / IMCR9SA3 */
+ { DSITX1_DSITX10, DSITX1_DSITX11, DISP, DSRV,
+ EMUX2_EMUX20I, EMUX2_EMUX21I, MSTIF0_MST00I, MSTIF0_MST01I } },
+ { 0xffd501a8, 0xffd501e8, 8, /* IMR10SA3 / IMCR10SA3 */
+ { MSTIF0_MST00I, MSTIF0_MST01I, 0, 0,
+ 0, 0, 0, 0 } },
+ { 0xffd60180, 0xffd601c0, 8, /* IMR0SA4 / IMCR0SA4 */
+ { SPUV, 0, 0, 0,
+ 0, 0, 0, 0 } },
+};
+
+/* Priority is needed for INTCA to receive the INTCS interrupt */
+static struct intc_prio_reg intcs_prio_registers[] = {
+ { 0xffd20000, 0, 16, 4, /* IPRAS */ { CTI, 0, _2DDMAC_2DDM0, ICB } },
+ { 0xffd20004, 0, 16, 4, /* IPRBS */ { JPU_JPEG, LCDC, 0, LCRC } },
+ { 0xffd20008, 0, 16, 4, /* IPRCS */ { BBIF2, 0, 0, 0 } },
+ { 0xffd2000c, 0, 16, 4, /* IPRDS */ { PINTCS_PINT1, PINTCS_PINT2,
+ 0, 0 } },
+ { 0xffd20010, 0, 16, 4, /* IPRES */ { RTDMAC_0, CEU, MFI, VPU } },
+ { 0xffd20014, 0, 16, 4, /* IPRFS */ { KEYSC_KEY, RTDMAC_1,
+ CMT2, CMT0 } },
+ { 0xffd20018, 0, 16, 4, /* IPRGS */ { TMU0_TUNI00, TMU0_TUNI01,
+ TMU0_TUNI02, TSIF1 } },
+ { 0xffd2001c, 0, 16, 4, /* IPRHS */ { VINT, 0, 0, 0 } },
+ { 0xffd20020, 0, 16, 4, /* IPRIS */ { 0, MSIOF, TSIF0, 0 } },
+ { 0xffd20024, 0, 16, 4, /* IPRJS */ { 0, _3DG_SGX543, MSUG, MSU } },
+ { 0xffd20028, 0, 16, 4, /* IPRKS */ { 0, ASA, LMB, PEP } },
+ { 0xffd20030, 0, 16, 4, /* IPRMS */ { 0, 0, 0, RWDT0 } },
+ { 0xffd50000, 0, 16, 4, /* IPRAS3 */ { RTDMAC_2, 0, 0, 0 } },
+ { 0xffd50004, 0, 16, 4, /* IPRBS3 */ { RTDMAC_3, 0, 0, 0 } },
+ { 0xffd50020, 0, 16, 4, /* IPRIS3 */ { FRC, 0, 0, 0 } },
+ { 0xffd50024, 0, 16, 4, /* IPRJS3 */ { LCDC1, CSIRX, DSITX0, 0 } },
+ { 0xffd50028, 0, 16, 4, /* IPRKS3 */ { SPU2, 0, FSI, 0 } },
+ { 0xffd50030, 0, 16, 4, /* IPRMS3 */ { TMU1, 0, 0, TSIF2 } },
+ { 0xffd50034, 0, 16, 4, /* IPRNS3 */ { CMT4, 0, 0, 0 } },
+ { 0xffd50038, 0, 16, 4, /* IPROS3 */ { MFIS2, CPORTS2R, 0, 0 } },
+ { 0xffd50040, 0, 16, 4, /* IPRQS3 */ { DMASCH1, 0, SCUW, VIO60 } },
+ { 0xffd50044, 0, 16, 4, /* IPRRS3 */ { VIO61, CEU21, 0, CSI21 } },
+ { 0xffd50048, 0, 16, 4, /* IPRSS3 */ { DSITX1_DSITX10, DSITX1_DSITX11,
+ DISP, DSRV } },
+ { 0xffd5004c, 0, 16, 4, /* IPRTS3 */ { EMUX2_EMUX20I, EMUX2_EMUX21I,
+ MSTIF0_MST00I, MSTIF0_MST01I } },
+ { 0xffd50050, 0, 16, 4, /* IPRUS3 */ { MSTIF1_MST10I, MSTIF1_MST11I,
+ 0, 0 } },
+ { 0xffd60000, 0, 16, 4, /* IPRAS4 */ { SPUV, 0, 0, 0 } },
+};
+
+static struct resource intcs_resources[] __initdata = {
+ [0] = {
+ .start = 0xffd20000,
+ .end = 0xffd201ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 0xffd50000,
+ .end = 0xffd501ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = 0xffd60000,
+ .end = 0xffd601ff,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct intc_desc intcs_desc __initdata = {
+ .name = "sh73a0-intcs",
+ .resource = intcs_resources,
+ .num_resources = ARRAY_SIZE(intcs_resources),
+ .hw = INTC_HW_DESC(intcs_vectors, intcs_groups, intcs_mask_registers,
+ intcs_prio_registers, NULL, NULL),
+};
+
+static struct irqaction sh73a0_intcs_cascade;
+
+static irqreturn_t sh73a0_intcs_demux(int irq, void *dev_id)
+{
+ unsigned int evtcodeas = ioread32((void __iomem *)dev_id);
+
+ generic_handle_irq(intcs_evt2irq(evtcodeas));
+
+ return IRQ_HANDLED;
+}
+
+#define PINTER0_PHYS 0xe69000a0
+#define PINTER1_PHYS 0xe69000a4
+#define PINTER0_VIRT IOMEM(0xe69000a0)
+#define PINTER1_VIRT IOMEM(0xe69000a4)
+#define PINTRR0 IOMEM(0xe69000d0)
+#define PINTRR1 IOMEM(0xe69000d4)
+
+#define PINT0A_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq))
+#define PINT0B_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 8))
+#define PINT0C_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 16))
+#define PINT0D_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 24))
+#define PINT1E_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT1_IRQ(irq))
+
+INTC_PINT(intc_pint0, PINTER0_PHYS, 0xe69000b0, "sh73a0-pint0", \
+ INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D), \
+ INTC_PINT_V(A, PINT0A_IRQ), INTC_PINT_V(B, PINT0B_IRQ), \
+ INTC_PINT_V(C, PINT0C_IRQ), INTC_PINT_V(D, PINT0D_IRQ), \
+ INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D), \
+ INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D));
+
+INTC_PINT(intc_pint1, PINTER1_PHYS, 0xe69000c0, "sh73a0-pint1", \
+ INTC_PINT_E(E), INTC_PINT_E_EMPTY, INTC_PINT_E_EMPTY, INTC_PINT_E_EMPTY, \
+ INTC_PINT_V(E, PINT1E_IRQ), INTC_PINT_V_NONE, \
+ INTC_PINT_V_NONE, INTC_PINT_V_NONE, \
+ INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E(E), \
+ INTC_PINT_E(E), INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E_NONE);
+
+static struct irqaction sh73a0_pint0_cascade;
+static struct irqaction sh73a0_pint1_cascade;
+
+static void pint_demux(void __iomem *rr, void __iomem *er, int base_irq)
+{
+ unsigned long value = ioread32(rr) & ioread32(er);
+ int k;
+
+ for (k = 0; k < 32; k++) {
+ if (value & (1 << (31 - k))) {
+ generic_handle_irq(base_irq + k);
+ iowrite32(~(1 << (31 - k)), rr);
+ }
+ }
+}
+
+static irqreturn_t sh73a0_pint0_demux(int irq, void *dev_id)
+{
+ pint_demux(PINTRR0, PINTER0_VIRT, SH73A0_PINT0_IRQ(0));
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t sh73a0_pint1_demux(int irq, void *dev_id)
+{
+ pint_demux(PINTRR1, PINTER1_VIRT, SH73A0_PINT1_IRQ(0));
+ return IRQ_HANDLED;
+}
+
+void __init sh73a0_init_irq(void)
+{
+ void __iomem *gic_dist_base = IOMEM(0xf0001000);
+ void __iomem *gic_cpu_base = IOMEM(0xf0000100);
+ void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
+
+ gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE);
+ gic_init(0, 29, gic_dist_base, gic_cpu_base);
+
+ register_intc_controller(&intcs_desc);
+ register_intc_controller(&intc_pint0_desc);
+ register_intc_controller(&intc_pint1_desc);
+
+ /* demux using INTEVTSA */
+ sh73a0_intcs_cascade.name = "INTCS cascade";
+ sh73a0_intcs_cascade.handler = sh73a0_intcs_demux;
+ sh73a0_intcs_cascade.dev_id = intevtsa;
+ setup_irq(gic_spi(50), &sh73a0_intcs_cascade);
+
+ /* PINT pins are sanely tied to the GIC as SPI */
+ sh73a0_pint0_cascade.name = "PINT0 cascade";
+ sh73a0_pint0_cascade.handler = sh73a0_pint0_demux;
+ setup_irq(gic_spi(33), &sh73a0_pint0_cascade);
+
+ sh73a0_pint1_cascade.name = "PINT1 cascade";
+ sh73a0_pint1_cascade.handler = sh73a0_pint1_demux;
+ setup_irq(gic_spi(34), &sh73a0_pint1_cascade);
+}
diff --git a/arch/arm/mach-shmobile/intc.h b/arch/arm/mach-shmobile/intc.h
new file mode 100644
index 000000000..40b2ad4ca
--- /dev/null
+++ b/arch/arm/mach-shmobile/intc.h
@@ -0,0 +1,295 @@
+#ifndef __ASM_MACH_INTC_H
+#define __ASM_MACH_INTC_H
+#include <linux/sh_intc.h>
+
+#define INTC_IRQ_PINS_ENUM_16L(p) \
+ p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3, \
+ p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7, \
+ p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11, \
+ p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15
+
+#define INTC_IRQ_PINS_ENUM_16H(p) \
+ p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19, \
+ p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23, \
+ p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27, \
+ p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31
+
+#define INTC_IRQ_PINS_VECT_16L(p, vect) \
+ vect(p ## _IRQ0, 0x0200), vect(p ## _IRQ1, 0x0220), \
+ vect(p ## _IRQ2, 0x0240), vect(p ## _IRQ3, 0x0260), \
+ vect(p ## _IRQ4, 0x0280), vect(p ## _IRQ5, 0x02a0), \
+ vect(p ## _IRQ6, 0x02c0), vect(p ## _IRQ7, 0x02e0), \
+ vect(p ## _IRQ8, 0x0300), vect(p ## _IRQ9, 0x0320), \
+ vect(p ## _IRQ10, 0x0340), vect(p ## _IRQ11, 0x0360), \
+ vect(p ## _IRQ12, 0x0380), vect(p ## _IRQ13, 0x03a0), \
+ vect(p ## _IRQ14, 0x03c0), vect(p ## _IRQ15, 0x03e0)
+
+#define INTC_IRQ_PINS_VECT_16H(p, vect) \
+ vect(p ## _IRQ16, 0x3200), vect(p ## _IRQ17, 0x3220), \
+ vect(p ## _IRQ18, 0x3240), vect(p ## _IRQ19, 0x3260), \
+ vect(p ## _IRQ20, 0x3280), vect(p ## _IRQ21, 0x32a0), \
+ vect(p ## _IRQ22, 0x32c0), vect(p ## _IRQ23, 0x32e0), \
+ vect(p ## _IRQ24, 0x3300), vect(p ## _IRQ25, 0x3320), \
+ vect(p ## _IRQ26, 0x3340), vect(p ## _IRQ27, 0x3360), \
+ vect(p ## _IRQ28, 0x3380), vect(p ## _IRQ29, 0x33a0), \
+ vect(p ## _IRQ30, 0x33c0), vect(p ## _IRQ31, 0x33e0)
+
+#define INTC_IRQ_PINS_MASK_16L(p, base) \
+ { base + 0x40, base + 0x60, 8, /* INTMSK00A / INTMSKCLR00A */ \
+ { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3, \
+ p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } }, \
+ { base + 0x44, base + 0x64, 8, /* INTMSK10A / INTMSKCLR10A */ \
+ { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11, \
+ p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_MASK_16H(p, base) \
+ { base + 0x48, base + 0x68, 8, /* INTMSK20A / INTMSKCLR20A */ \
+ { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19, \
+ p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } }, \
+ { base + 0x4c, base + 0x6c, 8, /* INTMSK30A / INTMSKCLR30A */ \
+ { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27, \
+ p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_PRIO_16L(p, base) \
+ { base + 0x10, 0, 32, 4, /* INTPRI00A */ \
+ { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3, \
+ p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } }, \
+ { base + 0x14, 0, 32, 4, /* INTPRI10A */ \
+ { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11, \
+ p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_PRIO_16H(p, base) \
+ { base + 0x18, 0, 32, 4, /* INTPRI20A */ \
+ { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19, \
+ p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } }, \
+ { base + 0x1c, 0, 32, 4, /* INTPRI30A */ \
+ { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27, \
+ p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_SENSE_16L(p, base) \
+ { base + 0x00, 32, 4, /* ICR1A */ \
+ { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3, \
+ p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } }, \
+ { base + 0x04, 32, 4, /* ICR2A */ \
+ { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11, \
+ p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_SENSE_16H(p, base) \
+ { base + 0x08, 32, 4, /* ICR3A */ \
+ { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19, \
+ p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } }, \
+ { base + 0x0c, 32, 4, /* ICR4A */ \
+ { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27, \
+ p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_ACK_16L(p, base) \
+ { base + 0x20, 0, 8, /* INTREQ00A */ \
+ { p ## _IRQ0, p ## _IRQ1, p ## _IRQ2, p ## _IRQ3, \
+ p ## _IRQ4, p ## _IRQ5, p ## _IRQ6, p ## _IRQ7 } }, \
+ { base + 0x24, 0, 8, /* INTREQ10A */ \
+ { p ## _IRQ8, p ## _IRQ9, p ## _IRQ10, p ## _IRQ11, \
+ p ## _IRQ12, p ## _IRQ13, p ## _IRQ14, p ## _IRQ15 } }
+
+#define INTC_IRQ_PINS_ACK_16H(p, base) \
+ { base + 0x28, 0, 8, /* INTREQ20A */ \
+ { p ## _IRQ16, p ## _IRQ17, p ## _IRQ18, p ## _IRQ19, \
+ p ## _IRQ20, p ## _IRQ21, p ## _IRQ22, p ## _IRQ23 } }, \
+ { base + 0x2c, 0, 8, /* INTREQ30A */ \
+ { p ## _IRQ24, p ## _IRQ25, p ## _IRQ26, p ## _IRQ27, \
+ p ## _IRQ28, p ## _IRQ29, p ## _IRQ30, p ## _IRQ31 } }
+
+#define INTC_IRQ_PINS_16(p, base, vect, str) \
+ \
+static struct resource p ## _resources[] __initdata = { \
+ [0] = { \
+ .start = base, \
+ .end = base + 0x64, \
+ .flags = IORESOURCE_MEM, \
+ }, \
+}; \
+ \
+enum { \
+ p ## _UNUSED = 0, \
+ INTC_IRQ_PINS_ENUM_16L(p), \
+}; \
+ \
+static struct intc_vect p ## _vectors[] __initdata = { \
+ INTC_IRQ_PINS_VECT_16L(p, vect), \
+}; \
+ \
+static struct intc_mask_reg p ## _mask_registers[] __initdata = { \
+ INTC_IRQ_PINS_MASK_16L(p, base), \
+}; \
+ \
+static struct intc_prio_reg p ## _prio_registers[] __initdata = { \
+ INTC_IRQ_PINS_PRIO_16L(p, base), \
+}; \
+ \
+static struct intc_sense_reg p ## _sense_registers[] __initdata = { \
+ INTC_IRQ_PINS_SENSE_16L(p, base), \
+}; \
+ \
+static struct intc_mask_reg p ## _ack_registers[] __initdata = { \
+ INTC_IRQ_PINS_ACK_16L(p, base), \
+}; \
+ \
+static struct intc_desc p ## _desc __initdata = { \
+ .name = str, \
+ .resource = p ## _resources, \
+ .num_resources = ARRAY_SIZE(p ## _resources), \
+ .hw = INTC_HW_DESC(p ## _vectors, NULL, \
+ p ## _mask_registers, p ## _prio_registers, \
+ p ## _sense_registers, p ## _ack_registers) \
+}
+
+#define INTC_IRQ_PINS_16H(p, base, vect, str) \
+ \
+static struct resource p ## _resources[] __initdata = { \
+ [0] = { \
+ .start = base, \
+ .end = base + 0x64, \
+ .flags = IORESOURCE_MEM, \
+ }, \
+}; \
+ \
+enum { \
+ p ## _UNUSED = 0, \
+ INTC_IRQ_PINS_ENUM_16H(p), \
+}; \
+ \
+static struct intc_vect p ## _vectors[] __initdata = { \
+ INTC_IRQ_PINS_VECT_16H(p, vect), \
+}; \
+ \
+static struct intc_mask_reg p ## _mask_registers[] __initdata = { \
+ INTC_IRQ_PINS_MASK_16H(p, base), \
+}; \
+ \
+static struct intc_prio_reg p ## _prio_registers[] __initdata = { \
+ INTC_IRQ_PINS_PRIO_16H(p, base), \
+}; \
+ \
+static struct intc_sense_reg p ## _sense_registers[] __initdata = { \
+ INTC_IRQ_PINS_SENSE_16H(p, base), \
+}; \
+ \
+static struct intc_mask_reg p ## _ack_registers[] __initdata = { \
+ INTC_IRQ_PINS_ACK_16H(p, base), \
+}; \
+ \
+static struct intc_desc p ## _desc __initdata = { \
+ .name = str, \
+ .resource = p ## _resources, \
+ .num_resources = ARRAY_SIZE(p ## _resources), \
+ .hw = INTC_HW_DESC(p ## _vectors, NULL, \
+ p ## _mask_registers, p ## _prio_registers, \
+ p ## _sense_registers, p ## _ack_registers) \
+}
+
+#define INTC_IRQ_PINS_32(p, base, vect, str) \
+ \
+static struct resource p ## _resources[] __initdata = { \
+ [0] = { \
+ .start = base, \
+ .end = base + 0x6c, \
+ .flags = IORESOURCE_MEM, \
+ }, \
+}; \
+ \
+enum { \
+ p ## _UNUSED = 0, \
+ INTC_IRQ_PINS_ENUM_16L(p), \
+ INTC_IRQ_PINS_ENUM_16H(p), \
+}; \
+ \
+static struct intc_vect p ## _vectors[] __initdata = { \
+ INTC_IRQ_PINS_VECT_16L(p, vect), \
+ INTC_IRQ_PINS_VECT_16H(p, vect), \
+}; \
+ \
+static struct intc_mask_reg p ## _mask_registers[] __initdata = { \
+ INTC_IRQ_PINS_MASK_16L(p, base), \
+ INTC_IRQ_PINS_MASK_16H(p, base), \
+}; \
+ \
+static struct intc_prio_reg p ## _prio_registers[] __initdata = { \
+ INTC_IRQ_PINS_PRIO_16L(p, base), \
+ INTC_IRQ_PINS_PRIO_16H(p, base), \
+}; \
+ \
+static struct intc_sense_reg p ## _sense_registers[] __initdata = { \
+ INTC_IRQ_PINS_SENSE_16L(p, base), \
+ INTC_IRQ_PINS_SENSE_16H(p, base), \
+}; \
+ \
+static struct intc_mask_reg p ## _ack_registers[] __initdata = { \
+ INTC_IRQ_PINS_ACK_16L(p, base), \
+ INTC_IRQ_PINS_ACK_16H(p, base), \
+}; \
+ \
+static struct intc_desc p ## _desc __initdata = { \
+ .name = str, \
+ .resource = p ## _resources, \
+ .num_resources = ARRAY_SIZE(p ## _resources), \
+ .hw = INTC_HW_DESC(p ## _vectors, NULL, \
+ p ## _mask_registers, p ## _prio_registers, \
+ p ## _sense_registers, p ## _ack_registers) \
+}
+
+#define INTC_PINT_E_EMPTY
+#define INTC_PINT_E_NONE 0, 0, 0, 0, 0, 0, 0, 0,
+#define INTC_PINT_E(p) \
+ PINT ## p ## 0, PINT ## p ## 1, PINT ## p ## 2, PINT ## p ## 3, \
+ PINT ## p ## 4, PINT ## p ## 5, PINT ## p ## 6, PINT ## p ## 7,
+
+#define INTC_PINT_V_NONE
+#define INTC_PINT_V(p, vect) \
+ vect(PINT ## p ## 0, 0), vect(PINT ## p ## 1, 1), \
+ vect(PINT ## p ## 2, 2), vect(PINT ## p ## 3, 3), \
+ vect(PINT ## p ## 4, 4), vect(PINT ## p ## 5, 5), \
+ vect(PINT ## p ## 6, 6), vect(PINT ## p ## 7, 7),
+
+#define INTC_PINT(p, mask_reg, sense_base, str, \
+ enums_1, enums_2, enums_3, enums_4, \
+ vect_1, vect_2, vect_3, vect_4, \
+ mask_a, mask_b, mask_c, mask_d, \
+ sense_a, sense_b, sense_c, sense_d) \
+ \
+enum { \
+ PINT ## p ## _UNUSED = 0, \
+ enums_1 enums_2 enums_3 enums_4 \
+}; \
+ \
+static struct intc_vect p ## _vectors[] __initdata = { \
+ vect_1 vect_2 vect_3 vect_4 \
+}; \
+ \
+static struct intc_mask_reg p ## _mask_registers[] __initdata = { \
+ { mask_reg, 0, 32, /* PINTER */ \
+ { mask_a mask_b mask_c mask_d } } \
+}; \
+ \
+static struct intc_sense_reg p ## _sense_registers[] __initdata = { \
+ { sense_base + 0x00, 16, 2, /* PINTCR */ \
+ { sense_a } }, \
+ { sense_base + 0x04, 16, 2, /* PINTCR */ \
+ { sense_b } }, \
+ { sense_base + 0x08, 16, 2, /* PINTCR */ \
+ { sense_c } }, \
+ { sense_base + 0x0c, 16, 2, /* PINTCR */ \
+ { sense_d } }, \
+}; \
+ \
+static struct intc_desc p ## _desc __initdata = { \
+ .name = str, \
+ .hw = INTC_HW_DESC(p ## _vectors, NULL, \
+ p ## _mask_registers, NULL, \
+ p ## _sense_registers, NULL), \
+}
+
+/* INTCS */
+#define INTCS_VECT_BASE 0x3400
+#define INTCS_VECT(n, vect) INTC_VECT((n), INTCS_VECT_BASE + (vect))
+#define intcs_evt2irq(evt) evt2irq(INTCS_VECT_BASE + (evt))
+
+#endif /* __ASM_MACH_INTC_H */
diff --git a/arch/arm/mach-shmobile/irqs.h b/arch/arm/mach-shmobile/irqs.h
new file mode 100644
index 000000000..3070f6d88
--- /dev/null
+++ b/arch/arm/mach-shmobile/irqs.h
@@ -0,0 +1,15 @@
+#ifndef __SHMOBILE_IRQS_H
+#define __SHMOBILE_IRQS_H
+
+#include "include/mach/irqs.h"
+
+/* GIC */
+#define gic_spi(nr) ((nr) + 32)
+#define gic_iid(nr) (nr) /* ICCIAR / interrupt ID */
+
+/* GPIO IRQ */
+#define _GPIO_IRQ_BASE 2500
+#define GPIO_IRQ_BASE(x) (_GPIO_IRQ_BASE + (32 * x))
+#define GPIO_IRQ(x, y) (_GPIO_IRQ_BASE + (32 * x) + y)
+
+#endif /* __SHMOBILE_IRQS_H */
diff --git a/arch/arm/mach-shmobile/platsmp-apmu.c b/arch/arm/mach-shmobile/platsmp-apmu.c
new file mode 100644
index 000000000..f483b560b
--- /dev/null
+++ b/arch/arm/mach-shmobile/platsmp-apmu.c
@@ -0,0 +1,238 @@
+/*
+ * SMP support for SoCs with APMU
+ *
+ * Copyright (C) 2014 Renesas Electronics Corporation
+ * Copyright (C) 2013 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/cpu_pm.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/of_address.h>
+#include <linux/smp.h>
+#include <linux/suspend.h>
+#include <linux/threads.h>
+#include <asm/cacheflush.h>
+#include <asm/cp15.h>
+#include <asm/proc-fns.h>
+#include <asm/smp_plat.h>
+#include <asm/suspend.h>
+#include "common.h"
+#include "platsmp-apmu.h"
+
+static struct {
+ void __iomem *iomem;
+ int bit;
+} apmu_cpus[NR_CPUS];
+
+#define WUPCR_OFFS 0x10
+#define PSTR_OFFS 0x40
+#define CPUNCR_OFFS(n) (0x100 + (0x10 * (n)))
+
+static int __maybe_unused apmu_power_on(void __iomem *p, int bit)
+{
+ /* request power on */
+ writel_relaxed(BIT(bit), p + WUPCR_OFFS);
+
+ /* wait for APMU to finish */
+ while (readl_relaxed(p + WUPCR_OFFS) != 0)
+ ;
+
+ return 0;
+}
+
+static int apmu_power_off(void __iomem *p, int bit)
+{
+ /* request Core Standby for next WFI */
+ writel_relaxed(3, p + CPUNCR_OFFS(bit));
+ return 0;
+}
+
+static int __maybe_unused apmu_power_off_poll(void __iomem *p, int bit)
+{
+ int k;
+
+ for (k = 0; k < 1000; k++) {
+ if (((readl_relaxed(p + PSTR_OFFS) >> (bit * 4)) & 0x03) == 3)
+ return 1;
+
+ mdelay(1);
+ }
+
+ return 0;
+}
+
+static int apmu_wrap(int cpu, int (*fn)(void __iomem *p, int cpu))
+{
+ void __iomem *p = apmu_cpus[cpu].iomem;
+
+ return p ? fn(p, apmu_cpus[cpu].bit) : -EINVAL;
+}
+
+static void apmu_init_cpu(struct resource *res, int cpu, int bit)
+{
+ if ((cpu >= ARRAY_SIZE(apmu_cpus)) || apmu_cpus[cpu].iomem)
+ return;
+
+ apmu_cpus[cpu].iomem = ioremap_nocache(res->start, resource_size(res));
+ apmu_cpus[cpu].bit = bit;
+
+ pr_debug("apmu ioremap %d %d %pr\n", cpu, bit, res);
+}
+
+static void apmu_parse_cfg(void (*fn)(struct resource *res, int cpu, int bit),
+ struct rcar_apmu_config *apmu_config, int num)
+{
+ u32 id;
+ int k;
+ int bit, index;
+ bool is_allowed;
+
+ for (k = 0; k < num; k++) {
+ /* only enable the cluster that includes the boot CPU */
+ is_allowed = false;
+ for (bit = 0; bit < ARRAY_SIZE(apmu_config[k].cpus); bit++) {
+ id = apmu_config[k].cpus[bit];
+ if (id >= 0) {
+ if (id == cpu_logical_map(0))
+ is_allowed = true;
+ }
+ }
+ if (!is_allowed)
+ continue;
+
+ for (bit = 0; bit < ARRAY_SIZE(apmu_config[k].cpus); bit++) {
+ id = apmu_config[k].cpus[bit];
+ if (id >= 0) {
+ index = get_logical_index(id);
+ if (index >= 0)
+ fn(&apmu_config[k].iomem, index, bit);
+ }
+ }
+ }
+}
+
+void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus,
+ struct rcar_apmu_config *apmu_config,
+ int num)
+{
+ /* install boot code shared by all CPUs */
+ shmobile_boot_fn = virt_to_phys(shmobile_smp_boot);
+ shmobile_boot_arg = MPIDR_HWID_BITMASK;
+
+ /* perform per-cpu setup */
+ apmu_parse_cfg(apmu_init_cpu, apmu_config, num);
+}
+
+#ifdef CONFIG_SMP
+int shmobile_smp_apmu_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ /* For this particular CPU register boot vector */
+ shmobile_smp_hook(cpu, virt_to_phys(shmobile_invalidate_start), 0);
+
+ return apmu_wrap(cpu, apmu_power_on);
+}
+#endif
+
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_SUSPEND)
+/* nicked from arch/arm/mach-exynos/hotplug.c */
+static inline void cpu_enter_lowpower_a15(void)
+{
+ unsigned int v;
+
+ asm volatile(
+ " mrc p15, 0, %0, c1, c0, 0\n"
+ " bic %0, %0, %1\n"
+ " mcr p15, 0, %0, c1, c0, 0\n"
+ : "=&r" (v)
+ : "Ir" (CR_C)
+ : "cc");
+
+ flush_cache_louis();
+
+ asm volatile(
+ /*
+ * Turn off coherency
+ */
+ " mrc p15, 0, %0, c1, c0, 1\n"
+ " bic %0, %0, %1\n"
+ " mcr p15, 0, %0, c1, c0, 1\n"
+ : "=&r" (v)
+ : "Ir" (0x40)
+ : "cc");
+
+ isb();
+ dsb();
+}
+
+void shmobile_smp_apmu_cpu_shutdown(unsigned int cpu)
+{
+
+ /* Select next sleep mode using the APMU */
+ apmu_wrap(cpu, apmu_power_off);
+
+ /* Do ARM specific CPU shutdown */
+ cpu_enter_lowpower_a15();
+}
+
+static inline void cpu_leave_lowpower(void)
+{
+ unsigned int v;
+
+ asm volatile("mrc p15, 0, %0, c1, c0, 0\n"
+ " orr %0, %0, %1\n"
+ " mcr p15, 0, %0, c1, c0, 0\n"
+ " mrc p15, 0, %0, c1, c0, 1\n"
+ " orr %0, %0, %2\n"
+ " mcr p15, 0, %0, c1, c0, 1\n"
+ : "=&r" (v)
+ : "Ir" (CR_C), "Ir" (0x40)
+ : "cc");
+}
+#endif
+
+#if defined(CONFIG_HOTPLUG_CPU)
+void shmobile_smp_apmu_cpu_die(unsigned int cpu)
+{
+ /* For this particular CPU deregister boot vector */
+ shmobile_smp_hook(cpu, 0, 0);
+
+ /* Shutdown CPU core */
+ shmobile_smp_apmu_cpu_shutdown(cpu);
+
+ /* jump to shared mach-shmobile sleep / reset code */
+ shmobile_smp_sleep();
+}
+
+int shmobile_smp_apmu_cpu_kill(unsigned int cpu)
+{
+ return apmu_wrap(cpu, apmu_power_off_poll);
+}
+#endif
+
+#if defined(CONFIG_SUSPEND)
+static int shmobile_smp_apmu_do_suspend(unsigned long cpu)
+{
+ shmobile_smp_hook(cpu, virt_to_phys(cpu_resume), 0);
+ shmobile_smp_apmu_cpu_shutdown(cpu);
+ cpu_do_idle(); /* WFI selects Core Standby */
+ return 1;
+}
+
+static int shmobile_smp_apmu_enter_suspend(suspend_state_t state)
+{
+ cpu_suspend(smp_processor_id(), shmobile_smp_apmu_do_suspend);
+ cpu_leave_lowpower();
+ return 0;
+}
+
+void __init shmobile_smp_apmu_suspend_init(void)
+{
+ shmobile_suspend_ops.enter = shmobile_smp_apmu_enter_suspend;
+}
+#endif
diff --git a/arch/arm/mach-shmobile/platsmp-apmu.h b/arch/arm/mach-shmobile/platsmp-apmu.h
new file mode 100644
index 000000000..76512c9a2
--- /dev/null
+++ b/arch/arm/mach-shmobile/platsmp-apmu.h
@@ -0,0 +1,32 @@
+/*
+ * rmobile apmu definition
+ *
+ * Copyright (C) 2014 Renesas Electronics Corporation
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef PLATSMP_APMU_H
+#define PLATSMP_APMU_H
+
+struct rcar_apmu_config {
+ struct resource iomem;
+ int cpus[4];
+};
+
+extern void shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus,
+ struct rcar_apmu_config *apmu_config,
+ int num);
+extern int shmobile_smp_apmu_boot_secondary(unsigned int cpu,
+ struct task_struct *idle);
+extern void shmobile_smp_apmu_cpu_die(unsigned int cpu);
+extern int shmobile_smp_apmu_cpu_kill(unsigned int cpu);
+
+#endif /* PLATSMP_APMU_H */
diff --git a/arch/arm/mach-shmobile/platsmp-scu.c b/arch/arm/mach-shmobile/platsmp-scu.c
new file mode 100644
index 000000000..64663110a
--- /dev/null
+++ b/arch/arm/mach-shmobile/platsmp-scu.c
@@ -0,0 +1,97 @@
+/*
+ * SMP support for SoCs with SCU covered by mach-shmobile
+ *
+ * Copyright (C) 2013 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/smp.h>
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
+#include "common.h"
+
+static int shmobile_smp_scu_notifier_call(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ unsigned int cpu = (long)hcpu;
+
+ switch (action) {
+ case CPU_UP_PREPARE:
+ /* For this particular CPU register SCU SMP boot vector */
+ shmobile_smp_hook(cpu, virt_to_phys(shmobile_boot_scu),
+ (unsigned long)shmobile_scu_base);
+ break;
+ };
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block shmobile_smp_scu_notifier = {
+ .notifier_call = shmobile_smp_scu_notifier_call,
+};
+
+void __init shmobile_smp_scu_prepare_cpus(unsigned int max_cpus)
+{
+ /* install boot code shared by all CPUs */
+ shmobile_boot_fn = virt_to_phys(shmobile_smp_boot);
+ shmobile_boot_arg = MPIDR_HWID_BITMASK;
+
+ /* enable SCU and cache coherency on booting CPU */
+ scu_enable(shmobile_scu_base);
+ scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
+
+ /* Use CPU notifier for reset vector control */
+ register_cpu_notifier(&shmobile_smp_scu_notifier);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+void shmobile_smp_scu_cpu_die(unsigned int cpu)
+{
+ /* For this particular CPU deregister boot vector */
+ shmobile_smp_hook(cpu, 0, 0);
+
+ dsb();
+ flush_cache_all();
+
+ /* disable cache coherency */
+ scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF);
+
+ /* jump to shared mach-shmobile sleep / reset code */
+ shmobile_smp_sleep();
+}
+
+static int shmobile_smp_scu_psr_core_disabled(int cpu)
+{
+ unsigned long mask = SCU_PM_POWEROFF << (cpu * 8);
+
+ if ((__raw_readl(shmobile_scu_base + 8) & mask) == mask)
+ return 1;
+
+ return 0;
+}
+
+int shmobile_smp_scu_cpu_kill(unsigned int cpu)
+{
+ int k;
+
+ /* this function is running on another CPU than the offline target,
+ * here we need wait for shutdown code in platform_cpu_die() to
+ * finish before asking SoC-specific code to power off the CPU core.
+ */
+ for (k = 0; k < 1000; k++) {
+ if (shmobile_smp_scu_psr_core_disabled(cpu))
+ return 1;
+
+ mdelay(1);
+ }
+
+ return 0;
+}
+#endif
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
new file mode 100644
index 000000000..3923e09e9
--- /dev/null
+++ b/arch/arm/mach-shmobile/platsmp.c
@@ -0,0 +1,38 @@
+/*
+ * SMP support for R-Mobile / SH-Mobile
+ *
+ * Copyright (C) 2010 Magnus Damm
+ * Copyright (C) 2011 Paul Mundt
+ *
+ * Based on vexpress, Copyright (C) 2002 ARM Ltd, All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+#include "common.h"
+
+extern unsigned long shmobile_smp_fn[];
+extern unsigned long shmobile_smp_arg[];
+extern unsigned long shmobile_smp_mpidr[];
+
+void shmobile_smp_hook(unsigned int cpu, unsigned long fn, unsigned long arg)
+{
+ shmobile_smp_fn[cpu] = 0;
+ flush_cache_all();
+
+ shmobile_smp_mpidr[cpu] = cpu_logical_map(cpu);
+ shmobile_smp_fn[cpu] = fn;
+ shmobile_smp_arg[cpu] = arg;
+ flush_cache_all();
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+int shmobile_smp_cpu_disable(unsigned int cpu)
+{
+ return 0; /* Hotplug of any CPU is supported */
+}
+#endif
diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c
new file mode 100644
index 000000000..34608fcf0
--- /dev/null
+++ b/arch/arm/mach-shmobile/pm-r8a7740.c
@@ -0,0 +1,129 @@
+/*
+ * r8a7740 power management support
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/console.h>
+#include <linux/io.h>
+#include <linux/suspend.h>
+
+#include "common.h"
+#include "pm-rmobile.h"
+
+#define SYSC_BASE IOMEM(0xe6180000)
+
+#if defined(CONFIG_PM) && !defined(CONFIG_ARCH_MULTIPLATFORM)
+static int r8a7740_pd_a3sm_suspend(void)
+{
+ /*
+ * The A3SM domain contains the CPU core and therefore it should
+ * only be turned off if the CPU is not in use.
+ */
+ return -EBUSY;
+}
+
+static int r8a7740_pd_a3sp_suspend(void)
+{
+ /*
+ * Serial consoles make use of SCIF hardware located in A3SP,
+ * keep such power domain on if "no_console_suspend" is set.
+ */
+ return console_suspend_enabled ? 0 : -EBUSY;
+}
+
+static int r8a7740_pd_d4_suspend(void)
+{
+ /*
+ * The D4 domain contains the Coresight-ETM hardware block and
+ * therefore it should only be turned off if the debug module is
+ * not in use.
+ */
+ return -EBUSY;
+}
+
+static struct rmobile_pm_domain r8a7740_pm_domains[] = {
+ {
+ .genpd.name = "A4LC",
+ .base = SYSC_BASE,
+ .bit_shift = 1,
+ }, {
+ .genpd.name = "A4MP",
+ .base = SYSC_BASE,
+ .bit_shift = 2,
+ }, {
+ .genpd.name = "D4",
+ .base = SYSC_BASE,
+ .bit_shift = 3,
+ .gov = &pm_domain_always_on_gov,
+ .suspend = r8a7740_pd_d4_suspend,
+ }, {
+ .genpd.name = "A4R",
+ .base = SYSC_BASE,
+ .bit_shift = 5,
+ }, {
+ .genpd.name = "A3RV",
+ .base = SYSC_BASE,
+ .bit_shift = 6,
+ }, {
+ .genpd.name = "A4S",
+ .base = SYSC_BASE,
+ .bit_shift = 10,
+ .no_debug = true,
+ }, {
+ .genpd.name = "A3SP",
+ .base = SYSC_BASE,
+ .bit_shift = 11,
+ .gov = &pm_domain_always_on_gov,
+ .no_debug = true,
+ .suspend = r8a7740_pd_a3sp_suspend,
+ }, {
+ .genpd.name = "A3SM",
+ .base = SYSC_BASE,
+ .bit_shift = 12,
+ .gov = &pm_domain_always_on_gov,
+ .suspend = r8a7740_pd_a3sm_suspend,
+ }, {
+ .genpd.name = "A3SG",
+ .base = SYSC_BASE,
+ .bit_shift = 13,
+ }, {
+ .genpd.name = "A4SU",
+ .base = SYSC_BASE,
+ .bit_shift = 20,
+ },
+};
+
+void __init r8a7740_init_pm_domains(void)
+{
+ rmobile_init_domains(r8a7740_pm_domains, ARRAY_SIZE(r8a7740_pm_domains));
+ pm_genpd_add_subdomain_names("A4R", "A3RV");
+ pm_genpd_add_subdomain_names("A4S", "A3SP");
+ pm_genpd_add_subdomain_names("A4S", "A3SM");
+ pm_genpd_add_subdomain_names("A4S", "A3SG");
+}
+#endif /* CONFIG_PM && !CONFIG_ARCH_MULTIPLATFORM */
+
+#ifdef CONFIG_SUSPEND
+static int r8a7740_enter_suspend(suspend_state_t suspend_state)
+{
+ cpu_do_idle();
+ return 0;
+}
+
+static void r8a7740_suspend_init(void)
+{
+ shmobile_suspend_ops.enter = r8a7740_enter_suspend;
+}
+#else
+static void r8a7740_suspend_init(void) {}
+#endif
+
+void __init r8a7740_pm_init(void)
+{
+ r8a7740_suspend_init();
+}
diff --git a/arch/arm/mach-shmobile/pm-r8a7779.c b/arch/arm/mach-shmobile/pm-r8a7779.c
new file mode 100644
index 000000000..44a74c4c5
--- /dev/null
+++ b/arch/arm/mach-shmobile/pm-r8a7779.c
@@ -0,0 +1,143 @@
+/*
+ * r8a7779 Power management support
+ *
+ * Copyright (C) 2011 Renesas Solutions Corp.
+ * Copyright (C) 2011 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/pm.h>
+#include <linux/suspend.h>
+#include <linux/err.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_domain.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/console.h>
+
+#include <asm/io.h>
+
+#include "common.h"
+#include "pm-rcar.h"
+#include "r8a7779.h"
+
+/* SYSC */
+#define SYSCIER 0x0c
+#define SYSCIMR 0x10
+
+struct r8a7779_pm_domain {
+ struct generic_pm_domain genpd;
+ struct rcar_sysc_ch ch;
+};
+
+static inline struct rcar_sysc_ch *to_r8a7779_ch(struct generic_pm_domain *d)
+{
+ return &container_of(d, struct r8a7779_pm_domain, genpd)->ch;
+}
+
+#if defined(CONFIG_PM) || defined(CONFIG_SMP)
+
+static void __init r8a7779_sysc_init(void)
+{
+ void __iomem *base = rcar_sysc_init(0xffd85000);
+
+ /* enable all interrupt sources, but do not use interrupt handler */
+ iowrite32(0x0131000e, base + SYSCIER);
+ iowrite32(0, base + SYSCIMR);
+}
+
+#else /* CONFIG_PM || CONFIG_SMP */
+
+static inline void r8a7779_sysc_init(void) {}
+
+#endif /* CONFIG_PM || CONFIG_SMP */
+
+#ifdef CONFIG_PM
+
+static int pd_power_down(struct generic_pm_domain *genpd)
+{
+ return rcar_sysc_power_down(to_r8a7779_ch(genpd));
+}
+
+static int pd_power_up(struct generic_pm_domain *genpd)
+{
+ return rcar_sysc_power_up(to_r8a7779_ch(genpd));
+}
+
+static bool pd_is_off(struct generic_pm_domain *genpd)
+{
+ return rcar_sysc_power_is_off(to_r8a7779_ch(genpd));
+}
+
+static bool pd_active_wakeup(struct device *dev)
+{
+ return true;
+}
+
+static void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd)
+{
+ struct generic_pm_domain *genpd = &r8a7779_pd->genpd;
+
+ genpd->flags = GENPD_FLAG_PM_CLK;
+ pm_genpd_init(genpd, NULL, false);
+ genpd->dev_ops.active_wakeup = pd_active_wakeup;
+ genpd->power_off = pd_power_down;
+ genpd->power_on = pd_power_up;
+
+ if (pd_is_off(&r8a7779_pd->genpd))
+ pd_power_up(&r8a7779_pd->genpd);
+}
+
+static struct r8a7779_pm_domain r8a7779_pm_domains[] = {
+ {
+ .genpd.name = "SH4A",
+ .ch = {
+ .chan_offs = 0x80, /* PWRSR1 .. PWRER1 */
+ .isr_bit = 16, /* SH4A */
+ },
+ },
+ {
+ .genpd.name = "SGX",
+ .ch = {
+ .chan_offs = 0xc0, /* PWRSR2 .. PWRER2 */
+ .isr_bit = 20, /* SGX */
+ },
+ },
+ {
+ .genpd.name = "VDP1",
+ .ch = {
+ .chan_offs = 0x100, /* PWRSR3 .. PWRER3 */
+ .isr_bit = 21, /* VDP */
+ },
+ },
+ {
+ .genpd.name = "IMPX3",
+ .ch = {
+ .chan_offs = 0x140, /* PWRSR4 .. PWRER4 */
+ .isr_bit = 24, /* IMP */
+ },
+ },
+};
+
+void __init r8a7779_init_pm_domains(void)
+{
+ int j;
+
+ for (j = 0; j < ARRAY_SIZE(r8a7779_pm_domains); j++)
+ r8a7779_init_pm_domain(&r8a7779_pm_domains[j]);
+}
+
+#endif /* CONFIG_PM */
+
+void __init r8a7779_pm_init(void)
+{
+ static int once;
+
+ if (!once++)
+ r8a7779_sysc_init();
+}
diff --git a/arch/arm/mach-shmobile/pm-rcar-gen2.c b/arch/arm/mach-shmobile/pm-rcar-gen2.c
new file mode 100644
index 000000000..6815781ad
--- /dev/null
+++ b/arch/arm/mach-shmobile/pm-rcar-gen2.c
@@ -0,0 +1,115 @@
+/*
+ * R-Car Generation 2 Power management support
+ *
+ * Copyright (C) 2013 - 2015 Renesas Electronics Corporation
+ * Copyright (C) 2011 Renesas Solutions Corp.
+ * Copyright (C) 2011 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/smp.h>
+#include <asm/io.h>
+#include "common.h"
+#include "pm-rcar.h"
+#include "rcar-gen2.h"
+
+/* RST */
+#define RST 0xe6160000
+#define CA15BAR 0x0020
+#define CA7BAR 0x0030
+#define CA15RESCNT 0x0040
+#define CA7RESCNT 0x0044
+
+/* On-chip RAM */
+#define MERAM 0xe8080000
+#define RAM 0xe6300000
+
+/* SYSC */
+#define SYSCIER 0x0c
+#define SYSCIMR 0x10
+
+#if defined(CONFIG_SMP)
+
+static void __init rcar_gen2_sysc_init(u32 syscier)
+{
+ void __iomem *base = rcar_sysc_init(0xe6180000);
+
+ /* enable all interrupt sources, but do not use interrupt handler */
+ iowrite32(syscier, base + SYSCIER);
+ iowrite32(0, base + SYSCIMR);
+}
+
+#else /* CONFIG_SMP */
+
+static inline void rcar_gen2_sysc_init(u32 syscier) {}
+
+#endif /* CONFIG_SMP */
+
+void __init rcar_gen2_pm_init(void)
+{
+ void __iomem *p;
+ u32 bar;
+ static int once;
+ struct device_node *np, *cpus;
+ bool has_a7 = false;
+ bool has_a15 = false;
+ phys_addr_t boot_vector_addr = 0;
+ u32 syscier = 0;
+
+ if (once++)
+ return;
+
+ cpus = of_find_node_by_path("/cpus");
+ if (!cpus)
+ return;
+
+ for_each_child_of_node(cpus, np) {
+ if (of_device_is_compatible(np, "arm,cortex-a15"))
+ has_a15 = true;
+ else if (of_device_is_compatible(np, "arm,cortex-a7"))
+ has_a7 = true;
+ }
+
+ if (of_machine_is_compatible("renesas,r8a7790")) {
+ boot_vector_addr = MERAM;
+ syscier = 0x013111ef;
+
+ } else if (of_machine_is_compatible("renesas,r8a7791")) {
+ boot_vector_addr = RAM;
+ syscier = 0x00111003;
+ }
+
+ /* RAM for jump stub, because BAR requires 256KB aligned address */
+ p = ioremap_nocache(boot_vector_addr, shmobile_boot_size);
+ memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
+ iounmap(p);
+
+ /* setup reset vectors */
+ p = ioremap_nocache(RST, 0x63);
+ bar = (boot_vector_addr >> 8) & 0xfffffc00;
+ if (has_a15) {
+ writel_relaxed(bar, p + CA15BAR);
+ writel_relaxed(bar | 0x10, p + CA15BAR);
+
+ /* de-assert reset for CA15 CPUs */
+ writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) |
+ 0xa5a50000, p + CA15RESCNT);
+ }
+ if (has_a7) {
+ writel_relaxed(bar, p + CA7BAR);
+ writel_relaxed(bar | 0x10, p + CA7BAR);
+
+ /* de-assert reset for CA7 CPUs */
+ writel_relaxed((readl_relaxed(p + CA7RESCNT) & ~0x0f) |
+ 0x5a5a0000, p + CA7RESCNT);
+ }
+ iounmap(p);
+
+ rcar_gen2_sysc_init(syscier);
+ shmobile_smp_apmu_suspend_init();
+}
diff --git a/arch/arm/mach-shmobile/pm-rcar.c b/arch/arm/mach-shmobile/pm-rcar.c
new file mode 100644
index 000000000..00022ee56
--- /dev/null
+++ b/arch/arm/mach-shmobile/pm-rcar.c
@@ -0,0 +1,137 @@
+/*
+ * R-Car SYSC Power management support
+ *
+ * Copyright (C) 2014 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include "pm-rcar.h"
+
+/* SYSC */
+#define SYSCSR 0x00
+#define SYSCISR 0x04
+#define SYSCISCR 0x08
+
+#define PWRSR_OFFS 0x00
+#define PWROFFCR_OFFS 0x04
+#define PWRONCR_OFFS 0x0c
+#define PWRER_OFFS 0x14
+
+#define SYSCSR_RETRIES 100
+#define SYSCSR_DELAY_US 1
+
+#define SYSCISR_RETRIES 1000
+#define SYSCISR_DELAY_US 1
+
+static void __iomem *rcar_sysc_base;
+static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */
+
+static int rcar_sysc_pwr_on_off(struct rcar_sysc_ch *sysc_ch,
+ int sr_bit, int reg_offs)
+{
+ int k;
+
+ for (k = 0; k < SYSCSR_RETRIES; k++) {
+ if (ioread32(rcar_sysc_base + SYSCSR) & (1 << sr_bit))
+ break;
+ udelay(SYSCSR_DELAY_US);
+ }
+
+ if (k == SYSCSR_RETRIES)
+ return -EAGAIN;
+
+ iowrite32(1 << sysc_ch->chan_bit,
+ rcar_sysc_base + sysc_ch->chan_offs + reg_offs);
+
+ return 0;
+}
+
+static int rcar_sysc_pwr_off(struct rcar_sysc_ch *sysc_ch)
+{
+ return rcar_sysc_pwr_on_off(sysc_ch, 0, PWROFFCR_OFFS);
+}
+
+static int rcar_sysc_pwr_on(struct rcar_sysc_ch *sysc_ch)
+{
+ return rcar_sysc_pwr_on_off(sysc_ch, 1, PWRONCR_OFFS);
+}
+
+static int rcar_sysc_update(struct rcar_sysc_ch *sysc_ch,
+ int (*on_off_fn)(struct rcar_sysc_ch *))
+{
+ unsigned int isr_mask = 1 << sysc_ch->isr_bit;
+ unsigned int chan_mask = 1 << sysc_ch->chan_bit;
+ unsigned int status;
+ unsigned long flags;
+ int ret = 0;
+ int k;
+
+ spin_lock_irqsave(&rcar_sysc_lock, flags);
+
+ iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
+
+ do {
+ ret = on_off_fn(sysc_ch);
+ if (ret)
+ goto out;
+
+ status = ioread32(rcar_sysc_base +
+ sysc_ch->chan_offs + PWRER_OFFS);
+ } while (status & chan_mask);
+
+ for (k = 0; k < SYSCISR_RETRIES; k++) {
+ if (ioread32(rcar_sysc_base + SYSCISR) & isr_mask)
+ break;
+ udelay(SYSCISR_DELAY_US);
+ }
+
+ if (k == SYSCISR_RETRIES)
+ ret = -EIO;
+
+ iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
+
+ out:
+ spin_unlock_irqrestore(&rcar_sysc_lock, flags);
+
+ pr_debug("sysc power domain %d: %08x -> %d\n",
+ sysc_ch->isr_bit, ioread32(rcar_sysc_base + SYSCISR), ret);
+ return ret;
+}
+
+int rcar_sysc_power_down(struct rcar_sysc_ch *sysc_ch)
+{
+ return rcar_sysc_update(sysc_ch, rcar_sysc_pwr_off);
+}
+
+int rcar_sysc_power_up(struct rcar_sysc_ch *sysc_ch)
+{
+ return rcar_sysc_update(sysc_ch, rcar_sysc_pwr_on);
+}
+
+bool rcar_sysc_power_is_off(struct rcar_sysc_ch *sysc_ch)
+{
+ unsigned int st;
+
+ st = ioread32(rcar_sysc_base + sysc_ch->chan_offs + PWRSR_OFFS);
+ if (st & (1 << sysc_ch->chan_bit))
+ return true;
+
+ return false;
+}
+
+void __iomem *rcar_sysc_init(phys_addr_t base)
+{
+ rcar_sysc_base = ioremap_nocache(base, PAGE_SIZE);
+ if (!rcar_sysc_base)
+ panic("unable to ioremap R-Car SYSC hardware block\n");
+
+ return rcar_sysc_base;
+}
diff --git a/arch/arm/mach-shmobile/pm-rcar.h b/arch/arm/mach-shmobile/pm-rcar.h
new file mode 100644
index 000000000..ef3a1ef62
--- /dev/null
+++ b/arch/arm/mach-shmobile/pm-rcar.h
@@ -0,0 +1,15 @@
+#ifndef PM_RCAR_H
+#define PM_RCAR_H
+
+struct rcar_sysc_ch {
+ unsigned long chan_offs;
+ unsigned int chan_bit;
+ unsigned int isr_bit;
+};
+
+int rcar_sysc_power_down(struct rcar_sysc_ch *sysc_ch);
+int rcar_sysc_power_up(struct rcar_sysc_ch *sysc_ch);
+bool rcar_sysc_power_is_off(struct rcar_sysc_ch *sysc_ch);
+void __iomem *rcar_sysc_init(phys_addr_t base);
+
+#endif /* PM_RCAR_H */
diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c
new file mode 100644
index 000000000..95018209f
--- /dev/null
+++ b/arch/arm/mach-shmobile/pm-rmobile.c
@@ -0,0 +1,434 @@
+/*
+ * rmobile power management support
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ * Copyright (C) 2014 Glider bvba
+ *
+ * based on pm-sh7372.c
+ * Copyright (C) 2011 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pm_clock.h>
+#include <linux/slab.h>
+
+#include <asm/io.h>
+
+#include "pm-rmobile.h"
+
+/* SYSC */
+#define SPDCR 0x08 /* SYS Power Down Control Register */
+#define SWUCR 0x14 /* SYS Wakeup Control Register */
+#define PSTR 0x80 /* Power Status Register */
+
+#define PSTR_RETRIES 100
+#define PSTR_DELAY_US 10
+
+static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
+{
+ struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd);
+ unsigned int mask;
+
+ if (rmobile_pd->bit_shift == ~0)
+ return -EBUSY;
+
+ mask = 1 << rmobile_pd->bit_shift;
+ if (rmobile_pd->suspend) {
+ int ret = rmobile_pd->suspend();
+
+ if (ret)
+ return ret;
+ }
+
+ if (__raw_readl(rmobile_pd->base + PSTR) & mask) {
+ unsigned int retry_count;
+ __raw_writel(mask, rmobile_pd->base + SPDCR);
+
+ for (retry_count = PSTR_RETRIES; retry_count; retry_count--) {
+ if (!(__raw_readl(rmobile_pd->base + SPDCR) & mask))
+ break;
+ cpu_relax();
+ }
+ }
+
+ if (!rmobile_pd->no_debug)
+ pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n",
+ genpd->name, mask,
+ __raw_readl(rmobile_pd->base + PSTR));
+
+ return 0;
+}
+
+static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd,
+ bool do_resume)
+{
+ unsigned int mask;
+ unsigned int retry_count;
+ int ret = 0;
+
+ if (rmobile_pd->bit_shift == ~0)
+ return 0;
+
+ mask = 1 << rmobile_pd->bit_shift;
+ if (__raw_readl(rmobile_pd->base + PSTR) & mask)
+ goto out;
+
+ __raw_writel(mask, rmobile_pd->base + SWUCR);
+
+ for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
+ if (!(__raw_readl(rmobile_pd->base + SWUCR) & mask))
+ break;
+ if (retry_count > PSTR_RETRIES)
+ udelay(PSTR_DELAY_US);
+ else
+ cpu_relax();
+ }
+ if (!retry_count)
+ ret = -EIO;
+
+ if (!rmobile_pd->no_debug)
+ pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
+ rmobile_pd->genpd.name, mask,
+ __raw_readl(rmobile_pd->base + PSTR));
+
+out:
+ if (ret == 0 && rmobile_pd->resume && do_resume)
+ rmobile_pd->resume();
+
+ return ret;
+}
+
+static int rmobile_pd_power_up(struct generic_pm_domain *genpd)
+{
+ return __rmobile_pd_power_up(to_rmobile_pd(genpd), true);
+}
+
+static bool rmobile_pd_active_wakeup(struct device *dev)
+{
+ return true;
+}
+
+static int rmobile_pd_attach_dev(struct generic_pm_domain *domain,
+ struct device *dev)
+{
+ int error;
+
+ error = pm_clk_create(dev);
+ if (error) {
+ dev_err(dev, "pm_clk_create failed %d\n", error);
+ return error;
+ }
+
+ error = pm_clk_add(dev, NULL);
+ if (error) {
+ dev_err(dev, "pm_clk_add failed %d\n", error);
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ pm_clk_destroy(dev);
+ return error;
+}
+
+static void rmobile_pd_detach_dev(struct generic_pm_domain *domain,
+ struct device *dev)
+{
+ pm_clk_destroy(dev);
+}
+
+static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
+{
+ struct generic_pm_domain *genpd = &rmobile_pd->genpd;
+ struct dev_power_governor *gov = rmobile_pd->gov;
+
+ genpd->flags = GENPD_FLAG_PM_CLK;
+ pm_genpd_init(genpd, gov ? : &simple_qos_governor, false);
+ genpd->dev_ops.active_wakeup = rmobile_pd_active_wakeup;
+ genpd->power_off = rmobile_pd_power_down;
+ genpd->power_on = rmobile_pd_power_up;
+ genpd->attach_dev = rmobile_pd_attach_dev;
+ genpd->detach_dev = rmobile_pd_detach_dev;
+ __rmobile_pd_power_up(rmobile_pd, false);
+}
+
+#ifdef CONFIG_ARCH_SHMOBILE_LEGACY
+
+void rmobile_init_domains(struct rmobile_pm_domain domains[], int num)
+{
+ int j;
+
+ for (j = 0; j < num; j++)
+ rmobile_init_pm_domain(&domains[j]);
+}
+
+void rmobile_add_device_to_domain_td(const char *domain_name,
+ struct platform_device *pdev,
+ struct gpd_timing_data *td)
+{
+ struct device *dev = &pdev->dev;
+
+ __pm_genpd_name_add_device(domain_name, dev, td);
+}
+
+void rmobile_add_devices_to_domains(struct pm_domain_device data[],
+ int size)
+{
+ struct gpd_timing_data latencies = {
+ .stop_latency_ns = DEFAULT_DEV_LATENCY_NS,
+ .start_latency_ns = DEFAULT_DEV_LATENCY_NS,
+ .save_state_latency_ns = DEFAULT_DEV_LATENCY_NS,
+ .restore_state_latency_ns = DEFAULT_DEV_LATENCY_NS,
+ };
+ int j;
+
+ for (j = 0; j < size; j++)
+ rmobile_add_device_to_domain_td(data[j].domain_name,
+ data[j].pdev, &latencies);
+}
+
+#else /* !CONFIG_ARCH_SHMOBILE_LEGACY */
+
+static int rmobile_pd_suspend_busy(void)
+{
+ /*
+ * This domain should not be turned off.
+ */
+ return -EBUSY;
+}
+
+static int rmobile_pd_suspend_console(void)
+{
+ /*
+ * Serial consoles make use of SCIF hardware located in this domain,
+ * hence keep the power domain on if "no_console_suspend" is set.
+ */
+ return console_suspend_enabled ? 0 : -EBUSY;
+}
+
+enum pd_types {
+ PD_NORMAL,
+ PD_CPU,
+ PD_CONSOLE,
+ PD_DEBUG,
+ PD_MEMCTL,
+};
+
+#define MAX_NUM_SPECIAL_PDS 16
+
+static struct special_pd {
+ struct device_node *pd;
+ enum pd_types type;
+} special_pds[MAX_NUM_SPECIAL_PDS] __initdata;
+
+static unsigned int num_special_pds __initdata;
+
+static const struct of_device_id special_ids[] __initconst = {
+ { .compatible = "arm,coresight-etm3x", .data = (void *)PD_DEBUG },
+ { .compatible = "renesas,dbsc-r8a73a4", .data = (void *)PD_MEMCTL, },
+ { .compatible = "renesas,dbsc3-r8a7740", .data = (void *)PD_MEMCTL, },
+ { .compatible = "renesas,sbsc-sh73a0", .data = (void *)PD_MEMCTL, },
+ { /* sentinel */ },
+};
+
+static void __init add_special_pd(struct device_node *np, enum pd_types type)
+{
+ unsigned int i;
+ struct device_node *pd;
+
+ pd = of_parse_phandle(np, "power-domains", 0);
+ if (!pd)
+ return;
+
+ for (i = 0; i < num_special_pds; i++)
+ if (pd == special_pds[i].pd && type == special_pds[i].type) {
+ of_node_put(pd);
+ return;
+ }
+
+ if (num_special_pds == ARRAY_SIZE(special_pds)) {
+ pr_warn("Too many special PM domains\n");
+ of_node_put(pd);
+ return;
+ }
+
+ pr_debug("Special PM domain %s type %d for %s\n", pd->name, type,
+ np->full_name);
+
+ special_pds[num_special_pds].pd = pd;
+ special_pds[num_special_pds].type = type;
+ num_special_pds++;
+}
+
+static void __init get_special_pds(void)
+{
+ struct device_node *np;
+ const struct of_device_id *id;
+
+ /* PM domains containing CPUs */
+ for_each_node_by_type(np, "cpu")
+ add_special_pd(np, PD_CPU);
+
+ /* PM domain containing console */
+ if (of_stdout)
+ add_special_pd(of_stdout, PD_CONSOLE);
+
+ /* PM domains containing other special devices */
+ for_each_matching_node_and_match(np, special_ids, &id)
+ add_special_pd(np, (enum pd_types)id->data);
+}
+
+static void __init put_special_pds(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_special_pds; i++)
+ of_node_put(special_pds[i].pd);
+}
+
+static enum pd_types __init pd_type(const struct device_node *pd)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_special_pds; i++)
+ if (pd == special_pds[i].pd)
+ return special_pds[i].type;
+
+ return PD_NORMAL;
+}
+
+static void __init rmobile_setup_pm_domain(struct device_node *np,
+ struct rmobile_pm_domain *pd)
+{
+ const char *name = pd->genpd.name;
+
+ switch (pd_type(np)) {
+ case PD_CPU:
+ /*
+ * This domain contains the CPU core and therefore it should
+ * only be turned off if the CPU is not in use.
+ */
+ pr_debug("PM domain %s contains CPU\n", name);
+ pd->gov = &pm_domain_always_on_gov;
+ pd->suspend = rmobile_pd_suspend_busy;
+ break;
+
+ case PD_CONSOLE:
+ pr_debug("PM domain %s contains serial console\n", name);
+ pd->gov = &pm_domain_always_on_gov;
+ pd->suspend = rmobile_pd_suspend_console;
+ break;
+
+ case PD_DEBUG:
+ /*
+ * This domain contains the Coresight-ETM hardware block and
+ * therefore it should only be turned off if the debug module
+ * is not in use.
+ */
+ pr_debug("PM domain %s contains Coresight-ETM\n", name);
+ pd->gov = &pm_domain_always_on_gov;
+ pd->suspend = rmobile_pd_suspend_busy;
+ break;
+
+ case PD_MEMCTL:
+ /*
+ * This domain contains a memory-controller and therefore it
+ * should only be turned off if memory is not in use.
+ */
+ pr_debug("PM domain %s contains MEMCTL\n", name);
+ pd->gov = &pm_domain_always_on_gov;
+ pd->suspend = rmobile_pd_suspend_busy;
+ break;
+
+ case PD_NORMAL:
+ break;
+ }
+
+ rmobile_init_pm_domain(pd);
+}
+
+static int __init rmobile_add_pm_domains(void __iomem *base,
+ struct device_node *parent,
+ struct generic_pm_domain *genpd_parent)
+{
+ struct device_node *np;
+
+ for_each_child_of_node(parent, np) {
+ struct rmobile_pm_domain *pd;
+ u32 idx = ~0;
+
+ if (of_property_read_u32(np, "reg", &idx)) {
+ /* always-on domain */
+ }
+
+ pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+ if (!pd)
+ return -ENOMEM;
+
+ pd->genpd.name = np->name;
+ pd->base = base;
+ pd->bit_shift = idx;
+
+ rmobile_setup_pm_domain(np, pd);
+ if (genpd_parent)
+ pm_genpd_add_subdomain(genpd_parent, &pd->genpd);
+ of_genpd_add_provider_simple(np, &pd->genpd);
+
+ rmobile_add_pm_domains(base, np, &pd->genpd);
+ }
+ return 0;
+}
+
+static int __init rmobile_init_pm_domains(void)
+{
+ struct device_node *np, *pmd;
+ bool scanned = false;
+ void __iomem *base;
+ int ret = 0;
+
+ for_each_compatible_node(np, NULL, "renesas,sysc-rmobile") {
+ base = of_iomap(np, 0);
+ if (!base) {
+ pr_warn("%s cannot map reg 0\n", np->full_name);
+ continue;
+ }
+
+ pmd = of_get_child_by_name(np, "pm-domains");
+ if (!pmd) {
+ pr_warn("%s lacks pm-domains node\n", np->full_name);
+ continue;
+ }
+
+ if (!scanned) {
+ /* Find PM domains containing special blocks */
+ get_special_pds();
+ scanned = true;
+ }
+
+ ret = rmobile_add_pm_domains(base, pmd, NULL);
+ of_node_put(pmd);
+ if (ret) {
+ of_node_put(np);
+ break;
+ }
+ }
+
+ put_special_pds();
+
+ return ret;
+}
+
+core_initcall(rmobile_init_pm_domains);
+
+#endif /* !CONFIG_ARCH_SHMOBILE_LEGACY */
diff --git a/arch/arm/mach-shmobile/pm-rmobile.h b/arch/arm/mach-shmobile/pm-rmobile.h
new file mode 100644
index 000000000..53219786f
--- /dev/null
+++ b/arch/arm/mach-shmobile/pm-rmobile.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef PM_RMOBILE_H
+#define PM_RMOBILE_H
+
+#include <linux/pm_domain.h>
+
+#define DEFAULT_DEV_LATENCY_NS 250000
+
+struct platform_device;
+
+struct rmobile_pm_domain {
+ struct generic_pm_domain genpd;
+ struct dev_power_governor *gov;
+ int (*suspend)(void);
+ void (*resume)(void);
+ void __iomem *base;
+ unsigned int bit_shift;
+ bool no_debug;
+};
+
+static inline
+struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d)
+{
+ return container_of(d, struct rmobile_pm_domain, genpd);
+}
+
+struct pm_domain_device {
+ const char *domain_name;
+ struct platform_device *pdev;
+};
+
+#if defined(CONFIG_PM_RMOBILE) && defined(CONFIG_ARCH_SHMOBILE_LEGACY)
+extern void rmobile_init_domains(struct rmobile_pm_domain domains[], int num);
+extern void rmobile_add_device_to_domain_td(const char *domain_name,
+ struct platform_device *pdev,
+ struct gpd_timing_data *td);
+
+static inline void rmobile_add_device_to_domain(const char *domain_name,
+ struct platform_device *pdev)
+{
+ rmobile_add_device_to_domain_td(domain_name, pdev, NULL);
+}
+
+extern void rmobile_add_devices_to_domains(struct pm_domain_device data[],
+ int size);
+#else
+
+#define rmobile_init_domains(domains, num) do { } while (0)
+#define rmobile_add_device_to_domain_td(name, pdev, td) do { } while (0)
+#define rmobile_add_device_to_domain(name, pdev) do { } while (0)
+
+static inline void rmobile_add_devices_to_domains(struct pm_domain_device d[],
+ int size) {}
+#endif /* CONFIG_PM_RMOBILE */
+
+#endif /* PM_RMOBILE_H */
diff --git a/arch/arm/mach-shmobile/pm-sh73a0.c b/arch/arm/mach-shmobile/pm-sh73a0.c
new file mode 100644
index 000000000..a7e466817
--- /dev/null
+++ b/arch/arm/mach-shmobile/pm-sh73a0.c
@@ -0,0 +1,32 @@
+/*
+ * sh73a0 Power management support
+ *
+ * Copyright (C) 2012 Bastian Hecht <hechtb+renesas@gmail.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/suspend.h>
+#include "common.h"
+
+#ifdef CONFIG_SUSPEND
+static int sh73a0_enter_suspend(suspend_state_t suspend_state)
+{
+ cpu_do_idle();
+ return 0;
+}
+
+static void sh73a0_suspend_init(void)
+{
+ shmobile_suspend_ops.enter = sh73a0_enter_suspend;
+}
+#else
+static void sh73a0_suspend_init(void) {}
+#endif
+
+void __init sh73a0_pm_init(void)
+{
+ sh73a0_suspend_init();
+}
diff --git a/arch/arm/mach-shmobile/r8a7740.h b/arch/arm/mach-shmobile/r8a7740.h
new file mode 100644
index 000000000..ca7805ad7
--- /dev/null
+++ b/arch/arm/mach-shmobile/r8a7740.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011 Renesas Solutions Corp.
+ * Copyright (C) 2011 Kuninori Morimoto <kuninori.morimoto.gx@renesas.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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_R8A7740_H__
+#define __ASM_R8A7740_H__
+
+/*
+ * MD_CKx pin
+ */
+#define MD_CK2 (1 << 2)
+#define MD_CK1 (1 << 1)
+#define MD_CK0 (1 << 0)
+
+/* DMA slave IDs */
+enum {
+ SHDMA_SLAVE_INVALID,
+ SHDMA_SLAVE_SDHI0_RX,
+ SHDMA_SLAVE_SDHI0_TX,
+ SHDMA_SLAVE_SDHI1_RX,
+ SHDMA_SLAVE_SDHI1_TX,
+ SHDMA_SLAVE_SDHI2_RX,
+ SHDMA_SLAVE_SDHI2_TX,
+ SHDMA_SLAVE_FSIA_RX,
+ SHDMA_SLAVE_FSIA_TX,
+ SHDMA_SLAVE_FSIB_TX,
+ SHDMA_SLAVE_USBHS_TX,
+ SHDMA_SLAVE_USBHS_RX,
+ SHDMA_SLAVE_MMCIF_TX,
+ SHDMA_SLAVE_MMCIF_RX,
+};
+
+extern void r8a7740_meram_workaround(void);
+extern void r8a7740_init_irq_of(void);
+extern void r8a7740_map_io(void);
+extern void r8a7740_add_early_devices(void);
+extern void r8a7740_add_standard_devices(void);
+extern void r8a7740_clock_init(u8 md_ck);
+extern void r8a7740_pinmux_init(void);
+extern void r8a7740_pm_init(void);
+
+#if defined(CONFIG_PM) && !defined(CONFIG_ARCH_MULTIPLATFORM)
+extern void __init r8a7740_init_pm_domains(void);
+#else
+static inline void r8a7740_init_pm_domains(void) {}
+#endif /* CONFIG_PM && !CONFIG_ARCH_MULTIPLATFORM */
+
+#endif /* __ASM_R8A7740_H__ */
diff --git a/arch/arm/mach-shmobile/r8a7778.h b/arch/arm/mach-shmobile/r8a7778.h
new file mode 100644
index 000000000..f64fedb1f
--- /dev/null
+++ b/arch/arm/mach-shmobile/r8a7778.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ * Copyright (C) 2013 Cogent Embedded, Inc.
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __ASM_R8A7778_H__
+#define __ASM_R8A7778_H__
+
+#include <linux/sh_eth.h>
+
+/* HPB-DMA slave IDs */
+enum {
+ HPBDMA_SLAVE_DUMMY,
+ HPBDMA_SLAVE_SDHI0_TX,
+ HPBDMA_SLAVE_SDHI0_RX,
+ HPBDMA_SLAVE_SSI0_TX,
+ HPBDMA_SLAVE_SSI0_RX,
+ HPBDMA_SLAVE_SSI1_TX,
+ HPBDMA_SLAVE_SSI1_RX,
+ HPBDMA_SLAVE_SSI2_TX,
+ HPBDMA_SLAVE_SSI2_RX,
+ HPBDMA_SLAVE_SSI3_TX,
+ HPBDMA_SLAVE_SSI3_RX,
+ HPBDMA_SLAVE_SSI4_TX,
+ HPBDMA_SLAVE_SSI4_RX,
+ HPBDMA_SLAVE_SSI5_TX,
+ HPBDMA_SLAVE_SSI5_RX,
+ HPBDMA_SLAVE_SSI6_TX,
+ HPBDMA_SLAVE_SSI6_RX,
+ HPBDMA_SLAVE_SSI7_TX,
+ HPBDMA_SLAVE_SSI7_RX,
+ HPBDMA_SLAVE_SSI8_TX,
+ HPBDMA_SLAVE_SSI8_RX,
+ HPBDMA_SLAVE_HPBIF0_TX,
+ HPBDMA_SLAVE_HPBIF0_RX,
+ HPBDMA_SLAVE_HPBIF1_TX,
+ HPBDMA_SLAVE_HPBIF1_RX,
+ HPBDMA_SLAVE_HPBIF2_TX,
+ HPBDMA_SLAVE_HPBIF2_RX,
+ HPBDMA_SLAVE_HPBIF3_TX,
+ HPBDMA_SLAVE_HPBIF3_RX,
+ HPBDMA_SLAVE_HPBIF4_TX,
+ HPBDMA_SLAVE_HPBIF4_RX,
+ HPBDMA_SLAVE_HPBIF5_TX,
+ HPBDMA_SLAVE_HPBIF5_RX,
+ HPBDMA_SLAVE_HPBIF6_TX,
+ HPBDMA_SLAVE_HPBIF6_RX,
+ HPBDMA_SLAVE_HPBIF7_TX,
+ HPBDMA_SLAVE_HPBIF7_RX,
+ HPBDMA_SLAVE_HPBIF8_TX,
+ HPBDMA_SLAVE_HPBIF8_RX,
+ HPBDMA_SLAVE_USBFUNC_TX,
+ HPBDMA_SLAVE_USBFUNC_RX,
+};
+
+extern void r8a7778_add_standard_devices(void);
+extern void r8a7778_add_standard_devices_dt(void);
+extern void r8a7778_add_dt_devices(void);
+
+extern void r8a7778_init_late(void);
+extern void r8a7778_init_irq_dt(void);
+extern void r8a7778_clock_init(void);
+extern void r8a7778_init_irq_extpin(int irlm);
+extern void r8a7778_init_irq_extpin_dt(int irlm);
+extern void r8a7778_pinmux_init(void);
+
+extern int r8a7778_usb_phy_power(bool enable);
+
+#endif /* __ASM_R8A7778_H__ */
diff --git a/arch/arm/mach-shmobile/r8a7779.h b/arch/arm/mach-shmobile/r8a7779.h
new file mode 100644
index 000000000..19f97046d
--- /dev/null
+++ b/arch/arm/mach-shmobile/r8a7779.h
@@ -0,0 +1,35 @@
+#ifndef __ASM_R8A7779_H__
+#define __ASM_R8A7779_H__
+
+#include <linux/sh_clk.h>
+
+/* HPB-DMA slave IDs */
+enum {
+ HPBDMA_SLAVE_DUMMY,
+ HPBDMA_SLAVE_SDHI0_TX,
+ HPBDMA_SLAVE_SDHI0_RX,
+};
+
+extern void r8a7779_init_irq_extpin(int irlm);
+extern void r8a7779_init_irq_extpin_dt(int irlm);
+extern void r8a7779_init_irq_dt(void);
+extern void r8a7779_map_io(void);
+extern void r8a7779_earlytimer_init(void);
+extern void r8a7779_add_early_devices(void);
+extern void r8a7779_add_standard_devices(void);
+extern void r8a7779_init_late(void);
+extern u32 r8a7779_read_mode_pins(void);
+extern void r8a7779_clock_init(void);
+extern void r8a7779_pinmux_init(void);
+extern void r8a7779_pm_init(void);
+extern void r8a7779_register_twd(void);
+
+#ifdef CONFIG_PM
+extern void __init r8a7779_init_pm_domains(void);
+#else
+static inline void r8a7779_init_pm_domains(void) {}
+#endif /* CONFIG_PM */
+
+extern struct smp_operations r8a7779_smp_ops;
+
+#endif /* __ASM_R8A7779_H__ */
diff --git a/arch/arm/mach-shmobile/r8a7790.h b/arch/arm/mach-shmobile/r8a7790.h
new file mode 100644
index 000000000..1a46d0260
--- /dev/null
+++ b/arch/arm/mach-shmobile/r8a7790.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_R8A7790_H__
+#define __ASM_R8A7790_H__
+
+extern struct smp_operations r8a7790_smp_ops;
+
+#endif /* __ASM_R8A7790_H__ */
diff --git a/arch/arm/mach-shmobile/r8a7791.h b/arch/arm/mach-shmobile/r8a7791.h
new file mode 100644
index 000000000..7ca0b7d0f
--- /dev/null
+++ b/arch/arm/mach-shmobile/r8a7791.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_R8A7791_H__
+#define __ASM_R8A7791_H__
+
+extern struct smp_operations r8a7791_smp_ops;
+
+#endif /* __ASM_R8A7791_H__ */
diff --git a/arch/arm/mach-shmobile/rcar-gen2.h b/arch/arm/mach-shmobile/rcar-gen2.h
new file mode 100644
index 000000000..8a66b4aae
--- /dev/null
+++ b/arch/arm/mach-shmobile/rcar-gen2.h
@@ -0,0 +1,10 @@
+#ifndef __ASM_RCAR_GEN2_H__
+#define __ASM_RCAR_GEN2_H__
+
+void rcar_gen2_timer_init(void);
+#define MD(nr) BIT(nr)
+u32 rcar_gen2_read_mode_pins(void);
+void rcar_gen2_reserve(void);
+void rcar_gen2_pm_init(void);
+
+#endif /* __ASM_RCAR_GEN2_H__ */
diff --git a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
new file mode 100644
index 000000000..384e6e934
--- /dev/null
+++ b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
@@ -0,0 +1,147 @@
+/*
+ * R-Car Generation 2 da9063/da9210 regulator quirk
+ *
+ * The r8a7790/lager and r8a7791/koelsch development boards have da9063 and
+ * da9210 regulators. Both regulators have their interrupt request lines tied
+ * to the same interrupt pin (IRQ2) on the SoC.
+ *
+ * After cold boot or da9063-induced restart, both the da9063 and da9210 seem
+ * to assert their interrupt request lines. Hence as soon as one driver
+ * requests this irq, it gets stuck in an interrupt storm, as it only manages
+ * to deassert its own interrupt request line, and the other driver hasn't
+ * installed an interrupt handler yet.
+ *
+ * To handle this, install a quirk that masks the interrupts in both the
+ * da9063 and da9210. This quirk has to run after the i2c master driver has
+ * been initialized, but before the i2c slave drivers are initialized.
+ *
+ * Copyright (C) 2015 Glider bvba
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/mfd/da9063/registers.h>
+
+
+#define IRQC_BASE 0xe61c0000
+#define IRQC_MONITOR 0x104 /* IRQn Signal Level Monitor Register */
+
+#define REGULATOR_IRQ_MASK BIT(2) /* IRQ2, active low */
+
+static void __iomem *irqc;
+
+static const u8 da9063_mask_regs[] = {
+ DA9063_REG_IRQ_MASK_A,
+ DA9063_REG_IRQ_MASK_B,
+ DA9063_REG_IRQ_MASK_C,
+ DA9063_REG_IRQ_MASK_D,
+};
+
+/* DA9210 System Control and Event Registers */
+#define DA9210_REG_MASK_A 0x54
+#define DA9210_REG_MASK_B 0x55
+
+static const u8 da9210_mask_regs[] = {
+ DA9210_REG_MASK_A,
+ DA9210_REG_MASK_B,
+};
+
+static void da9xxx_mask_irqs(struct i2c_client *client, const u8 regs[],
+ unsigned int nregs)
+{
+ unsigned int i;
+
+ dev_info(&client->dev, "Masking %s interrupt sources\n", client->name);
+
+ for (i = 0; i < nregs; i++) {
+ int error = i2c_smbus_write_byte_data(client, regs[i], ~0);
+ if (error) {
+ dev_err(&client->dev, "i2c error %d\n", error);
+ return;
+ }
+ }
+}
+
+static int regulator_quirk_notify(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct device *dev = data;
+ struct i2c_client *client;
+ u32 mon;
+
+ mon = ioread32(irqc + IRQC_MONITOR);
+ dev_dbg(dev, "%s: %ld, IRQC_MONITOR = 0x%x\n", __func__, action, mon);
+ if (mon & REGULATOR_IRQ_MASK)
+ goto remove;
+
+ if (action != BUS_NOTIFY_ADD_DEVICE || dev->type == &i2c_adapter_type)
+ return 0;
+
+ client = to_i2c_client(dev);
+ dev_dbg(dev, "Detected %s\n", client->name);
+
+ if ((client->addr == 0x58 && !strcmp(client->name, "da9063")))
+ da9xxx_mask_irqs(client, da9063_mask_regs,
+ ARRAY_SIZE(da9063_mask_regs));
+ else if (client->addr == 0x68 && !strcmp(client->name, "da9210"))
+ da9xxx_mask_irqs(client, da9210_mask_regs,
+ ARRAY_SIZE(da9210_mask_regs));
+
+ mon = ioread32(irqc + IRQC_MONITOR);
+ if (mon & REGULATOR_IRQ_MASK)
+ goto remove;
+
+ return 0;
+
+remove:
+ dev_info(dev, "IRQ2 is not asserted, removing quirk\n");
+
+ bus_unregister_notifier(&i2c_bus_type, nb);
+ iounmap(irqc);
+ return 0;
+}
+
+static struct notifier_block regulator_quirk_nb = {
+ .notifier_call = regulator_quirk_notify
+};
+
+static int __init rcar_gen2_regulator_quirk(void)
+{
+ u32 mon;
+
+ if (!of_machine_is_compatible("renesas,koelsch") &&
+ !of_machine_is_compatible("renesas,lager"))
+ return -ENODEV;
+
+ irqc = ioremap(IRQC_BASE, PAGE_SIZE);
+ if (!irqc)
+ return -ENOMEM;
+
+ mon = ioread32(irqc + IRQC_MONITOR);
+ if (mon & REGULATOR_IRQ_MASK) {
+ pr_debug("%s: IRQ2 is not asserted, not installing quirk\n",
+ __func__);
+ iounmap(irqc);
+ return 0;
+ }
+
+ pr_info("IRQ2 is asserted, installing da9063/da9210 regulator quirk\n");
+
+ bus_register_notifier(&i2c_bus_type, &regulator_quirk_nb);
+ return 0;
+}
+
+arch_initcall(rcar_gen2_regulator_quirk);
diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c
new file mode 100644
index 000000000..37f7b15c0
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-emev2.c
@@ -0,0 +1,53 @@
+/*
+ * Emma Mobile EV2 processor support
+ *
+ * Copyright (C) 2012 Magnus Damm
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include "common.h"
+
+static struct map_desc emev2_io_desc[] __initdata = {
+#ifdef CONFIG_SMP
+ /* 2M mapping for SCU + L2 controller */
+ {
+ .virtual = 0xf0000000,
+ .pfn = __phys_to_pfn(0x1e000000),
+ .length = SZ_2M,
+ .type = MT_DEVICE
+ },
+#endif
+};
+
+static void __init emev2_map_io(void)
+{
+ iotable_init(emev2_io_desc, ARRAY_SIZE(emev2_io_desc));
+}
+
+static const char *const emev2_boards_compat_dt[] __initconst = {
+ "renesas,emev2",
+ NULL,
+};
+
+extern struct smp_operations emev2_smp_ops;
+
+DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)")
+ .smp = smp_ops(emev2_smp_ops),
+ .map_io = emev2_map_io,
+ .init_early = shmobile_init_delay,
+ .init_late = shmobile_init_late,
+ .dt_compat = emev2_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/setup-r7s72100.c b/arch/arm/mach-shmobile/setup-r7s72100.c
new file mode 100644
index 000000000..171174777
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-r7s72100.c
@@ -0,0 +1,32 @@
+/*
+ * r7s72100 processor support
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Magnus Damm
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+
+#include <asm/mach/arch.h>
+
+#include "common.h"
+
+static const char *r7s72100_boards_compat_dt[] __initdata = {
+ "renesas,r7s72100",
+ NULL,
+};
+
+DT_MACHINE_START(R7S72100_DT, "Generic R7S72100 (Flattened Device Tree)")
+ .init_early = shmobile_init_delay,
+ .init_late = shmobile_init_late,
+ .dt_compat = r7s72100_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/setup-r8a73a4.c b/arch/arm/mach-shmobile/setup-r8a73a4.c
new file mode 100644
index 000000000..446cee611
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-r8a73a4.c
@@ -0,0 +1,32 @@
+/*
+ * r8a73a4 processor support
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Magnus Damm
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+
+#include <asm/mach/arch.h>
+
+#include "common.h"
+
+static const char *r8a73a4_boards_compat_dt[] __initdata = {
+ "renesas,r8a73a4",
+ NULL,
+};
+
+DT_MACHINE_START(R8A73A4_DT, "Generic R8A73A4 (Flattened Device Tree)")
+ .init_early = shmobile_init_delay,
+ .init_late = shmobile_init_late,
+ .dt_compat = r8a73a4_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
new file mode 100644
index 000000000..9832e4839
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
@@ -0,0 +1,859 @@
+/*
+ * R8A7740 processor support
+ *
+ * Copyright (C) 2011 Renesas Solutions Corp.
+ * Copyright (C) 2011 Kuninori Morimoto <kuninori.morimoto.gx@renesas.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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/arm-gic.h>
+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
+#include <linux/platform_device.h>
+#include <linux/of_platform.h>
+#include <linux/serial_sci.h>
+#include <linux/sh_dma.h>
+#include <linux/sh_timer.h>
+#include <linux/platform_data/sh_ipmmu.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include "common.h"
+#include "dma-register.h"
+#include "irqs.h"
+#include "pm-rmobile.h"
+#include "r8a7740.h"
+
+static struct map_desc r8a7740_io_desc[] __initdata = {
+ /*
+ * for CPGA/INTC/PFC
+ * 0xe6000000-0xefffffff -> 0xe6000000-0xefffffff
+ */
+ {
+ .virtual = 0xe6000000,
+ .pfn = __phys_to_pfn(0xe6000000),
+ .length = 160 << 20,
+ .type = MT_DEVICE_NONSHARED
+ },
+#ifdef CONFIG_CACHE_L2X0
+ /*
+ * for l2x0_init()
+ * 0xf0100000-0xf0101000 -> 0xf0002000-0xf0003000
+ */
+ {
+ .virtual = 0xf0002000,
+ .pfn = __phys_to_pfn(0xf0100000),
+ .length = PAGE_SIZE,
+ .type = MT_DEVICE_NONSHARED
+ },
+#endif
+};
+
+void __init r8a7740_map_io(void)
+{
+ debug_ll_io_init();
+ iotable_init(r8a7740_io_desc, ARRAY_SIZE(r8a7740_io_desc));
+}
+
+/* PFC */
+static const struct resource pfc_resources[] = {
+ DEFINE_RES_MEM(0xe6050000, 0x8000),
+ DEFINE_RES_MEM(0xe605800c, 0x0020),
+};
+
+void __init r8a7740_pinmux_init(void)
+{
+ platform_device_register_simple("pfc-r8a7740", -1, pfc_resources,
+ ARRAY_SIZE(pfc_resources));
+}
+
+static struct renesas_intc_irqpin_config irqpin0_platform_data = {
+ .irq_base = irq_pin(0), /* IRQ0 -> IRQ7 */
+};
+
+static struct resource irqpin0_resources[] = {
+ DEFINE_RES_MEM(0xe6900000, 4), /* ICR1A */
+ DEFINE_RES_MEM(0xe6900010, 4), /* INTPRI00A */
+ DEFINE_RES_MEM(0xe6900020, 1), /* INTREQ00A */
+ DEFINE_RES_MEM(0xe6900040, 1), /* INTMSK00A */
+ DEFINE_RES_MEM(0xe6900060, 1), /* INTMSKCLR00A */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ0 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ1 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ2 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ3 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ4 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ5 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ6 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ7 */
+};
+
+static struct platform_device irqpin0_device = {
+ .name = "renesas_intc_irqpin",
+ .id = 0,
+ .resource = irqpin0_resources,
+ .num_resources = ARRAY_SIZE(irqpin0_resources),
+ .dev = {
+ .platform_data = &irqpin0_platform_data,
+ },
+};
+
+static struct renesas_intc_irqpin_config irqpin1_platform_data = {
+ .irq_base = irq_pin(8), /* IRQ8 -> IRQ15 */
+};
+
+static struct resource irqpin1_resources[] = {
+ DEFINE_RES_MEM(0xe6900004, 4), /* ICR2A */
+ DEFINE_RES_MEM(0xe6900014, 4), /* INTPRI10A */
+ DEFINE_RES_MEM(0xe6900024, 1), /* INTREQ10A */
+ DEFINE_RES_MEM(0xe6900044, 1), /* INTMSK10A */
+ DEFINE_RES_MEM(0xe6900064, 1), /* INTMSKCLR10A */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ8 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ9 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ10 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ11 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ12 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ13 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ14 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ15 */
+};
+
+static struct platform_device irqpin1_device = {
+ .name = "renesas_intc_irqpin",
+ .id = 1,
+ .resource = irqpin1_resources,
+ .num_resources = ARRAY_SIZE(irqpin1_resources),
+ .dev = {
+ .platform_data = &irqpin1_platform_data,
+ },
+};
+
+static struct renesas_intc_irqpin_config irqpin2_platform_data = {
+ .irq_base = irq_pin(16), /* IRQ16 -> IRQ23 */
+};
+
+static struct resource irqpin2_resources[] = {
+ DEFINE_RES_MEM(0xe6900008, 4), /* ICR3A */
+ DEFINE_RES_MEM(0xe6900018, 4), /* INTPRI30A */
+ DEFINE_RES_MEM(0xe6900028, 1), /* INTREQ30A */
+ DEFINE_RES_MEM(0xe6900048, 1), /* INTMSK30A */
+ DEFINE_RES_MEM(0xe6900068, 1), /* INTMSKCLR30A */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ16 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ17 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ18 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ19 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ20 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ21 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ22 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ23 */
+};
+
+static struct platform_device irqpin2_device = {
+ .name = "renesas_intc_irqpin",
+ .id = 2,
+ .resource = irqpin2_resources,
+ .num_resources = ARRAY_SIZE(irqpin2_resources),
+ .dev = {
+ .platform_data = &irqpin2_platform_data,
+ },
+};
+
+static struct renesas_intc_irqpin_config irqpin3_platform_data = {
+ .irq_base = irq_pin(24), /* IRQ24 -> IRQ31 */
+};
+
+static struct resource irqpin3_resources[] = {
+ DEFINE_RES_MEM(0xe690000c, 4), /* ICR3A */
+ DEFINE_RES_MEM(0xe690001c, 4), /* INTPRI30A */
+ DEFINE_RES_MEM(0xe690002c, 1), /* INTREQ30A */
+ DEFINE_RES_MEM(0xe690004c, 1), /* INTMSK30A */
+ DEFINE_RES_MEM(0xe690006c, 1), /* INTMSKCLR30A */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ24 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ25 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ26 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ27 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ28 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ29 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ30 */
+ DEFINE_RES_IRQ(gic_spi(149)), /* IRQ31 */
+};
+
+static struct platform_device irqpin3_device = {
+ .name = "renesas_intc_irqpin",
+ .id = 3,
+ .resource = irqpin3_resources,
+ .num_resources = ARRAY_SIZE(irqpin3_resources),
+ .dev = {
+ .platform_data = &irqpin3_platform_data,
+ },
+};
+
+/* SCIF */
+#define R8A7740_SCIF(scif_type, index, baseaddr, irq) \
+static struct plat_sci_port scif##index##_platform_data = { \
+ .type = scif_type, \
+ .flags = UPF_BOOT_AUTOCONF, \
+ .scscr = SCSCR_RE | SCSCR_TE, \
+}; \
+ \
+static struct resource scif##index##_resources[] = { \
+ DEFINE_RES_MEM(baseaddr, 0x100), \
+ DEFINE_RES_IRQ(irq), \
+}; \
+ \
+static struct platform_device scif##index##_device = { \
+ .name = "sh-sci", \
+ .id = index, \
+ .resource = scif##index##_resources, \
+ .num_resources = ARRAY_SIZE(scif##index##_resources), \
+ .dev = { \
+ .platform_data = &scif##index##_platform_data, \
+ }, \
+}
+
+R8A7740_SCIF(PORT_SCIFA, 0, 0xe6c40000, gic_spi(100));
+R8A7740_SCIF(PORT_SCIFA, 1, 0xe6c50000, gic_spi(101));
+R8A7740_SCIF(PORT_SCIFA, 2, 0xe6c60000, gic_spi(102));
+R8A7740_SCIF(PORT_SCIFA, 3, 0xe6c70000, gic_spi(103));
+R8A7740_SCIF(PORT_SCIFA, 4, 0xe6c80000, gic_spi(104));
+R8A7740_SCIF(PORT_SCIFA, 5, 0xe6cb0000, gic_spi(105));
+R8A7740_SCIF(PORT_SCIFA, 6, 0xe6cc0000, gic_spi(106));
+R8A7740_SCIF(PORT_SCIFA, 7, 0xe6cd0000, gic_spi(107));
+R8A7740_SCIF(PORT_SCIFB, 8, 0xe6c30000, gic_spi(108));
+
+/* CMT */
+static struct sh_timer_config cmt1_platform_data = {
+ .channels_mask = 0x3f,
+};
+
+static struct resource cmt1_resources[] = {
+ DEFINE_RES_MEM(0xe6138000, 0x170),
+ DEFINE_RES_IRQ(gic_spi(58)),
+};
+
+static struct platform_device cmt1_device = {
+ .name = "sh-cmt-48",
+ .id = 1,
+ .dev = {
+ .platform_data = &cmt1_platform_data,
+ },
+ .resource = cmt1_resources,
+ .num_resources = ARRAY_SIZE(cmt1_resources),
+};
+
+/* TMU */
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xfff80000, 0x2c),
+ DEFINE_RES_IRQ(gic_spi(198)),
+ DEFINE_RES_IRQ(gic_spi(199)),
+ DEFINE_RES_IRQ(gic_spi(200)),
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh-tmu",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
+/* IPMMUI (an IPMMU module for ICB/LMB) */
+static struct resource ipmmu_resources[] = {
+ [0] = {
+ .name = "IPMMUI",
+ .start = 0xfe951000,
+ .end = 0xfe9510ff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static const char * const ipmmu_dev_names[] = {
+ "sh_mobile_lcdc_fb.0",
+ "sh_mobile_lcdc_fb.1",
+ "sh_mobile_ceu.0",
+};
+
+static struct shmobile_ipmmu_platform_data ipmmu_platform_data = {
+ .dev_names = ipmmu_dev_names,
+ .num_dev_names = ARRAY_SIZE(ipmmu_dev_names),
+};
+
+static struct platform_device ipmmu_device = {
+ .name = "ipmmu",
+ .id = -1,
+ .dev = {
+ .platform_data = &ipmmu_platform_data,
+ },
+ .resource = ipmmu_resources,
+ .num_resources = ARRAY_SIZE(ipmmu_resources),
+};
+
+static struct platform_device *r8a7740_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &scif6_device,
+ &scif7_device,
+ &scif8_device,
+ &irqpin0_device,
+ &irqpin1_device,
+ &irqpin2_device,
+ &irqpin3_device,
+ &tmu0_device,
+ &ipmmu_device,
+ &cmt1_device,
+};
+
+/* DMA */
+static const struct sh_dmae_slave_config r8a7740_dmae_slaves[] = {
+ {
+ .slave_id = SHDMA_SLAVE_SDHI0_TX,
+ .addr = 0xe6850030,
+ .chcr = CHCR_TX(XMIT_SZ_16BIT),
+ .mid_rid = 0xc1,
+ }, {
+ .slave_id = SHDMA_SLAVE_SDHI0_RX,
+ .addr = 0xe6850030,
+ .chcr = CHCR_RX(XMIT_SZ_16BIT),
+ .mid_rid = 0xc2,
+ }, {
+ .slave_id = SHDMA_SLAVE_SDHI1_TX,
+ .addr = 0xe6860030,
+ .chcr = CHCR_TX(XMIT_SZ_16BIT),
+ .mid_rid = 0xc9,
+ }, {
+ .slave_id = SHDMA_SLAVE_SDHI1_RX,
+ .addr = 0xe6860030,
+ .chcr = CHCR_RX(XMIT_SZ_16BIT),
+ .mid_rid = 0xca,
+ }, {
+ .slave_id = SHDMA_SLAVE_SDHI2_TX,
+ .addr = 0xe6870030,
+ .chcr = CHCR_TX(XMIT_SZ_16BIT),
+ .mid_rid = 0xcd,
+ }, {
+ .slave_id = SHDMA_SLAVE_SDHI2_RX,
+ .addr = 0xe6870030,
+ .chcr = CHCR_RX(XMIT_SZ_16BIT),
+ .mid_rid = 0xce,
+ }, {
+ .slave_id = SHDMA_SLAVE_FSIA_TX,
+ .addr = 0xfe1f0024,
+ .chcr = CHCR_TX(XMIT_SZ_32BIT),
+ .mid_rid = 0xb1,
+ }, {
+ .slave_id = SHDMA_SLAVE_FSIA_RX,
+ .addr = 0xfe1f0020,
+ .chcr = CHCR_RX(XMIT_SZ_32BIT),
+ .mid_rid = 0xb2,
+ }, {
+ .slave_id = SHDMA_SLAVE_FSIB_TX,
+ .addr = 0xfe1f0064,
+ .chcr = CHCR_TX(XMIT_SZ_32BIT),
+ .mid_rid = 0xb5,
+ }, {
+ .slave_id = SHDMA_SLAVE_MMCIF_TX,
+ .addr = 0xe6bd0034,
+ .chcr = CHCR_TX(XMIT_SZ_32BIT),
+ .mid_rid = 0xd1,
+ }, {
+ .slave_id = SHDMA_SLAVE_MMCIF_RX,
+ .addr = 0xe6bd0034,
+ .chcr = CHCR_RX(XMIT_SZ_32BIT),
+ .mid_rid = 0xd2,
+ },
+};
+
+#define DMA_CHANNEL(a, b, c) \
+{ \
+ .offset = a, \
+ .dmars = b, \
+ .dmars_bit = c, \
+ .chclr_offset = (0x220 - 0x20) + a \
+}
+
+static const struct sh_dmae_channel r8a7740_dmae_channels[] = {
+ DMA_CHANNEL(0x00, 0, 0),
+ DMA_CHANNEL(0x10, 0, 8),
+ DMA_CHANNEL(0x20, 4, 0),
+ DMA_CHANNEL(0x30, 4, 8),
+ DMA_CHANNEL(0x50, 8, 0),
+ DMA_CHANNEL(0x60, 8, 8),
+};
+
+static struct sh_dmae_pdata dma_platform_data = {
+ .slave = r8a7740_dmae_slaves,
+ .slave_num = ARRAY_SIZE(r8a7740_dmae_slaves),
+ .channel = r8a7740_dmae_channels,
+ .channel_num = ARRAY_SIZE(r8a7740_dmae_channels),
+ .ts_low_shift = TS_LOW_SHIFT,
+ .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT,
+ .ts_high_shift = TS_HI_SHIFT,
+ .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT,
+ .ts_shift = dma_ts_shift,
+ .ts_shift_num = ARRAY_SIZE(dma_ts_shift),
+ .dmaor_init = DMAOR_DME,
+ .chclr_present = 1,
+};
+
+/* Resource order important! */
+static struct resource r8a7740_dmae0_resources[] = {
+ {
+ /* Channel registers and DMAOR */
+ .start = 0xfe008020,
+ .end = 0xfe00828f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ /* DMARSx */
+ .start = 0xfe009000,
+ .end = 0xfe00900b,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "error_irq",
+ .start = gic_spi(34),
+ .end = gic_spi(34),
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 0-5 */
+ .start = gic_spi(28),
+ .end = gic_spi(33),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/* Resource order important! */
+static struct resource r8a7740_dmae1_resources[] = {
+ {
+ /* Channel registers and DMAOR */
+ .start = 0xfe018020,
+ .end = 0xfe01828f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ /* DMARSx */
+ .start = 0xfe019000,
+ .end = 0xfe01900b,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "error_irq",
+ .start = gic_spi(41),
+ .end = gic_spi(41),
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 0-5 */
+ .start = gic_spi(35),
+ .end = gic_spi(40),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/* Resource order important! */
+static struct resource r8a7740_dmae2_resources[] = {
+ {
+ /* Channel registers and DMAOR */
+ .start = 0xfe028020,
+ .end = 0xfe02828f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ /* DMARSx */
+ .start = 0xfe029000,
+ .end = 0xfe02900b,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "error_irq",
+ .start = gic_spi(48),
+ .end = gic_spi(48),
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 0-5 */
+ .start = gic_spi(42),
+ .end = gic_spi(47),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device dma0_device = {
+ .name = "sh-dma-engine",
+ .id = 0,
+ .resource = r8a7740_dmae0_resources,
+ .num_resources = ARRAY_SIZE(r8a7740_dmae0_resources),
+ .dev = {
+ .platform_data = &dma_platform_data,
+ },
+};
+
+static struct platform_device dma1_device = {
+ .name = "sh-dma-engine",
+ .id = 1,
+ .resource = r8a7740_dmae1_resources,
+ .num_resources = ARRAY_SIZE(r8a7740_dmae1_resources),
+ .dev = {
+ .platform_data = &dma_platform_data,
+ },
+};
+
+static struct platform_device dma2_device = {
+ .name = "sh-dma-engine",
+ .id = 2,
+ .resource = r8a7740_dmae2_resources,
+ .num_resources = ARRAY_SIZE(r8a7740_dmae2_resources),
+ .dev = {
+ .platform_data = &dma_platform_data,
+ },
+};
+
+/* USB-DMAC */
+static const struct sh_dmae_channel r8a7740_usb_dma_channels[] = {
+ {
+ .offset = 0,
+ }, {
+ .offset = 0x20,
+ },
+};
+
+static const struct sh_dmae_slave_config r8a7740_usb_dma_slaves[] = {
+ {
+ .slave_id = SHDMA_SLAVE_USBHS_TX,
+ .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE),
+ }, {
+ .slave_id = SHDMA_SLAVE_USBHS_RX,
+ .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE),
+ },
+};
+
+static struct sh_dmae_pdata usb_dma_platform_data = {
+ .slave = r8a7740_usb_dma_slaves,
+ .slave_num = ARRAY_SIZE(r8a7740_usb_dma_slaves),
+ .channel = r8a7740_usb_dma_channels,
+ .channel_num = ARRAY_SIZE(r8a7740_usb_dma_channels),
+ .ts_low_shift = USBTS_LOW_SHIFT,
+ .ts_low_mask = USBTS_LOW_BIT << USBTS_LOW_SHIFT,
+ .ts_high_shift = USBTS_HI_SHIFT,
+ .ts_high_mask = USBTS_HI_BIT << USBTS_HI_SHIFT,
+ .ts_shift = dma_usbts_shift,
+ .ts_shift_num = ARRAY_SIZE(dma_usbts_shift),
+ .dmaor_init = DMAOR_DME,
+ .chcr_offset = 0x14,
+ .chcr_ie_bit = 1 << 5,
+ .dmaor_is_32bit = 1,
+ .needs_tend_set = 1,
+ .no_dmars = 1,
+ .slave_only = 1,
+};
+
+static struct resource r8a7740_usb_dma_resources[] = {
+ {
+ /* Channel registers and DMAOR */
+ .start = 0xe68a0020,
+ .end = 0xe68a0064 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ /* VCR/SWR/DMICR */
+ .start = 0xe68a0000,
+ .end = 0xe68a0014 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ /* IRQ for channels */
+ .start = gic_spi(49),
+ .end = gic_spi(49),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device usb_dma_device = {
+ .name = "sh-dma-engine",
+ .id = 3,
+ .resource = r8a7740_usb_dma_resources,
+ .num_resources = ARRAY_SIZE(r8a7740_usb_dma_resources),
+ .dev = {
+ .platform_data = &usb_dma_platform_data,
+ },
+};
+
+/* I2C */
+static struct resource i2c0_resources[] = {
+ [0] = {
+ .name = "IIC0",
+ .start = 0xfff20000,
+ .end = 0xfff20425 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(201),
+ .end = gic_spi(204),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource i2c1_resources[] = {
+ [0] = {
+ .name = "IIC1",
+ .start = 0xe6c20000,
+ .end = 0xe6c20425 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_spi(70), /* IIC1_ALI1 */
+ .end = gic_spi(73), /* IIC1_DTEI1 */
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device i2c0_device = {
+ .name = "i2c-sh_mobile",
+ .id = 0,
+ .resource = i2c0_resources,
+ .num_resources = ARRAY_SIZE(i2c0_resources),
+};
+
+static struct platform_device i2c1_device = {
+ .name = "i2c-sh_mobile",
+ .id = 1,
+ .resource = i2c1_resources,
+ .num_resources = ARRAY_SIZE(i2c1_resources),
+};
+
+static struct resource pmu_resources[] = {
+ [0] = {
+ .start = gic_spi(83),
+ .end = gic_spi(83),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device pmu_device = {
+ .name = "armv7-pmu",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(pmu_resources),
+ .resource = pmu_resources,
+};
+
+static struct platform_device *r8a7740_late_devices[] __initdata = {
+ &i2c0_device,
+ &i2c1_device,
+ &dma0_device,
+ &dma1_device,
+ &dma2_device,
+ &usb_dma_device,
+ &pmu_device,
+};
+
+/*
+ * r8a7740 chip has lasting errata on MERAM buffer.
+ * this is work-around for it.
+ * see
+ * "Media RAM (MERAM)" on r8a7740 documentation
+ */
+#define MEBUFCNTR 0xFE950098
+void __init r8a7740_meram_workaround(void)
+{
+ void __iomem *reg;
+
+ reg = ioremap_nocache(MEBUFCNTR, 4);
+ if (reg) {
+ iowrite32(0x01600164, reg);
+ iounmap(reg);
+ }
+}
+
+#define ICCR 0x0004
+#define ICSTART 0x0070
+
+#define i2c_read(reg, offset) ioread8(reg + offset)
+#define i2c_write(reg, offset, data) iowrite8(data, reg + offset)
+
+/*
+ * r8a7740 chip has lasting errata on I2C I/O pad reset.
+ * this is work-around for it.
+ */
+static void r8a7740_i2c_workaround(struct platform_device *pdev)
+{
+ struct resource *res;
+ void __iomem *reg;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (unlikely(!res)) {
+ pr_err("r8a7740 i2c workaround fail (cannot find resource)\n");
+ return;
+ }
+
+ reg = ioremap(res->start, resource_size(res));
+ if (unlikely(!reg)) {
+ pr_err("r8a7740 i2c workaround fail (cannot map IO)\n");
+ return;
+ }
+
+ i2c_write(reg, ICCR, i2c_read(reg, ICCR) | 0x80);
+ i2c_read(reg, ICCR); /* dummy read */
+
+ i2c_write(reg, ICSTART, i2c_read(reg, ICSTART) | 0x10);
+ i2c_read(reg, ICSTART); /* dummy read */
+
+ udelay(10);
+
+ i2c_write(reg, ICCR, 0x01);
+ i2c_write(reg, ICSTART, 0x00);
+
+ udelay(10);
+
+ i2c_write(reg, ICCR, 0x10);
+ udelay(10);
+ i2c_write(reg, ICCR, 0x00);
+ udelay(10);
+ i2c_write(reg, ICCR, 0x10);
+ udelay(10);
+
+ iounmap(reg);
+}
+
+void __init r8a7740_add_standard_devices(void)
+{
+ static struct pm_domain_device domain_devices[] __initdata = {
+ { "A4R", &tmu0_device },
+ { "A4R", &i2c0_device },
+ { "A4S", &irqpin0_device },
+ { "A4S", &irqpin1_device },
+ { "A4S", &irqpin2_device },
+ { "A4S", &irqpin3_device },
+ { "A3SP", &scif0_device },
+ { "A3SP", &scif1_device },
+ { "A3SP", &scif2_device },
+ { "A3SP", &scif3_device },
+ { "A3SP", &scif4_device },
+ { "A3SP", &scif5_device },
+ { "A3SP", &scif6_device },
+ { "A3SP", &scif7_device },
+ { "A3SP", &scif8_device },
+ { "A3SP", &i2c1_device },
+ { "A3SP", &ipmmu_device },
+ { "A3SP", &dma0_device },
+ { "A3SP", &dma1_device },
+ { "A3SP", &dma2_device },
+ { "A3SP", &usb_dma_device },
+ };
+
+ /* I2C work-around */
+ r8a7740_i2c_workaround(&i2c0_device);
+ r8a7740_i2c_workaround(&i2c1_device);
+
+ r8a7740_init_pm_domains();
+
+ /* add devices */
+ platform_add_devices(r8a7740_early_devices,
+ ARRAY_SIZE(r8a7740_early_devices));
+ platform_add_devices(r8a7740_late_devices,
+ ARRAY_SIZE(r8a7740_late_devices));
+
+ /* add devices to PM domain */
+ rmobile_add_devices_to_domains(domain_devices,
+ ARRAY_SIZE(domain_devices));
+}
+
+void __init r8a7740_add_early_devices(void)
+{
+ early_platform_add_devices(r8a7740_early_devices,
+ ARRAY_SIZE(r8a7740_early_devices));
+
+ /* setup early console here as well */
+ shmobile_setup_console();
+}
+
+#ifdef CONFIG_USE_OF
+
+void __init r8a7740_init_irq_of(void)
+{
+ void __iomem *intc_prio_base = ioremap_nocache(0xe6900010, 0x10);
+ void __iomem *intc_msk_base = ioremap_nocache(0xe6900040, 0x10);
+ void __iomem *pfc_inta_ctrl = ioremap_nocache(0xe605807c, 0x4);
+
+#ifdef CONFIG_ARCH_SHMOBILE_LEGACY
+ void __iomem *gic_dist_base = ioremap_nocache(0xc2800000, 0x1000);
+ void __iomem *gic_cpu_base = ioremap_nocache(0xc2000000, 0x1000);
+
+ gic_init(0, 29, gic_dist_base, gic_cpu_base);
+#else
+ irqchip_init();
+#endif
+
+ /* route signals to GIC */
+ iowrite32(0x0, pfc_inta_ctrl);
+
+ /*
+ * To mask the shared interrupt to SPI 149 we must ensure to set
+ * PRIO *and* MASK. Else we run into IRQ floods when registering
+ * the intc_irqpin devices
+ */
+ iowrite32(0x0, intc_prio_base + 0x0);
+ iowrite32(0x0, intc_prio_base + 0x4);
+ iowrite32(0x0, intc_prio_base + 0x8);
+ iowrite32(0x0, intc_prio_base + 0xc);
+ iowrite8(0xff, intc_msk_base + 0x0);
+ iowrite8(0xff, intc_msk_base + 0x4);
+ iowrite8(0xff, intc_msk_base + 0x8);
+ iowrite8(0xff, intc_msk_base + 0xc);
+
+ iounmap(intc_prio_base);
+ iounmap(intc_msk_base);
+ iounmap(pfc_inta_ctrl);
+}
+
+static void __init r8a7740_generic_init(void)
+{
+ r8a7740_meram_workaround();
+
+#ifdef CONFIG_CACHE_L2X0
+ /* Shared attribute override enable, 32K*8way */
+ l2x0_init(IOMEM(0xf0002000), 0x00400000, 0xc20f0fff);
+#endif
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *r8a7740_boards_compat_dt[] __initdata = {
+ "renesas,r8a7740",
+ NULL,
+};
+
+DT_MACHINE_START(R8A7740_DT, "Generic R8A7740 (Flattened Device Tree)")
+ .map_io = r8a7740_map_io,
+ .init_early = shmobile_init_delay,
+ .init_irq = r8a7740_init_irq_of,
+ .init_machine = r8a7740_generic_init,
+ .init_late = shmobile_init_late,
+ .dt_compat = r8a7740_boards_compat_dt,
+MACHINE_END
+
+#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-r8a7778.c b/arch/arm/mach-shmobile/setup-r8a7778.c
new file mode 100644
index 000000000..c49aa094f
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-r8a7778.c
@@ -0,0 +1,633 @@
+/*
+ * r8a7778 processor support
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ * Copyright (C) 2013 Cogent Embedded, Inc.
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk/shmobile.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/irqchip/arm-gic.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_data/dma-rcar-hpbdma.h>
+#include <linux/platform_data/gpio-rcar.h>
+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
+#include <linux/platform_device.h>
+#include <linux/irqchip.h>
+#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/pm_runtime.h>
+#include <linux/usb/phy.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/mach/arch.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include "common.h"
+#include "irqs.h"
+#include "r8a7778.h"
+
+#define MODEMR 0xffcc0020
+
+#ifdef CONFIG_COMMON_CLK
+static void __init r8a7778_timer_init(void)
+{
+ u32 mode;
+ void __iomem *modemr = ioremap_nocache(MODEMR, 4);
+
+ BUG_ON(!modemr);
+ mode = ioread32(modemr);
+ iounmap(modemr);
+ r8a7778_clocks_init(mode);
+}
+#endif
+
+/* SCIF */
+#define R8A7778_SCIF(index, baseaddr, irq) \
+static struct plat_sci_port scif##index##_platform_data = { \
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, \
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, \
+ .type = PORT_SCIF, \
+}; \
+ \
+static struct resource scif##index##_resources[] = { \
+ DEFINE_RES_MEM(baseaddr, 0x100), \
+ DEFINE_RES_IRQ(irq), \
+}
+
+R8A7778_SCIF(0, 0xffe40000, gic_iid(0x66));
+R8A7778_SCIF(1, 0xffe41000, gic_iid(0x67));
+R8A7778_SCIF(2, 0xffe42000, gic_iid(0x68));
+R8A7778_SCIF(3, 0xffe43000, gic_iid(0x69));
+R8A7778_SCIF(4, 0xffe44000, gic_iid(0x6a));
+R8A7778_SCIF(5, 0xffe45000, gic_iid(0x6b));
+
+#define r8a7778_register_scif(index) \
+ platform_device_register_resndata(NULL, "sh-sci", index, \
+ scif##index##_resources, \
+ ARRAY_SIZE(scif##index##_resources), \
+ &scif##index##_platform_data, \
+ sizeof(scif##index##_platform_data))
+
+/* TMU */
+static struct sh_timer_config sh_tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource sh_tmu0_resources[] = {
+ DEFINE_RES_MEM(0xffd80000, 0x30),
+ DEFINE_RES_IRQ(gic_iid(0x40)),
+ DEFINE_RES_IRQ(gic_iid(0x41)),
+ DEFINE_RES_IRQ(gic_iid(0x42)),
+};
+
+#define r8a7778_register_tmu(idx) \
+ platform_device_register_resndata( \
+ NULL, "sh-tmu", idx, \
+ sh_tmu##idx##_resources, \
+ ARRAY_SIZE(sh_tmu##idx##_resources), \
+ &sh_tmu##idx##_platform_data, \
+ sizeof(sh_tmu##idx##_platform_data))
+
+int r8a7778_usb_phy_power(bool enable)
+{
+ static struct usb_phy *phy = NULL;
+ int ret = 0;
+
+ if (!phy)
+ phy = usb_get_phy(USB_PHY_TYPE_USB2);
+
+ if (IS_ERR(phy)) {
+ pr_err("kernel doesn't have usb phy driver\n");
+ return PTR_ERR(phy);
+ }
+
+ if (enable)
+ ret = usb_phy_init(phy);
+ else
+ usb_phy_shutdown(phy);
+
+ return ret;
+}
+
+/* USB */
+static int usb_power_on(struct platform_device *pdev)
+{
+ int ret = r8a7778_usb_phy_power(true);
+
+ if (ret)
+ return ret;
+
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
+
+ return 0;
+}
+
+static void usb_power_off(struct platform_device *pdev)
+{
+ if (r8a7778_usb_phy_power(false))
+ return;
+
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+}
+
+static int ehci_init_internal_buffer(struct usb_hcd *hcd)
+{
+ /*
+ * Below are recommended values from the datasheet;
+ * see [USB :: Setting of EHCI Internal Buffer].
+ */
+ /* EHCI IP internal buffer setting */
+ iowrite32(0x00ff0040, hcd->regs + 0x0094);
+ /* EHCI IP internal buffer enable */
+ iowrite32(0x00000001, hcd->regs + 0x009C);
+
+ return 0;
+}
+
+static struct usb_ehci_pdata ehci_pdata __initdata = {
+ .power_on = usb_power_on,
+ .power_off = usb_power_off,
+ .power_suspend = usb_power_off,
+ .pre_setup = ehci_init_internal_buffer,
+};
+
+static struct resource ehci_resources[] __initdata = {
+ DEFINE_RES_MEM(0xffe70000, 0x400),
+ DEFINE_RES_IRQ(gic_iid(0x4c)),
+};
+
+static struct usb_ohci_pdata ohci_pdata __initdata = {
+ .power_on = usb_power_on,
+ .power_off = usb_power_off,
+ .power_suspend = usb_power_off,
+};
+
+static struct resource ohci_resources[] __initdata = {
+ DEFINE_RES_MEM(0xffe70400, 0x400),
+ DEFINE_RES_IRQ(gic_iid(0x4c)),
+};
+
+#define USB_PLATFORM_INFO(hci) \
+static struct platform_device_info hci##_info __initdata = { \
+ .name = #hci "-platform", \
+ .id = -1, \
+ .res = hci##_resources, \
+ .num_res = ARRAY_SIZE(hci##_resources), \
+ .data = &hci##_pdata, \
+ .size_data = sizeof(hci##_pdata), \
+ .dma_mask = DMA_BIT_MASK(32), \
+}
+
+USB_PLATFORM_INFO(ehci);
+USB_PLATFORM_INFO(ohci);
+
+/* PFC/GPIO */
+static struct resource pfc_resources[] __initdata = {
+ DEFINE_RES_MEM(0xfffc0000, 0x118),
+};
+
+#define R8A7778_GPIO(idx) \
+static struct resource r8a7778_gpio##idx##_resources[] __initdata = { \
+ DEFINE_RES_MEM(0xffc40000 + 0x1000 * (idx), 0x30), \
+ DEFINE_RES_IRQ(gic_iid(0x87)), \
+}; \
+ \
+static struct gpio_rcar_config r8a7778_gpio##idx##_platform_data __initdata = { \
+ .gpio_base = 32 * (idx), \
+ .irq_base = GPIO_IRQ_BASE(idx), \
+ .number_of_pins = 32, \
+ .pctl_name = "pfc-r8a7778", \
+}
+
+R8A7778_GPIO(0);
+R8A7778_GPIO(1);
+R8A7778_GPIO(2);
+R8A7778_GPIO(3);
+R8A7778_GPIO(4);
+
+#define r8a7778_register_gpio(idx) \
+ platform_device_register_resndata( \
+ NULL, "gpio_rcar", idx, \
+ r8a7778_gpio##idx##_resources, \
+ ARRAY_SIZE(r8a7778_gpio##idx##_resources), \
+ &r8a7778_gpio##idx##_platform_data, \
+ sizeof(r8a7778_gpio##idx##_platform_data))
+
+void __init r8a7778_pinmux_init(void)
+{
+ platform_device_register_simple(
+ "pfc-r8a7778", -1,
+ pfc_resources,
+ ARRAY_SIZE(pfc_resources));
+
+ r8a7778_register_gpio(0);
+ r8a7778_register_gpio(1);
+ r8a7778_register_gpio(2);
+ r8a7778_register_gpio(3);
+ r8a7778_register_gpio(4);
+};
+
+/* I2C */
+static struct resource i2c_resources[] __initdata = {
+ /* I2C0 */
+ DEFINE_RES_MEM(0xffc70000, 0x1000),
+ DEFINE_RES_IRQ(gic_iid(0x63)),
+ /* I2C1 */
+ DEFINE_RES_MEM(0xffc71000, 0x1000),
+ DEFINE_RES_IRQ(gic_iid(0x6e)),
+ /* I2C2 */
+ DEFINE_RES_MEM(0xffc72000, 0x1000),
+ DEFINE_RES_IRQ(gic_iid(0x6c)),
+ /* I2C3 */
+ DEFINE_RES_MEM(0xffc73000, 0x1000),
+ DEFINE_RES_IRQ(gic_iid(0x6d)),
+};
+
+static void __init r8a7778_register_i2c(int id)
+{
+ BUG_ON(id < 0 || id > 3);
+
+ platform_device_register_simple(
+ "i2c-rcar", id,
+ i2c_resources + (2 * id), 2);
+}
+
+/* HSPI */
+static struct resource hspi_resources[] __initdata = {
+ /* HSPI0 */
+ DEFINE_RES_MEM(0xfffc7000, 0x18),
+ DEFINE_RES_IRQ(gic_iid(0x5f)),
+ /* HSPI1 */
+ DEFINE_RES_MEM(0xfffc8000, 0x18),
+ DEFINE_RES_IRQ(gic_iid(0x74)),
+ /* HSPI2 */
+ DEFINE_RES_MEM(0xfffc6000, 0x18),
+ DEFINE_RES_IRQ(gic_iid(0x75)),
+};
+
+static void __init r8a7778_register_hspi(int id)
+{
+ BUG_ON(id < 0 || id > 2);
+
+ platform_device_register_simple(
+ "sh-hspi", id,
+ hspi_resources + (2 * id), 2);
+}
+
+void __init r8a7778_add_dt_devices(void)
+{
+#ifdef CONFIG_CACHE_L2X0
+ void __iomem *base = ioremap_nocache(0xf0100000, 0x1000);
+ if (base) {
+ /*
+ * Shared attribute override enable, 64K*16way
+ * don't call iounmap(base)
+ */
+ l2x0_init(base, 0x00400000, 0xc20f0fff);
+ }
+#endif
+}
+
+/* HPB-DMA */
+
+/* Asynchronous mode register (ASYNCMDR) bits */
+#define HPB_DMAE_ASYNCMDR_ASMD22_MASK BIT(2) /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD22_SINGLE BIT(2) /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD22_MULTI 0 /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD21_MASK BIT(1) /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD21_SINGLE BIT(1) /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD21_MULTI 0 /* SDHI0 */
+
+#define HPBDMA_SSI(_id) \
+{ \
+ .id = HPBDMA_SLAVE_SSI## _id ##_TX, \
+ .addr = 0xffd91008 + (_id * 0x40), \
+ .dcr = HPB_DMAE_DCR_CT | \
+ HPB_DMAE_DCR_DIP | \
+ HPB_DMAE_DCR_SPDS_32BIT | \
+ HPB_DMAE_DCR_DMDL | \
+ HPB_DMAE_DCR_DPDS_32BIT, \
+ .port = _id + (_id << 8), \
+ .dma_ch = (28 + _id), \
+}, { \
+ .id = HPBDMA_SLAVE_SSI## _id ##_RX, \
+ .addr = 0xffd9100c + (_id * 0x40), \
+ .dcr = HPB_DMAE_DCR_CT | \
+ HPB_DMAE_DCR_DIP | \
+ HPB_DMAE_DCR_SMDL | \
+ HPB_DMAE_DCR_SPDS_32BIT | \
+ HPB_DMAE_DCR_DPDS_32BIT, \
+ .port = _id + (_id << 8), \
+ .dma_ch = (28 + _id), \
+}
+
+#define HPBDMA_HPBIF(_id) \
+{ \
+ .id = HPBDMA_SLAVE_HPBIF## _id ##_TX, \
+ .addr = 0xffda0000 + (_id * 0x1000), \
+ .dcr = HPB_DMAE_DCR_CT | \
+ HPB_DMAE_DCR_DIP | \
+ HPB_DMAE_DCR_SPDS_32BIT | \
+ HPB_DMAE_DCR_DMDL | \
+ HPB_DMAE_DCR_DPDS_32BIT, \
+ .port = 0x1111, \
+ .dma_ch = (28 + _id), \
+}, { \
+ .id = HPBDMA_SLAVE_HPBIF## _id ##_RX, \
+ .addr = 0xffda0000 + (_id * 0x1000), \
+ .dcr = HPB_DMAE_DCR_CT | \
+ HPB_DMAE_DCR_DIP | \
+ HPB_DMAE_DCR_SMDL | \
+ HPB_DMAE_DCR_SPDS_32BIT | \
+ HPB_DMAE_DCR_DPDS_32BIT, \
+ .port = 0x1111, \
+ .dma_ch = (28 + _id), \
+}
+
+static const struct hpb_dmae_slave_config hpb_dmae_slaves[] = {
+ {
+ .id = HPBDMA_SLAVE_SDHI0_TX,
+ .addr = 0xffe4c000 + 0x30,
+ .dcr = HPB_DMAE_DCR_SPDS_16BIT |
+ HPB_DMAE_DCR_DMDL |
+ HPB_DMAE_DCR_DPDS_16BIT,
+ .rstr = HPB_DMAE_ASYNCRSTR_ASRST21 |
+ HPB_DMAE_ASYNCRSTR_ASRST22 |
+ HPB_DMAE_ASYNCRSTR_ASRST23,
+ .mdr = HPB_DMAE_ASYNCMDR_ASMD21_MULTI,
+ .mdm = HPB_DMAE_ASYNCMDR_ASMD21_MASK,
+ .port = 0x0D0C,
+ .flags = HPB_DMAE_SET_ASYNC_RESET | HPB_DMAE_SET_ASYNC_MODE,
+ .dma_ch = 21,
+ }, {
+ .id = HPBDMA_SLAVE_SDHI0_RX,
+ .addr = 0xffe4c000 + 0x30,
+ .dcr = HPB_DMAE_DCR_SMDL |
+ HPB_DMAE_DCR_SPDS_16BIT |
+ HPB_DMAE_DCR_DPDS_16BIT,
+ .rstr = HPB_DMAE_ASYNCRSTR_ASRST21 |
+ HPB_DMAE_ASYNCRSTR_ASRST22 |
+ HPB_DMAE_ASYNCRSTR_ASRST23,
+ .mdr = HPB_DMAE_ASYNCMDR_ASMD22_MULTI,
+ .mdm = HPB_DMAE_ASYNCMDR_ASMD22_MASK,
+ .port = 0x0D0C,
+ .flags = HPB_DMAE_SET_ASYNC_RESET | HPB_DMAE_SET_ASYNC_MODE,
+ .dma_ch = 22,
+ }, {
+ .id = HPBDMA_SLAVE_USBFUNC_TX, /* for D0 */
+ .addr = 0xffe60018,
+ .dcr = HPB_DMAE_DCR_SPDS_32BIT |
+ HPB_DMAE_DCR_DMDL |
+ HPB_DMAE_DCR_DPDS_32BIT,
+ .port = 0x0000,
+ .dma_ch = 14,
+ }, {
+ .id = HPBDMA_SLAVE_USBFUNC_RX, /* for D1 */
+ .addr = 0xffe6001c,
+ .dcr = HPB_DMAE_DCR_SMDL |
+ HPB_DMAE_DCR_SPDS_32BIT |
+ HPB_DMAE_DCR_DPDS_32BIT,
+ .port = 0x0101,
+ .dma_ch = 15,
+ },
+
+ HPBDMA_SSI(0),
+ HPBDMA_SSI(1),
+ HPBDMA_SSI(2),
+ HPBDMA_SSI(3),
+ HPBDMA_SSI(4),
+ HPBDMA_SSI(5),
+ HPBDMA_SSI(6),
+ HPBDMA_SSI(7),
+ HPBDMA_SSI(8),
+
+ HPBDMA_HPBIF(0),
+ HPBDMA_HPBIF(1),
+ HPBDMA_HPBIF(2),
+ HPBDMA_HPBIF(3),
+ HPBDMA_HPBIF(4),
+ HPBDMA_HPBIF(5),
+ HPBDMA_HPBIF(6),
+ HPBDMA_HPBIF(7),
+ HPBDMA_HPBIF(8),
+};
+
+static const struct hpb_dmae_channel hpb_dmae_channels[] = {
+ HPB_DMAE_CHANNEL(0x7c, HPBDMA_SLAVE_USBFUNC_TX), /* ch. 14 */
+ HPB_DMAE_CHANNEL(0x7c, HPBDMA_SLAVE_USBFUNC_RX), /* ch. 15 */
+ HPB_DMAE_CHANNEL(0x7e, HPBDMA_SLAVE_SDHI0_TX), /* ch. 21 */
+ HPB_DMAE_CHANNEL(0x7e, HPBDMA_SLAVE_SDHI0_RX), /* ch. 22 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI0_TX), /* ch. 28 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI0_RX), /* ch. 28 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF0_TX), /* ch. 28 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF0_RX), /* ch. 28 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI1_TX), /* ch. 29 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI1_RX), /* ch. 29 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF1_TX), /* ch. 29 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF1_RX), /* ch. 29 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI2_TX), /* ch. 30 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI2_RX), /* ch. 30 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF2_TX), /* ch. 30 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF2_RX), /* ch. 30 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI3_TX), /* ch. 31 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI3_RX), /* ch. 31 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF3_TX), /* ch. 31 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF3_RX), /* ch. 31 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI4_TX), /* ch. 32 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI4_RX), /* ch. 32 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF4_TX), /* ch. 32 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF4_RX), /* ch. 32 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI5_TX), /* ch. 33 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI5_RX), /* ch. 33 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF5_TX), /* ch. 33 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF5_RX), /* ch. 33 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI6_TX), /* ch. 34 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI6_RX), /* ch. 34 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF6_TX), /* ch. 34 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF6_RX), /* ch. 34 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI7_TX), /* ch. 35 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI7_RX), /* ch. 35 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF7_TX), /* ch. 35 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF7_RX), /* ch. 35 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI8_TX), /* ch. 36 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI8_RX), /* ch. 36 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF8_TX), /* ch. 36 */
+ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF8_RX), /* ch. 36 */
+};
+
+static struct hpb_dmae_pdata dma_platform_data __initdata = {
+ .slaves = hpb_dmae_slaves,
+ .num_slaves = ARRAY_SIZE(hpb_dmae_slaves),
+ .channels = hpb_dmae_channels,
+ .num_channels = ARRAY_SIZE(hpb_dmae_channels),
+ .ts_shift = {
+ [XMIT_SZ_8BIT] = 0,
+ [XMIT_SZ_16BIT] = 1,
+ [XMIT_SZ_32BIT] = 2,
+ },
+ .num_hw_channels = 39,
+};
+
+static struct resource hpb_dmae_resources[] __initdata = {
+ /* Channel registers */
+ DEFINE_RES_MEM(0xffc08000, 0x1000),
+ /* Common registers */
+ DEFINE_RES_MEM(0xffc09000, 0x170),
+ /* Asynchronous reset registers */
+ DEFINE_RES_MEM(0xffc00300, 4),
+ /* Asynchronous mode registers */
+ DEFINE_RES_MEM(0xffc00400, 4),
+ /* IRQ for DMA channels */
+ DEFINE_RES_NAMED(gic_iid(0x7b), 5, NULL, IORESOURCE_IRQ),
+};
+
+static void __init r8a7778_register_hpb_dmae(void)
+{
+ platform_device_register_resndata(NULL, "hpb-dma-engine",
+ -1, hpb_dmae_resources,
+ ARRAY_SIZE(hpb_dmae_resources),
+ &dma_platform_data,
+ sizeof(dma_platform_data));
+}
+
+void __init r8a7778_add_standard_devices(void)
+{
+ r8a7778_add_dt_devices();
+ r8a7778_register_tmu(0);
+ r8a7778_register_scif(0);
+ r8a7778_register_scif(1);
+ r8a7778_register_scif(2);
+ r8a7778_register_scif(3);
+ r8a7778_register_scif(4);
+ r8a7778_register_scif(5);
+ r8a7778_register_i2c(0);
+ r8a7778_register_i2c(1);
+ r8a7778_register_i2c(2);
+ r8a7778_register_i2c(3);
+ r8a7778_register_hspi(0);
+ r8a7778_register_hspi(1);
+ r8a7778_register_hspi(2);
+
+ r8a7778_register_hpb_dmae();
+}
+
+void __init r8a7778_init_late(void)
+{
+ shmobile_init_late();
+ platform_device_register_full(&ehci_info);
+ platform_device_register_full(&ohci_info);
+}
+
+static struct renesas_intc_irqpin_config irqpin_platform_data __initdata = {
+ .irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
+ .sense_bitfield_width = 2,
+};
+
+static struct resource irqpin_resources[] __initdata = {
+ DEFINE_RES_MEM(0xfe78001c, 4), /* ICR1 */
+ DEFINE_RES_MEM(0xfe780010, 4), /* INTPRI */
+ DEFINE_RES_MEM(0xfe780024, 4), /* INTREQ */
+ DEFINE_RES_MEM(0xfe780044, 4), /* INTMSK0 */
+ DEFINE_RES_MEM(0xfe780064, 4), /* INTMSKCLR0 */
+ DEFINE_RES_IRQ(gic_iid(0x3b)), /* IRQ0 */
+ DEFINE_RES_IRQ(gic_iid(0x3c)), /* IRQ1 */
+ DEFINE_RES_IRQ(gic_iid(0x3d)), /* IRQ2 */
+ DEFINE_RES_IRQ(gic_iid(0x3e)), /* IRQ3 */
+};
+
+void __init r8a7778_init_irq_extpin_dt(int irlm)
+{
+ void __iomem *icr0 = ioremap_nocache(0xfe780000, PAGE_SIZE);
+ unsigned long tmp;
+
+ if (!icr0) {
+ pr_warn("r8a7778: unable to setup external irq pin mode\n");
+ return;
+ }
+
+ tmp = ioread32(icr0);
+ if (irlm)
+ tmp |= 1 << 23; /* IRQ0 -> IRQ3 as individual pins */
+ else
+ tmp &= ~(1 << 23); /* IRL mode - not supported */
+ tmp |= (1 << 21); /* LVLMODE = 1 */
+ iowrite32(tmp, icr0);
+ iounmap(icr0);
+}
+
+void __init r8a7778_init_irq_extpin(int irlm)
+{
+ r8a7778_init_irq_extpin_dt(irlm);
+ if (irlm)
+ platform_device_register_resndata(
+ NULL, "renesas_intc_irqpin", -1,
+ irqpin_resources, ARRAY_SIZE(irqpin_resources),
+ &irqpin_platform_data, sizeof(irqpin_platform_data));
+}
+
+#ifdef CONFIG_USE_OF
+#define INT2SMSKCR0 0x82288 /* 0xfe782288 */
+#define INT2SMSKCR1 0x8228c /* 0xfe78228c */
+
+#define INT2NTSR0 0x00018 /* 0xfe700018 */
+#define INT2NTSR1 0x0002c /* 0xfe70002c */
+void __init r8a7778_init_irq_dt(void)
+{
+ void __iomem *base = ioremap_nocache(0xfe700000, 0x00100000);
+#ifdef CONFIG_ARCH_SHMOBILE_LEGACY
+ void __iomem *gic_dist_base = ioremap_nocache(0xfe438000, 0x1000);
+ void __iomem *gic_cpu_base = ioremap_nocache(0xfe430000, 0x1000);
+#endif
+
+ BUG_ON(!base);
+
+#ifdef CONFIG_ARCH_SHMOBILE_LEGACY
+ gic_init(0, 29, gic_dist_base, gic_cpu_base);
+#else
+ irqchip_init();
+#endif
+ /* route all interrupts to ARM */
+ __raw_writel(0x73ffffff, base + INT2NTSR0);
+ __raw_writel(0xffffffff, base + INT2NTSR1);
+
+ /* unmask all known interrupts in INTCS2 */
+ __raw_writel(0x08330773, base + INT2SMSKCR0);
+ __raw_writel(0x00311110, base + INT2SMSKCR1);
+
+ iounmap(base);
+}
+
+static const char *r8a7778_compat_dt[] __initdata = {
+ "renesas,r8a7778",
+ NULL,
+};
+
+DT_MACHINE_START(R8A7778_DT, "Generic R8A7778 (Flattened Device Tree)")
+ .init_early = shmobile_init_delay,
+ .init_irq = r8a7778_init_irq_dt,
+ .init_late = shmobile_init_late,
+#ifdef CONFIG_COMMON_CLK
+ .init_time = r8a7778_timer_init,
+#endif
+ .dt_compat = r8a7778_compat_dt,
+MACHINE_END
+
+#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c
new file mode 100644
index 000000000..c03e562be
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-r8a7779.c
@@ -0,0 +1,771 @@
+/*
+ * r8a7779 processor support
+ *
+ * Copyright (C) 2011, 2013 Renesas Solutions Corp.
+ * Copyright (C) 2011 Magnus Damm
+ * Copyright (C) 2013 Cogent Embedded, Inc.
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/arm-gic.h>
+#include <linux/of_platform.h>
+#include <linux/platform_data/dma-rcar-hpbdma.h>
+#include <linux/platform_data/gpio-rcar.h>
+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/dma-mapping.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
+#include <linux/pm_runtime.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include "common.h"
+#include "irqs.h"
+#include "r8a7779.h"
+
+static struct map_desc r8a7779_io_desc[] __initdata = {
+ /* 2M identity mapping for 0xf0000000 (MPCORE) */
+ {
+ .virtual = 0xf0000000,
+ .pfn = __phys_to_pfn(0xf0000000),
+ .length = SZ_2M,
+ .type = MT_DEVICE_NONSHARED
+ },
+ /* 16M identity mapping for 0xfexxxxxx (DMAC-S/HPBREG/INTC2/LRAM/DBSC) */
+ {
+ .virtual = 0xfe000000,
+ .pfn = __phys_to_pfn(0xfe000000),
+ .length = SZ_16M,
+ .type = MT_DEVICE_NONSHARED
+ },
+};
+
+void __init r8a7779_map_io(void)
+{
+ debug_ll_io_init();
+ iotable_init(r8a7779_io_desc, ARRAY_SIZE(r8a7779_io_desc));
+}
+
+/* IRQ */
+#define INT2SMSKCR0 IOMEM(0xfe7822a0)
+#define INT2SMSKCR1 IOMEM(0xfe7822a4)
+#define INT2SMSKCR2 IOMEM(0xfe7822a8)
+#define INT2SMSKCR3 IOMEM(0xfe7822ac)
+#define INT2SMSKCR4 IOMEM(0xfe7822b0)
+
+#define INT2NTSR0 IOMEM(0xfe700060)
+#define INT2NTSR1 IOMEM(0xfe700064)
+
+static struct renesas_intc_irqpin_config irqpin0_platform_data __initdata = {
+ .irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
+ .sense_bitfield_width = 2,
+};
+
+static struct resource irqpin0_resources[] __initdata = {
+ DEFINE_RES_MEM(0xfe78001c, 4), /* ICR1 */
+ DEFINE_RES_MEM(0xfe780010, 4), /* INTPRI */
+ DEFINE_RES_MEM(0xfe780024, 4), /* INTREQ */
+ DEFINE_RES_MEM(0xfe780044, 4), /* INTMSK0 */
+ DEFINE_RES_MEM(0xfe780064, 4), /* INTMSKCLR0 */
+ DEFINE_RES_IRQ(gic_spi(27)), /* IRQ0 */
+ DEFINE_RES_IRQ(gic_spi(28)), /* IRQ1 */
+ DEFINE_RES_IRQ(gic_spi(29)), /* IRQ2 */
+ DEFINE_RES_IRQ(gic_spi(30)), /* IRQ3 */
+};
+
+void __init r8a7779_init_irq_extpin_dt(int irlm)
+{
+ void __iomem *icr0 = ioremap_nocache(0xfe780000, PAGE_SIZE);
+ u32 tmp;
+
+ if (!icr0) {
+ pr_warn("r8a7779: unable to setup external irq pin mode\n");
+ return;
+ }
+
+ tmp = ioread32(icr0);
+ if (irlm)
+ tmp |= 1 << 23; /* IRQ0 -> IRQ3 as individual pins */
+ else
+ tmp &= ~(1 << 23); /* IRL mode - not supported */
+ tmp |= (1 << 21); /* LVLMODE = 1 */
+ iowrite32(tmp, icr0);
+ iounmap(icr0);
+}
+
+void __init r8a7779_init_irq_extpin(int irlm)
+{
+ r8a7779_init_irq_extpin_dt(irlm);
+ if (irlm)
+ platform_device_register_resndata(
+ NULL, "renesas_intc_irqpin", -1,
+ irqpin0_resources, ARRAY_SIZE(irqpin0_resources),
+ &irqpin0_platform_data, sizeof(irqpin0_platform_data));
+}
+
+/* PFC/GPIO */
+static struct resource r8a7779_pfc_resources[] = {
+ DEFINE_RES_MEM(0xfffc0000, 0x023c),
+};
+
+static struct platform_device r8a7779_pfc_device = {
+ .name = "pfc-r8a7779",
+ .id = -1,
+ .resource = r8a7779_pfc_resources,
+ .num_resources = ARRAY_SIZE(r8a7779_pfc_resources),
+};
+
+#define R8A7779_GPIO(idx, npins) \
+static struct resource r8a7779_gpio##idx##_resources[] = { \
+ DEFINE_RES_MEM(0xffc40000 + (0x1000 * (idx)), 0x002c), \
+ DEFINE_RES_IRQ(gic_iid(0xad + (idx))), \
+}; \
+ \
+static struct gpio_rcar_config r8a7779_gpio##idx##_platform_data = { \
+ .gpio_base = 32 * (idx), \
+ .irq_base = 0, \
+ .number_of_pins = npins, \
+ .pctl_name = "pfc-r8a7779", \
+}; \
+ \
+static struct platform_device r8a7779_gpio##idx##_device = { \
+ .name = "gpio_rcar", \
+ .id = idx, \
+ .resource = r8a7779_gpio##idx##_resources, \
+ .num_resources = ARRAY_SIZE(r8a7779_gpio##idx##_resources), \
+ .dev = { \
+ .platform_data = &r8a7779_gpio##idx##_platform_data, \
+ }, \
+}
+
+R8A7779_GPIO(0, 32);
+R8A7779_GPIO(1, 32);
+R8A7779_GPIO(2, 32);
+R8A7779_GPIO(3, 32);
+R8A7779_GPIO(4, 32);
+R8A7779_GPIO(5, 32);
+R8A7779_GPIO(6, 9);
+
+static struct platform_device *r8a7779_pinctrl_devices[] __initdata = {
+ &r8a7779_pfc_device,
+ &r8a7779_gpio0_device,
+ &r8a7779_gpio1_device,
+ &r8a7779_gpio2_device,
+ &r8a7779_gpio3_device,
+ &r8a7779_gpio4_device,
+ &r8a7779_gpio5_device,
+ &r8a7779_gpio6_device,
+};
+
+void __init r8a7779_pinmux_init(void)
+{
+ platform_add_devices(r8a7779_pinctrl_devices,
+ ARRAY_SIZE(r8a7779_pinctrl_devices));
+}
+
+/* SCIF */
+#define R8A7779_SCIF(index, baseaddr, irq) \
+static struct plat_sci_port scif##index##_platform_data = { \
+ .type = PORT_SCIF, \
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, \
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, \
+}; \
+ \
+static struct resource scif##index##_resources[] = { \
+ DEFINE_RES_MEM(baseaddr, 0x100), \
+ DEFINE_RES_IRQ(irq), \
+}; \
+ \
+static struct platform_device scif##index##_device = { \
+ .name = "sh-sci", \
+ .id = index, \
+ .resource = scif##index##_resources, \
+ .num_resources = ARRAY_SIZE(scif##index##_resources), \
+ .dev = { \
+ .platform_data = &scif##index##_platform_data, \
+ }, \
+}
+
+R8A7779_SCIF(0, 0xffe40000, gic_iid(0x78));
+R8A7779_SCIF(1, 0xffe41000, gic_iid(0x79));
+R8A7779_SCIF(2, 0xffe42000, gic_iid(0x7a));
+R8A7779_SCIF(3, 0xffe43000, gic_iid(0x7b));
+R8A7779_SCIF(4, 0xffe44000, gic_iid(0x7c));
+R8A7779_SCIF(5, 0xffe45000, gic_iid(0x7d));
+
+/* TMU */
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xffd80000, 0x30),
+ DEFINE_RES_IRQ(gic_iid(0x40)),
+ DEFINE_RES_IRQ(gic_iid(0x41)),
+ DEFINE_RES_IRQ(gic_iid(0x42)),
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh-tmu",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
+/* I2C */
+static struct resource rcar_i2c0_res[] = {
+ {
+ .start = 0xffc70000,
+ .end = 0xffc70fff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = gic_iid(0x6f),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device i2c0_device = {
+ .name = "i2c-rcar",
+ .id = 0,
+ .resource = rcar_i2c0_res,
+ .num_resources = ARRAY_SIZE(rcar_i2c0_res),
+};
+
+static struct resource rcar_i2c1_res[] = {
+ {
+ .start = 0xffc71000,
+ .end = 0xffc71fff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = gic_iid(0x72),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device i2c1_device = {
+ .name = "i2c-rcar",
+ .id = 1,
+ .resource = rcar_i2c1_res,
+ .num_resources = ARRAY_SIZE(rcar_i2c1_res),
+};
+
+static struct resource rcar_i2c2_res[] = {
+ {
+ .start = 0xffc72000,
+ .end = 0xffc72fff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = gic_iid(0x70),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device i2c2_device = {
+ .name = "i2c-rcar",
+ .id = 2,
+ .resource = rcar_i2c2_res,
+ .num_resources = ARRAY_SIZE(rcar_i2c2_res),
+};
+
+static struct resource rcar_i2c3_res[] = {
+ {
+ .start = 0xffc73000,
+ .end = 0xffc73fff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = gic_iid(0x71),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device i2c3_device = {
+ .name = "i2c-rcar",
+ .id = 3,
+ .resource = rcar_i2c3_res,
+ .num_resources = ARRAY_SIZE(rcar_i2c3_res),
+};
+
+static struct resource sata_resources[] = {
+ [0] = {
+ .name = "rcar-sata",
+ .start = 0xfc600000,
+ .end = 0xfc601fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_iid(0x84),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sata_device = {
+ .name = "sata_rcar",
+ .id = -1,
+ .resource = sata_resources,
+ .num_resources = ARRAY_SIZE(sata_resources),
+ .dev = {
+ .dma_mask = &sata_device.dev.coherent_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+/* USB */
+static struct usb_phy *phy;
+
+static int usb_power_on(struct platform_device *pdev)
+{
+ if (IS_ERR(phy))
+ return PTR_ERR(phy);
+
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
+
+ usb_phy_init(phy);
+
+ return 0;
+}
+
+static void usb_power_off(struct platform_device *pdev)
+{
+ if (IS_ERR(phy))
+ return;
+
+ usb_phy_shutdown(phy);
+
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+}
+
+static int ehci_init_internal_buffer(struct usb_hcd *hcd)
+{
+ /*
+ * Below are recommended values from the datasheet;
+ * see [USB :: Setting of EHCI Internal Buffer].
+ */
+ /* EHCI IP internal buffer setting */
+ iowrite32(0x00ff0040, hcd->regs + 0x0094);
+ /* EHCI IP internal buffer enable */
+ iowrite32(0x00000001, hcd->regs + 0x009C);
+
+ return 0;
+}
+
+static struct usb_ehci_pdata ehcix_pdata = {
+ .power_on = usb_power_on,
+ .power_off = usb_power_off,
+ .power_suspend = usb_power_off,
+ .pre_setup = ehci_init_internal_buffer,
+};
+
+static struct resource ehci0_resources[] = {
+ [0] = {
+ .start = 0xffe70000,
+ .end = 0xffe70400 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_iid(0x4c),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ehci0_device = {
+ .name = "ehci-platform",
+ .id = 0,
+ .dev = {
+ .dma_mask = &ehci0_device.dev.coherent_dma_mask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &ehcix_pdata,
+ },
+ .num_resources = ARRAY_SIZE(ehci0_resources),
+ .resource = ehci0_resources,
+};
+
+static struct resource ehci1_resources[] = {
+ [0] = {
+ .start = 0xfff70000,
+ .end = 0xfff70400 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_iid(0x4d),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ehci1_device = {
+ .name = "ehci-platform",
+ .id = 1,
+ .dev = {
+ .dma_mask = &ehci1_device.dev.coherent_dma_mask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &ehcix_pdata,
+ },
+ .num_resources = ARRAY_SIZE(ehci1_resources),
+ .resource = ehci1_resources,
+};
+
+static struct usb_ohci_pdata ohcix_pdata = {
+ .power_on = usb_power_on,
+ .power_off = usb_power_off,
+ .power_suspend = usb_power_off,
+};
+
+static struct resource ohci0_resources[] = {
+ [0] = {
+ .start = 0xffe70400,
+ .end = 0xffe70800 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_iid(0x4c),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ohci0_device = {
+ .name = "ohci-platform",
+ .id = 0,
+ .dev = {
+ .dma_mask = &ohci0_device.dev.coherent_dma_mask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &ohcix_pdata,
+ },
+ .num_resources = ARRAY_SIZE(ohci0_resources),
+ .resource = ohci0_resources,
+};
+
+static struct resource ohci1_resources[] = {
+ [0] = {
+ .start = 0xfff70400,
+ .end = 0xfff70800 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_iid(0x4d),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ohci1_device = {
+ .name = "ohci-platform",
+ .id = 1,
+ .dev = {
+ .dma_mask = &ohci1_device.dev.coherent_dma_mask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &ohcix_pdata,
+ },
+ .num_resources = ARRAY_SIZE(ohci1_resources),
+ .resource = ohci1_resources,
+};
+
+/* HPB-DMA */
+
+/* Asynchronous mode register bits */
+#define HPB_DMAE_ASYNCMDR_ASMD43_MASK BIT(23) /* MMC1 */
+#define HPB_DMAE_ASYNCMDR_ASMD43_SINGLE BIT(23) /* MMC1 */
+#define HPB_DMAE_ASYNCMDR_ASMD43_MULTI 0 /* MMC1 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD43_MASK BIT(22) /* MMC1 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD43_BURST BIT(22) /* MMC1 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD43_NBURST 0 /* MMC1 */
+#define HPB_DMAE_ASYNCMDR_ASMD24_MASK BIT(21) /* MMC0 */
+#define HPB_DMAE_ASYNCMDR_ASMD24_SINGLE BIT(21) /* MMC0 */
+#define HPB_DMAE_ASYNCMDR_ASMD24_MULTI 0 /* MMC0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD24_MASK BIT(20) /* MMC0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD24_BURST BIT(20) /* MMC0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD24_NBURST 0 /* MMC0 */
+#define HPB_DMAE_ASYNCMDR_ASMD41_MASK BIT(19) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD41_SINGLE BIT(19) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD41_MULTI 0 /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD41_MASK BIT(18) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD41_BURST BIT(18) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD41_NBURST 0 /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD40_MASK BIT(17) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD40_SINGLE BIT(17) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD40_MULTI 0 /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD40_MASK BIT(16) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD40_BURST BIT(16) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD40_NBURST 0 /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD39_MASK BIT(15) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD39_SINGLE BIT(15) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD39_MULTI 0 /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD39_MASK BIT(14) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD39_BURST BIT(14) /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD39_NBURST 0 /* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD27_MASK BIT(13) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD27_SINGLE BIT(13) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD27_MULTI 0 /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD27_MASK BIT(12) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD27_BURST BIT(12) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD27_NBURST 0 /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD26_MASK BIT(11) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD26_SINGLE BIT(11) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD26_MULTI 0 /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD26_MASK BIT(10) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD26_BURST BIT(10) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD26_NBURST 0 /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD25_MASK BIT(9) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD25_SINGLE BIT(9) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD25_MULTI 0 /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD25_MASK BIT(8) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD25_BURST BIT(8) /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD25_NBURST 0 /* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD23_MASK BIT(7) /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD23_SINGLE BIT(7) /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD23_MULTI 0 /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD23_MASK BIT(6) /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD23_BURST BIT(6) /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD23_NBURST 0 /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD22_MASK BIT(5) /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD22_SINGLE BIT(5) /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD22_MULTI 0 /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD22_MASK BIT(4) /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD22_BURST BIT(4) /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD22_NBURST 0 /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD21_MASK BIT(3) /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD21_SINGLE BIT(3) /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD21_MULTI 0 /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD21_MASK BIT(2) /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD21_BURST BIT(2) /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD21_NBURST 0 /* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD20_MASK BIT(1) /* SDHI1 */
+#define HPB_DMAE_ASYNCMDR_ASMD20_SINGLE BIT(1) /* SDHI1 */
+#define HPB_DMAE_ASYNCMDR_ASMD20_MULTI 0 /* SDHI1 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD20_MASK BIT(0) /* SDHI1 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD20_BURST BIT(0) /* SDHI1 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD20_NBURST 0 /* SDHI1 */
+
+static const struct hpb_dmae_slave_config hpb_dmae_slaves[] = {
+ {
+ .id = HPBDMA_SLAVE_SDHI0_TX,
+ .addr = 0xffe4c000 + 0x30,
+ .dcr = HPB_DMAE_DCR_SPDS_16BIT |
+ HPB_DMAE_DCR_DMDL |
+ HPB_DMAE_DCR_DPDS_16BIT,
+ .rstr = HPB_DMAE_ASYNCRSTR_ASRST21 |
+ HPB_DMAE_ASYNCRSTR_ASRST22 |
+ HPB_DMAE_ASYNCRSTR_ASRST23,
+ .mdr = HPB_DMAE_ASYNCMDR_ASMD21_SINGLE |
+ HPB_DMAE_ASYNCMDR_ASBTMD21_NBURST,
+ .mdm = HPB_DMAE_ASYNCMDR_ASMD21_MASK |
+ HPB_DMAE_ASYNCMDR_ASBTMD21_MASK,
+ .port = 0x0D0C,
+ .flags = HPB_DMAE_SET_ASYNC_RESET | HPB_DMAE_SET_ASYNC_MODE,
+ .dma_ch = 21,
+ }, {
+ .id = HPBDMA_SLAVE_SDHI0_RX,
+ .addr = 0xffe4c000 + 0x30,
+ .dcr = HPB_DMAE_DCR_SMDL |
+ HPB_DMAE_DCR_SPDS_16BIT |
+ HPB_DMAE_DCR_DPDS_16BIT,
+ .rstr = HPB_DMAE_ASYNCRSTR_ASRST21 |
+ HPB_DMAE_ASYNCRSTR_ASRST22 |
+ HPB_DMAE_ASYNCRSTR_ASRST23,
+ .mdr = HPB_DMAE_ASYNCMDR_ASMD22_SINGLE |
+ HPB_DMAE_ASYNCMDR_ASBTMD22_NBURST,
+ .mdm = HPB_DMAE_ASYNCMDR_ASMD22_MASK |
+ HPB_DMAE_ASYNCMDR_ASBTMD22_MASK,
+ .port = 0x0D0C,
+ .flags = HPB_DMAE_SET_ASYNC_RESET | HPB_DMAE_SET_ASYNC_MODE,
+ .dma_ch = 22,
+ },
+};
+
+static const struct hpb_dmae_channel hpb_dmae_channels[] = {
+ HPB_DMAE_CHANNEL(0x93, HPBDMA_SLAVE_SDHI0_TX), /* ch. 21 */
+ HPB_DMAE_CHANNEL(0x93, HPBDMA_SLAVE_SDHI0_RX), /* ch. 22 */
+};
+
+static struct hpb_dmae_pdata dma_platform_data __initdata = {
+ .slaves = hpb_dmae_slaves,
+ .num_slaves = ARRAY_SIZE(hpb_dmae_slaves),
+ .channels = hpb_dmae_channels,
+ .num_channels = ARRAY_SIZE(hpb_dmae_channels),
+ .ts_shift = {
+ [XMIT_SZ_8BIT] = 0,
+ [XMIT_SZ_16BIT] = 1,
+ [XMIT_SZ_32BIT] = 2,
+ },
+ .num_hw_channels = 44,
+};
+
+static struct resource hpb_dmae_resources[] __initdata = {
+ /* Channel registers */
+ DEFINE_RES_MEM(0xffc08000, 0x1000),
+ /* Common registers */
+ DEFINE_RES_MEM(0xffc09000, 0x170),
+ /* Asynchronous reset registers */
+ DEFINE_RES_MEM(0xffc00300, 4),
+ /* Asynchronous mode registers */
+ DEFINE_RES_MEM(0xffc00400, 4),
+ /* IRQ for DMA channels */
+ DEFINE_RES_NAMED(gic_iid(0x8e), 12, NULL, IORESOURCE_IRQ),
+};
+
+static void __init r8a7779_register_hpb_dmae(void)
+{
+ platform_device_register_resndata(NULL, "hpb-dma-engine",
+ -1, hpb_dmae_resources,
+ ARRAY_SIZE(hpb_dmae_resources),
+ &dma_platform_data,
+ sizeof(dma_platform_data));
+}
+
+static struct platform_device *r8a7779_early_devices[] __initdata = {
+ &tmu0_device,
+};
+
+static struct platform_device *r8a7779_standard_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &i2c0_device,
+ &i2c1_device,
+ &i2c2_device,
+ &i2c3_device,
+ &sata_device,
+};
+
+void __init r8a7779_add_standard_devices(void)
+{
+#ifdef CONFIG_CACHE_L2X0
+ /* Shared attribute override enable, 64K*16way */
+ l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff);
+#endif
+ r8a7779_pm_init();
+
+ r8a7779_init_pm_domains();
+
+ platform_add_devices(r8a7779_early_devices,
+ ARRAY_SIZE(r8a7779_early_devices));
+ platform_add_devices(r8a7779_standard_devices,
+ ARRAY_SIZE(r8a7779_standard_devices));
+ r8a7779_register_hpb_dmae();
+}
+
+void __init r8a7779_add_early_devices(void)
+{
+ early_platform_add_devices(r8a7779_early_devices,
+ ARRAY_SIZE(r8a7779_early_devices));
+
+ /* Early serial console setup is not included here due to
+ * memory map collisions. The SCIF serial ports in r8a7779
+ * are difficult to identity map 1:1 due to collision with the
+ * virtual memory range used by the coherent DMA code on ARM.
+ *
+ * Anyone wanting to debug early can remove UPF_IOREMAP from
+ * the sh-sci serial console platform data, adjust mapbase
+ * to a static M:N virt:phys mapping that needs to be added to
+ * the mappings passed with iotable_init() above.
+ *
+ * Then add a call to shmobile_setup_console() from this function.
+ *
+ * As a final step pass earlyprint=sh-sci.2,115200 on the kernel
+ * command line in case of the marzen board.
+ */
+}
+
+static struct platform_device *r8a7779_late_devices[] __initdata = {
+ &ehci0_device,
+ &ehci1_device,
+ &ohci0_device,
+ &ohci1_device,
+};
+
+void __init r8a7779_init_late(void)
+{
+ /* get USB PHY */
+ phy = usb_get_phy(USB_PHY_TYPE_USB2);
+
+ shmobile_init_late();
+ platform_add_devices(r8a7779_late_devices,
+ ARRAY_SIZE(r8a7779_late_devices));
+}
+
+#ifdef CONFIG_USE_OF
+void __init r8a7779_init_irq_dt(void)
+{
+#ifdef CONFIG_ARCH_SHMOBILE_LEGACY
+ void __iomem *gic_dist_base = ioremap_nocache(0xf0001000, 0x1000);
+ void __iomem *gic_cpu_base = ioremap_nocache(0xf0000100, 0x1000);
+#endif
+ gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE);
+
+#ifdef CONFIG_ARCH_SHMOBILE_LEGACY
+ gic_init(0, 29, gic_dist_base, gic_cpu_base);
+#else
+ irqchip_init();
+#endif
+ /* route all interrupts to ARM */
+ __raw_writel(0xffffffff, INT2NTSR0);
+ __raw_writel(0x3fffffff, INT2NTSR1);
+
+ /* unmask all known interrupts in INTCS2 */
+ __raw_writel(0xfffffff0, INT2SMSKCR0);
+ __raw_writel(0xfff7ffff, INT2SMSKCR1);
+ __raw_writel(0xfffbffdf, INT2SMSKCR2);
+ __raw_writel(0xbffffffc, INT2SMSKCR3);
+ __raw_writel(0x003fee3f, INT2SMSKCR4);
+}
+
+#define MODEMR 0xffcc0020
+
+u32 __init r8a7779_read_mode_pins(void)
+{
+ static u32 mode;
+ static bool mode_valid;
+
+ if (!mode_valid) {
+ void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
+ BUG_ON(!modemr);
+ mode = ioread32(modemr);
+ iounmap(modemr);
+ mode_valid = true;
+ }
+
+ return mode;
+}
+
+static const char *r8a7779_compat_dt[] __initdata = {
+ "renesas,r8a7779",
+ NULL,
+};
+
+DT_MACHINE_START(R8A7779_DT, "Generic R8A7779 (Flattened Device Tree)")
+ .map_io = r8a7779_map_io,
+ .init_early = shmobile_init_delay,
+ .init_irq = r8a7779_init_irq_dt,
+ .init_late = shmobile_init_late,
+ .dt_compat = r8a7779_compat_dt,
+MACHINE_END
+#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c
new file mode 100644
index 000000000..3a18af492
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -0,0 +1,37 @@
+/*
+ * r8a7790 processor support
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Magnus Damm
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+
+#include <asm/mach/arch.h>
+
+#include "common.h"
+#include "r8a7790.h"
+#include "rcar-gen2.h"
+
+static const char * const r8a7790_boards_compat_dt[] __initconst = {
+ "renesas,r8a7790",
+ NULL,
+};
+
+DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)")
+ .smp = smp_ops(r8a7790_smp_ops),
+ .init_early = shmobile_init_delay,
+ .init_time = rcar_gen2_timer_init,
+ .init_late = shmobile_init_late,
+ .reserve = rcar_gen2_reserve,
+ .dt_compat = r8a7790_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/setup-r8a7791.c b/arch/arm/mach-shmobile/setup-r8a7791.c
new file mode 100644
index 000000000..ef8eb3af5
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-r8a7791.c
@@ -0,0 +1,38 @@
+/*
+ * r8a7791 processor support
+ *
+ * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Magnus Damm
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+
+#include <asm/mach/arch.h>
+
+#include "common.h"
+#include "r8a7791.h"
+#include "rcar-gen2.h"
+
+static const char *r8a7791_boards_compat_dt[] __initdata = {
+ "renesas,r8a7791",
+ NULL,
+};
+
+DT_MACHINE_START(R8A7791_DT, "Generic R8A7791 (Flattened Device Tree)")
+ .smp = smp_ops(r8a7791_smp_ops),
+ .init_early = shmobile_init_delay,
+ .init_time = rcar_gen2_timer_init,
+ .init_late = shmobile_init_late,
+ .reserve = rcar_gen2_reserve,
+ .dt_compat = r8a7791_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/setup-r8a7794.c b/arch/arm/mach-shmobile/setup-r8a7794.c
new file mode 100644
index 000000000..d2b093033
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-r8a7794.c
@@ -0,0 +1,33 @@
+/*
+ * r8a7794 processor support
+ *
+ * Copyright (C) 2014 Renesas Electronics Corporation
+ * Copyright (C) 2014 Ulrich Hecht
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of_platform.h>
+#include "common.h"
+#include "rcar-gen2.h"
+#include <asm/mach/arch.h>
+
+static const char * const r8a7794_boards_compat_dt[] __initconst = {
+ "renesas,r8a7794",
+ NULL,
+};
+
+DT_MACHINE_START(R8A7794_DT, "Generic R8A7794 (Flattened Device Tree)")
+ .init_early = shmobile_init_delay,
+ .init_late = shmobile_init_late,
+ .init_time = rcar_gen2_timer_init,
+ .reserve = rcar_gen2_reserve,
+ .dt_compat = r8a7794_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c
new file mode 100644
index 000000000..5d13595aa
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c
@@ -0,0 +1,203 @@
+/*
+ * R-Car Generation 2 support
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Magnus Damm
+ * Copyright (C) 2014 Ulrich Hecht
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk/shmobile.h>
+#include <linux/clocksource.h>
+#include <linux/device.h>
+#include <linux/dma-contiguous.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/memblock.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <asm/mach/arch.h>
+#include "common.h"
+#include "rcar-gen2.h"
+
+#define MODEMR 0xe6160060
+
+u32 rcar_gen2_read_mode_pins(void)
+{
+ static u32 mode;
+ static bool mode_valid;
+
+ if (!mode_valid) {
+ void __iomem *modemr = ioremap_nocache(MODEMR, 4);
+ BUG_ON(!modemr);
+ mode = ioread32(modemr);
+ iounmap(modemr);
+ mode_valid = true;
+ }
+
+ return mode;
+}
+
+#define CNTCR 0
+#define CNTFID0 0x20
+
+void __init rcar_gen2_timer_init(void)
+{
+ u32 mode = rcar_gen2_read_mode_pins();
+#ifdef CONFIG_ARM_ARCH_TIMER
+ void __iomem *base;
+ int extal_mhz = 0;
+ u32 freq;
+
+ if (of_machine_is_compatible("renesas,r8a7794")) {
+ freq = 260000000 / 8; /* ZS / 8 */
+ /* CNTVOFF has to be initialized either from non-secure
+ * Hypervisor mode or secure Monitor mode with SCR.NS==1.
+ * If TrustZone is enabled then it should be handled by the
+ * secure code.
+ */
+ asm volatile(
+ " cps 0x16\n"
+ " mrc p15, 0, r1, c1, c1, 0\n"
+ " orr r0, r1, #1\n"
+ " mcr p15, 0, r0, c1, c1, 0\n"
+ " isb\n"
+ " mov r0, #0\n"
+ " mcrr p15, 4, r0, r0, c14\n"
+ " isb\n"
+ " mcr p15, 0, r1, c1, c1, 0\n"
+ " isb\n"
+ " cps 0x13\n"
+ : : : "r0", "r1");
+ } else {
+ /* At Linux boot time the r8a7790 arch timer comes up
+ * with the counter disabled. Moreover, it may also report
+ * a potentially incorrect fixed 13 MHz frequency. To be
+ * correct these registers need to be updated to use the
+ * frequency EXTAL / 2 which can be determined by the MD pins.
+ */
+
+ switch (mode & (MD(14) | MD(13))) {
+ case 0:
+ extal_mhz = 15;
+ break;
+ case MD(13):
+ extal_mhz = 20;
+ break;
+ case MD(14):
+ extal_mhz = 26;
+ break;
+ case MD(13) | MD(14):
+ extal_mhz = 30;
+ break;
+ }
+
+ /* The arch timer frequency equals EXTAL / 2 */
+ freq = extal_mhz * (1000000 / 2);
+ }
+
+ /* Remap "armgcnt address map" space */
+ base = ioremap(0xe6080000, PAGE_SIZE);
+
+ /*
+ * Update the timer if it is either not running, or is not at the
+ * right frequency. The timer is only configurable in secure mode
+ * so this avoids an abort if the loader started the timer and
+ * entered the kernel in non-secure mode.
+ */
+
+ if ((ioread32(base + CNTCR) & 1) == 0 ||
+ ioread32(base + CNTFID0) != freq) {
+ /* Update registers with correct frequency */
+ iowrite32(freq, base + CNTFID0);
+ asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq));
+
+ /* make sure arch timer is started by setting bit 0 of CNTCR */
+ iowrite32(1, base + CNTCR);
+ }
+
+ iounmap(base);
+#endif /* CONFIG_ARM_ARCH_TIMER */
+
+ rcar_gen2_clocks_init(mode);
+#ifdef CONFIG_ARCH_SHMOBILE_MULTI
+ clocksource_of_init();
+#endif
+}
+
+struct memory_reserve_config {
+ u64 reserved;
+ u64 base, size;
+};
+
+static int __init rcar_gen2_scan_mem(unsigned long node, const char *uname,
+ int depth, void *data)
+{
+ const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+ const __be32 *reg, *endp;
+ int l;
+ struct memory_reserve_config *mrc = data;
+ u64 lpae_start = 1ULL << 32;
+
+ /* We are scanning "memory" nodes only */
+ if (type == NULL || strcmp(type, "memory"))
+ return 0;
+
+ reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
+ if (reg == NULL)
+ reg = of_get_flat_dt_prop(node, "reg", &l);
+ if (reg == NULL)
+ return 0;
+
+ endp = reg + (l / sizeof(__be32));
+ while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
+ u64 base, size;
+
+ base = dt_mem_next_cell(dt_root_addr_cells, &reg);
+ size = dt_mem_next_cell(dt_root_size_cells, &reg);
+
+ if (base >= lpae_start)
+ continue;
+
+ if ((base + size) >= lpae_start)
+ size = lpae_start - base;
+
+ if (size < mrc->reserved)
+ continue;
+
+ if (base < mrc->base)
+ continue;
+
+ /* keep the area at top near the 32-bit legacy limit */
+ mrc->base = base + size - mrc->reserved;
+ mrc->size = mrc->reserved;
+ }
+
+ return 0;
+}
+
+struct cma *rcar_gen2_dma_contiguous;
+
+void __init rcar_gen2_reserve(void)
+{
+ struct memory_reserve_config mrc;
+
+ /* reserve 256 MiB at the top of the physical legacy 32-bit space */
+ memset(&mrc, 0, sizeof(mrc));
+ mrc.reserved = SZ_256M;
+
+ of_scan_flat_dt(rcar_gen2_scan_mem, &mrc);
+#ifdef CONFIG_DMA_CMA
+ if (mrc.size && memblock_is_region_memory(mrc.base, mrc.size))
+ dma_contiguous_reserve_area(mrc.size, mrc.base, 0,
+ &rcar_gen2_dma_contiguous, true);
+#endif
+}
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
new file mode 100644
index 000000000..fb2ab7590
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -0,0 +1,810 @@
+/*
+ * sh73a0 processor support
+ *
+ * Copyright (C) 2010 Takashi Yoshii
+ * Copyright (C) 2010 Magnus Damm
+ * Copyright (C) 2008 Yoshihiro Shimoda
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/of_platform.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/i2c/i2c-sh_mobile.h>
+#include <linux/io.h>
+#include <linux/serial_sci.h>
+#include <linux/sh_dma.h>
+#include <linux/sh_timer.h>
+#include <linux/platform_data/sh_ipmmu.h>
+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
+
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "common.h"
+#include "dma-register.h"
+#include "intc.h"
+#include "irqs.h"
+#include "sh73a0.h"
+
+static struct map_desc sh73a0_io_desc[] __initdata = {
+ /* create a 1:1 identity mapping for 0xe6xxxxxx
+ * used by CPGA, INTC and PFC.
+ */
+ {
+ .virtual = 0xe6000000,
+ .pfn = __phys_to_pfn(0xe6000000),
+ .length = 256 << 20,
+ .type = MT_DEVICE_NONSHARED
+ },
+};
+
+void __init sh73a0_map_io(void)
+{
+ debug_ll_io_init();
+ iotable_init(sh73a0_io_desc, ARRAY_SIZE(sh73a0_io_desc));
+}
+
+/* PFC */
+static struct resource pfc_resources[] __initdata = {
+ DEFINE_RES_MEM(0xe6050000, 0x8000),
+ DEFINE_RES_MEM(0xe605801c, 0x000c),
+};
+
+void __init sh73a0_pinmux_init(void)
+{
+ platform_device_register_simple("pfc-sh73a0", -1, pfc_resources,
+ ARRAY_SIZE(pfc_resources));
+}
+
+/* SCIF */
+#define SH73A0_SCIF(scif_type, index, baseaddr, irq) \
+static struct plat_sci_port scif##index##_platform_data = { \
+ .type = scif_type, \
+ .flags = UPF_BOOT_AUTOCONF, \
+ .scscr = SCSCR_RE | SCSCR_TE, \
+}; \
+ \
+static struct resource scif##index##_resources[] = { \
+ DEFINE_RES_MEM(baseaddr, 0x100), \
+ DEFINE_RES_IRQ(irq), \
+}; \
+ \
+static struct platform_device scif##index##_device = { \
+ .name = "sh-sci", \
+ .id = index, \
+ .resource = scif##index##_resources, \
+ .num_resources = ARRAY_SIZE(scif##index##_resources), \
+ .dev = { \
+ .platform_data = &scif##index##_platform_data, \
+ }, \
+}
+
+SH73A0_SCIF(PORT_SCIFA, 0, 0xe6c40000, gic_spi(72));
+SH73A0_SCIF(PORT_SCIFA, 1, 0xe6c50000, gic_spi(73));
+SH73A0_SCIF(PORT_SCIFA, 2, 0xe6c60000, gic_spi(74));
+SH73A0_SCIF(PORT_SCIFA, 3, 0xe6c70000, gic_spi(75));
+SH73A0_SCIF(PORT_SCIFA, 4, 0xe6c80000, gic_spi(78));
+SH73A0_SCIF(PORT_SCIFA, 5, 0xe6cb0000, gic_spi(79));
+SH73A0_SCIF(PORT_SCIFA, 6, 0xe6cc0000, gic_spi(156));
+SH73A0_SCIF(PORT_SCIFA, 7, 0xe6cd0000, gic_spi(143));
+SH73A0_SCIF(PORT_SCIFB, 8, 0xe6c30000, gic_spi(80));
+
+static struct sh_timer_config cmt1_platform_data = {
+ .channels_mask = 0x3f,
+};
+
+static struct resource cmt1_resources[] = {
+ DEFINE_RES_MEM(0xe6138000, 0x200),
+ DEFINE_RES_IRQ(gic_spi(65)),
+};
+
+static struct platform_device cmt1_device = {
+ .name = "sh-cmt-48",
+ .id = 1,
+ .dev = {
+ .platform_data = &cmt1_platform_data,
+ },
+ .resource = cmt1_resources,
+ .num_resources = ARRAY_SIZE(cmt1_resources),
+};
+
+/* TMU */
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xfff60000, 0x2c),
+ DEFINE_RES_IRQ(intcs_evt2irq(0xe80)),
+ DEFINE_RES_IRQ(intcs_evt2irq(0xea0)),
+ DEFINE_RES_IRQ(intcs_evt2irq(0xec0)),
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh-tmu",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
+static struct resource i2c0_resources[] = {
+ [0] = DEFINE_RES_MEM(0xe6820000, 0x426),
+ [1] = {
+ .start = gic_spi(167),
+ .end = gic_spi(170),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource i2c1_resources[] = {
+ [0] = DEFINE_RES_MEM(0xe6822000, 0x426),
+ [1] = {
+ .start = gic_spi(51),
+ .end = gic_spi(54),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource i2c2_resources[] = {
+ [0] = DEFINE_RES_MEM(0xe6824000, 0x426),
+ [1] = {
+ .start = gic_spi(171),
+ .end = gic_spi(174),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource i2c3_resources[] = {
+ [0] = DEFINE_RES_MEM(0xe6826000, 0x426),
+ [1] = {
+ .start = gic_spi(183),
+ .end = gic_spi(186),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource i2c4_resources[] = {
+ [0] = DEFINE_RES_MEM(0xe6828000, 0x426),
+ [1] = {
+ .start = gic_spi(187),
+ .end = gic_spi(190),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct i2c_sh_mobile_platform_data i2c_platform_data = {
+ .clks_per_count = 2,
+};
+
+static struct platform_device i2c0_device = {
+ .name = "i2c-sh_mobile",
+ .id = 0,
+ .resource = i2c0_resources,
+ .num_resources = ARRAY_SIZE(i2c0_resources),
+ .dev = {
+ .platform_data = &i2c_platform_data,
+ },
+};
+
+static struct platform_device i2c1_device = {
+ .name = "i2c-sh_mobile",
+ .id = 1,
+ .resource = i2c1_resources,
+ .num_resources = ARRAY_SIZE(i2c1_resources),
+ .dev = {
+ .platform_data = &i2c_platform_data,
+ },
+};
+
+static struct platform_device i2c2_device = {
+ .name = "i2c-sh_mobile",
+ .id = 2,
+ .resource = i2c2_resources,
+ .num_resources = ARRAY_SIZE(i2c2_resources),
+ .dev = {
+ .platform_data = &i2c_platform_data,
+ },
+};
+
+static struct platform_device i2c3_device = {
+ .name = "i2c-sh_mobile",
+ .id = 3,
+ .resource = i2c3_resources,
+ .num_resources = ARRAY_SIZE(i2c3_resources),
+ .dev = {
+ .platform_data = &i2c_platform_data,
+ },
+};
+
+static struct platform_device i2c4_device = {
+ .name = "i2c-sh_mobile",
+ .id = 4,
+ .resource = i2c4_resources,
+ .num_resources = ARRAY_SIZE(i2c4_resources),
+ .dev = {
+ .platform_data = &i2c_platform_data,
+ },
+};
+
+static const struct sh_dmae_slave_config sh73a0_dmae_slaves[] = {
+ {
+ .slave_id = SHDMA_SLAVE_SCIF0_TX,
+ .addr = 0xe6c40020,
+ .chcr = CHCR_TX(XMIT_SZ_8BIT),
+ .mid_rid = 0x21,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF0_RX,
+ .addr = 0xe6c40024,
+ .chcr = CHCR_RX(XMIT_SZ_8BIT),
+ .mid_rid = 0x22,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF1_TX,
+ .addr = 0xe6c50020,
+ .chcr = CHCR_TX(XMIT_SZ_8BIT),
+ .mid_rid = 0x25,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF1_RX,
+ .addr = 0xe6c50024,
+ .chcr = CHCR_RX(XMIT_SZ_8BIT),
+ .mid_rid = 0x26,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF2_TX,
+ .addr = 0xe6c60020,
+ .chcr = CHCR_TX(XMIT_SZ_8BIT),
+ .mid_rid = 0x29,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF2_RX,
+ .addr = 0xe6c60024,
+ .chcr = CHCR_RX(XMIT_SZ_8BIT),
+ .mid_rid = 0x2a,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF3_TX,
+ .addr = 0xe6c70020,
+ .chcr = CHCR_TX(XMIT_SZ_8BIT),
+ .mid_rid = 0x2d,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF3_RX,
+ .addr = 0xe6c70024,
+ .chcr = CHCR_RX(XMIT_SZ_8BIT),
+ .mid_rid = 0x2e,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF4_TX,
+ .addr = 0xe6c80020,
+ .chcr = CHCR_TX(XMIT_SZ_8BIT),
+ .mid_rid = 0x39,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF4_RX,
+ .addr = 0xe6c80024,
+ .chcr = CHCR_RX(XMIT_SZ_8BIT),
+ .mid_rid = 0x3a,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF5_TX,
+ .addr = 0xe6cb0020,
+ .chcr = CHCR_TX(XMIT_SZ_8BIT),
+ .mid_rid = 0x35,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF5_RX,
+ .addr = 0xe6cb0024,
+ .chcr = CHCR_RX(XMIT_SZ_8BIT),
+ .mid_rid = 0x36,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF6_TX,
+ .addr = 0xe6cc0020,
+ .chcr = CHCR_TX(XMIT_SZ_8BIT),
+ .mid_rid = 0x1d,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF6_RX,
+ .addr = 0xe6cc0024,
+ .chcr = CHCR_RX(XMIT_SZ_8BIT),
+ .mid_rid = 0x1e,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF7_TX,
+ .addr = 0xe6cd0020,
+ .chcr = CHCR_TX(XMIT_SZ_8BIT),
+ .mid_rid = 0x19,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF7_RX,
+ .addr = 0xe6cd0024,
+ .chcr = CHCR_RX(XMIT_SZ_8BIT),
+ .mid_rid = 0x1a,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF8_TX,
+ .addr = 0xe6c30040,
+ .chcr = CHCR_TX(XMIT_SZ_8BIT),
+ .mid_rid = 0x3d,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF8_RX,
+ .addr = 0xe6c30060,
+ .chcr = CHCR_RX(XMIT_SZ_8BIT),
+ .mid_rid = 0x3e,
+ }, {
+ .slave_id = SHDMA_SLAVE_SDHI0_TX,
+ .addr = 0xee100030,
+ .chcr = CHCR_TX(XMIT_SZ_16BIT),
+ .mid_rid = 0xc1,
+ }, {
+ .slave_id = SHDMA_SLAVE_SDHI0_RX,
+ .addr = 0xee100030,
+ .chcr = CHCR_RX(XMIT_SZ_16BIT),
+ .mid_rid = 0xc2,
+ }, {
+ .slave_id = SHDMA_SLAVE_SDHI1_TX,
+ .addr = 0xee120030,
+ .chcr = CHCR_TX(XMIT_SZ_16BIT),
+ .mid_rid = 0xc9,
+ }, {
+ .slave_id = SHDMA_SLAVE_SDHI1_RX,
+ .addr = 0xee120030,
+ .chcr = CHCR_RX(XMIT_SZ_16BIT),
+ .mid_rid = 0xca,
+ }, {
+ .slave_id = SHDMA_SLAVE_SDHI2_TX,
+ .addr = 0xee140030,
+ .chcr = CHCR_TX(XMIT_SZ_16BIT),
+ .mid_rid = 0xcd,
+ }, {
+ .slave_id = SHDMA_SLAVE_SDHI2_RX,
+ .addr = 0xee140030,
+ .chcr = CHCR_RX(XMIT_SZ_16BIT),
+ .mid_rid = 0xce,
+ }, {
+ .slave_id = SHDMA_SLAVE_MMCIF_TX,
+ .addr = 0xe6bd0034,
+ .chcr = CHCR_TX(XMIT_SZ_32BIT),
+ .mid_rid = 0xd1,
+ }, {
+ .slave_id = SHDMA_SLAVE_MMCIF_RX,
+ .addr = 0xe6bd0034,
+ .chcr = CHCR_RX(XMIT_SZ_32BIT),
+ .mid_rid = 0xd2,
+ },
+};
+
+#define DMAE_CHANNEL(_offset) \
+ { \
+ .offset = _offset - 0x20, \
+ .dmars = _offset - 0x20 + 0x40, \
+ }
+
+static const struct sh_dmae_channel sh73a0_dmae_channels[] = {
+ DMAE_CHANNEL(0x8000),
+ DMAE_CHANNEL(0x8080),
+ DMAE_CHANNEL(0x8100),
+ DMAE_CHANNEL(0x8180),
+ DMAE_CHANNEL(0x8200),
+ DMAE_CHANNEL(0x8280),
+ DMAE_CHANNEL(0x8300),
+ DMAE_CHANNEL(0x8380),
+ DMAE_CHANNEL(0x8400),
+ DMAE_CHANNEL(0x8480),
+ DMAE_CHANNEL(0x8500),
+ DMAE_CHANNEL(0x8580),
+ DMAE_CHANNEL(0x8600),
+ DMAE_CHANNEL(0x8680),
+ DMAE_CHANNEL(0x8700),
+ DMAE_CHANNEL(0x8780),
+ DMAE_CHANNEL(0x8800),
+ DMAE_CHANNEL(0x8880),
+ DMAE_CHANNEL(0x8900),
+ DMAE_CHANNEL(0x8980),
+};
+
+static struct sh_dmae_pdata sh73a0_dmae_platform_data = {
+ .slave = sh73a0_dmae_slaves,
+ .slave_num = ARRAY_SIZE(sh73a0_dmae_slaves),
+ .channel = sh73a0_dmae_channels,
+ .channel_num = ARRAY_SIZE(sh73a0_dmae_channels),
+ .ts_low_shift = TS_LOW_SHIFT,
+ .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT,
+ .ts_high_shift = TS_HI_SHIFT,
+ .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT,
+ .ts_shift = dma_ts_shift,
+ .ts_shift_num = ARRAY_SIZE(dma_ts_shift),
+ .dmaor_init = DMAOR_DME,
+};
+
+static struct resource sh73a0_dmae_resources[] = {
+ DEFINE_RES_MEM(0xfe000020, 0x89e0),
+ {
+ .name = "error_irq",
+ .start = gic_spi(129),
+ .end = gic_spi(129),
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 0-19 */
+ .start = gic_spi(109),
+ .end = gic_spi(128),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device dma0_device = {
+ .name = "sh-dma-engine",
+ .id = 0,
+ .resource = sh73a0_dmae_resources,
+ .num_resources = ARRAY_SIZE(sh73a0_dmae_resources),
+ .dev = {
+ .platform_data = &sh73a0_dmae_platform_data,
+ },
+};
+
+/* MPDMAC */
+static const struct sh_dmae_slave_config sh73a0_mpdma_slaves[] = {
+ {
+ .slave_id = SHDMA_SLAVE_FSI2A_RX,
+ .addr = 0xec230020,
+ .chcr = CHCR_RX(XMIT_SZ_32BIT),
+ .mid_rid = 0xd6, /* CHECK ME */
+ }, {
+ .slave_id = SHDMA_SLAVE_FSI2A_TX,
+ .addr = 0xec230024,
+ .chcr = CHCR_TX(XMIT_SZ_32BIT),
+ .mid_rid = 0xd5, /* CHECK ME */
+ }, {
+ .slave_id = SHDMA_SLAVE_FSI2C_RX,
+ .addr = 0xec230060,
+ .chcr = CHCR_RX(XMIT_SZ_32BIT),
+ .mid_rid = 0xda, /* CHECK ME */
+ }, {
+ .slave_id = SHDMA_SLAVE_FSI2C_TX,
+ .addr = 0xec230064,
+ .chcr = CHCR_TX(XMIT_SZ_32BIT),
+ .mid_rid = 0xd9, /* CHECK ME */
+ }, {
+ .slave_id = SHDMA_SLAVE_FSI2B_RX,
+ .addr = 0xec240020,
+ .chcr = CHCR_RX(XMIT_SZ_32BIT),
+ .mid_rid = 0x8e, /* CHECK ME */
+ }, {
+ .slave_id = SHDMA_SLAVE_FSI2B_TX,
+ .addr = 0xec240024,
+ .chcr = CHCR_RX(XMIT_SZ_32BIT),
+ .mid_rid = 0x8d, /* CHECK ME */
+ }, {
+ .slave_id = SHDMA_SLAVE_FSI2D_RX,
+ .addr = 0xec240060,
+ .chcr = CHCR_RX(XMIT_SZ_32BIT),
+ .mid_rid = 0x9a, /* CHECK ME */
+ },
+};
+
+#define MPDMA_CHANNEL(a, b, c) \
+{ \
+ .offset = a, \
+ .dmars = b, \
+ .dmars_bit = c, \
+ .chclr_offset = (0x220 - 0x20) + a \
+}
+
+static const struct sh_dmae_channel sh73a0_mpdma_channels[] = {
+ MPDMA_CHANNEL(0x00, 0, 0),
+ MPDMA_CHANNEL(0x10, 0, 8),
+ MPDMA_CHANNEL(0x20, 4, 0),
+ MPDMA_CHANNEL(0x30, 4, 8),
+ MPDMA_CHANNEL(0x50, 8, 0),
+ MPDMA_CHANNEL(0x70, 8, 8),
+};
+
+static struct sh_dmae_pdata sh73a0_mpdma_platform_data = {
+ .slave = sh73a0_mpdma_slaves,
+ .slave_num = ARRAY_SIZE(sh73a0_mpdma_slaves),
+ .channel = sh73a0_mpdma_channels,
+ .channel_num = ARRAY_SIZE(sh73a0_mpdma_channels),
+ .ts_low_shift = TS_LOW_SHIFT,
+ .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT,
+ .ts_high_shift = TS_HI_SHIFT,
+ .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT,
+ .ts_shift = dma_ts_shift,
+ .ts_shift_num = ARRAY_SIZE(dma_ts_shift),
+ .dmaor_init = DMAOR_DME,
+ .chclr_present = 1,
+};
+
+/* Resource order important! */
+static struct resource sh73a0_mpdma_resources[] = {
+ /* Channel registers and DMAOR */
+ DEFINE_RES_MEM(0xec618020, 0x270),
+ /* DMARSx */
+ DEFINE_RES_MEM(0xec619000, 0xc),
+ {
+ .name = "error_irq",
+ .start = gic_spi(181),
+ .end = gic_spi(181),
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 0-5 */
+ .start = gic_spi(175),
+ .end = gic_spi(180),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mpdma0_device = {
+ .name = "sh-dma-engine",
+ .id = 1,
+ .resource = sh73a0_mpdma_resources,
+ .num_resources = ARRAY_SIZE(sh73a0_mpdma_resources),
+ .dev = {
+ .platform_data = &sh73a0_mpdma_platform_data,
+ },
+};
+
+static struct resource pmu_resources[] = {
+ [0] = {
+ .start = gic_spi(55),
+ .end = gic_spi(55),
+ .flags = IORESOURCE_IRQ,
+ },
+ [1] = {
+ .start = gic_spi(56),
+ .end = gic_spi(56),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device pmu_device = {
+ .name = "armv7-pmu",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(pmu_resources),
+ .resource = pmu_resources,
+};
+
+/* an IPMMU module for ICB */
+static struct resource ipmmu_resources[] = {
+ DEFINE_RES_MEM(0xfe951000, 0x100),
+};
+
+static const char * const ipmmu_dev_names[] = {
+ "sh_mobile_lcdc_fb.0",
+};
+
+static struct shmobile_ipmmu_platform_data ipmmu_platform_data = {
+ .dev_names = ipmmu_dev_names,
+ .num_dev_names = ARRAY_SIZE(ipmmu_dev_names),
+};
+
+static struct platform_device ipmmu_device = {
+ .name = "ipmmu",
+ .id = -1,
+ .dev = {
+ .platform_data = &ipmmu_platform_data,
+ },
+ .resource = ipmmu_resources,
+ .num_resources = ARRAY_SIZE(ipmmu_resources),
+};
+
+static struct renesas_intc_irqpin_config irqpin0_platform_data = {
+ .irq_base = irq_pin(0), /* IRQ0 -> IRQ7 */
+ .control_parent = true,
+};
+
+static struct resource irqpin0_resources[] = {
+ DEFINE_RES_MEM(0xe6900000, 4), /* ICR1A */
+ DEFINE_RES_MEM(0xe6900010, 4), /* INTPRI00A */
+ DEFINE_RES_MEM(0xe6900020, 1), /* INTREQ00A */
+ DEFINE_RES_MEM(0xe6900040, 1), /* INTMSK00A */
+ DEFINE_RES_MEM(0xe6900060, 1), /* INTMSKCLR00A */
+ DEFINE_RES_IRQ(gic_spi(1)), /* IRQ0 */
+ DEFINE_RES_IRQ(gic_spi(2)), /* IRQ1 */
+ DEFINE_RES_IRQ(gic_spi(3)), /* IRQ2 */
+ DEFINE_RES_IRQ(gic_spi(4)), /* IRQ3 */
+ DEFINE_RES_IRQ(gic_spi(5)), /* IRQ4 */
+ DEFINE_RES_IRQ(gic_spi(6)), /* IRQ5 */
+ DEFINE_RES_IRQ(gic_spi(7)), /* IRQ6 */
+ DEFINE_RES_IRQ(gic_spi(8)), /* IRQ7 */
+};
+
+static struct platform_device irqpin0_device = {
+ .name = "renesas_intc_irqpin",
+ .id = 0,
+ .resource = irqpin0_resources,
+ .num_resources = ARRAY_SIZE(irqpin0_resources),
+ .dev = {
+ .platform_data = &irqpin0_platform_data,
+ },
+};
+
+static struct renesas_intc_irqpin_config irqpin1_platform_data = {
+ .irq_base = irq_pin(8), /* IRQ8 -> IRQ15 */
+ .control_parent = true, /* Disable spurious IRQ10 */
+};
+
+static struct resource irqpin1_resources[] = {
+ DEFINE_RES_MEM(0xe6900004, 4), /* ICR2A */
+ DEFINE_RES_MEM(0xe6900014, 4), /* INTPRI10A */
+ DEFINE_RES_MEM(0xe6900024, 1), /* INTREQ10A */
+ DEFINE_RES_MEM(0xe6900044, 1), /* INTMSK10A */
+ DEFINE_RES_MEM(0xe6900064, 1), /* INTMSKCLR10A */
+ DEFINE_RES_IRQ(gic_spi(9)), /* IRQ8 */
+ DEFINE_RES_IRQ(gic_spi(10)), /* IRQ9 */
+ DEFINE_RES_IRQ(gic_spi(11)), /* IRQ10 */
+ DEFINE_RES_IRQ(gic_spi(12)), /* IRQ11 */
+ DEFINE_RES_IRQ(gic_spi(13)), /* IRQ12 */
+ DEFINE_RES_IRQ(gic_spi(14)), /* IRQ13 */
+ DEFINE_RES_IRQ(gic_spi(15)), /* IRQ14 */
+ DEFINE_RES_IRQ(gic_spi(16)), /* IRQ15 */
+};
+
+static struct platform_device irqpin1_device = {
+ .name = "renesas_intc_irqpin",
+ .id = 1,
+ .resource = irqpin1_resources,
+ .num_resources = ARRAY_SIZE(irqpin1_resources),
+ .dev = {
+ .platform_data = &irqpin1_platform_data,
+ },
+};
+
+static struct renesas_intc_irqpin_config irqpin2_platform_data = {
+ .irq_base = irq_pin(16), /* IRQ16 -> IRQ23 */
+ .control_parent = true,
+};
+
+static struct resource irqpin2_resources[] = {
+ DEFINE_RES_MEM(0xe6900008, 4), /* ICR3A */
+ DEFINE_RES_MEM(0xe6900018, 4), /* INTPRI20A */
+ DEFINE_RES_MEM(0xe6900028, 1), /* INTREQ20A */
+ DEFINE_RES_MEM(0xe6900048, 1), /* INTMSK20A */
+ DEFINE_RES_MEM(0xe6900068, 1), /* INTMSKCLR20A */
+ DEFINE_RES_IRQ(gic_spi(17)), /* IRQ16 */
+ DEFINE_RES_IRQ(gic_spi(18)), /* IRQ17 */
+ DEFINE_RES_IRQ(gic_spi(19)), /* IRQ18 */
+ DEFINE_RES_IRQ(gic_spi(20)), /* IRQ19 */
+ DEFINE_RES_IRQ(gic_spi(21)), /* IRQ20 */
+ DEFINE_RES_IRQ(gic_spi(22)), /* IRQ21 */
+ DEFINE_RES_IRQ(gic_spi(23)), /* IRQ22 */
+ DEFINE_RES_IRQ(gic_spi(24)), /* IRQ23 */
+};
+
+static struct platform_device irqpin2_device = {
+ .name = "renesas_intc_irqpin",
+ .id = 2,
+ .resource = irqpin2_resources,
+ .num_resources = ARRAY_SIZE(irqpin2_resources),
+ .dev = {
+ .platform_data = &irqpin2_platform_data,
+ },
+};
+
+static struct renesas_intc_irqpin_config irqpin3_platform_data = {
+ .irq_base = irq_pin(24), /* IRQ24 -> IRQ31 */
+ .control_parent = true,
+};
+
+static struct resource irqpin3_resources[] = {
+ DEFINE_RES_MEM(0xe690000c, 4), /* ICR4A */
+ DEFINE_RES_MEM(0xe690001c, 4), /* INTPRI30A */
+ DEFINE_RES_MEM(0xe690002c, 1), /* INTREQ30A */
+ DEFINE_RES_MEM(0xe690004c, 1), /* INTMSK30A */
+ DEFINE_RES_MEM(0xe690006c, 1), /* INTMSKCLR30A */
+ DEFINE_RES_IRQ(gic_spi(25)), /* IRQ24 */
+ DEFINE_RES_IRQ(gic_spi(26)), /* IRQ25 */
+ DEFINE_RES_IRQ(gic_spi(27)), /* IRQ26 */
+ DEFINE_RES_IRQ(gic_spi(28)), /* IRQ27 */
+ DEFINE_RES_IRQ(gic_spi(29)), /* IRQ28 */
+ DEFINE_RES_IRQ(gic_spi(30)), /* IRQ29 */
+ DEFINE_RES_IRQ(gic_spi(31)), /* IRQ30 */
+ DEFINE_RES_IRQ(gic_spi(32)), /* IRQ31 */
+};
+
+static struct platform_device irqpin3_device = {
+ .name = "renesas_intc_irqpin",
+ .id = 3,
+ .resource = irqpin3_resources,
+ .num_resources = ARRAY_SIZE(irqpin3_resources),
+ .dev = {
+ .platform_data = &irqpin3_platform_data,
+ },
+};
+
+static struct platform_device *sh73a0_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &scif6_device,
+ &scif7_device,
+ &scif8_device,
+ &tmu0_device,
+ &ipmmu_device,
+ &cmt1_device,
+};
+
+static struct platform_device *sh73a0_late_devices[] __initdata = {
+ &i2c0_device,
+ &i2c1_device,
+ &i2c2_device,
+ &i2c3_device,
+ &i2c4_device,
+ &dma0_device,
+ &mpdma0_device,
+ &pmu_device,
+ &irqpin0_device,
+ &irqpin1_device,
+ &irqpin2_device,
+ &irqpin3_device,
+};
+
+#define SRCR2 IOMEM(0xe61580b0)
+
+void __init sh73a0_add_standard_devices(void)
+{
+ /* Clear software reset bit on SY-DMAC module */
+ __raw_writel(__raw_readl(SRCR2) & ~(1 << 18), SRCR2);
+
+ platform_add_devices(sh73a0_early_devices,
+ ARRAY_SIZE(sh73a0_early_devices));
+ platform_add_devices(sh73a0_late_devices,
+ ARRAY_SIZE(sh73a0_late_devices));
+}
+
+/* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
+void __init __weak sh73a0_register_twd(void) { }
+
+void __init sh73a0_earlytimer_init(void)
+{
+ shmobile_init_delay();
+#ifndef CONFIG_COMMON_CLK
+ sh73a0_clock_init();
+#endif
+ shmobile_earlytimer_init();
+ sh73a0_register_twd();
+}
+
+void __init sh73a0_add_early_devices(void)
+{
+ early_platform_add_devices(sh73a0_early_devices,
+ ARRAY_SIZE(sh73a0_early_devices));
+
+ /* setup early console here as well */
+ shmobile_setup_console();
+}
+
+#ifdef CONFIG_USE_OF
+
+static void __init sh73a0_generic_init(void)
+{
+#ifdef CONFIG_CACHE_L2X0
+ /* Shared attribute override enable, 64K*8way */
+ l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff);
+#endif
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *sh73a0_boards_compat_dt[] __initdata = {
+ "renesas,sh73a0",
+ NULL,
+};
+
+DT_MACHINE_START(SH73A0_DT, "Generic SH73A0 (Flattened Device Tree)")
+ .smp = smp_ops(sh73a0_smp_ops),
+ .map_io = sh73a0_map_io,
+ .init_early = shmobile_init_delay,
+ .init_machine = sh73a0_generic_init,
+ .init_late = shmobile_init_late,
+ .dt_compat = sh73a0_boards_compat_dt,
+MACHINE_END
+#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/sh-gpio.h b/arch/arm/mach-shmobile/sh-gpio.h
new file mode 100644
index 000000000..2c4141413
--- /dev/null
+++ b/arch/arm/mach-shmobile/sh-gpio.h
@@ -0,0 +1,29 @@
+/*
+ * Generic GPIO API and pinmux table support
+ *
+ * Copyright (c) 2008 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+
+/*
+ * FIXME !!
+ *
+ * current gpio frame work doesn't have
+ * the method to control only pull up/down/free.
+ * this function should be replaced by correct gpio function
+ */
+static inline void __init gpio_direction_none(void __iomem * addr)
+{
+ __raw_writeb(0x00, addr);
+}
+
+#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-shmobile/sh73a0.h b/arch/arm/mach-shmobile/sh73a0.h
new file mode 100644
index 000000000..5a80f18b4
--- /dev/null
+++ b/arch/arm/mach-shmobile/sh73a0.h
@@ -0,0 +1,89 @@
+#ifndef __ASM_SH73A0_H__
+#define __ASM_SH73A0_H__
+
+/* DMA slave IDs */
+enum {
+ SHDMA_SLAVE_INVALID,
+ SHDMA_SLAVE_SCIF0_TX,
+ SHDMA_SLAVE_SCIF0_RX,
+ SHDMA_SLAVE_SCIF1_TX,
+ SHDMA_SLAVE_SCIF1_RX,
+ SHDMA_SLAVE_SCIF2_TX,
+ SHDMA_SLAVE_SCIF2_RX,
+ SHDMA_SLAVE_SCIF3_TX,
+ SHDMA_SLAVE_SCIF3_RX,
+ SHDMA_SLAVE_SCIF4_TX,
+ SHDMA_SLAVE_SCIF4_RX,
+ SHDMA_SLAVE_SCIF5_TX,
+ SHDMA_SLAVE_SCIF5_RX,
+ SHDMA_SLAVE_SCIF6_TX,
+ SHDMA_SLAVE_SCIF6_RX,
+ SHDMA_SLAVE_SCIF7_TX,
+ SHDMA_SLAVE_SCIF7_RX,
+ SHDMA_SLAVE_SCIF8_TX,
+ SHDMA_SLAVE_SCIF8_RX,
+ SHDMA_SLAVE_SDHI0_TX,
+ SHDMA_SLAVE_SDHI0_RX,
+ SHDMA_SLAVE_SDHI1_TX,
+ SHDMA_SLAVE_SDHI1_RX,
+ SHDMA_SLAVE_SDHI2_TX,
+ SHDMA_SLAVE_SDHI2_RX,
+ SHDMA_SLAVE_MMCIF_TX,
+ SHDMA_SLAVE_MMCIF_RX,
+ SHDMA_SLAVE_FSI2A_TX,
+ SHDMA_SLAVE_FSI2A_RX,
+ SHDMA_SLAVE_FSI2B_TX,
+ SHDMA_SLAVE_FSI2B_RX,
+ SHDMA_SLAVE_FSI2C_TX,
+ SHDMA_SLAVE_FSI2C_RX,
+ SHDMA_SLAVE_FSI2D_RX,
+};
+
+/*
+ * SH73A0 IRQ LOCATION TABLE
+ *
+ * 416 -----------------------------------------
+ * IRQ0-IRQ15
+ * 431 -----------------------------------------
+ * ...
+ * 448 -----------------------------------------
+ * sh73a0-intcs
+ * sh73a0-intca-irq-pins
+ * 680 -----------------------------------------
+ * ...
+ * 700 -----------------------------------------
+ * sh73a0-pint0
+ * 731 -----------------------------------------
+ * 732 -----------------------------------------
+ * sh73a0-pint1
+ * 739 -----------------------------------------
+ * ...
+ * 800 -----------------------------------------
+ * IRQ16-IRQ31
+ * 815 -----------------------------------------
+ * ...
+ * 928 -----------------------------------------
+ * sh73a0-intca-irq-pins
+ * 943 -----------------------------------------
+ */
+
+/* PINT interrupts are located at Linux IRQ 700 and up */
+#define SH73A0_PINT0_IRQ(irq) ((irq) + 700)
+#define SH73A0_PINT1_IRQ(irq) ((irq) + 732)
+
+extern void sh73a0_init_irq(void);
+extern void sh73a0_init_irq_dt(void);
+extern void sh73a0_map_io(void);
+extern void sh73a0_earlytimer_init(void);
+extern void sh73a0_add_early_devices(void);
+extern void sh73a0_add_standard_devices(void);
+extern void sh73a0_clock_init(void);
+extern void sh73a0_pinmux_init(void);
+extern void sh73a0_pm_init(void);
+extern struct clk sh73a0_extal1_clk;
+extern struct clk sh73a0_extal2_clk;
+extern struct clk sh73a0_extcki_clk;
+extern struct clk sh73a0_extalr_clk;
+extern struct smp_operations sh73a0_smp_ops;
+
+#endif /* __ASM_SH73A0_H__ */
diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c
new file mode 100644
index 000000000..baff3b5ef
--- /dev/null
+++ b/arch/arm/mach-shmobile/smp-emev2.c
@@ -0,0 +1,55 @@
+/*
+ * SMP support for Emma Mobile EV2
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Copyright (C) 2012 Magnus Damm
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
+#include "common.h"
+
+#define EMEV2_SCU_BASE 0x1e000000
+#define EMEV2_SMU_BASE 0xe0110000
+#define SMU_GENERAL_REG0 0x7c0
+
+static int emev2_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ arch_send_wakeup_ipi_mask(cpumask_of(cpu_logical_map(cpu)));
+ return 0;
+}
+
+static void __init emev2_smp_prepare_cpus(unsigned int max_cpus)
+{
+ void __iomem *smu;
+
+ /* Tell ROM loader about our vector (in headsmp.S) */
+ smu = ioremap(EMEV2_SMU_BASE, PAGE_SIZE);
+ if (smu) {
+ iowrite32(__pa(shmobile_boot_vector), smu + SMU_GENERAL_REG0);
+ iounmap(smu);
+ }
+
+ /* setup EMEV2 specific SCU bits */
+ shmobile_scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE);
+ shmobile_smp_scu_prepare_cpus(max_cpus);
+}
+
+struct smp_operations emev2_smp_ops __initdata = {
+ .smp_prepare_cpus = emev2_smp_prepare_cpus,
+ .smp_boot_secondary = emev2_boot_secondary,
+};
diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c
new file mode 100644
index 000000000..01f792fcb
--- /dev/null
+++ b/arch/arm/mach-shmobile/smp-r8a7779.c
@@ -0,0 +1,136 @@
+/*
+ * SMP support for R-Mobile / SH-Mobile - r8a7779 portion
+ *
+ * Copyright (C) 2011 Renesas Solutions Corp.
+ * Copyright (C) 2011 Magnus Damm
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
+#include <asm/smp_twd.h>
+
+#include "common.h"
+#include "pm-rcar.h"
+#include "r8a7779.h"
+
+#define AVECR IOMEM(0xfe700040)
+#define R8A7779_SCU_BASE 0xf0000000
+
+static struct rcar_sysc_ch r8a7779_ch_cpu1 = {
+ .chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
+ .chan_bit = 1, /* ARM1 */
+ .isr_bit = 1, /* ARM1 */
+};
+
+static struct rcar_sysc_ch r8a7779_ch_cpu2 = {
+ .chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
+ .chan_bit = 2, /* ARM2 */
+ .isr_bit = 2, /* ARM2 */
+};
+
+static struct rcar_sysc_ch r8a7779_ch_cpu3 = {
+ .chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
+ .chan_bit = 3, /* ARM3 */
+ .isr_bit = 3, /* ARM3 */
+};
+
+static struct rcar_sysc_ch *r8a7779_ch_cpu[4] = {
+ [1] = &r8a7779_ch_cpu1,
+ [2] = &r8a7779_ch_cpu2,
+ [3] = &r8a7779_ch_cpu3,
+};
+
+#if defined(CONFIG_HAVE_ARM_TWD) && !defined(CONFIG_ARCH_MULTIPLATFORM)
+static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, R8A7779_SCU_BASE + 0x600, 29);
+void __init r8a7779_register_twd(void)
+{
+ twd_local_timer_register(&twd_local_timer);
+}
+#endif
+
+static int r8a7779_platform_cpu_kill(unsigned int cpu)
+{
+ struct rcar_sysc_ch *ch = NULL;
+ int ret = -EIO;
+
+ cpu = cpu_logical_map(cpu);
+
+ if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
+ ch = r8a7779_ch_cpu[cpu];
+
+ if (ch)
+ ret = rcar_sysc_power_down(ch);
+
+ return ret ? ret : 1;
+}
+
+static int r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ struct rcar_sysc_ch *ch = NULL;
+ unsigned int lcpu = cpu_logical_map(cpu);
+ int ret;
+
+ if (lcpu < ARRAY_SIZE(r8a7779_ch_cpu))
+ ch = r8a7779_ch_cpu[lcpu];
+
+ if (ch)
+ ret = rcar_sysc_power_up(ch);
+ else
+ ret = -EIO;
+
+ return ret;
+}
+
+static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
+{
+ /* Map the reset vector (in headsmp-scu.S, headsmp.S) */
+ __raw_writel(__pa(shmobile_boot_vector), AVECR);
+ shmobile_boot_fn = virt_to_phys(shmobile_boot_scu);
+ shmobile_boot_arg = (unsigned long)shmobile_scu_base;
+
+ /* setup r8a7779 specific SCU bits */
+ shmobile_scu_base = IOMEM(R8A7779_SCU_BASE);
+ shmobile_smp_scu_prepare_cpus(max_cpus);
+
+ r8a7779_pm_init();
+
+ /* power off secondary CPUs */
+ r8a7779_platform_cpu_kill(1);
+ r8a7779_platform_cpu_kill(2);
+ r8a7779_platform_cpu_kill(3);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static int r8a7779_cpu_kill(unsigned int cpu)
+{
+ if (shmobile_smp_scu_cpu_kill(cpu))
+ return r8a7779_platform_cpu_kill(cpu);
+
+ return 0;
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
+struct smp_operations r8a7779_smp_ops __initdata = {
+ .smp_prepare_cpus = r8a7779_smp_prepare_cpus,
+ .smp_boot_secondary = r8a7779_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_die = shmobile_smp_scu_cpu_die,
+ .cpu_kill = r8a7779_cpu_kill,
+#endif
+};
diff --git a/arch/arm/mach-shmobile/smp-r8a7790.c b/arch/arm/mach-shmobile/smp-r8a7790.c
new file mode 100644
index 000000000..930f45cbc
--- /dev/null
+++ b/arch/arm/mach-shmobile/smp-r8a7790.c
@@ -0,0 +1,71 @@
+/*
+ * SMP support for r8a7790
+ *
+ * Copyright (C) 2012-2013 Renesas Solutions Corp.
+ * Copyright (C) 2012 Takashi Yoshii <takashi.yoshii.ze@renesas.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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/smp_plat.h>
+
+#include "common.h"
+#include "platsmp-apmu.h"
+#include "pm-rcar.h"
+#include "rcar-gen2.h"
+#include "r8a7790.h"
+
+static struct rcar_sysc_ch r8a7790_ca15_scu = {
+ .chan_offs = 0x180, /* PWRSR5 .. PWRER5 */
+ .isr_bit = 12, /* CA15-SCU */
+};
+
+static struct rcar_sysc_ch r8a7790_ca7_scu = {
+ .chan_offs = 0x100, /* PWRSR3 .. PWRER3 */
+ .isr_bit = 21, /* CA7-SCU */
+};
+
+static struct rcar_apmu_config r8a7790_apmu_config[] = {
+ {
+ .iomem = DEFINE_RES_MEM(0xe6152000, 0x188),
+ .cpus = { 0, 1, 2, 3 },
+ },
+ {
+ .iomem = DEFINE_RES_MEM(0xe6151000, 0x188),
+ .cpus = { 0x100, 0x0101, 0x102, 0x103 },
+ }
+};
+
+static void __init r8a7790_smp_prepare_cpus(unsigned int max_cpus)
+{
+ /* let APMU code install data related to shmobile_boot_vector */
+ shmobile_smp_apmu_prepare_cpus(max_cpus,
+ r8a7790_apmu_config,
+ ARRAY_SIZE(r8a7790_apmu_config));
+
+ /* turn on power to SCU */
+ rcar_gen2_pm_init();
+ rcar_sysc_power_up(&r8a7790_ca15_scu);
+ rcar_sysc_power_up(&r8a7790_ca7_scu);
+}
+
+struct smp_operations r8a7790_smp_ops __initdata = {
+ .smp_prepare_cpus = r8a7790_smp_prepare_cpus,
+ .smp_boot_secondary = shmobile_smp_apmu_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_disable = shmobile_smp_cpu_disable,
+ .cpu_die = shmobile_smp_apmu_cpu_die,
+ .cpu_kill = shmobile_smp_apmu_cpu_kill,
+#endif
+};
diff --git a/arch/arm/mach-shmobile/smp-r8a7791.c b/arch/arm/mach-shmobile/smp-r8a7791.c
new file mode 100644
index 000000000..5e2d1db79
--- /dev/null
+++ b/arch/arm/mach-shmobile/smp-r8a7791.c
@@ -0,0 +1,65 @@
+/*
+ * SMP support for r8a7791
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Magnus Damm
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/smp_plat.h>
+
+#include "common.h"
+#include "platsmp-apmu.h"
+#include "r8a7791.h"
+#include "rcar-gen2.h"
+
+static struct rcar_apmu_config r8a7791_apmu_config[] = {
+ {
+ .iomem = DEFINE_RES_MEM(0xe6152000, 0x188),
+ .cpus = { 0, 1 },
+ }
+};
+
+static void __init r8a7791_smp_prepare_cpus(unsigned int max_cpus)
+{
+ /* let APMU code install data related to shmobile_boot_vector */
+ shmobile_smp_apmu_prepare_cpus(max_cpus,
+ r8a7791_apmu_config,
+ ARRAY_SIZE(r8a7791_apmu_config));
+
+ rcar_gen2_pm_init();
+}
+
+static int r8a7791_smp_boot_secondary(unsigned int cpu,
+ struct task_struct *idle)
+{
+ /* Error out when hardware debug mode is enabled */
+ if (rcar_gen2_read_mode_pins() & BIT(21)) {
+ pr_warn("Unable to boot CPU%u when MD21 is set\n", cpu);
+ return -ENOTSUPP;
+ }
+
+ return shmobile_smp_apmu_boot_secondary(cpu, idle);
+}
+
+struct smp_operations r8a7791_smp_ops __initdata = {
+ .smp_prepare_cpus = r8a7791_smp_prepare_cpus,
+ .smp_boot_secondary = r8a7791_smp_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_disable = shmobile_smp_cpu_disable,
+ .cpu_die = shmobile_smp_apmu_cpu_die,
+ .cpu_kill = shmobile_smp_apmu_cpu_kill,
+#endif
+};
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
new file mode 100644
index 000000000..2106d6b76
--- /dev/null
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -0,0 +1,75 @@
+/*
+ * SMP support for R-Mobile / SH-Mobile - sh73a0 portion
+ *
+ * Copyright (C) 2010 Magnus Damm
+ * Copyright (C) 2010 Takashi Yoshii
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#include <asm/smp_plat.h>
+#include <asm/smp_twd.h>
+
+#include "common.h"
+#include "sh73a0.h"
+
+#define WUPCR IOMEM(0xe6151010)
+#define SRESCR IOMEM(0xe6151018)
+#define PSTR IOMEM(0xe6151040)
+#define SBAR IOMEM(0xe6180020)
+#define APARMBAREA IOMEM(0xe6f10020)
+
+#define SH73A0_SCU_BASE 0xf0000000
+
+#if defined(CONFIG_HAVE_ARM_TWD) && !defined(CONFIG_ARCH_MULTIPLATFORM)
+static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, SH73A0_SCU_BASE + 0x600, 29);
+void __init sh73a0_register_twd(void)
+{
+ twd_local_timer_register(&twd_local_timer);
+}
+#endif
+
+static int sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ unsigned int lcpu = cpu_logical_map(cpu);
+
+ if (((__raw_readl(PSTR) >> (4 * lcpu)) & 3) == 3)
+ __raw_writel(1 << lcpu, WUPCR); /* wake up */
+ else
+ __raw_writel(1 << lcpu, SRESCR); /* reset */
+
+ return 0;
+}
+
+static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
+{
+ /* Map the reset vector (in headsmp.S) */
+ __raw_writel(0, APARMBAREA); /* 4k */
+ __raw_writel(__pa(shmobile_boot_vector), SBAR);
+
+ /* setup sh73a0 specific SCU bits */
+ shmobile_scu_base = IOMEM(SH73A0_SCU_BASE);
+ shmobile_smp_scu_prepare_cpus(max_cpus);
+}
+
+struct smp_operations sh73a0_smp_ops __initdata = {
+ .smp_prepare_cpus = sh73a0_smp_prepare_cpus,
+ .smp_boot_secondary = sh73a0_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_disable = shmobile_smp_cpu_disable,
+ .cpu_die = shmobile_smp_scu_cpu_die,
+ .cpu_kill = shmobile_smp_scu_cpu_kill,
+#endif
+};
diff --git a/arch/arm/mach-shmobile/suspend.c b/arch/arm/mach-shmobile/suspend.c
new file mode 100644
index 000000000..5d92b5dd4
--- /dev/null
+++ b/arch/arm/mach-shmobile/suspend.c
@@ -0,0 +1,48 @@
+/*
+ * Suspend-to-RAM support code for SH-Mobile ARM
+ *
+ * Copyright (C) 2011 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/pm.h>
+#include <linux/suspend.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/cpu.h>
+
+#include <asm/io.h>
+#include <asm/system_misc.h>
+
+static int shmobile_suspend_default_enter(suspend_state_t suspend_state)
+{
+ cpu_do_idle();
+ return 0;
+}
+
+static int shmobile_suspend_begin(suspend_state_t state)
+{
+ cpu_idle_poll_ctrl(true);
+ return 0;
+}
+
+static void shmobile_suspend_end(void)
+{
+ cpu_idle_poll_ctrl(false);
+}
+
+struct platform_suspend_ops shmobile_suspend_ops = {
+ .begin = shmobile_suspend_begin,
+ .end = shmobile_suspend_end,
+ .enter = shmobile_suspend_default_enter,
+ .valid = suspend_valid_only_mem,
+};
+
+int __init shmobile_suspend_init(void)
+{
+ suspend_set_ops(&shmobile_suspend_ops);
+ return 0;
+}
diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c
new file mode 100644
index 000000000..0edf2a6d2
--- /dev/null
+++ b/arch/arm/mach-shmobile/timer.c
@@ -0,0 +1,112 @@
+/*
+ * SH-Mobile Timer
+ *
+ * Copyright (C) 2010 Magnus Damm
+ * Copyright (C) 2002 - 2009 Paul Mundt
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/clocksource.h>
+#include <linux/delay.h>
+#include <linux/of_address.h>
+
+static void __init shmobile_setup_delay_hz(unsigned int max_cpu_core_hz,
+ unsigned int mult, unsigned int div)
+{
+ /* calculate a worst-case loops-per-jiffy value
+ * based on maximum cpu core hz setting and the
+ * __delay() implementation in arch/arm/lib/delay.S
+ *
+ * this will result in a longer delay than expected
+ * when the cpu core runs on lower frequencies.
+ */
+
+ unsigned int value = HZ * div / mult;
+
+ if (!preset_lpj)
+ preset_lpj = max_cpu_core_hz / value;
+}
+
+void __init shmobile_init_delay(void)
+{
+ struct device_node *np, *cpus;
+ bool is_a7_a8_a9 = false;
+ bool is_a15 = false;
+ bool has_arch_timer = false;
+ u32 max_freq = 0;
+
+ cpus = of_find_node_by_path("/cpus");
+ if (!cpus)
+ return;
+
+ for_each_child_of_node(cpus, np) {
+ u32 freq;
+
+ if (!of_property_read_u32(np, "clock-frequency", &freq))
+ max_freq = max(max_freq, freq);
+
+ if (of_device_is_compatible(np, "arm,cortex-a8") ||
+ of_device_is_compatible(np, "arm,cortex-a9")) {
+ is_a7_a8_a9 = true;
+ } else if (of_device_is_compatible(np, "arm,cortex-a7")) {
+ is_a7_a8_a9 = true;
+ has_arch_timer = true;
+ } else if (of_device_is_compatible(np, "arm,cortex-a15")) {
+ is_a15 = true;
+ has_arch_timer = true;
+ }
+ }
+
+ of_node_put(cpus);
+
+ if (!max_freq)
+ return;
+
+#ifdef CONFIG_ARCH_SHMOBILE_LEGACY
+ /* Non-multiplatform r8a73a4 SoC cannot use arch timer due
+ * to GIC being initialized from C and arch timer via DT */
+ if (of_machine_is_compatible("renesas,r8a73a4"))
+ has_arch_timer = false;
+
+ /* Non-multiplatform r8a7790 SoC cannot use arch timer due
+ * to GIC being initialized from C and arch timer via DT */
+ if (of_machine_is_compatible("renesas,r8a7790"))
+ has_arch_timer = false;
+#endif
+
+ if (!has_arch_timer || !IS_ENABLED(CONFIG_ARM_ARCH_TIMER)) {
+ if (is_a7_a8_a9)
+ shmobile_setup_delay_hz(max_freq, 1, 3);
+ else if (is_a15)
+ shmobile_setup_delay_hz(max_freq, 2, 4);
+ }
+}
+
+static void __init shmobile_late_time_init(void)
+{
+ /*
+ * Make sure all compiled-in early timers register themselves.
+ *
+ * Run probe() for two "earlytimer" devices, these will be the
+ * clockevents and clocksource devices respectively. In the event
+ * that only a clockevents device is available, we -ENODEV on the
+ * clocksource and the jiffies clocksource is used transparently
+ * instead. No error handling is necessary here.
+ */
+ early_platform_driver_register_all("earlytimer");
+ early_platform_driver_probe("earlytimer", 2, 0);
+}
+
+void __init shmobile_earlytimer_init(void)
+{
+ late_time_init = shmobile_late_time_init;
+}
+