Commit 4c4d285a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'rmobile-for-linus' of git://github.com/pmundt/linux-sh

SH/R-Mobile updates for 3.3 merge window.

* tag 'rmobile-for-linus' of git://github.com/pmundt/linux-sh: (32 commits)
  arm: mach-shmobile: add a resource name for shdma
  ARM: mach-shmobile: r8a7779 SMP support V3
  ARM: mach-shmobile: Add kota2 defconfig.
  ARM: mach-shmobile: Add marzen defconfig.
  ARM: mach-shmobile: r8a7779 power domain support V2
  ARM: mach-shmobile: Fix up marzen build for recent GIC changes.
  ARM: mach-shmobile: r8a7779 PFC function support
  ARM: mach-shmobile: Flush caches in platform_cpu_die()
  ARM: mach-shmobile: Allow SoC specific CPU kill code
  ARM: mach-shmobile: Fix headsmp.S code to use CPUINIT
  ARM: mach-shmobile: clock-r8a7779: clkz/clkzs support
  ARM: mach-shmobile: clock-r8a7779: add DIV4 clock support
  ARM: mach-shmobile: Marzen LAN89218 support
  ARM: mach-shmobile: Marzen SCIF2/SCIF4 support
  ARM: mach-shmobile: r8a7779 PFC GPIO-only support V2
  ARM: mach-shmobile: r8a7779 and Marzen base support V2
  sh: pfc: Unlock register support
  sh: pfc: Variable bitfield width config register support
  sh: pfc: Add config_reg_helper() function
  sh: pfc: Convert index to field and value pair
  ...
parents 56c8bc3b e64e1b11
CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=16
# CONFIG_UTS_NS is not set
# CONFIG_IPC_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SLAB=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
CONFIG_ARCH_SHMOBILE=y
CONFIG_ARCH_R8A7740=y
CONFIG_MACH_BONITO=y
# CONFIG_SH_TIMER_TMU is not set
CONFIG_AEABI=y
# CONFIG_OABI_COMPAT is not set
CONFIG_FORCE_MAX_ZONEORDER=12
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_CMDLINE="console=ttySC5,115200 earlyprintk=sh-sci.5,115200 ignore_loglevel"
CONFIG_KEXEC=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_SUSPEND is not set
CONFIG_PM_RUNTIME=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
# CONFIG_FIRMWARE_IN_KERNEL is not set
CONFIG_MTD=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_ARM_INTEGRATOR=y
CONFIG_MTD_BLOCK2MTD=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_LOWLEVEL is not set
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_SH_SCI=y
CONFIG_SERIAL_SH_SCI_NR_UARTS=9
CONFIG_SERIAL_SH_SCI_CONSOLE=y
# CONFIG_HW_RANDOM is not set
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_SH_MOBILE=y
CONFIG_GPIO_SYSFS=y
# CONFIG_HWMON is not set
# CONFIG_MFD_SUPPORT is not set
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_UIO=y
CONFIG_UIO_PDRV=y
CONFIG_UIO_PDRV_GENIRQ=y
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY_USER is not set
CONFIG_TMPFS=y
# CONFIG_MISC_FILESYSTEMS is not set
# CONFIG_ENABLE_WARN_DEPRECATED is not set
# CONFIG_ENABLE_MUST_CHECK is not set
# CONFIG_ARM_UNWIND is not set
# CONFIG_ARM_PATCH_PHYS_VIRT is not set
CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=16
CONFIG_CGROUPS=y
CONFIG_CPUSETS=y
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
# CONFIG_IPC_NS is not set
# CONFIG_USER_NS is not set
# CONFIG_PID_NS is not set
CONFIG_SYSCTL_SYSCALL=y
CONFIG_EMBEDDED=y
CONFIG_SLAB=y
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
CONFIG_ARCH_SHMOBILE=y
CONFIG_KEYBOARD_GPIO_POLLED=y
CONFIG_ARCH_SH73A0=y
CONFIG_MACH_KOTA2=y
CONFIG_MEMORY_SIZE=0x1e0000000
# CONFIG_SH_TIMER_TMU is not set
# CONFIG_SWP_EMULATE is not set
CONFIG_CPU_BPREDICT_DISABLE=y
CONFIG_ARM_ERRATA_460075=y
CONFIG_ARM_ERRATA_742230=y
CONFIG_ARM_ERRATA_742231=y
CONFIG_PL310_ERRATA_588369=y
CONFIG_ARM_ERRATA_720789=y
CONFIG_PL310_ERRATA_727915=y
CONFIG_ARM_ERRATA_743622=y
CONFIG_ARM_ERRATA_751472=y
CONFIG_PL310_ERRATA_753970=y
CONFIG_ARM_ERRATA_754322=y
CONFIG_PL310_ERRATA_769419=y
CONFIG_NO_HZ=y
CONFIG_SMP=y
CONFIG_AEABI=y
# CONFIG_OABI_COMPAT is not set
CONFIG_HIGHMEM=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_CMDLINE="console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel"
CONFIG_CMDLINE_FORCE=y
CONFIG_KEXEC=y
CONFIG_CPU_IDLE=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
# CONFIG_INET_DIAG is not set
# CONFIG_IPV6 is not set
CONFIG_CFG80211=y
CONFIG_WIRELESS_EXT_SYSFS=y
CONFIG_MAC80211=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
# CONFIG_BLK_DEV is not set
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CHELSIO is not set
# CONFIG_NET_VENDOR_FARADAY is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_SEEQ is not set
CONFIG_SMSC911X=y
# CONFIG_NET_VENDOR_STMICRO is not set
CONFIG_B43=y
CONFIG_B43_PHY_N=y
CONFIG_B43_DEBUG=y
CONFIG_INPUT_SPARSEKMAP=y
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_SH_KEYSC=y
# CONFIG_INPUT_MOUSE is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_SH_SCI=y
CONFIG_SERIAL_SH_SCI_NR_UARTS=9
CONFIG_SERIAL_SH_SCI_CONSOLE=y
# CONFIG_HW_RANDOM is not set
CONFIG_I2C_SH_MOBILE=y
# CONFIG_HWMON is not set
CONFIG_BCMA=y
CONFIG_BCMA_DEBUG=y
CONFIG_FB=y
CONFIG_FB_SH_MOBILE_LCDC=y
CONFIG_LCD_PLATFORM=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_MMC=y
CONFIG_MMC_SDHI=y
CONFIG_MMC_SH_MMCIF=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_RENESAS_TPU=y
CONFIG_LEDS_TRIGGERS=y
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY_USER is not set
CONFIG_TMPFS=y
# CONFIG_MISC_FILESYSTEMS is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_REDUCED=y
# CONFIG_FTRACE is not set
CONFIG_DEBUG_USER=y
# CONFIG_ARM_PATCH_PHYS_VIRT is not set
CONFIG_EXPERIMENTAL=y
CONFIG_KERNEL_LZMA=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=16
CONFIG_SYSCTL_SYSCALL=y
CONFIG_EMBEDDED=y
CONFIG_SLAB=y
# CONFIG_BLOCK is not set
CONFIG_ARCH_SHMOBILE=y
CONFIG_ARCH_R8A7779=y
CONFIG_MACH_MARZEN=y
CONFIG_MEMORY_START=0x60000000
CONFIG_MEMORY_SIZE=0x10000000
CONFIG_SHMOBILE_TIMER_HZ=1024
# CONFIG_SH_TIMER_CMT is not set
# CONFIG_SWP_EMULATE is not set
CONFIG_ARM_ERRATA_430973=y
CONFIG_ARM_ERRATA_458693=y
CONFIG_ARM_ERRATA_460075=y
CONFIG_ARM_ERRATA_743622=y
CONFIG_ARM_ERRATA_754322=y
CONFIG_NO_HZ=y
CONFIG_SMP=y
# CONFIG_ARM_CPU_TOPOLOGY is not set
CONFIG_AEABI=y
# CONFIG_OABI_COMPAT is not set
CONFIG_HIGHMEM=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_CMDLINE="console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel"
CONFIG_CMDLINE_FORCE=y
CONFIG_KEXEC=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_INET=y
# CONFIG_IPV6 is not set
# CONFIG_WIRELESS is not set
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_STANDALONE is not set
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
# CONFIG_FW_LOADER is not set
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_FARADAY is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_SEEQ is not set
CONFIG_SMC911X=y
CONFIG_SMSC911X=y
# CONFIG_NET_VENDOR_STMICRO is not set
# CONFIG_WLAN is not set
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_SH_SCI=y
CONFIG_SERIAL_SH_SCI_NR_UARTS=6
CONFIG_SERIAL_SH_SCI_CONSOLE=y
# CONFIG_HW_RANDOM is not set
CONFIG_GPIO_SYSFS=y
# CONFIG_HWMON is not set
CONFIG_SSB=y
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_UIO=y
CONFIG_UIO_PDRV_GENIRQ=y
# CONFIG_IOMMU_SUPPORT is not set
# CONFIG_FILE_LOCKING is not set
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY_USER is not set
CONFIG_TMPFS=y
# CONFIG_MISC_FILESYSTEMS is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_REDUCED=y
# CONFIG_FTRACE is not set
CONFIG_DEBUG_USER=y
CONFIG_AVERAGE=y
......@@ -28,6 +28,19 @@ config ARCH_SH73A0
select ARM_GIC
select I2C
config ARCH_R8A7740
bool "R-Mobile A1 (R8A77400)"
select CPU_V7
select SH_CLK_CPG
select ARCH_WANT_OPTIONAL_GPIOLIB
config ARCH_R8A7779
bool "R-Car H1 (R8A77790)"
select CPU_V7
select SH_CLK_CPG
select ARM_GIC
select ARCH_WANT_OPTIONAL_GPIOLIB
comment "SH-Mobile Board Type"
config MACH_G3EVM
......@@ -75,6 +88,16 @@ config MACH_KOTA2
select ARCH_REQUIRE_GPIOLIB
depends on ARCH_SH73A0
config MACH_BONITO
bool "bonito board"
select ARCH_REQUIRE_GPIOLIB
depends on ARCH_R8A7740
config MACH_MARZEN
bool "MARZEN board"
depends on ARCH_R8A7779
select ARCH_REQUIRE_GPIOLIB
comment "SH-Mobile System Configuration"
menu "Memory configuration"
......@@ -83,7 +106,7 @@ config MEMORY_START
hex "Physical memory start address"
default "0x50000000" if MACH_G3EVM
default "0x40000000" if MACH_G4EVM || MACH_AP4EVB || MACH_AG5EVM || \
MACH_MACKEREL
MACH_MACKEREL || MACH_BONITO
default "0x41000000" if MACH_KOTA2
default "0x00000000"
---help---
......@@ -95,7 +118,7 @@ config MEMORY_SIZE
hex "Physical memory size"
default "0x08000000" if MACH_G3EVM
default "0x08000000" if MACH_G4EVM
default "0x20000000" if MACH_AG5EVM
default "0x20000000" if MACH_AG5EVM || MACH_BONITO
default "0x1e000000" if MACH_KOTA2
default "0x10000000" if MACH_AP4EVB || MACH_MACKEREL
default "0x04000000"
......
......@@ -10,12 +10,15 @@ 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 intc-sh73a0.o
obj-$(CONFIG_ARCH_R8A7740) += setup-r8a7740.o clock-r8a7740.o intc-r8a7740.o
obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o clock-r8a7779.o intc-r8a7779.o
# SMP objects
smp-y := platsmp.o headsmp.o
smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o
smp-$(CONFIG_LOCAL_TIMERS) += localtimer.o
smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o
smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o
# Pinmux setup
pfc-y :=
......@@ -23,16 +26,20 @@ pfc-$(CONFIG_ARCH_SH7367) += pfc-sh7367.o
pfc-$(CONFIG_ARCH_SH7377) += pfc-sh7377.o
pfc-$(CONFIG_ARCH_SH7372) += pfc-sh7372.o
pfc-$(CONFIG_ARCH_SH73A0) += pfc-sh73a0.o
pfc-$(CONFIG_ARCH_R8A7740) += pfc-r8a7740.o
pfc-$(CONFIG_ARCH_R8A7779) += pfc-r8a7779.o
# IRQ objects
obj-$(CONFIG_ARCH_SH7367) += entry-intc.o
obj-$(CONFIG_ARCH_SH7377) += entry-intc.o
obj-$(CONFIG_ARCH_SH7372) += entry-intc.o
obj-$(CONFIG_ARCH_R8A7740) += entry-intc.o
# PM objects
obj-$(CONFIG_SUSPEND) += suspend.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_ARCH_SH7372) += pm-sh7372.o sleep-sh7372.o
obj-$(CONFIG_ARCH_R8A7779) += pm-r8a7779.o
# Board objects
obj-$(CONFIG_MACH_G3EVM) += board-g3evm.o
......@@ -41,6 +48,8 @@ obj-$(CONFIG_MACH_AP4EVB) += board-ap4evb.o
obj-$(CONFIG_MACH_AG5EVM) += board-ag5evm.o
obj-$(CONFIG_MACH_MACKEREL) += board-mackerel.o
obj-$(CONFIG_MACH_KOTA2) += board-kota2.o
obj-$(CONFIG_MACH_BONITO) += board-bonito.o
obj-$(CONFIG_MACH_MARZEN) += board-marzen.o
# Framework support
obj-$(CONFIG_SMP) += $(smp-y)
......
This diff is collapsed.
/*
* marzen board 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; 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/gpio.h>
#include <linux/dma-mapping.h>
#include <linux/smsc911x.h>
#include <mach/hardware.h>
#include <mach/r8a7779.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/traps.h>
/* SMSC LAN89218 */
static struct resource smsc911x_resources[] = {
[0] = {
.start = 0x18000000, /* ExCS0 */
.end = 0x180000ff, /* A1->A7 */
.flags = IORESOURCE_MEM,
},
[1] = {
.start = gic_spi(28), /* 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 = 0,
.dev = {
.platform_data = &smsc911x_platdata,
},
.resource = smsc911x_resources,
.num_resources = ARRAY_SIZE(smsc911x_resources),
};
static struct platform_device *marzen_devices[] __initdata = {
&eth_device,
};
static struct map_desc marzen_io_desc[] __initdata = {
/* 2M entity map for 0xf0000000 (MPCORE) */
{
.virtual = 0xf0000000,
.pfn = __phys_to_pfn(0xf0000000),
.length = SZ_2M,
.type = MT_DEVICE_NONSHARED
},
/* 16M entity map for 0xfexxxxxx (DMAC-S/HPBREG/INTC2/LRAM/DBSC) */
{
.virtual = 0xfe000000,
.pfn = __phys_to_pfn(0xfe000000),
.length = SZ_16M,
.type = MT_DEVICE_NONSHARED
},
};
static void __init marzen_map_io(void)
{
iotable_init(marzen_io_desc, ARRAY_SIZE(marzen_io_desc));
}
static void __init marzen_init_early(void)
{
r8a7779_add_early_devices();
/* Early serial console setup is not included here due to
* memory map collisions. The SCIF serial ports in r8a7779
* are difficult to entity 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.
*/
}
static void __init marzen_init(void)
{
r8a7779_pinmux_init();
/* SCIF2 (CN18: DEBUG0) */
gpio_request(GPIO_FN_TX2_C, NULL);
gpio_request(GPIO_FN_RX2_C, NULL);
/* SCIF4 (CN19: DEBUG1) */
gpio_request(GPIO_FN_TX4, NULL);
gpio_request(GPIO_FN_RX4, NULL);
/* LAN89218 */
gpio_request(GPIO_FN_EX_CS0, NULL); /* nCS */
gpio_request(GPIO_FN_IRQ1_B, NULL); /* IRQ + PME */
r8a7779_add_standard_devices();
platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices));
}
static void __init marzen_timer_init(void)
{
r8a7779_clock_init();
shmobile_timer.init();
return;
}
struct sys_timer marzen_timer = {
.init = marzen_timer_init,
};
MACHINE_START(MARZEN, "marzen")
.map_io = marzen_map_io,
.init_early = marzen_init_early,
.nr_irqs = NR_IRQS_LEGACY,
.init_irq = r8a7779_init_irq,
.handle_irq = gic_handle_irq,
.init_machine = marzen_init,
.timer = &marzen_timer,
MACHINE_END
This diff is collapsed.
/*
* 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.
*
* 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 <linux/clkdev.h>
#include <mach/common.h>
#define FRQMR 0xffc80014
#define MSTPCR0 0xffc80030
#define MSTPCR1 0xffc80034
#define MSTPCR3 0xffc8003c
#define MSTPSR1 0xffc80044
#define MSTPSR4 0xffc80048
#define MSTPSR6 0xffc8004c
#define MSTPCR4 0xffc80050
#define MSTPCR5 0xffc80054
#define MSTPCR6 0xffc80058
#define MSTPCR7 0xffc80040
/* 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 = 1500000000,
.mapping = &cpg_mapping,
};
static struct clk *main_clks[] = {
&plla_clk,
};
static int divisors[] = { 0, 0, 0, 6, 8, 12, 16, 0, 24, 32, 36, 0, 0, 0, 0, 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,
};
enum { DIV4_S, DIV4_OUT, DIV4_S4, DIV4_S3, DIV4_S1, DIV4_P, DIV4_NR };
static struct clk div4_clks[DIV4_NR] = {
[DIV4_S] = SH_CLK_DIV4(&plla_clk, FRQMR, 20,
0x0018, CLK_ENABLE_ON_INIT),
[DIV4_OUT] = SH_CLK_DIV4(&plla_clk, FRQMR, 16,
0x0700, CLK_ENABLE_ON_INIT),
[DIV4_S4] = SH_CLK_DIV4(&plla_clk, FRQMR, 12,
0x0040, CLK_ENABLE_ON_INIT),
[DIV4_S3] = SH_CLK_DIV4(&plla_clk, FRQMR, 8,
0x0010, CLK_ENABLE_ON_INIT),
[DIV4_S1] = SH_CLK_DIV4(&plla_clk, FRQMR, 4,
0x0060, CLK_ENABLE_ON_INIT),
[DIV4_P] = SH_CLK_DIV4(&plla_clk, FRQMR, 0,
0x0300, CLK_ENABLE_ON_INIT),
};
enum { MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
MSTP016, MSTP015, MSTP014,
MSTP_NR };
static struct clk mstp_clks[MSTP_NR] = {
[MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0), /* SCIF0 */
[MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0), /* SCIF1 */
[MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0), /* SCIF2 */
[MSTP023] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 23, 0), /* SCIF3 */
[MSTP022] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 22, 0), /* SCIF4 */
[MSTP021] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 21, 0), /* SCIF5 */
[MSTP016] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 16, 0), /* TMU0 */
[MSTP015] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 15, 0), /* TMU1 */
[MSTP014] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 14, 0), /* TMU2 */
};
static unsigned long mul4_recalc(struct clk *clk)
{
return clk->parent->rate * 4;
}
static struct clk_ops mul4_clk_ops = {
.recalc = mul4_recalc,
};
struct clk clkz_clk = {
.ops = &mul4_clk_ops,
.parent = &div4_clks[DIV4_S],
};
struct clk clkzs_clk = {
/* clks x 4 / 4 = clks */
.parent = &div4_clks[DIV4_S],
};
static struct clk *late_main_clks[] = {
&clkz_clk,
&clkzs_clk,
};
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", &div4_clks[DIV4_S]),
CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_OUT]),
CLKDEV_CON_ID("shyway4_clk", &div4_clks[DIV4_S4]),
CLKDEV_CON_ID("shyway3_clk", &div4_clks[DIV4_S3]),
CLKDEV_CON_ID("shyway1_clk", &div4_clks[DIV4_S1]),
CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
/* MSTP32 clocks */
CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP016]), /* TMU00 */
CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP016]), /* TMU01 */
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 */
};
void __init r8a7779_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_div4_register(div4_clks, DIV4_NR, &div4_table);
if (!ret)
ret = sh_clk_mstp32_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)
clk_init();
else
panic("failed to setup r8a7779 clocks\n");
}
......@@ -14,7 +14,7 @@
#include <linux/init.h>
#include <asm/memory.h>
__INIT
__CPUINIT
/*
* Reset vector for secondary CPUs.
......
......@@ -12,14 +12,43 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/smp.h>
#include <linux/cpumask.h>
#include <linux/delay.h>
#include <mach/common.h>
#include <asm/cacheflush.h>
static cpumask_t dead_cpus;
int platform_cpu_kill(unsigned int cpu)
{
return 1;
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 (cpumask_test_cpu(cpu, &dead_cpus))
return shmobile_platform_cpu_kill(cpu);
mdelay(1);
}
return 0;
}
void platform_cpu_die(unsigned int cpu)
{
/* hardware shutdown code running on the CPU that is being offlined */
flush_cache_all();
dsb();
/* notify platform_cpu_kill() that hardware shutdown is finished */
cpumask_set_cpu(cpu, &dead_cpus);
/* wait for SoC code in platform_cpu_kill() to shut off CPU core
* power. CPU bring up starts from the reset vector.
*/
while (1) {
/*
* here's the WFI
......@@ -33,6 +62,7 @@ void platform_cpu_die(unsigned int cpu)
int platform_cpu_disable(unsigned int cpu)
{
cpumask_clear_cpu(cpu, &dead_cpus);
/*
* we don't allow CPU 0 to be shutdown (it is still too special
* e.g. clock tick interrupts)
......
......@@ -4,6 +4,7 @@
extern struct sys_timer shmobile_timer;
extern void shmobile_setup_console(void);
extern void shmobile_secondary_vector(void);
extern int shmobile_platform_cpu_kill(unsigned int cpu);
struct clk;
extern int clk_init(void);
extern void shmobile_handle_irq_intc(struct pt_regs *);
......@@ -54,4 +55,23 @@ extern void sh73a0_secondary_init(unsigned int cpu);
extern int sh73a0_boot_secondary(unsigned int cpu);
extern void sh73a0_smp_prepare_cpus(void);
extern void r8a7740_init_irq(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 r8a7779_init_irq(void);
extern void r8a7779_add_early_devices(void);
extern void r8a7779_add_standard_devices(void);
extern void r8a7779_clock_init(void);
extern void r8a7779_pinmux_init(void);
extern void r8a7779_pm_init(void);
extern unsigned int r8a7779_get_core_count(void);
extern int r8a7779_platform_cpu_kill(unsigned int cpu);
extern void r8a7779_secondary_init(unsigned int cpu);
extern int r8a7779_boot_secondary(unsigned int cpu);
extern void r8a7779_smp_prepare_cpus(void);
#endif /* __ARCH_MACH_COMMON_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* r8a7779 processor support - INTC hardware block
*
* 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.
*
* 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/io.h>
#include <mach/common.h>
#include <mach/intc.h>
#include <mach/r8a7779.h>
#include <asm/hardware/gic.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#define INT2SMSKCR0 0xfe7822a0
#define INT2SMSKCR1 0xfe7822a4
#define INT2SMSKCR2 0xfe7822a8
#define INT2SMSKCR3 0xfe7822ac
#define INT2SMSKCR4 0xfe7822b0
static int r8a7779_set_wake(struct irq_data *data, unsigned int on)
{
return 0; /* always allow wakeup */
}
void __init r8a7779_init_irq(void)
{
void __iomem *gic_dist_base = __io(0xf0001000);
void __iomem *gic_cpu_base = __io(0xf0000100);
/* use GIC to handle interrupts */
gic_init(0, 29, gic_dist_base, gic_cpu_base);
gic_arch_extn.irq_set_wake = r8a7779_set_wake;
/* 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);
}
This diff is collapsed.
This diff is collapsed.
......@@ -22,12 +22,16 @@
#include <mach/common.h>
#define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2())
#define is_r8a7779() machine_is_marzen()
static unsigned int __init shmobile_smp_get_core_count(void)
{
if (is_sh73a0())
return sh73a0_get_core_count();
if (is_r8a7779())
return r8a7779_get_core_count();
return 1;
}
......@@ -35,6 +39,17 @@ static void __init shmobile_smp_prepare_cpus(void)
{
if (is_sh73a0())
sh73a0_smp_prepare_cpus();
if (is_r8a7779())
r8a7779_smp_prepare_cpus();
}
int shmobile_platform_cpu_kill(unsigned int cpu)
{
if (is_r8a7779())
return r8a7779_platform_cpu_kill(cpu);
return 1;
}
void __cpuinit platform_secondary_init(unsigned int cpu)
......@@ -43,6 +58,9 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
if (is_sh73a0())
sh73a0_secondary_init(cpu);
if (is_r8a7779())
r8a7779_secondary_init(cpu);
}
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
......@@ -50,6 +68,9 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
if (is_sh73a0())
return sh73a0_boot_secondary(cpu);
if (is_r8a7779())
return r8a7779_boot_secondary(cpu);
return -ENOSYS;
}
......
/*
* 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/platform_device.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/console.h>
#include <asm/system.h>
#include <asm/io.h>
#include <mach/common.h>
#include <mach/r8a7779.h>
static void __iomem *r8a7779_sysc_base;
/* SYSC */
#define SYSCSR 0x00
#define SYSCISR 0x04
#define SYSCISCR 0x08
#define SYSCIER 0x0c
#define SYSCIMR 0x10
#define PWRSR0 0x40
#define PWRSR1 0x80
#define PWRSR2 0xc0
#define PWRSR3 0x100
#define PWRSR4 0x140
#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
#if defined(CONFIG_PM) || defined(CONFIG_SMP)
static DEFINE_SPINLOCK(r8a7779_sysc_lock); /* SMP CPUs + I/O devices */
static int r8a7779_sysc_pwr_on_off(struct r8a7779_pm_ch *r8a7779_ch,
int sr_bit, int reg_offs)
{
int k;
for (k = 0; k < SYSCSR_RETRIES; k++) {
if (ioread32(r8a7779_sysc_base + SYSCSR) & (1 << sr_bit))
break;
udelay(SYSCSR_DELAY_US);
}
if (k == SYSCSR_RETRIES)
return -EAGAIN;
iowrite32(1 << r8a7779_ch->chan_bit,
r8a7779_sysc_base + r8a7779_ch->chan_offs + reg_offs);
return 0;
}
static int r8a7779_sysc_pwr_off(struct r8a7779_pm_ch *r8a7779_ch)
{
return r8a7779_sysc_pwr_on_off(r8a7779_ch, 0, PWROFFCR_OFFS);
}
static int r8a7779_sysc_pwr_on(struct r8a7779_pm_ch *r8a7779_ch)
{
return r8a7779_sysc_pwr_on_off(r8a7779_ch, 1, PWRONCR_OFFS);
}
static int r8a7779_sysc_update(struct r8a7779_pm_ch *r8a7779_ch,
int (*on_off_fn)(struct r8a7779_pm_ch *))
{
unsigned int isr_mask = 1 << r8a7779_ch->isr_bit;
unsigned int chan_mask = 1 << r8a7779_ch->chan_bit;
unsigned int status;
unsigned long flags;
int ret = 0;
int k;
spin_lock_irqsave(&r8a7779_sysc_lock, flags);
iowrite32(isr_mask, r8a7779_sysc_base + SYSCISCR);
do {
ret = on_off_fn(r8a7779_ch);
if (ret)
goto out;
status = ioread32(r8a7779_sysc_base +
r8a7779_ch->chan_offs + PWRER_OFFS);
} while (status & chan_mask);
for (k = 0; k < SYSCISR_RETRIES; k++) {
if (ioread32(r8a7779_sysc_base + SYSCISR) & isr_mask)
break;
udelay(SYSCISR_DELAY_US);
}
if (k == SYSCISR_RETRIES)
ret = -EIO;
iowrite32(isr_mask, r8a7779_sysc_base + SYSCISCR);
out:
spin_unlock_irqrestore(&r8a7779_sysc_lock, flags);
pr_debug("r8a7779 power domain %d: %02x %02x %02x %02x %02x -> %d\n",
r8a7779_ch->isr_bit, ioread32(r8a7779_sysc_base + PWRSR0),
ioread32(r8a7779_sysc_base + PWRSR1),
ioread32(r8a7779_sysc_base + PWRSR2),
ioread32(r8a7779_sysc_base + PWRSR3),
ioread32(r8a7779_sysc_base + PWRSR4), ret);
return ret;
}
int r8a7779_sysc_power_down(struct r8a7779_pm_ch *r8a7779_ch)
{
return r8a7779_sysc_update(r8a7779_ch, r8a7779_sysc_pwr_off);
}
int r8a7779_sysc_power_up(struct r8a7779_pm_ch *r8a7779_ch)
{
return r8a7779_sysc_update(r8a7779_ch, r8a7779_sysc_pwr_on);
}
static void __init r8a7779_sysc_init(void)
{
r8a7779_sysc_base = ioremap_nocache(0xffd85000, PAGE_SIZE);
if (!r8a7779_sysc_base)
panic("unable to ioremap r8a7779 SYSC hardware block\n");
/* enable all interrupt sources, but do not use interrupt handler */
iowrite32(0x0131000e, r8a7779_sysc_base + SYSCIER);
iowrite32(0, r8a7779_sysc_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 r8a7779_sysc_power_down(to_r8a7779_ch(genpd));
}
static int pd_power_up(struct generic_pm_domain *genpd)
{
return r8a7779_sysc_power_up(to_r8a7779_ch(genpd));
}
static bool pd_is_off(struct generic_pm_domain *genpd)
{
struct r8a7779_pm_ch *r8a7779_ch = to_r8a7779_ch(genpd);
unsigned int st;
st = ioread32(r8a7779_sysc_base + r8a7779_ch->chan_offs + PWRSR_OFFS);
if (st & (1 << r8a7779_ch->chan_bit))
return true;
return false;
}
static bool pd_active_wakeup(struct device *dev)
{
return true;
}
void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd)
{
struct generic_pm_domain *genpd = &r8a7779_pd->genpd;
pm_genpd_init(genpd, NULL, false);
genpd->dev_ops.stop = pm_clk_suspend;
genpd->dev_ops.start = pm_clk_resume;
genpd->dev_ops.active_wakeup = pd_active_wakeup;
genpd->dev_irq_safe = true;
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);
}
void r8a7779_add_device_to_domain(struct r8a7779_pm_domain *r8a7779_pd,
struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
pm_genpd_add_device(&r8a7779_pd->genpd, dev);
if (pm_clk_no_clocks(dev))
pm_clk_add(dev, NULL);
}
struct r8a7779_pm_domain r8a7779_sh4a = {
.ch = {
.chan_offs = 0x80, /* PWRSR1 .. PWRER1 */
.isr_bit = 16, /* SH4A */
}
};
struct r8a7779_pm_domain r8a7779_sgx = {
.ch = {
.chan_offs = 0xc0, /* PWRSR2 .. PWRER2 */
.isr_bit = 20, /* SGX */
}
};
struct r8a7779_pm_domain r8a7779_vdp1 = {
.ch = {
.chan_offs = 0x100, /* PWRSR3 .. PWRER3 */
.isr_bit = 21, /* VDP */
}
};
struct r8a7779_pm_domain r8a7779_impx3 = {
.ch = {
.chan_offs = 0x140, /* PWRSR4 .. PWRER4 */
.isr_bit = 24, /* IMP */
}
};
#endif /* CONFIG_PM */
void __init r8a7779_pm_init(void)
{
static int once;
if (!once++)
r8a7779_sysc_init();
}
/*
* 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.
*
* 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/delay.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/serial_sci.h>
#include <linux/sh_timer.h>
#include <mach/r8a7740.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
/* SCIFA0 */
static struct plat_sci_port scif0_platform_data = {
.mapbase = 0xe6c40000,
.flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIFA,
.irqs = SCIx_IRQ_MUXED(evt2irq(0x0c00)),
};
static struct platform_device scif0_device = {
.name = "sh-sci",
.id = 0,
.dev = {
.platform_data = &scif0_platform_data,
},
};
/* SCIFA1 */
static struct plat_sci_port scif1_platform_data = {
.mapbase = 0xe6c50000,
.flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIFA,
.irqs = SCIx_IRQ_MUXED(evt2irq(0x0c20)),
};
static struct platform_device scif1_device = {
.name = "sh-sci",
.id = 1,
.dev = {
.platform_data = &scif1_platform_data,
},
};
/* SCIFA2 */
static struct plat_sci_port scif2_platform_data = {
.mapbase = 0xe6c60000,
.flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIFA,
.irqs = SCIx_IRQ_MUXED(evt2irq(0x0c40)),
};
static struct platform_device scif2_device = {
.name = "sh-sci",
.id = 2,
.dev = {
.platform_data = &scif2_platform_data,
},
};
/* SCIFA3 */
static struct plat_sci_port scif3_platform_data = {
.mapbase = 0xe6c70000,
.flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIFA,
.irqs = SCIx_IRQ_MUXED(evt2irq(0x0c60)),
};
static struct platform_device scif3_device = {
.name = "sh-sci",
.id = 3,
.dev = {
.platform_data = &scif3_platform_data,
},
};
/* SCIFA4 */
static struct plat_sci_port scif4_platform_data = {
.mapbase = 0xe6c80000,
.flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIFA,
.irqs = SCIx_IRQ_MUXED(evt2irq(0x0d20)),
};
static struct platform_device scif4_device = {
.name = "sh-sci",
.id = 4,
.dev = {
.platform_data = &scif4_platform_data,
},
};
/* SCIFA5 */
static struct plat_sci_port scif5_platform_data = {
.mapbase = 0xe6cb0000,
.flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIFA,
.irqs = SCIx_IRQ_MUXED(evt2irq(0x0d40)),
};
static struct platform_device scif5_device = {
.name = "sh-sci",
.id = 5,
.dev = {
.platform_data = &scif5_platform_data,
},
};
/* SCIFA6 */
static struct plat_sci_port scif6_platform_data = {
.mapbase = 0xe6cc0000,
.flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIFA,
.irqs = SCIx_IRQ_MUXED(evt2irq(0x04c0)),
};
static struct platform_device scif6_device = {
.name = "sh-sci",
.id = 6,
.dev = {
.platform_data = &scif6_platform_data,
},
};
/* SCIFA7 */
static struct plat_sci_port scif7_platform_data = {
.mapbase = 0xe6cd0000,
.flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIFA,
.irqs = SCIx_IRQ_MUXED(evt2irq(0x04e0)),
};
static struct platform_device scif7_device = {
.name = "sh-sci",
.id = 7,
.dev = {
.platform_data = &scif7_platform_data,
},
};
/* SCIFB */
static struct plat_sci_port scifb_platform_data = {
.mapbase = 0xe6c30000,
.flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIFB,
.irqs = SCIx_IRQ_MUXED(evt2irq(0x0d60)),
};
static struct platform_device scifb_device = {
.name = "sh-sci",
.id = 8,
.dev = {
.platform_data = &scifb_platform_data,
},
};
/* CMT */
static struct sh_timer_config cmt10_platform_data = {
.name = "CMT10",
.channel_offset = 0x10,
.timer_bit = 0,
.clockevent_rating = 125,
.clocksource_rating = 125,
};
static struct resource cmt10_resources[] = {
[0] = {
.name = "CMT10",
.start = 0xe6138010,
.end = 0xe613801b,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = evt2irq(0x0b00),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device cmt10_device = {
.name = "sh_cmt",
.id = 10,
.dev = {
.platform_data = &cmt10_platform_data,
},
.resource = cmt10_resources,
.num_resources = ARRAY_SIZE(cmt10_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,
&scifb_device,
&cmt10_device,
};
/* I2C */
static struct resource i2c0_resources[] = {
[0] = {
.name = "IIC0",
.start = 0xfff20000,
.end = 0xfff20425 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = intcs_evt2irq(0xe00),
.end = intcs_evt2irq(0xe60),
.flags = IORESOURCE_IRQ,
},
};
static struct resource i2c1_resources[] = {
[0] = {
.name = "IIC1",
.start = 0xe6c20000,
.end = 0xe6c20425 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = evt2irq(0x780), /* IIC1_ALI1 */
.end = evt2irq(0x7e0), /* 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 platform_device *r8a7740_late_devices[] __initdata = {
&i2c0_device,
&i2c1_device,
};
#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 */
mdelay(100);
i2c_write(reg, ICCR, 0x01);
i2c_read(reg, ICCR);
i2c_write(reg, ICSTART, 0x00);
i2c_read(reg, ICSTART);
i2c_write(reg, ICCR, 0x10);
mdelay(100);
i2c_write(reg, ICCR, 0x00);
mdelay(100);
i2c_write(reg, ICCR, 0x10);
mdelay(100);
iounmap(reg);
}
void __init r8a7740_add_standard_devices(void)
{
/* I2C work-around */
r8a7740_i2c_workaround(&i2c0_device);
r8a7740_i2c_workaround(&i2c1_device);
platform_add_devices(r8a7740_early_devices,
ARRAY_SIZE(r8a7740_early_devices));
platform_add_devices(r8a7740_late_devices,
ARRAY_SIZE(r8a7740_late_devices));
}
void __init r8a7740_add_early_devices(void)
{
early_platform_add_devices(r8a7740_early_devices,
ARRAY_SIZE(r8a7740_early_devices));
}
/*
* r8a7779 processor 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; 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/input.h>
#include <linux/io.h>
#include <linux/serial_sci.h>
#include <linux/sh_intc.h>
#include <linux/sh_timer.h>
#include <mach/hardware.h>
#include <mach/r8a7779.h>
#include <mach/common.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
static struct plat_sci_port scif0_platform_data = {
.mapbase = 0xffe40000,
.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
.irqs = { gic_spi(88), gic_spi(88),
gic_spi(88), gic_spi(88) },
};
static struct platform_device scif0_device = {
.name = "sh-sci",
.id = 0,
.dev = {
.platform_data = &scif0_platform_data,
},
};
static struct plat_sci_port scif1_platform_data = {
.mapbase = 0xffe41000,
.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
.irqs = { gic_spi(89), gic_spi(89),
gic_spi(89), gic_spi(89) },
};
static struct platform_device scif1_device = {
.name = "sh-sci",
.id = 1,
.dev = {
.platform_data = &scif1_platform_data,
},
};
static struct plat_sci_port scif2_platform_data = {
.mapbase = 0xffe42000,
.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
.irqs = { gic_spi(90), gic_spi(90),
gic_spi(90), gic_spi(90) },
};
static struct platform_device scif2_device = {
.name = "sh-sci",
.id = 2,
.dev = {
.platform_data = &scif2_platform_data,
},
};
static struct plat_sci_port scif3_platform_data = {
.mapbase = 0xffe43000,
.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
.irqs = { gic_spi(91), gic_spi(91),
gic_spi(91), gic_spi(91) },
};
static struct platform_device scif3_device = {
.name = "sh-sci",
.id = 3,
.dev = {
.platform_data = &scif3_platform_data,
},
};
static struct plat_sci_port scif4_platform_data = {
.mapbase = 0xffe44000,
.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
.irqs = { gic_spi(92), gic_spi(92),
gic_spi(92), gic_spi(92) },
};
static struct platform_device scif4_device = {
.name = "sh-sci",
.id = 4,
.dev = {
.platform_data = &scif4_platform_data,
},
};
static struct plat_sci_port scif5_platform_data = {
.mapbase = 0xffe45000,
.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
.irqs = { gic_spi(93), gic_spi(93),
gic_spi(93), gic_spi(93) },
};
static struct platform_device scif5_device = {
.name = "sh-sci",
.id = 5,
.dev = {
.platform_data = &scif5_platform_data,
},
};
/* TMU */
static struct sh_timer_config tmu00_platform_data = {
.name = "TMU00",
.channel_offset = 0x4,
.timer_bit = 0,
.clockevent_rating = 200,
};
static struct resource tmu00_resources[] = {
[0] = {
.name = "TMU00",
.start = 0xffd80008,
.end = 0xffd80013,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = gic_spi(32),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device tmu00_device = {
.name = "sh_tmu",
.id = 0,
.dev = {
.platform_data = &tmu00_platform_data,
},
.resource = tmu00_resources,
.num_resources = ARRAY_SIZE(tmu00_resources),
};
static struct sh_timer_config tmu01_platform_data = {
.name = "TMU01",
.channel_offset = 0x10,
.timer_bit = 1,
.clocksource_rating = 200,
};
static struct resource tmu01_resources[] = {
[0] = {
.name = "TMU01",
.start = 0xffd80014,
.end = 0xffd8001f,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = gic_spi(33),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device tmu01_device = {
.name = "sh_tmu",
.id = 1,
.dev = {
.platform_data = &tmu01_platform_data,
},
.resource = tmu01_resources,
.num_resources = ARRAY_SIZE(tmu01_resources),
};
static struct platform_device *r8a7779_early_devices[] __initdata = {
&scif0_device,
&scif1_device,
&scif2_device,
&scif3_device,
&scif4_device,
&scif5_device,
&tmu00_device,
&tmu01_device,
};
static struct platform_device *r8a7779_late_devices[] __initdata = {
};
void __init r8a7779_add_standard_devices(void)
{
r8a7779_pm_init();
r8a7779_init_pm_domain(&r8a7779_sh4a);
r8a7779_init_pm_domain(&r8a7779_sgx);
r8a7779_init_pm_domain(&r8a7779_vdp1);
r8a7779_init_pm_domain(&r8a7779_impx3);
platform_add_devices(r8a7779_early_devices,
ARRAY_SIZE(r8a7779_early_devices));
platform_add_devices(r8a7779_late_devices,
ARRAY_SIZE(r8a7779_late_devices));
}
void __init r8a7779_add_early_devices(void)
{
early_platform_add_devices(r8a7779_early_devices,
ARRAY_SIZE(r8a7779_early_devices));
}
......@@ -504,7 +504,7 @@ static struct resource sh7372_dmae0_resources[] = {
.flags = IORESOURCE_MEM,
},
{
/* DMA error IRQ */
.name = "error_irq",
.start = evt2irq(0x20c0),
.end = evt2irq(0x20c0),
.flags = IORESOURCE_IRQ,
......@@ -532,7 +532,7 @@ static struct resource sh7372_dmae1_resources[] = {
.flags = IORESOURCE_MEM,
},
{
/* DMA error IRQ */
.name = "error_irq",
.start = evt2irq(0x21c0),
.end = evt2irq(0x21c0),
.flags = IORESOURCE_IRQ,
......@@ -560,7 +560,7 @@ static struct resource sh7372_dmae2_resources[] = {
.flags = IORESOURCE_MEM,
},
{
/* DMA error IRQ */
.name = "error_irq",
.start = evt2irq(0x22c0),
.end = evt2irq(0x22c0),
.flags = IORESOURCE_IRQ,
......
......@@ -607,7 +607,7 @@ static struct resource sh73a0_dmae_resources[] = {
.flags = IORESOURCE_MEM,
},
{
/* DMA error IRQ */
.name = "error_irq",
.start = gic_spi(129),
.end = gic_spi(129),
.flags = IORESOURCE_IRQ,
......
/*
* 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.
*
* 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/smp.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <mach/common.h>
#include <mach/r8a7779.h>
#include <asm/smp_scu.h>
#include <asm/smp_twd.h>
#include <asm/hardware/gic.h>
#define AVECR 0xfe700040
static struct r8a7779_pm_ch r8a7779_ch_cpu1 = {
.chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
.chan_bit = 1, /* ARM1 */
.isr_bit = 1, /* ARM1 */
};
static struct r8a7779_pm_ch r8a7779_ch_cpu2 = {
.chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
.chan_bit = 2, /* ARM2 */
.isr_bit = 2, /* ARM2 */
};
static struct r8a7779_pm_ch r8a7779_ch_cpu3 = {
.chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
.chan_bit = 3, /* ARM3 */
.isr_bit = 3, /* ARM3 */
};
static struct r8a7779_pm_ch *r8a7779_ch_cpu[4] = {
[1] = &r8a7779_ch_cpu1,
[2] = &r8a7779_ch_cpu2,
[3] = &r8a7779_ch_cpu3,
};
static void __iomem *scu_base_addr(void)
{
return (void __iomem *)0xf0000000;
}
static DEFINE_SPINLOCK(scu_lock);
static unsigned long tmp;
static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
{
void __iomem *scu_base = scu_base_addr();
spin_lock(&scu_lock);
tmp = __raw_readl(scu_base + 8);
tmp &= ~clr;
tmp |= set;
spin_unlock(&scu_lock);
/* disable cache coherency after releasing the lock */
__raw_writel(tmp, scu_base + 8);
}
unsigned int __init r8a7779_get_core_count(void)
{
void __iomem *scu_base = scu_base_addr();
#ifdef CONFIG_HAVE_ARM_TWD
/* twd_base needs to be initialized before percpu_timer_setup() */
twd_base = (void __iomem *)0xf0000600;
#endif
return scu_get_core_count(scu_base);
}
int r8a7779_platform_cpu_kill(unsigned int cpu)
{
struct r8a7779_pm_ch *ch = NULL;
int ret = -EIO;
cpu = cpu_logical_map(cpu);
/* disable cache coherency */
modify_scu_cpu_psr(3 << (cpu * 8), 0);
if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
ch = r8a7779_ch_cpu[cpu];
if (ch)
ret = r8a7779_sysc_power_down(ch);
return ret ? ret : 1;
}
void __cpuinit r8a7779_secondary_init(unsigned int cpu)
{
gic_secondary_init(0);
}
int __cpuinit r8a7779_boot_secondary(unsigned int cpu)
{
struct r8a7779_pm_ch *ch = NULL;
int ret = -EIO;
cpu = cpu_logical_map(cpu);
/* enable cache coherency */
modify_scu_cpu_psr(0, 3 << (cpu * 8));
if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
ch = r8a7779_ch_cpu[cpu];
if (ch)
ret = r8a7779_sysc_power_up(ch);
return ret;
}
void __init r8a7779_smp_prepare_cpus(void)
{
int cpu = cpu_logical_map(0);
scu_enable(scu_base_addr());
/* Map the reset vector (in headsmp.S) */
__raw_writel(__pa(shmobile_secondary_vector), __io(AVECR));
/* enable cache coherency on CPU0 */
modify_scu_cpu_psr(0, 3 << (cpu * 8));
r8a7779_pm_init();
/* power off secondary CPUs */
r8a7779_platform_cpu_kill(1);
r8a7779_platform_cpu_kill(2);
r8a7779_platform_cpu_kill(3);
}
......@@ -135,6 +135,19 @@ static void gpio_write_raw_reg(void __iomem *mapped_reg,
BUG();
}
static int gpio_read_bit(struct pinmux_data_reg *dr,
unsigned long in_pos)
{
unsigned long pos;
pos = dr->reg_width - (in_pos + 1);
pr_debug("read_bit: addr = %lx, pos = %ld, "
"r_width = %ld\n", dr->reg, pos, dr->reg_width);
return (gpio_read_raw_reg(dr->mapped_reg, dr->reg_width) >> pos) & 1;
}
static void gpio_write_bit(struct pinmux_data_reg *dr,
unsigned long in_pos, unsigned long value)
{
......@@ -154,51 +167,69 @@ static void gpio_write_bit(struct pinmux_data_reg *dr,
gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow);
}
static int gpio_read_reg(void __iomem *mapped_reg, unsigned long reg_width,
unsigned long field_width, unsigned long in_pos,
unsigned long reg)
static void config_reg_helper(struct pinmux_info *gpioc,
struct pinmux_cfg_reg *crp,
unsigned long in_pos,
void __iomem **mapped_regp,
unsigned long *maskp,
unsigned long *posp)
{
unsigned long data, mask, pos;
int k;
data = 0;
mask = (1 << field_width) - 1;
pos = reg_width - ((in_pos + 1) * field_width);
*mapped_regp = pfc_phys_to_virt(gpioc, crp->reg);
pr_debug("read_reg: addr = %lx, pos = %ld, "
if (crp->field_width) {
*maskp = (1 << crp->field_width) - 1;
*posp = crp->reg_width - ((in_pos + 1) * crp->field_width);
} else {
*maskp = (1 << crp->var_field_width[in_pos]) - 1;
*posp = crp->reg_width;
for (k = 0; k <= in_pos; k++)
*posp -= crp->var_field_width[k];
}
}
static int read_config_reg(struct pinmux_info *gpioc,
struct pinmux_cfg_reg *crp,
unsigned long field)
{
void __iomem *mapped_reg;
unsigned long mask, pos;
config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos);
pr_debug("read_reg: addr = %lx, field = %ld, "
"r_width = %ld, f_width = %ld\n",
reg, pos, reg_width, field_width);
crp->reg, field, crp->reg_width, crp->field_width);
data = gpio_read_raw_reg(mapped_reg, reg_width);
return (data >> pos) & mask;
return (gpio_read_raw_reg(mapped_reg, crp->reg_width) >> pos) & mask;
}
static void gpio_write_reg(void __iomem *mapped_reg, unsigned long reg_width,
unsigned long field_width, unsigned long in_pos,
unsigned long value, unsigned long reg)
static void write_config_reg(struct pinmux_info *gpioc,
struct pinmux_cfg_reg *crp,
unsigned long field, unsigned long value)
{
unsigned long mask, pos;
void __iomem *mapped_reg;
unsigned long mask, pos, data;
mask = (1 << field_width) - 1;
pos = reg_width - ((in_pos + 1) * field_width);
config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos);
pr_debug("write_reg addr = %lx, value = %ld, pos = %ld, "
pr_debug("write_reg addr = %lx, value = %ld, field = %ld, "
"r_width = %ld, f_width = %ld\n",
reg, value, pos, reg_width, field_width);
crp->reg, value, field, crp->reg_width, crp->field_width);
mask = ~(mask << pos);
value = value << pos;
switch (reg_width) {
case 8:
iowrite8((ioread8(mapped_reg) & mask) | value, mapped_reg);
break;
case 16:
iowrite16((ioread16(mapped_reg) & mask) | value, mapped_reg);
break;
case 32:
iowrite32((ioread32(mapped_reg) & mask) | value, mapped_reg);
break;
}
data = gpio_read_raw_reg(mapped_reg, crp->reg_width);
data &= mask;
data |= value;
if (gpioc->unlock_reg)
gpio_write_raw_reg(pfc_phys_to_virt(gpioc, gpioc->unlock_reg),
32, ~data);
gpio_write_raw_reg(mapped_reg, crp->reg_width, data);
}
static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
......@@ -274,12 +305,13 @@ static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio,
}
static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
struct pinmux_cfg_reg **crp, int *indexp,
struct pinmux_cfg_reg **crp,
int *fieldp, int *valuep,
unsigned long **cntp)
{
struct pinmux_cfg_reg *config_reg;
unsigned long r_width, f_width;
int k, n;
unsigned long r_width, f_width, curr_width, ncomb;
int k, m, n, pos, bit_pos;
k = 0;
while (1) {
......@@ -290,13 +322,27 @@ static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
if (!r_width)
break;
for (n = 0; n < (r_width / f_width) * (1 << f_width); n++) {
if (config_reg->enum_ids[n] == enum_id) {
*crp = config_reg;
*indexp = n;
*cntp = &config_reg->cnt[n / (1 << f_width)];
return 0;
pos = 0;
m = 0;
for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) {
if (f_width)
curr_width = f_width;
else
curr_width = config_reg->var_field_width[m];
ncomb = 1 << curr_width;
for (n = 0; n < ncomb; n++) {
if (config_reg->enum_ids[pos + n] == enum_id) {
*crp = config_reg;
*fieldp = m;
*valuep = n;
*cntp = &config_reg->cnt[m];
return 0;
}
}
pos += ncomb;
m++;
}
k++;
}
......@@ -334,43 +380,6 @@ static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio,
return -1;
}
static void write_config_reg(struct pinmux_info *gpioc,
struct pinmux_cfg_reg *crp,
int index)
{
unsigned long ncomb, pos, value;
void __iomem *mapped_reg;
ncomb = 1 << crp->field_width;
pos = index / ncomb;
value = index % ncomb;
mapped_reg = pfc_phys_to_virt(gpioc, crp->reg);
gpio_write_reg(mapped_reg, crp->reg_width, crp->field_width,
pos, value, crp->reg);
}
static int check_config_reg(struct pinmux_info *gpioc,
struct pinmux_cfg_reg *crp,
int index)
{
unsigned long ncomb, pos, value;
void __iomem *mapped_reg;
ncomb = 1 << crp->field_width;
pos = index / ncomb;
value = index % ncomb;
mapped_reg = pfc_phys_to_virt(gpioc, crp->reg);
if (gpio_read_reg(mapped_reg, crp->reg_width,
crp->field_width, pos, crp->reg) == value)
return 0;
return -1;
}
enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE };
static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
......@@ -379,7 +388,7 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
struct pinmux_cfg_reg *cr = NULL;
pinmux_enum_t enum_id;
struct pinmux_range *range;
int in_range, pos, index;
int in_range, pos, field, value;
unsigned long *cntp;
switch (pinmux_type) {
......@@ -410,7 +419,8 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
pos = 0;
enum_id = 0;
index = 0;
field = 0;
value = 0;
while (1) {
pos = get_gpio_enum_id(gpioc, gpio, pos, &enum_id);
if (pos <= 0)
......@@ -457,17 +467,19 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
if (!in_range)
continue;
if (get_config_reg(gpioc, enum_id, &cr, &index, &cntp) != 0)
if (get_config_reg(gpioc, enum_id, &cr,
&field, &value, &cntp) != 0)
goto out_err;
switch (cfg_mode) {
case GPIO_CFG_DRYRUN:
if (!*cntp || !check_config_reg(gpioc, cr, index))
if (!*cntp ||
(read_config_reg(gpioc, cr, field) != value))
continue;
break;
case GPIO_CFG_REQ:
write_config_reg(gpioc, cr, index);
write_config_reg(gpioc, cr, field, value);
*cntp = *cntp + 1;
break;
......@@ -644,7 +656,7 @@ static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio)
if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
return -EINVAL;
return gpio_read_reg(dr->mapped_reg, dr->reg_width, 1, bit, dr->reg);
return gpio_read_bit(dr, bit);
}
static int sh_gpio_get(struct gpio_chip *chip, unsigned offset)
......
......@@ -17,7 +17,9 @@
defined(CONFIG_ARCH_SH73A0) || \
defined(CONFIG_ARCH_SH7367) || \
defined(CONFIG_ARCH_SH7377) || \
defined(CONFIG_ARCH_SH7372)
defined(CONFIG_ARCH_SH7372) || \
defined(CONFIG_ARCH_R8A7740)
# define SCxSR_RDxF_CLEAR(port) (sci_in(port, SCxSR) & 0xfffc)
# define SCxSR_ERROR_CLEAR(port) (sci_in(port, SCxSR) & 0xfd73)
# define SCxSR_TDxE_CLEAR(port) (sci_in(port, SCxSR) & 0xffdf)
......
......@@ -45,12 +45,19 @@ struct pinmux_cfg_reg {
unsigned long reg, reg_width, field_width;
unsigned long *cnt;
pinmux_enum_t *enum_ids;
unsigned long *var_field_width;
};
#define PINMUX_CFG_REG(name, r, r_width, f_width) \
.reg = r, .reg_width = r_width, .field_width = f_width, \
.cnt = (unsigned long [r_width / f_width]) {}, \
.enum_ids = (pinmux_enum_t [(r_width / f_width) * (1 << f_width)]) \
.enum_ids = (pinmux_enum_t [(r_width / f_width) * (1 << f_width)])
#define PINMUX_CFG_REG_VAR(name, r, r_width, var_fw0, var_fwn...) \
.reg = r, .reg_width = r_width, \
.cnt = (unsigned long [r_width]) {}, \
.var_field_width = (unsigned long [r_width]) { var_fw0, var_fwn, 0 }, \
.enum_ids = (pinmux_enum_t [])
struct pinmux_data_reg {
unsigned long reg, reg_width, reg_shadow;
......@@ -109,6 +116,8 @@ struct pinmux_info {
unsigned int num_resources;
struct pfc_window *window;
unsigned long unlock_reg;
struct gpio_chip chip;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment