Merge tags 'renesas-pinmux-for-v3.11' and 'renesas-soc-for-v3.11' into cleanup

This merge has been performed in order to provide the pre-requisites for
a cleanup patch for the lager board to annotate various structures
with __initdata.

Conflicts:
	arch/arm/mach-shmobile/Kconfig
	arch/arm/mach-shmobile/include/mach/r8a7778.h
	arch/arm/mach-shmobile/setup-r8a7778.c
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 06da4d3..5414402 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -36,7 +36,7 @@
 	select RENESAS_INTC_IRQPIN
 
 config ARCH_R8A7778
-	bool "R-Car M1 (R8A77780)"
+	bool "R-Car M1A (R8A77781)"
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select CPU_V7
 	select SH_CLK_CPG
@@ -170,6 +170,8 @@
 config MACH_KZM9G
 	bool "KZM-A9-GT board"
 	depends on ARCH_SH73A0
+	select ARCH_HAS_CPUFREQ
+	select ARCH_HAS_OPP
 	select ARCH_REQUIRE_GPIOLIB
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
 	select SND_SOC_AK4642 if SND_SIMPLE_CARD
diff --git a/arch/arm/mach-shmobile/clock-r8a73a4.c b/arch/arm/mach-shmobile/clock-r8a73a4.c
index e710c00..f6227bb 100644
--- a/arch/arm/mach-shmobile/clock-r8a73a4.c
+++ b/arch/arm/mach-shmobile/clock-r8a73a4.c
@@ -22,15 +22,43 @@
 #include <linux/kernel.h>
 #include <linux/sh_clk.h>
 #include <linux/clkdev.h>
+#include <mach/clock.h>
 #include <mach/common.h>
 
 #define CPG_BASE 0xe6150000
 #define CPG_LEN 0x270
 
-#define MPCKCR 0xe6150080
 #define SMSTPCR2 0xe6150138
 #define SMSTPCR5 0xe6150144
 
+#define FRQCRA		0xE6150000
+#define FRQCRB		0xE6150004
+#define VCLKCR1		0xE6150008
+#define VCLKCR2		0xE615000C
+#define VCLKCR3		0xE615001C
+#define VCLKCR4		0xE6150014
+#define VCLKCR5		0xE6150034
+#define ZBCKCR		0xE6150010
+#define SD0CKCR		0xE6150074
+#define SD1CKCR		0xE6150078
+#define SD2CKCR		0xE615007C
+#define MMC0CKCR	0xE6150240
+#define MMC1CKCR	0xE6150244
+#define FSIACKCR	0xE6150018
+#define FSIBCKCR	0xE6150090
+#define MPCKCR		0xe6150080
+#define SPUVCKCR	0xE6150094
+#define HSICKCR		0xE615026C
+#define M4CKCR		0xE6150098
+#define PLLECR		0xE61500D0
+#define PLL1CR		0xE6150028
+#define PLL2CR		0xE615002C
+#define PLL2SCR		0xE61501F4
+#define PLL2HCR		0xE61501E4
+#define CKSCR		0xE61500C0
+
+#define CPG_MAP(o) ((o - CPG_BASE) + cpg_mapping.base)
+
 static struct clk_mapping cpg_mapping = {
 	.phys   = CPG_BASE,
 	.len    = CPG_LEN,
@@ -51,12 +79,273 @@
 	.mapping	= &cpg_mapping,
 };
 
+static struct sh_clk_ops followparent_clk_ops = {
+	.recalc	= followparent_recalc,
+};
+
+static struct clk main_clk = {
+	/* .parent will be set r8a73a4_clock_init */
+	.ops	= &followparent_clk_ops,
+};
+
+SH_CLK_RATIO(div2,	1, 2);
+SH_CLK_RATIO(div4,	1, 4);
+
+SH_FIXED_RATIO_CLK(main_div2_clk,	main_clk,		div2);
+SH_FIXED_RATIO_CLK(extal1_div2_clk,	extal1_clk,		div2);
+SH_FIXED_RATIO_CLK(extal2_div2_clk,	extal2_clk,		div2);
+SH_FIXED_RATIO_CLK(extal2_div4_clk,	extal2_clk,		div4);
+
+/* External FSIACK/FSIBCK clock */
+static struct clk fsiack_clk = {
+};
+
+static struct clk fsibck_clk = {
+};
+
+/*
+ *		PLL clocks
+ */
+static struct clk *pll_parent_main[] = {
+	[0] = &main_clk,
+	[1] = &main_div2_clk
+};
+
+static struct clk *pll_parent_main_extal[8] = {
+	[0] = &main_div2_clk,
+	[1] = &extal2_div2_clk,
+	[3] = &extal2_div4_clk,
+	[4] = &main_clk,
+	[5] = &extal2_clk,
+};
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+	unsigned long mult = 1;
+
+	if (ioread32(CPG_MAP(PLLECR)) & (1 << clk->enable_bit))
+		mult = (((ioread32(clk->mapped_reg) >> 24) & 0x7f) + 1);
+
+	return clk->parent->rate * mult;
+}
+
+static int pll_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 val;
+	int i, ret;
+
+	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 = ioread32(clk->mapped_reg) &
+		~(((1 << clk->src_width) - 1) << clk->src_shift);
+
+	iowrite32(val | i << clk->src_shift, clk->mapped_reg);
+
+	return 0;
+}
+
+static struct sh_clk_ops pll_clk_ops = {
+	.recalc		= pll_recalc,
+	.set_parent	= pll_set_parent,
+};
+
+#define PLL_CLOCK(name, p, pt, w, s, reg, e)		\
+	static struct clk name = {			\
+		.ops		= &pll_clk_ops,		\
+		.flags		= CLK_ENABLE_ON_INIT,	\
+		.parent		= p,			\
+		.parent_table	= pt,			\
+		.parent_num	= ARRAY_SIZE(pt),	\
+		.src_width	= w,			\
+		.src_shift	= s,			\
+		.enable_reg	= (void __iomem *)reg,	\
+		.enable_bit	= e,			\
+		.mapping	= &cpg_mapping,		\
+	}
+
+PLL_CLOCK(pll1_clk,  &main_clk,      pll_parent_main,       1, 7, PLL1CR,  1);
+PLL_CLOCK(pll2_clk,  &main_div2_clk, pll_parent_main_extal, 3, 5, PLL2CR,  2);
+PLL_CLOCK(pll2s_clk, &main_div2_clk, pll_parent_main_extal, 3, 5, PLL2SCR, 4);
+PLL_CLOCK(pll2h_clk, &main_div2_clk, pll_parent_main_extal, 3, 5, PLL2HCR, 5);
+
+SH_FIXED_RATIO_CLK(pll1_div2_clk,	pll1_clk,	div2);
+
 static struct clk *main_clks[] = {
 	&extalr_clk,
 	&extal1_clk,
+	&extal1_div2_clk,
 	&extal2_clk,
+	&extal2_div2_clk,
+	&extal2_div4_clk,
+	&main_clk,
+	&main_div2_clk,
+	&fsiack_clk,
+	&fsibck_clk,
+	&pll1_clk,
+	&pll1_div2_clk,
+	&pll2_clk,
+	&pll2s_clk,
+	&pll2h_clk,
 };
 
+/* DIV4 */
+static void div4_kick(struct clk *clk)
+{
+	unsigned long value;
+
+	/* set KICK bit in FRQCRB to update hardware setting */
+	value = ioread32(CPG_MAP(FRQCRB));
+	value |= (1 << 31);
+	iowrite32(value, CPG_MAP(FRQCRB));
+}
+
+static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18, 24, 0, 36, 48, 10};
+
+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_M3, DIV4_B, DIV4_M1, DIV4_M2,
+	DIV4_ZX, DIV4_ZS, DIV4_HP,
+	DIV4_NR };
+
+static struct clk div4_clks[DIV4_NR] = {
+	[DIV4_I]	= SH_CLK_DIV4(&pll1_clk, FRQCRA, 20, 0x0dff, CLK_ENABLE_ON_INIT),
+	[DIV4_M3]	= SH_CLK_DIV4(&pll1_clk, FRQCRA, 12, 0x1dff, CLK_ENABLE_ON_INIT),
+	[DIV4_B]	= SH_CLK_DIV4(&pll1_clk, FRQCRA,  8, 0x0dff, CLK_ENABLE_ON_INIT),
+	[DIV4_M1]	= SH_CLK_DIV4(&pll1_clk, FRQCRA,  4, 0x1dff, 0),
+	[DIV4_M2]	= SH_CLK_DIV4(&pll1_clk, FRQCRA,  0, 0x1dff, 0),
+	[DIV4_ZX]	= SH_CLK_DIV4(&pll1_clk, FRQCRB, 12, 0x0dff, 0),
+	[DIV4_ZS]	= SH_CLK_DIV4(&pll1_clk, FRQCRB,  8, 0x0dff, 0),
+	[DIV4_HP]	= SH_CLK_DIV4(&pll1_clk, FRQCRB,  4, 0x0dff, 0),
+};
+
+enum {
+	DIV6_ZB,
+	DIV6_SDHI0, DIV6_SDHI1, DIV6_SDHI2,
+	DIV6_MMC0, DIV6_MMC1,
+	DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_VCK4, DIV6_VCK5,
+	DIV6_FSIA, DIV6_FSIB,
+	DIV6_MP, DIV6_M4, DIV6_HSI, DIV6_SPUV,
+	DIV6_NR };
+
+static struct clk *div6_parents[8] = {
+	[0] = &pll1_div2_clk,
+	[1] = &pll2s_clk,
+	[3] = &extal2_clk,
+	[4] = &main_div2_clk,
+	[6] = &extalr_clk,
+};
+
+static struct clk *fsia_parents[4] = {
+	[0] = &pll1_div2_clk,
+	[1] = &pll2s_clk,
+	[2] = &fsiack_clk,
+};
+
+static struct clk *fsib_parents[4] = {
+	[0] = &pll1_div2_clk,
+	[1] = &pll2s_clk,
+	[2] = &fsibck_clk,
+};
+
+static struct clk *mp_parents[4] = {
+	[0] = &pll1_div2_clk,
+	[1] = &pll2s_clk,
+	[2] = &extal2_clk,
+	[3] = &extal2_clk,
+};
+
+static struct clk *m4_parents[2] = {
+	[0] = &pll2s_clk,
+};
+
+static struct clk *hsi_parents[4] = {
+	[0] = &pll2h_clk,
+	[1] = &pll1_div2_clk,
+	[3] = &pll2s_clk,
+};
+
+/*** FIXME ***
+ * SH_CLK_DIV6_EXT() macro doesn't care .mapping
+ * but, it is necessary on R-Car (= ioremap() base CPG)
+ * The difference between
+ * SH_CLK_DIV6_EXT() <--> SH_CLK_MAP_DIV6_EXT()
+ * is only .mapping
+ */
+#define SH_CLK_MAP_DIV6_EXT(_reg, _flags, _parents,			\
+			    _num_parents, _src_shift, _src_width)	\
+{									\
+	.enable_reg	= (void __iomem *)_reg,				\
+	.enable_bit	= 0, /* unused */				\
+	.flags		= _flags | CLK_MASK_DIV_ON_DISABLE,		\
+	.div_mask	= SH_CLK_DIV6_MSK,				\
+	.parent_table	= _parents,					\
+	.parent_num	= _num_parents,					\
+	.src_shift	= _src_shift,					\
+	.src_width	= _src_width,					\
+	.mapping	= &cpg_mapping,					\
+}
+
+static struct clk div6_clks[DIV6_NR] = {
+	[DIV6_ZB] = SH_CLK_MAP_DIV6_EXT(ZBCKCR, CLK_ENABLE_ON_INIT,
+				div6_parents, 2, 7, 1),
+	[DIV6_SDHI0] = SH_CLK_MAP_DIV6_EXT(SD0CKCR, 0,
+				div6_parents, 2, 6, 2),
+	[DIV6_SDHI1] = SH_CLK_MAP_DIV6_EXT(SD1CKCR, 0,
+				div6_parents, 2, 6, 2),
+	[DIV6_SDHI2] = SH_CLK_MAP_DIV6_EXT(SD2CKCR, 0,
+				div6_parents, 2, 6, 2),
+	[DIV6_MMC0] = SH_CLK_MAP_DIV6_EXT(MMC0CKCR, 0,
+				div6_parents, 2, 6, 2),
+	[DIV6_MMC1] = SH_CLK_MAP_DIV6_EXT(MMC1CKCR, 0,
+				div6_parents, 2, 6, 2),
+	[DIV6_VCK1] = SH_CLK_MAP_DIV6_EXT(VCLKCR1, 0, /* didn't care bit[6-7] */
+				div6_parents, ARRAY_SIZE(div6_parents), 12, 3),
+	[DIV6_VCK2] = SH_CLK_MAP_DIV6_EXT(VCLKCR2, 0, /* didn't care bit[6-7] */
+				div6_parents, ARRAY_SIZE(div6_parents), 12, 3),
+	[DIV6_VCK3] = SH_CLK_MAP_DIV6_EXT(VCLKCR3, 0, /* didn't care bit[6-7] */
+				div6_parents, ARRAY_SIZE(div6_parents), 12, 3),
+	[DIV6_VCK4] = SH_CLK_MAP_DIV6_EXT(VCLKCR4, 0, /* didn't care bit[6-7] */
+				div6_parents, ARRAY_SIZE(div6_parents), 12, 3),
+	[DIV6_VCK5] = SH_CLK_MAP_DIV6_EXT(VCLKCR5, 0, /* didn't care bit[6-7] */
+				div6_parents, ARRAY_SIZE(div6_parents), 12, 3),
+	[DIV6_FSIA] = SH_CLK_MAP_DIV6_EXT(FSIACKCR, 0,
+				fsia_parents, ARRAY_SIZE(fsia_parents), 6, 2),
+	[DIV6_FSIB] = SH_CLK_MAP_DIV6_EXT(FSIBCKCR, 0,
+				fsib_parents, ARRAY_SIZE(fsib_parents), 6, 2),
+	[DIV6_MP] = SH_CLK_MAP_DIV6_EXT(MPCKCR, 0, /* it needs bit[9-11] control */
+				mp_parents, ARRAY_SIZE(mp_parents), 6, 2),
+	/* pll2s will be selected always for M4 */
+	[DIV6_M4] = SH_CLK_MAP_DIV6_EXT(M4CKCR, 0, /* it needs bit[9] control */
+				m4_parents, ARRAY_SIZE(m4_parents), 6, 1),
+	[DIV6_HSI] = SH_CLK_MAP_DIV6_EXT(HSICKCR, 0, /* it needs bit[9] control */
+				hsi_parents, ARRAY_SIZE(hsi_parents), 6, 2),
+	[DIV6_SPUV] = SH_CLK_MAP_DIV6_EXT(SPUVCKCR, 0,
+				mp_parents, ARRAY_SIZE(mp_parents), 6, 2),
+};
+
+/* MSTP */
 enum {
 	MSTP217, MSTP216, MSTP207, MSTP206, MSTP204, MSTP203,
 	MSTP522,
@@ -64,16 +353,52 @@
 };
 
 static struct clk mstp_clks[MSTP_NR] = {
-	[MSTP204] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR2, 4, 0), /* SCIFA0 */
-	[MSTP203] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR2, 3, 0), /* SCIFA1 */
-	[MSTP206] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR2, 6, 0), /* SCIFB0 */
-	[MSTP207] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR2, 7, 0), /* SCIFB1 */
-	[MSTP216] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR2, 16, 0), /* SCIFB2 */
-	[MSTP217] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR2, 17, 0), /* SCIFB3 */
+	[MSTP204] = SH_CLK_MSTP32(&div6_clks[DIV6_MP],	SMSTPCR2, 4, 0), /* SCIFA0 */
+	[MSTP203] = SH_CLK_MSTP32(&div6_clks[DIV6_MP],	SMSTPCR2, 3, 0), /* SCIFA1 */
+	[MSTP206] = SH_CLK_MSTP32(&div6_clks[DIV6_MP],	SMSTPCR2, 6, 0), /* SCIFB0 */
+	[MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_MP],	SMSTPCR2, 7, 0), /* SCIFB1 */
+	[MSTP216] = SH_CLK_MSTP32(&div6_clks[DIV6_MP],	SMSTPCR2, 16, 0), /* SCIFB2 */
+	[MSTP217] = SH_CLK_MSTP32(&div6_clks[DIV6_MP],	SMSTPCR2, 17, 0), /* SCIFB3 */
 	[MSTP522] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR5, 22, 0), /* Thermal */
 };
 
 static struct clk_lookup lookups[] = {
+	/* main clock */
+	CLKDEV_CON_ID("extal1",			&extal1_clk),
+	CLKDEV_CON_ID("extal1_div2",		&extal1_div2_clk),
+	CLKDEV_CON_ID("extal2",			&extal2_clk),
+	CLKDEV_CON_ID("extal2_div2",		&extal2_div2_clk),
+	CLKDEV_CON_ID("extal2_div4",		&extal2_div4_clk),
+	CLKDEV_CON_ID("fsiack",			&fsiack_clk),
+	CLKDEV_CON_ID("fsibck",			&fsibck_clk),
+
+	/* pll clock */
+	CLKDEV_CON_ID("pll1",			&pll1_clk),
+	CLKDEV_CON_ID("pll1_div2",		&pll1_div2_clk),
+	CLKDEV_CON_ID("pll2",			&pll2_clk),
+	CLKDEV_CON_ID("pll2s",			&pll2s_clk),
+	CLKDEV_CON_ID("pll2h",			&pll2h_clk),
+
+	/* DIV6 */
+	CLKDEV_CON_ID("zb",			&div6_clks[DIV6_ZB]),
+	CLKDEV_CON_ID("sdhi0",			&div6_clks[DIV6_SDHI0]),
+	CLKDEV_CON_ID("sdhi1",			&div6_clks[DIV6_SDHI1]),
+	CLKDEV_CON_ID("sdhi2",			&div6_clks[DIV6_SDHI2]),
+	CLKDEV_CON_ID("mmc0",			&div6_clks[DIV6_MMC0]),
+	CLKDEV_CON_ID("mmc1",			&div6_clks[DIV6_MMC1]),
+	CLKDEV_CON_ID("vck1",			&div6_clks[DIV6_VCK1]),
+	CLKDEV_CON_ID("vck2",			&div6_clks[DIV6_VCK2]),
+	CLKDEV_CON_ID("vck3",			&div6_clks[DIV6_VCK3]),
+	CLKDEV_CON_ID("vck4",			&div6_clks[DIV6_VCK4]),
+	CLKDEV_CON_ID("vck5",			&div6_clks[DIV6_VCK5]),
+	CLKDEV_CON_ID("fsia",			&div6_clks[DIV6_FSIA]),
+	CLKDEV_CON_ID("fsib",			&div6_clks[DIV6_FSIB]),
+	CLKDEV_CON_ID("mp",			&div6_clks[DIV6_MP]),
+	CLKDEV_CON_ID("m4",			&div6_clks[DIV6_M4]),
+	CLKDEV_CON_ID("hsi",			&div6_clks[DIV6_HSI]),
+	CLKDEV_CON_ID("spuv",			&div6_clks[DIV6_SPUV]),
+
+	/* MSTP */
 	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]),
 	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]),
 	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP206]),
@@ -88,22 +413,40 @@
 
 void __init r8a73a4_clock_init(void)
 {
-	void __iomem *cpg_base, *reg;
+	void __iomem *reg;
 	int k, ret = 0;
+	u32 ckscr;
 
-	/* fix MPCLK to EXTAL2 for now.
-	 * this is needed until more detailed clock topology is supported
-	 */
-	cpg_base = ioremap_nocache(CPG_BASE, CPG_LEN);
-	BUG_ON(!cpg_base);
-	reg = cpg_base + (MPCKCR - CPG_BASE);
-	iowrite32(ioread32(reg) | 1 << 7 | 0x0c, reg); /* set CKSEL */
-	iounmap(cpg_base);
+	reg = ioremap_nocache(CKSCR, PAGE_SIZE);
+	BUG_ON(!reg);
+	ckscr = ioread32(reg);
+	iounmap(reg);
+
+	switch ((ckscr >> 28) & 0x3) {
+	case 0:
+		main_clk.parent = &extal1_clk;
+		break;
+	case 1:
+		main_clk.parent = &extal1_div2_clk;
+		break;
+	case 2:
+		main_clk.parent = &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)
+		ret = sh_clk_div6_reparent_register(div6_clks, DIV6_NR);
+
+	if (!ret)
 		ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
 
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
index c0d39aa..7fd32d6 100644
--- a/arch/arm/mach-shmobile/clock-r8a7740.c
+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
@@ -266,7 +266,7 @@
 static struct clk fsibck_clk = {
 };
 
-struct clk *main_clks[] = {
+static struct clk *main_clks[] = {
 	&extalr_clk,
 	&extal1_clk,
 	&extal2_clk,
@@ -317,7 +317,7 @@
 	DIV4_NR
 };
 
-struct clk div4_clks[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),
@@ -461,7 +461,7 @@
 
 	MSTP329, MSTP328, MSTP323, MSTP320,
 	MSTP314, MSTP313, MSTP312,
-	MSTP309,
+	MSTP309, MSTP304,
 
 	MSTP416, MSTP415, MSTP407, MSTP406,
 
@@ -499,6 +499,7 @@
 	[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 */
@@ -551,6 +552,7 @@
 	CLKDEV_DEV_ID("sh_tmu.4",		&mstp_clks[MSTP111]),
 	CLKDEV_DEV_ID("sh_tmu.5",		&mstp_clks[MSTP111]),
 	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_tmu.0",		&mstp_clks[MSTP125]),
 	CLKDEV_DEV_ID("sh_tmu.1",		&mstp_clks[MSTP125]),
@@ -584,6 +586,7 @@
 	CLKDEV_DEV_ID("sh_cmt.10",		&mstp_clks[MSTP329]),
 	CLKDEV_DEV_ID("sh_fsi2",		&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.sdhi",          &mstp_clks[MSTP314]),
@@ -592,6 +595,8 @@
 	CLKDEV_DEV_ID("sh_mmcif",		&mstp_clks[MSTP312]),
 	CLKDEV_DEV_ID("e6bd0000.mmcif",         &mstp_clks[MSTP312]),
 	CLKDEV_DEV_ID("sh-eth",			&mstp_clks[MSTP309]),
+	CLKDEV_DEV_ID("e9a00000.sh-eth",	&mstp_clks[MSTP309]),
+	CLKDEV_DEV_ID("renesas_tpu_pwm",	&mstp_clks[MSTP304]),
 
 	CLKDEV_DEV_ID("sh_mobile_sdhi.2",	&mstp_clks[MSTP415]),
 	CLKDEV_DEV_ID("e6870000.sdhi",          &mstp_clks[MSTP415]),
diff --git a/arch/arm/mach-shmobile/clock-r8a7778.c b/arch/arm/mach-shmobile/clock-r8a7778.c
index cd68552..b251e4d 100644
--- a/arch/arm/mach-shmobile/clock-r8a7778.c
+++ b/arch/arm/mach-shmobile/clock-r8a7778.c
@@ -23,9 +23,23 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+/*
+ *     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 <mach/clock.h>
 #include <mach/common.h>
 
 #define MSTPCR0		IOMEM(0xffc80030)
@@ -37,6 +51,9 @@
 #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.
@@ -47,36 +64,71 @@
 	.len	= 0x80,
 };
 
-static struct clk clkp = {
-	.rate   = 62500000, /* FIXME: shortcut */
-	.flags  = CLK_ENABLE_ON_INIT,
+static struct clk extal_clk = {
+	/* .rate will be updated on r8a7778_clock_init() */
 	.mapping = &cpg_mapping,
 };
 
+/*
+ * 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[] = {
-	&clkp,
+	&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,
 };
 
 enum {
+	MSTP323, MSTP322, MSTP321,
 	MSTP114,
 	MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
 	MSTP016, MSTP015,
 	MSTP_NR };
 
 static struct clk mstp_clks[MSTP_NR] = {
-	[MSTP114] = SH_CLK_MSTP32(&clkp, MSTPCR1, 14, 0), /* Ether */
-	[MSTP026] = SH_CLK_MSTP32(&clkp, MSTPCR0, 26, 0), /* SCIF0 */
-	[MSTP025] = SH_CLK_MSTP32(&clkp, MSTPCR0, 25, 0), /* SCIF1 */
-	[MSTP024] = SH_CLK_MSTP32(&clkp, MSTPCR0, 24, 0), /* SCIF2 */
-	[MSTP023] = SH_CLK_MSTP32(&clkp, MSTPCR0, 23, 0), /* SCIF3 */
-	[MSTP022] = SH_CLK_MSTP32(&clkp, MSTPCR0, 22, 0), /* SCIF4 */
-	[MSTP021] = SH_CLK_MSTP32(&clkp, MSTPCR0, 21, 0), /* SCIF5 */
-	[MSTP016] = SH_CLK_MSTP32(&clkp, MSTPCR0, 16, 0), /* TMU0 */
-	[MSTP015] = SH_CLK_MSTP32(&clkp, MSTPCR0, 15, 0), /* TMU1 */
+	[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 */
+	[MSTP114] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 14, 0), /* Ether */
+	[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 */
 };
 
 static struct clk_lookup lookups[] = {
 	/* MSTP32 clocks */
+	CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP323]), /* SDHI0 */
+	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
+	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
 	CLKDEV_DEV_ID("sh-eth",	&mstp_clks[MSTP114]), /* Ether */
 	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */
 	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */
@@ -90,8 +142,86 @@
 
 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]);
 
diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c
index 31d5cd4..9daeb8c 100644
--- a/arch/arm/mach-shmobile/clock-r8a7779.c
+++ b/arch/arm/mach-shmobile/clock-r8a7779.c
@@ -112,7 +112,7 @@
 };
 
 enum { MSTP323, MSTP322, MSTP321, MSTP320,
-	MSTP115, MSTP114,
+	MSTP116, MSTP115, MSTP114,
 	MSTP103, MSTP101, MSTP100,
 	MSTP030,
 	MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
@@ -125,6 +125,7 @@
 	[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 */
+	[MSTP116] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 16, 0), /* PCIe */
 	[MSTP115] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 15, 0), /* SATA */
 	[MSTP114] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 14, 0), /* Ether */
 	[MSTP103] = SH_CLK_MSTP32(&clks_clk, MSTPCR1,  3, 0), /* DU */
@@ -161,6 +162,7 @@
 	CLKDEV_CON_ID("peripheral_clk",	&clkp_clk),
 
 	/* MSTP32 clocks */
+	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("sh-eth", &mstp_clks[MSTP114]), /* Ether */
diff --git a/arch/arm/mach-shmobile/clock-r8a7790.c b/arch/arm/mach-shmobile/clock-r8a7790.c
index bad9bf2..b393592 100644
--- a/arch/arm/mach-shmobile/clock-r8a7790.c
+++ b/arch/arm/mach-shmobile/clock-r8a7790.c
@@ -22,39 +22,174 @@
 #include <linux/kernel.h>
 #include <linux/sh_clk.h>
 #include <linux/clkdev.h>
+#include <mach/clock.h>
 #include <mach/common.h>
 
+/*
+ *   MD		EXTAL		PLL0	PLL1	PLL3
+ * 14 13 19	(MHz)		*1	*1
+ *---------------------------------------------------
+ * 0  0  0	15 x 1		x172/2	x208/2	x106
+ * 0  0  1	15 x 1		x172/2	x208/2	x88
+ * 0  1  0	20 x 1		x130/2	x156/2	x80
+ * 0  1  1	20 x 1		x130/2	x156/2	x66
+ * 1  0  0	26 / 2		x200/2	x240/2	x122
+ * 1  0  1	26 / 2		x200/2	x240/2	x102
+ * 1  1  0	30 / 2		x172/2	x208/2	x106
+ * 1  1  1	30 / 2		x172/2	x208/2	x88
+ *
+ * *1 :	Table 7.6 indicates VCO ouput (PLLx = VCO/2)
+ *	see "p1 / 2" on R8A7790_CLOCK_ROOT() below
+ */
+
+#define MD(nr)	(1 << nr)
+
 #define CPG_BASE 0xe6150000
 #define CPG_LEN 0x1000
 
 #define SMSTPCR2 0xe6150138
+#define SMSTPCR3 0xe615013c
 #define SMSTPCR7 0xe615014c
 
+#define MODEMR		0xE6160060
+#define SDCKCR		0xE6150074
+#define SD2CKCR		0xE6150078
+#define SD3CKCR		0xE615007C
+#define MMC0CKCR	0xE6150240
+#define MMC1CKCR	0xE6150244
+#define SSPCKCR		0xE6150248
+#define SSPRSCKCR	0xE615024C
+
 static struct clk_mapping cpg_mapping = {
 	.phys   = CPG_BASE,
 	.len    = CPG_LEN,
 };
 
-static struct clk p_clk = {
-	.rate	= 65000000, /* shortcut for now */
+static struct clk extal_clk = {
+	/* .rate will be updated on r8a7790_clock_init() */
 	.mapping	= &cpg_mapping,
 };
 
-static struct clk mp_clk = {
-	.rate	= 52000000,  /* shortcut for now */
-	.mapping	= &cpg_mapping,
+static struct sh_clk_ops followparent_clk_ops = {
+	.recalc	= followparent_recalc,
 };
 
+static struct clk main_clk = {
+	/* .parent will be set r8a73a4_clock_init */
+	.ops	= &followparent_clk_ops,
+};
+
+/*
+ * clock ratio of these clock will be updated
+ * on r8a7790_clock_init()
+ */
+SH_FIXED_RATIO_CLK_SET(pll1_clk,		main_clk,	1, 1);
+SH_FIXED_RATIO_CLK_SET(pll3_clk,		main_clk,	1, 1);
+SH_FIXED_RATIO_CLK_SET(lb_clk,			pll1_clk,	1, 1);
+SH_FIXED_RATIO_CLK_SET(qspi_clk,		pll1_clk,	1, 1);
+
+/* fixed ratio clock */
+SH_FIXED_RATIO_CLK_SET(extal_div2_clk,		extal_clk,	1, 2);
+SH_FIXED_RATIO_CLK_SET(cp_clk,			extal_clk,	1, 2);
+
+SH_FIXED_RATIO_CLK_SET(pll1_div2_clk,		pll1_clk,	1, 2);
+SH_FIXED_RATIO_CLK_SET(zg_clk,			pll1_clk,	1, 3);
+SH_FIXED_RATIO_CLK_SET(zx_clk,			pll1_clk,	1, 3);
+SH_FIXED_RATIO_CLK_SET(zs_clk,			pll1_clk,	1, 6);
+SH_FIXED_RATIO_CLK_SET(hp_clk,			pll1_clk,	1, 12);
+SH_FIXED_RATIO_CLK_SET(i_clk,			pll1_clk,	1, 2);
+SH_FIXED_RATIO_CLK_SET(b_clk,			pll1_clk,	1, 12);
+SH_FIXED_RATIO_CLK_SET(p_clk,			pll1_clk,	1, 24);
+SH_FIXED_RATIO_CLK_SET(cl_clk,			pll1_clk,	1, 48);
+SH_FIXED_RATIO_CLK_SET(m2_clk,			pll1_clk,	1, 8);
+SH_FIXED_RATIO_CLK_SET(imp_clk,			pll1_clk,	1, 4);
+SH_FIXED_RATIO_CLK_SET(rclk_clk,		pll1_clk,	1, (48 * 1024));
+SH_FIXED_RATIO_CLK_SET(oscclk_clk,		pll1_clk,	1, (12 * 1024));
+
+SH_FIXED_RATIO_CLK_SET(zb3_clk,			pll3_clk,	1, 4);
+SH_FIXED_RATIO_CLK_SET(zb3d2_clk,		pll3_clk,	1, 8);
+SH_FIXED_RATIO_CLK_SET(ddr_clk,			pll3_clk,	1, 8);
+SH_FIXED_RATIO_CLK_SET(mp_clk,			pll1_div2_clk,	1, 15);
+
 static struct clk *main_clks[] = {
+	&extal_clk,
+	&extal_div2_clk,
+	&main_clk,
+	&pll1_clk,
+	&pll1_div2_clk,
+	&pll3_clk,
+	&lb_clk,
+	&qspi_clk,
+	&zg_clk,
+	&zx_clk,
+	&zs_clk,
+	&hp_clk,
+	&i_clk,
+	&b_clk,
 	&p_clk,
+	&cl_clk,
+	&m2_clk,
+	&imp_clk,
+	&rclk_clk,
+	&oscclk_clk,
+	&zb3_clk,
+	&zb3d2_clk,
+	&ddr_clk,
 	&mp_clk,
+	&cp_clk,
 };
 
-enum { MSTP721, MSTP720,
-	MSTP216, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP_NR };
+/* SDHI (DIV4) clock */
+static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18, 24, 0, 36, 48, 10 };
+
+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,
+};
+
+enum {
+	DIV4_SDH, DIV4_SD0, DIV4_SD1, DIV4_NR
+};
+
+static struct clk div4_clks[DIV4_NR] = {
+	[DIV4_SDH] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 8, 0x0dff, CLK_ENABLE_ON_INIT),
+	[DIV4_SD0] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 4, 0x1de0, CLK_ENABLE_ON_INIT),
+	[DIV4_SD1] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 0, 0x1de0, CLK_ENABLE_ON_INIT),
+};
+
+/* DIV6 clocks */
+enum {
+	DIV6_SD2, DIV6_SD3,
+	DIV6_MMC0, DIV6_MMC1,
+	DIV6_SSP, DIV6_SSPRS,
+	DIV6_NR
+};
+
+static struct clk div6_clks[DIV6_NR] = {
+	[DIV6_SD2]	= SH_CLK_DIV6(&pll1_div2_clk, SD2CKCR, 0),
+	[DIV6_SD3]	= SH_CLK_DIV6(&pll1_div2_clk, SD3CKCR, 0),
+	[DIV6_MMC0]	= SH_CLK_DIV6(&pll1_div2_clk, MMC0CKCR, 0),
+	[DIV6_MMC1]	= SH_CLK_DIV6(&pll1_div2_clk, MMC1CKCR, 0),
+	[DIV6_SSP]	= SH_CLK_DIV6(&pll1_div2_clk, SSPCKCR, 0),
+	[DIV6_SSPRS]	= SH_CLK_DIV6(&pll1_div2_clk, SSPRSCKCR, 0),
+};
+
+/* MSTP */
+enum {
+	MSTP721, MSTP720,
+	MSTP304,
+	MSTP216, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202,
+	MSTP_NR
+};
+
 static struct clk mstp_clks[MSTP_NR] = {
 	[MSTP721] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 21, 0), /* SCIF0 */
 	[MSTP720] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 20, 0), /* SCIF1 */
+	[MSTP304] = SH_CLK_MSTP32(&cp_clk, SMSTPCR3, 4, 0), /* TPU0 */
 	[MSTP216] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 16, 0), /* SCIFB2 */
 	[MSTP207] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 7, 0), /* SCIFB1 */
 	[MSTP206] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 6, 0), /* SCIFB0 */
@@ -64,6 +199,48 @@
 };
 
 static struct clk_lookup lookups[] = {
+
+	/* main clocks */
+	CLKDEV_CON_ID("extal",		&extal_clk),
+	CLKDEV_CON_ID("extal_div2",	&extal_div2_clk),
+	CLKDEV_CON_ID("main",		&main_clk),
+	CLKDEV_CON_ID("pll1",		&pll1_clk),
+	CLKDEV_CON_ID("pll1_div2",	&pll1_div2_clk),
+	CLKDEV_CON_ID("pll3",		&pll3_clk),
+	CLKDEV_CON_ID("zg",		&zg_clk),
+	CLKDEV_CON_ID("zx",		&zx_clk),
+	CLKDEV_CON_ID("zs",		&zs_clk),
+	CLKDEV_CON_ID("hp",		&hp_clk),
+	CLKDEV_CON_ID("i",		&i_clk),
+	CLKDEV_CON_ID("b",		&b_clk),
+	CLKDEV_CON_ID("lb",		&lb_clk),
+	CLKDEV_CON_ID("p",		&p_clk),
+	CLKDEV_CON_ID("cl",		&cl_clk),
+	CLKDEV_CON_ID("m2",		&m2_clk),
+	CLKDEV_CON_ID("imp",		&imp_clk),
+	CLKDEV_CON_ID("rclk",		&rclk_clk),
+	CLKDEV_CON_ID("oscclk",		&oscclk_clk),
+	CLKDEV_CON_ID("zb3",		&zb3_clk),
+	CLKDEV_CON_ID("zb3d2",		&zb3d2_clk),
+	CLKDEV_CON_ID("ddr",		&ddr_clk),
+	CLKDEV_CON_ID("mp",		&mp_clk),
+	CLKDEV_CON_ID("qspi",		&qspi_clk),
+	CLKDEV_CON_ID("cp",		&cp_clk),
+
+	/* DIV4 */
+	CLKDEV_CON_ID("sdh",		&div4_clks[DIV4_SDH]),
+	CLKDEV_CON_ID("sd0",		&div4_clks[DIV4_SD0]),
+	CLKDEV_CON_ID("sd1",		&div4_clks[DIV4_SD1]),
+
+	/* DIV6 */
+	CLKDEV_CON_ID("sd2",		&div6_clks[DIV6_SD2]),
+	CLKDEV_CON_ID("sd3",		&div6_clks[DIV6_SD3]),
+	CLKDEV_CON_ID("mmc0",		&div6_clks[DIV6_MMC0]),
+	CLKDEV_CON_ID("mmc1",		&div6_clks[DIV6_MMC1]),
+	CLKDEV_CON_ID("ssp",		&div6_clks[DIV6_SSP]),
+	CLKDEV_CON_ID("ssprs",		&div6_clks[DIV6_SSPRS]),
+
+	/* MSTP */
 	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]),
 	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]),
 	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP206]),
@@ -74,14 +251,61 @@
 	CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP720]),
 };
 
+#define R8A7790_CLOCK_ROOT(e, m, p0, p1, p30, p31)		\
+	extal_clk.rate	= e * 1000 * 1000;			\
+	main_clk.parent	= m;					\
+	SH_CLK_SET_RATIO(&pll1_clk_ratio, p1 / 2, 1);		\
+	if (mode & MD(19))					\
+		SH_CLK_SET_RATIO(&pll3_clk_ratio, p31, 1);	\
+	else							\
+		SH_CLK_SET_RATIO(&pll3_clk_ratio, p30, 1)
+
+
 void __init r8a7790_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(14) | MD(13))) {
+	case 0:
+		R8A7790_CLOCK_ROOT(15, &extal_clk, 172, 208, 106, 88);
+		break;
+	case MD(13):
+		R8A7790_CLOCK_ROOT(20, &extal_clk, 130, 156, 80, 66);
+		break;
+	case MD(14):
+		R8A7790_CLOCK_ROOT(26, &extal_div2_clk, 200, 240, 122, 102);
+		break;
+	case MD(13) | MD(14):
+		R8A7790_CLOCK_ROOT(30, &extal_div2_clk, 172, 208, 106, 88);
+		break;
+	}
+
+	if (mode & (MD(18)))
+		SH_CLK_SET_RATIO(&lb_clk_ratio, 1, 36);
+	else
+		SH_CLK_SET_RATIO(&lb_clk_ratio, 1, 24);
+
+	if ((mode & (MD(3) | MD(2) | MD(1))) == MD(2))
+		SH_CLK_SET_RATIO(&qspi_clk_ratio, 1, 16);
+	else
+		SH_CLK_SET_RATIO(&qspi_clk_ratio, 1, 20);
+
 	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_mstp_register(mstp_clks, MSTP_NR);
 
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
index 784fbaa..d9fd033 100644
--- a/arch/arm/mach-shmobile/clock-sh73a0.c
+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
@@ -228,6 +228,11 @@
 
 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),
@@ -252,6 +257,101 @@
 	.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,
@@ -450,7 +550,7 @@
 };
 
 enum { MSTP001,
-	MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, MSTP118, MSTP116, MSTP100,
+	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,
@@ -471,6 +571,7 @@
 	[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 */
@@ -513,6 +614,9 @@
 	CLKDEV_CON_ID("r_clk", &r_clk),
 	CLKDEV_DEV_ID("smp_twd", &twd_clk), /* smp_twd */
 
+	/* DIV4 clocks */
+	CLKDEV_DEV_ID("cpufreq-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]),
@@ -604,8 +708,11 @@
 	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
 		ret = clk_register(main_clks[k]);
 
-	if (!ret)
+	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);
diff --git a/arch/arm/mach-shmobile/include/mach/clock.h b/arch/arm/mach-shmobile/include/mach/clock.h
index 76ac612..03e5607 100644
--- a/arch/arm/mach-shmobile/include/mach/clock.h
+++ b/arch/arm/mach-shmobile/include/mach/clock.h
@@ -24,16 +24,16 @@
 }
 
 #define SH_FIXED_RATIO_CLK(name, p, r)		\
-static SH_FIXED_RATIO_CLKg(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);
+	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/include/mach/r8a7778.h b/arch/arm/mach-shmobile/include/mach/r8a7778.h
index 68053fc..ae65b45 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7778.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7778.h
@@ -18,6 +18,7 @@
 #ifndef __ASM_R8A7778_H__
 #define __ASM_R8A7778_H__
 
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/sh_eth.h>
 
 extern void r8a7778_add_standard_devices(void);
@@ -29,5 +30,6 @@
 extern void r8a7778_clock_init(void);
 extern void r8a7778_init_irq_extpin(int irlm);
 extern void r8a7778_pinmux_init(void);
+extern void r8a7778_sdhi_init(int id, struct sh_mobile_sdhi_info *info);
 
 #endif /* __ASM_R8A7778_H__ */
diff --git a/arch/arm/mach-shmobile/setup-r8a7778.c b/arch/arm/mach-shmobile/setup-r8a7778.c
index 1f36ecc..1b9b7f2 100644
--- a/arch/arm/mach-shmobile/setup-r8a7778.c
+++ b/arch/arm/mach-shmobile/setup-r8a7778.c
@@ -81,12 +81,6 @@
 	.clocksource_rating	= 200,
 };
 
-/* Ether */
-static struct resource ether_resources[] = {
-	DEFINE_RES_MEM(0xfde00000, 0x400),
-	DEFINE_RES_IRQ(gic_iid(0x89)),
-};
-
 #define r8a7778_register_tmu(idx)			\
 	platform_device_register_resndata(		\
 		&platform_bus, "sh_tmu", idx,		\
@@ -95,6 +89,20 @@
 		&sh_tmu##idx##_platform_data,		\
 		sizeof(sh_tmu##idx##_platform_data))
 
+/* Ether */
+static struct resource ether_resources[] = {
+	DEFINE_RES_MEM(0xfde00000, 0x400),
+	DEFINE_RES_IRQ(gic_iid(0x89)),
+};
+
+void __init r8a7778_add_ether_device(struct sh_eth_plat_data *pdata)
+{
+	platform_device_register_resndata(&platform_bus, "sh_eth", -1,
+					  ether_resources,
+					  ARRAY_SIZE(ether_resources),
+					  pdata, sizeof(*pdata));
+}
+
 /* PFC/GPIO */
 static struct resource pfc_resources[] = {
 	DEFINE_RES_MEM(0xfffc0000, 0x118),
@@ -139,6 +147,30 @@
 	r8a7778_register_gpio(2);
 	r8a7778_register_gpio(3);
 	r8a7778_register_gpio(4);
+};
+
+/* SDHI */
+static struct resource sdhi_resources[] = {
+	/* SDHI0 */
+	DEFINE_RES_MEM(0xFFE4C000, 0x100),
+	DEFINE_RES_IRQ(gic_iid(0x77)),
+	/* SDHI1 */
+	DEFINE_RES_MEM(0xFFE4D000, 0x100),
+	DEFINE_RES_IRQ(gic_iid(0x78)),
+	/* SDHI2 */
+	DEFINE_RES_MEM(0xFFE4F000, 0x100),
+	DEFINE_RES_IRQ(gic_iid(0x76)),
+};
+
+void __init r8a7778_sdhi_init(int id,
+			      struct sh_mobile_sdhi_info *info)
+{
+	BUG_ON(id < 0 || id > 2);
+
+	platform_device_register_resndata(
+		&platform_bus, "sh_mobile_sdhi", id,
+		sdhi_resources + (2 * id), 2,
+		info, sizeof(*info));
 }
 
 void __init r8a7778_add_standard_devices(void)
@@ -165,14 +197,6 @@
 	r8a7778_register_tmu(1);
 }
 
-void __init r8a7778_add_ether_device(struct sh_eth_plat_data *pdata)
-{
-	platform_device_register_resndata(&platform_bus, "sh_eth", -1,
-					  ether_resources,
-					  ARRAY_SIZE(ether_resources),
-					  pdata, sizeof(*pdata));
-}
-
 static struct renesas_intc_irqpin_config irqpin_platform_data = {
 	.irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
 	.sense_bitfield_width = 2,
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
index 9696f36..96e7ca1 100644
--- a/arch/arm/mach-shmobile/setup-sh73a0.c
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -288,12 +288,7 @@
 };
 
 static struct resource tmu00_resources[] = {
-	[0] = {
-		.name	= "TMU00",
-		.start	= 0xfff60008,
-		.end	= 0xfff60013,
-		.flags	= IORESOURCE_MEM,
-	},
+	[0] = DEFINE_RES_MEM_NAMED(0xfff60008, 0xc, "TMU00"),
 	[1] = {
 		.start	= intcs_evt2irq(0x0e80), /* TMU0_TUNI00 */
 		.flags	= IORESOURCE_IRQ,
@@ -318,12 +313,7 @@
 };
 
 static struct resource tmu01_resources[] = {
-	[0] = {
-		.name	= "TMU01",
-		.start	= 0xfff60014,
-		.end	= 0xfff6001f,
-		.flags	= IORESOURCE_MEM,
-	},
+	[0] = DEFINE_RES_MEM_NAMED(0xfff60014, 0xc, "TMU00"),
 	[1] = {
 		.start	= intcs_evt2irq(0x0ea0), /* TMU0_TUNI01 */
 		.flags	= IORESOURCE_IRQ,
@@ -341,12 +331,7 @@
 };
 
 static struct resource i2c0_resources[] = {
-	[0] = {
-		.name	= "IIC0",
-		.start	= 0xe6820000,
-		.end	= 0xe6820425 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
+	[0] = DEFINE_RES_MEM_NAMED(0xe6820000, 0x426, "IIC0"),
 	[1] = {
 		.start	= gic_spi(167),
 		.end	= gic_spi(170),
@@ -355,12 +340,7 @@
 };
 
 static struct resource i2c1_resources[] = {
-	[0] = {
-		.name	= "IIC1",
-		.start	= 0xe6822000,
-		.end	= 0xe6822425 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
+	[0] = DEFINE_RES_MEM_NAMED(0xe6822000, 0x426, "IIC1"),
 	[1] = {
 		.start	= gic_spi(51),
 		.end	= gic_spi(54),
@@ -369,12 +349,7 @@
 };
 
 static struct resource i2c2_resources[] = {
-	[0] = {
-		.name	= "IIC2",
-		.start	= 0xe6824000,
-		.end	= 0xe6824425 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
+	[0] = DEFINE_RES_MEM_NAMED(0xe6824000, 0x426, "IIC2"),
 	[1] = {
 		.start	= gic_spi(171),
 		.end	= gic_spi(174),
@@ -383,12 +358,7 @@
 };
 
 static struct resource i2c3_resources[] = {
-	[0] = {
-		.name	= "IIC3",
-		.start	= 0xe6826000,
-		.end	= 0xe6826425 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
+	[0] = DEFINE_RES_MEM_NAMED(0xe6826000, 0x426, "IIC3"),
 	[1] = {
 		.start	= gic_spi(183),
 		.end	= gic_spi(186),
@@ -397,12 +367,7 @@
 };
 
 static struct resource i2c4_resources[] = {
-	[0] = {
-		.name	= "IIC4",
-		.start	= 0xe6828000,
-		.end	= 0xe6828425 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
+	[0] = DEFINE_RES_MEM_NAMED(0xe6828000, 0x426, "IIC4"),
 	[1] = {
 		.start	= gic_spi(187),
 		.end	= gic_spi(190),
@@ -623,12 +588,7 @@
 };
 
 static struct resource sh73a0_dmae_resources[] = {
-	{
-		/* Registers including DMAOR and channels including DMARSx */
-		.start  = 0xfe000020,
-		.end    = 0xfe008a00 - 1,
-		.flags  = IORESOURCE_MEM,
-	},
+	DEFINE_RES_MEM(0xfe000020, 0x89e0),
 	{
 		.name	= "error_irq",
 		.start  = gic_spi(129),
@@ -727,18 +687,10 @@
 
 /* Resource order important! */
 static struct resource sh73a0_mpdma_resources[] = {
-	{
-		/* Channel registers and DMAOR */
-		.start	= 0xec618020,
-		.end	= 0xec61828f,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		/* DMARSx */
-		.start	= 0xec619000,
-		.end	= 0xec61900b,
-		.flags	= IORESOURCE_MEM,
-	},
+	/* Channel registers and DMAOR */
+	DEFINE_RES_MEM(0xec618020, 0x270),
+	/* DMARSx */
+	DEFINE_RES_MEM(0xec619000, 0xc),
 	{
 		.name	= "error_irq",
 		.start	= gic_spi(181),
@@ -785,12 +737,7 @@
 
 /* an IPMMU module for ICB */
 static struct resource ipmmu_resources[] = {
-	[0] = {
-		.name	= "IPMMU",
-		.start	= 0xfe951000,
-		.end	= 0xfe9510ff,
-		.flags	= IORESOURCE_MEM,
-	},
+	DEFINE_RES_MEM_NAMED(0xfe951000, 0x100, "IPMMU"),
 };
 
 static const char * const ipmmu_dev_names[] = {
@@ -982,11 +929,17 @@
 			    ARRAY_SIZE(sh73a0_late_devices));
 }
 
+void __init sh73a0_init_delay(void)
+{
+	shmobile_setup_delay(1196, 44, 46); /* Cortex-A9 @ 1196MHz */
+}
+
 /* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
 void __init __weak sh73a0_register_twd(void) { }
 
 void __init sh73a0_earlytimer_init(void)
 {
+	sh73a0_init_delay();
 	sh73a0_clock_init();
 	shmobile_earlytimer_init();
 	sh73a0_register_twd();
@@ -1005,17 +958,14 @@
 
 #ifdef CONFIG_USE_OF
 
-void __init sh73a0_init_delay(void)
-{
-	shmobile_setup_delay(1196, 44, 46); /* Cortex-A9 @ 1196MHz */
-}
-
 static const struct of_dev_auxdata sh73a0_auxdata_lookup[] __initconst = {
 	{},
 };
 
 void __init sh73a0_add_standard_devices_dt(void)
 {
+	struct platform_device_info devinfo = { .name = "cpufreq-cpu0", .id = -1, };
+
 	/* clocks are setup late during boot in the case of DT */
 	sh73a0_clock_init();
 
@@ -1023,6 +973,9 @@
 			     ARRAY_SIZE(sh73a0_devices_dt));
 	of_platform_populate(NULL, of_default_bus_match_table,
 			     sh73a0_auxdata_lookup, NULL);
+
+	/* Instantiate cpufreq-cpu0 */
+	platform_device_register_full(&devinfo);
 }
 
 static const char *sh73a0_boards_compat_dt[] __initdata = {