Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6d9598e2 authored by Magnus Damm's avatar Magnus Damm Committed by Paul Mundt
Browse files

ARM: mach-shmobile: Initial AG5 and AG5EVM support



This patch adds initial support for Renesas SH-Mobile AG5.

At this point the AG5 CPU support is limited to the ARM
core, SCIF serial and a CMT timer together with L2 cache
and the GIC. The AG5EVM board also supports Ethernet.

Future patches will add support for GPIO, INTCS, CPGA
and platform data / driver updates for devices such as
IIC, LCDC, FSI, KEYSC, CEU and SDHI among others.

The code in entry-macro.S will be cleaned up when the
ARM IRQ demux code improvements have been merged.

Depends on the AG5EVM mach-type recently registered but
not yet present in arch/arm/tools/mach-types.

As the AG5EVM board comes with 512MiB memory it is
recommended to turn on HIGHMEM.

Many thanks to Yoshii-san for initial bring up.

Signed-off-by: default avatarMagnus Damm <damm@opensource.se>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 6d72ad35
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -20,6 +20,12 @@ config ARCH_SH7372
	select SH_CLK_CPG
	select ARCH_WANT_OPTIONAL_GPIOLIB

config ARCH_SH73A0
	bool "SH-Mobile AG5 (R8A73A00)"
	select CPU_V7
	select SH_CLK_CPG
	select ARM_GIC

comment "SH-Mobile Board Type"

config MACH_G3EVM
@@ -51,6 +57,10 @@ config AP4EVB_WVGA

endchoice

config MACH_AG5EVM
	bool "AG5EVM board"
	depends on ARCH_SH73A0

comment "SH-Mobile System Configuration"

menu "Memory configuration"
@@ -60,6 +70,7 @@ config MEMORY_START
	default "0x50000000" if MACH_G3EVM
	default "0x40000000" if MACH_G4EVM
	default "0x40000000" if MACH_AP4EVB
	default "0x40000000" if MACH_AG5EVM
	default "0x00000000"
	---help---
	  Tweak this only when porting to a new machine which does not
@@ -71,6 +82,7 @@ config MEMORY_SIZE
	default "0x08000000" if MACH_G3EVM
	default "0x08000000" if MACH_G4EVM
	default "0x10000000" if MACH_AP4EVB
	default "0x20000000" if MACH_AG5EVM
	default "0x04000000"
	help
	  This sets the default memory size assumed by your kernel. It can
+2 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ obj-y := timer.o console.o clock.o pm_runtime.o
obj-$(CONFIG_ARCH_SH7367)	+= setup-sh7367.o clock-sh7367.o intc-sh7367.o
obj-$(CONFIG_ARCH_SH7377)	+= setup-sh7377.o clock-sh7377.o intc-sh7377.o
obj-$(CONFIG_ARCH_SH7372)	+= setup-sh7372.o clock-sh7372.o intc-sh7372.o
obj-$(CONFIG_ARCH_SH73A0)	+= setup-sh73a0.o clock-sh73a0.o

# Pinmux setup
pfc-$(CONFIG_ARCH_SH7367)	:= pfc-sh7367.o
@@ -20,3 +21,4 @@ obj-$(CONFIG_GENERIC_GPIO) += $(pfc-y)
obj-$(CONFIG_MACH_G3EVM)	+= board-g3evm.o
obj-$(CONFIG_MACH_G4EVM)	+= board-g4evm.o
obj-$(CONFIG_MACH_AP4EVB)	+= board-ap4evb.o
obj-$(CONFIG_MACH_AG5EVM)	+= board-ag5evm.o
+159 −0
Original line number Diff line number Diff line
/*
 * arch/arm/mach-shmobile/board-ag5evm.c
 *
 * Copyright (C) 2010  Takashi Yoshii <yoshii.takashi.zj@renesas.com>
 * Copyright (C) 2009  Yoshihiro Shimoda <shimoda.yoshihiro@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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/serial_sci.h>
#include <linux/smsc911x.h>
#include <linux/gpio.h>
#include <mach/hardware.h>
#include <mach/sh73a0.h>
#include <mach/common.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>
#include <asm/hardware/gic.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/traps.h>

static struct resource smsc9220_resources[] = {
	[0] = {
		.start		= 0x14000000,
		.end		= 0x14000000 + SZ_64K - 1,
		.flags		= IORESOURCE_MEM,
	},
	[1] = {
		.start		= gic_spi(33), /* PINT1 */
		.flags		= IORESOURCE_IRQ,
	},
};

static struct smsc911x_platform_config smsc9220_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 eth_device = {
	.name		= "smsc911x",
	.id		= 0,
	.dev  = {
		.platform_data = &smsc9220_platdata,
	},
	.resource	= smsc9220_resources,
	.num_resources	= ARRAY_SIZE(smsc9220_resources),
};

static struct platform_device *ag5evm_devices[] __initdata = {
	&eth_device,
};

static struct map_desc ag5evm_io_desc[] __initdata = {
	/* create a 1:1 entity map for 0xe6xxxxxx
	 * used by CPGA, INTC and PFC.
	 */
	{
		.virtual	= 0xe6000000,
		.pfn		= __phys_to_pfn(0xe6000000),
		.length		= 256 << 20,
		.type		= MT_DEVICE_NONSHARED
	},
};

static void __init ag5evm_map_io(void)
{
	iotable_init(ag5evm_io_desc, ARRAY_SIZE(ag5evm_io_desc));

	/* setup early devices and console here as well */
	sh73a0_add_early_devices();
	shmobile_setup_console();
}

#define PINTC_ADDR	0xe6900000
#define PINTER0A	(PINTC_ADDR + 0xa0)
#define PINTCR0A	(PINTC_ADDR + 0xb0)

void __init ag5evm_init_irq(void)
{
	/* setup PINT: enable PINTA2 as active low */
	__raw_writel(__raw_readl(PINTER0A) | (1<<29), PINTER0A);
	__raw_writew(__raw_readw(PINTCR0A) | (2<<10), PINTCR0A);

	gic_dist_init(0, __io(0xf0001000), 29);
	gic_cpu_init(0, __io(0xf0000100));
}

#define PORT144CR 0xe6052090
#define PORT145CR 0xe6052091

#define PORT154CR 0xe605209a
#define PORT155CR 0xe605209b
#define PORT156CR 0xe605209c
#define PORT157CR 0xe605209d

#define PORTR159_128DR 0xe6056004

static void __init ag5evm_init(void)
{
	/* enable SCIFA2 */
	__raw_writeb(0x12, PORT154CR); /* TXD */
	__raw_writeb(0x22, PORT155CR); /* RXD */
	__raw_writeb(0x12, PORT156CR); /* RTS */
	__raw_writeb(0x22, PORT157CR); /* CTS */

	/* enable SMSC911X */
	__raw_writeb(0x20, PORT144CR); /* PINTA2 */
	__raw_writeb(0x10, PORT145CR); /* RESET */
	__raw_writel(__raw_readl(PORTR159_128DR) & ~(1 << 17), PORTR159_128DR);

#ifdef CONFIG_CACHE_L2X0
	/* Shared attribute override enable, 64K*8way */
	l2x0_init(__io(0xf0100000), 0x00460000, 0xc2000fff);
#endif
	sh73a0_add_standard_devices();
	platform_add_devices(ag5evm_devices, ARRAY_SIZE(ag5evm_devices));
}

static void __init ag5evm_timer_init(void)
{
	sh73a0_clock_init();
	shmobile_timer.init();
	return;
}

struct sys_timer ag5evm_timer = {
	.init	= ag5evm_timer_init,
};

MACHINE_START(AG5EVM, "ag5evm")
	.map_io		= ag5evm_map_io,
	.init_irq	= ag5evm_init_irq,
	.init_machine	= ag5evm_init,
	.timer		= &ag5evm_timer,
MACHINE_END
+101 −0
Original line number Diff line number Diff line
/*
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/sh_clk.h>
#include <mach/common.h>
#include <asm/clkdev.h>

#define SMSTPCR0	0xe6150130
#define SMSTPCR1	0xe6150134
#define SMSTPCR2	0xe6150138
#define SMSTPCR3	0xe615013c
#define SMSTPCR4	0xe6150140
#define SMSTPCR5	0xe6150144

/* Fixed 32 KHz root clock from EXTALR pin */
static struct clk r_clk = {
	.rate           = 32768,
};

/* Temporarily fixed 48 MHz SUB clock */
static struct clk sub_clk = {
	.rate           = 48000000,
};

static struct clk *main_clks[] = {
	&r_clk,
	&sub_clk,
};

enum { MSTP219,
	MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
	MSTP331, MSTP329,
	MSTP_NR };

#define MSTP(_parent, _reg, _bit, _flags) \
	SH_CLK_MSTP32(_parent, _reg, _bit, _flags)

static struct clk mstp_clks[MSTP_NR] = {
	[MSTP219] = MSTP(&sub_clk, SMSTPCR2, 19, 0), /* SCIFA7 */
	[MSTP207] = MSTP(&sub_clk, SMSTPCR2, 7, 0), /* SCIFA5 */
	[MSTP206] = MSTP(&sub_clk, SMSTPCR2, 6, 0), /* SCIFB */
	[MSTP204] = MSTP(&sub_clk, SMSTPCR2, 4, 0), /* SCIFA0 */
	[MSTP203] = MSTP(&sub_clk, SMSTPCR2, 3, 0), /* SCIFA1 */
	[MSTP202] = MSTP(&sub_clk, SMSTPCR2, 2, 0), /* SCIFA2 */
	[MSTP201] = MSTP(&sub_clk, SMSTPCR2, 1, 0), /* SCIFA3 */
	[MSTP200] = MSTP(&sub_clk, SMSTPCR2, 0, 0), /* SCIFA4 */
	[MSTP331] = MSTP(&sub_clk, SMSTPCR3, 31, 0), /* SCIFA6 */
	[MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
};

#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }

static struct clk_lookup lookups[] = {
	/* MSTP32 clocks */
	CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP219]), /* SCIFA7 */
	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */
	CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]), /* SCIFB */
	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */
	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), /* SCIFA1 */
	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */
	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */
	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
	CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */
	CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */
};

void __init sh73a0_clock_init(void)
{
	int k, ret = 0;

	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
		ret = clk_register(main_clks[k]);

	if (!ret)
		ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);

	clkdev_add_table(lookups, ARRAY_SIZE(lookups));

	if (!ret)
		clk_init();
	else
		panic("failed to setup sh73a0 clocks\n");
}
+4 −0
Original line number Diff line number Diff line
@@ -30,4 +30,8 @@ extern void sh7372_pinmux_init(void);
extern struct clk sh7372_extal1_clk;
extern struct clk sh7372_extal2_clk;

extern void sh73a0_add_early_devices(void);
extern void sh73a0_add_standard_devices(void);
extern void sh73a0_clock_init(void);

#endif /* __ARCH_MACH_COMMON_H */
Loading