Commit 928a726b authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6: (96 commits)
  sh: add support for SMSC Polaris platform
  sh: fix the HD64461 level-triggered interrupts handling
  sh: sh-rtc wakeup support
  sh: sh-rtc invalid time rework
  sh: sh-rtc carry interrupt rework
  sh: disallow kexec virtual entry
  sh: kexec jump: fix for ftrace.
  sh: kexec: Drop SR.BL bit toggling.
  sh: add kexec jump support
  sh: rework kexec segment code
  sh: simplify kexec vbr code
  sh: Flush only the needed range when unmapping a VMA.
  sh: Update debugfs ASID dumping for 16-bit ASID support.
  sh: tlb-pteaex: Kill off legacy PTEA updates.
  sh: Support for extended ASIDs on PTEAEX-capable SH-X3 cores.
  sh: sh7763rdp: Change IRQ number for sh_eth of sh7763rdp
  sh: espt-giga board support
  sh: dma: Make G2 DMA configurable.
  sh: dma: Make PVR2 DMA configurable.
  sh: Move IRQ multi definition of DMAC to defconfig
  ...
parents 8ff64b53 eaeed5d3
......@@ -107,6 +107,9 @@ config SYS_SUPPORTS_NUMA
config SYS_SUPPORTS_PCI
bool
config SYS_SUPPORTS_CMT
bool
config STACKTRACE_SUPPORT
def_bool y
......@@ -176,6 +179,10 @@ config CPU_SHX2
config CPU_SHX3
bool
config ARCH_SHMOBILE
bool
select ARCH_SUSPEND_POSSIBLE
choice
prompt "Processor sub-type selection"
......@@ -188,6 +195,7 @@ choice
config CPU_SUBTYPE_SH7619
bool "Support SH7619 processor"
select CPU_SH2
select SYS_SUPPORTS_CMT
# SH-2A Processor Support
......@@ -200,15 +208,18 @@ config CPU_SUBTYPE_SH7203
bool "Support SH7203 processor"
select CPU_SH2A
select CPU_HAS_FPU
select SYS_SUPPORTS_CMT
config CPU_SUBTYPE_SH7206
bool "Support SH7206 processor"
select CPU_SH2A
select SYS_SUPPORTS_CMT
config CPU_SUBTYPE_SH7263
bool "Support SH7263 processor"
select CPU_SH2A
select CPU_HAS_FPU
select SYS_SUPPORTS_CMT
config CPU_SUBTYPE_MXG
bool "Support MX-G processor"
......@@ -323,7 +334,9 @@ config CPU_SUBTYPE_SH7723
bool "Support SH7723 processor"
select CPU_SH4A
select CPU_SHX2
select ARCH_SHMOBILE
select ARCH_SPARSEMEM_ENABLE
select SYS_SUPPORTS_CMT
help
Select SH7723 if you have an SH-MobileR2 CPU.
......@@ -348,6 +361,14 @@ config CPU_SUBTYPE_SH7785
select ARCH_SPARSEMEM_ENABLE
select SYS_SUPPORTS_NUMA
config CPU_SUBTYPE_SH7786
bool "Support SH7786 processor"
select CPU_SH4A
select CPU_SHX3
select CPU_HAS_PTEAEX
select ARCH_SPARSEMEM_ENABLE
select SYS_SUPPORTS_NUMA
config CPU_SUBTYPE_SHX3
bool "Support SH-X3 processor"
select CPU_SH4A
......@@ -362,20 +383,26 @@ config CPU_SUBTYPE_SHX3
config CPU_SUBTYPE_SH7343
bool "Support SH7343 processor"
select CPU_SH4AL_DSP
select ARCH_SHMOBILE
select SYS_SUPPORTS_CMT
config CPU_SUBTYPE_SH7722
bool "Support SH7722 processor"
select CPU_SH4AL_DSP
select CPU_SHX2
select ARCH_SHMOBILE
select ARCH_SPARSEMEM_ENABLE
select SYS_SUPPORTS_NUMA
select SYS_SUPPORTS_CMT
config CPU_SUBTYPE_SH7366
bool "Support SH7366 processor"
select CPU_SH4AL_DSP
select CPU_SHX2
select ARCH_SHMOBILE
select ARCH_SPARSEMEM_ENABLE
select SYS_SUPPORTS_NUMA
select SYS_SUPPORTS_CMT
# SH-5 Processor Support
......@@ -398,25 +425,34 @@ source "arch/sh/boards/Kconfig"
menu "Timer and clock configuration"
config SH_TMU
def_bool y
prompt "TMU timer support"
bool "TMU timer support"
depends on CPU_SH3 || CPU_SH4
default y
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
help
This enables the use of the TMU as the system timer.
config SH_CMT
def_bool y
prompt "CMT timer support"
depends on CPU_SH2 && !CPU_SUBTYPE_MXG
bool "CMT timer support"
depends on SYS_SUPPORTS_CMT && CPU_SH2
default y
help
This enables the use of the CMT as the system timer.
#
# Support for the new-style CMT driver. This will replace SH_CMT
# once its other dependencies are merged.
#
config SH_TIMER_CMT
bool "CMT clockevents driver"
depends on SYS_SUPPORTS_CMT && !SH_CMT
select GENERIC_CLOCKEVENTS
config SH_MTU2
def_bool n
prompt "MTU2 timer support"
bool "MTU2 timer support"
depends on CPU_SH2A
default y
help
This enables the use of the MTU2 as the system timer.
......@@ -426,7 +462,8 @@ config SH_TIMER_IRQ
CPU_SUBTYPE_SH7763
default "86" if CPU_SUBTYPE_SH7619
default "140" if CPU_SUBTYPE_SH7206
default "142" if CPU_SUBTYPE_SH7203
default "142" if CPU_SUBTYPE_SH7203 && SH_CMT
default "153" if CPU_SUBTYPE_SH7203 && SH_MTU2
default "238" if CPU_SUBTYPE_MXG
default "16"
......@@ -438,7 +475,8 @@ config SH_PCLK_FREQ
default "33333333" if CPU_SUBTYPE_SH7770 || CPU_SUBTYPE_SH7723 || \
CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 || \
CPU_SUBTYPE_SH7203 || CPU_SUBTYPE_SH7206 || \
CPU_SUBTYPE_SH7263 || CPU_SUBTYPE_MXG
CPU_SUBTYPE_SH7263 || CPU_SUBTYPE_MXG || \
CPU_SUBTYPE_SH7786
default "60000000" if CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7751R
default "66000000" if CPU_SUBTYPE_SH4_202
default "50000000"
......@@ -521,6 +559,13 @@ config CRASH_DUMP
For more details see Documentation/kdump/kdump.txt
config KEXEC_JUMP
bool "kexec jump (EXPERIMENTAL)"
depends on SUPERH32 && KEXEC && HIBERNATION && EXPERIMENTAL
help
Jump between original kernel and kexeced kernel and invoke
code via KEXEC
config SECCOMP
bool "Enable seccomp to safely compute untrusted bytecode"
depends on PROC_FS
......
......@@ -104,6 +104,9 @@ config CPU_HAS_SR_RB
config CPU_HAS_PTEA
bool
config CPU_HAS_PTEAEX
bool
config CPU_HAS_DSP
bool
......
......@@ -80,6 +80,7 @@ OBJCOPYFLAGS := -O binary -R .note -R .note.gnu.build-id -R .comment \
defaultimage-$(CONFIG_SUPERH32) := zImage
defaultimage-$(CONFIG_SH_SH7785LCR) := uImage
defaultimage-$(CONFIG_SH_RSK) := uImage
defaultimage-$(CONFIG_SH_URQUELL) := uImage
defaultimage-$(CONFIG_SH_7206_SOLUTION_ENGINE) := vmlinux
defaultimage-$(CONFIG_SH_7619_SOLUTION_ENGINE) := vmlinux
......
......@@ -155,17 +155,22 @@ config SH_SH7785LCR
config SH_SH7785LCR_29BIT_PHYSMAPS
bool "SH7785LCR 29bit physmaps"
depends on SH_SH7785LCR
depends on SH_SH7785LCR && 29BIT
default y
help
This board has 2 physical memory maps. It can be changed with
DIP switch(S2-5). If you set the DIP switch for S2-5 = ON,
you can access all on-board device in 29bit address mode.
config SH_URQUELL
bool "Urquell"
depends on CPU_SUBTYPE_SH7786
select ARCH_REQUIRE_GPIOLIB
config SH_MIGOR
bool "Migo-R"
depends on CPU_SUBTYPE_SH7722
select GENERIC_GPIO
select ARCH_REQUIRE_GPIOLIB
help
Select Migo-R if configuring for the SH7722 Migo-R platform
by Renesas System Solutions Asia Pte. Ltd.
......@@ -173,7 +178,7 @@ config SH_MIGOR
config SH_AP325RXA
bool "AP-325RXA"
depends on CPU_SUBTYPE_SH7723
select GENERIC_GPIO
select ARCH_REQUIRE_GPIOLIB
help
Renesas "AP-325RXA" support.
Compatible with ALGO SYSTEM CO.,LTD. "AP-320A"
......@@ -185,6 +190,13 @@ config SH_SH7763RDP
Select SH7763RDP if configuring for a Renesas SH7763
evaluation board.
config SH_ESPT
bool "ESPT"
depends on CPU_SUBTYPE_SH7763
help
Select ESPT if configuring for a Renesas SH7763
with gigabit ether evaluation board.
config SH_EDOSK7705
bool "EDOSK7705"
depends on CPU_SUBTYPE_SH7705
......@@ -240,7 +252,7 @@ config SH_X3PROTO
config SH_MAGIC_PANEL_R2
bool "Magic Panel R2"
depends on CPU_SUBTYPE_SH7720
select GENERIC_GPIO
select ARCH_REQUIRE_GPIOLIB
help
Select Magic Panel R2 if configuring for Magic Panel R2.
......@@ -249,6 +261,13 @@ config SH_CAYMAN
depends on CPU_SUBTYPE_SH5_101 || CPU_SUBTYPE_SH5_103
select SYS_SUPPORTS_PCI
config SH_POLARIS
bool "SMSC Polaris"
select CPU_HAS_IPR_IRQ
depends on CPU_SUBTYPE_SH7709
help
Select if configuring for an SMSC Polaris development board
endmenu
source "arch/sh/boards/mach-r2d/Kconfig"
......
......@@ -4,5 +4,8 @@
obj-$(CONFIG_SH_AP325RXA) += board-ap325rxa.o
obj-$(CONFIG_SH_MAGIC_PANEL_R2) += board-magicpanelr2.o
obj-$(CONFIG_SH_SH7785LCR) += board-sh7785lcr.o
obj-$(CONFIG_SH_URQUELL) += board-urquell.o
obj-$(CONFIG_SH_SHMIN) += board-shmin.o
obj-$(CONFIG_SH_EDOSK7760) += board-edosk7760.o
obj-$(CONFIG_SH_ESPT) += board-espt.o
obj-$(CONFIG_SH_POLARIS) += board-polaris.o
......@@ -166,6 +166,16 @@ static void ap320_wvga_power_on(void *board_data)
ctrl_outw(0x100, FPGA_BKLREG);
}
static void ap320_wvga_power_off(void *board_data)
{
/* backlight */
ctrl_outw(0, FPGA_BKLREG);
gpio_set_value(GPIO_PTS3, 1);
/* ASD AP-320/325 LCD OFF */
ctrl_outw(0, FPGA_LCDREG);
}
static struct sh_mobile_lcdc_info lcdc_info = {
.clock_source = LCDC_CLK_EXTERNAL,
.ch[0] = {
......@@ -191,6 +201,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
},
.board_cfg = {
.display_on = ap320_wvga_power_on,
.display_off = ap320_wvga_power_off,
},
}
};
......
/*
* Data Technology Inc. ESPT-GIGA board suport
*
* Copyright (C) 2008, 2009 Renesas Solutions Corp.
* Copyright (C) 2008, 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/mtd/physmap.h>
#include <linux/io.h>
#include <asm/machvec.h>
#include <asm/sizes.h>
#include <asm/sh_eth.h>
/* NOR Flash */
static struct mtd_partition espt_nor_flash_partitions[] = {
{
.name = "U-Boot",
.offset = 0,
.size = (2 * SZ_128K),
.mask_flags = MTD_WRITEABLE, /* Read-only */
}, {
.name = "Linux-Kernel",
.offset = MTDPART_OFS_APPEND,
.size = (20 * SZ_128K),
}, {
.name = "Root Filesystem",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
},
};
static struct physmap_flash_data espt_nor_flash_data = {
.width = 2,
.parts = espt_nor_flash_partitions,
.nr_parts = ARRAY_SIZE(espt_nor_flash_partitions),
};
static struct resource espt_nor_flash_resources[] = {
[0] = {
.name = "NOR Flash",
.start = 0,
.end = SZ_8M - 1,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device espt_nor_flash_device = {
.name = "physmap-flash",
.resource = espt_nor_flash_resources,
.num_resources = ARRAY_SIZE(espt_nor_flash_resources),
.dev = {
.platform_data = &espt_nor_flash_data,
},
};
/* SH-Ether */
static struct resource sh_eth_resources[] = {
{
.start = 0xFEE00800, /* use eth1 */
.end = 0xFEE00F7C - 1,
.flags = IORESOURCE_MEM,
}, {
.start = 57, /* irq number */
.flags = IORESOURCE_IRQ,
},
};
static struct sh_eth_plat_data sh7763_eth_pdata = {
.phy = 0,
.edmac_endian = EDMAC_LITTLE_ENDIAN,
};
static struct platform_device espt_eth_device = {
.name = "sh-eth",
.resource = sh_eth_resources,
.num_resources = ARRAY_SIZE(sh_eth_resources),
.dev = {
.platform_data = &sh7763_eth_pdata,
},
};
static struct platform_device *espt_devices[] __initdata = {
&espt_nor_flash_device,
&espt_eth_device,
};
static int __init espt_devices_setup(void)
{
return platform_add_devices(espt_devices,
ARRAY_SIZE(espt_devices));
}
device_initcall(espt_devices_setup);
static struct sh_machine_vector mv_espt __initmv = {
.mv_name = "ESPT-GIGA",
};
/*
* June 2006 steve.glendinning@smsc.com
*
* Polaris-specific resource declaration
*
*/
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/smsc911x.h>
#include <linux/io.h>
#include <asm/irq.h>
#include <asm/machvec.h>
#include <asm/heartbeat.h>
#include <cpu/gpio.h>
#include <mach-se/mach/se.h>
#define BCR2 (0xFFFFFF62)
#define WCR2 (0xFFFFFF66)
#define AREA5_WAIT_CTRL (0x1C00)
#define WAIT_STATES_10 (0x7)
static struct resource smsc911x_resources[] = {
[0] = {
.name = "smsc911x-memory",
.start = PA_EXT5,
.end = PA_EXT5 + 0x1fff,
.flags = IORESOURCE_MEM,
},
[1] = {
.name = "smsc911x-irq",
.start = IRQ0_IRQ,
.end = IRQ0_IRQ,
.flags = IORESOURCE_IRQ,
},
};
static struct smsc911x_platform_config smsc911x_config = {
.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
.irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
.flags = SMSC911X_USE_32BIT,
.phy_interface = PHY_INTERFACE_MODE_MII,
};
static struct platform_device smsc911x_device = {
.name = "smsc911x",
.id = 0,
.num_resources = ARRAY_SIZE(smsc911x_resources),
.resource = smsc911x_resources,
.dev = {
.platform_data = &smsc911x_config,
},
};
static unsigned char heartbeat_bit_pos[] = { 0, 1, 2, 3 };
static struct heartbeat_data heartbeat_data = {
.bit_pos = heartbeat_bit_pos,
.nr_bits = ARRAY_SIZE(heartbeat_bit_pos),
.regsize = 8,
};
static struct resource heartbeat_resources[] = {
[0] = {
.start = PORT_PCDR,
.end = PORT_PCDR,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device heartbeat_device = {
.name = "heartbeat",
.id = -1,
.dev = {
.platform_data = &heartbeat_data,
},
.num_resources = ARRAY_SIZE(heartbeat_resources),
.resource = heartbeat_resources,
};
static struct platform_device *polaris_devices[] __initdata = {
&smsc911x_device,
&heartbeat_device,
};
static int __init polaris_initialise(void)
{
u16 wcr, bcr_mask;
printk(KERN_INFO "Configuring Polaris external bus\n");
/* Configure area 5 with 2 wait states */
wcr = ctrl_inw(WCR2);
wcr &= (~AREA5_WAIT_CTRL);
wcr |= (WAIT_STATES_10 << 10);
ctrl_outw(wcr, WCR2);
/* Configure area 5 for 32-bit access */
bcr_mask = ctrl_inw(BCR2);
bcr_mask |= 1 << 10;
ctrl_outw(bcr_mask, BCR2);
return platform_add_devices(polaris_devices,
ARRAY_SIZE(polaris_devices));
}
arch_initcall(polaris_initialise);
static struct ipr_data ipr_irq_table[] = {
/* External IRQs */
{ IRQ0_IRQ, 0, 0, 1, }, /* IRQ0 */
{ IRQ1_IRQ, 0, 4, 1, }, /* IRQ1 */
};
static unsigned long ipr_offsets[] = {
INTC_IPRC
};
static struct ipr_desc ipr_irq_desc = {
.ipr_offsets = ipr_offsets,
.nr_offsets = ARRAY_SIZE(ipr_offsets),
.ipr_data = ipr_irq_table,
.nr_irqs = ARRAY_SIZE(ipr_irq_table),
.chip = {
.name = "sh7709-ext",
},
};
static void __init init_polaris_irq(void)
{
/* Disable all interrupts */
ctrl_outw(0, BCR_ILCRA);
ctrl_outw(0, BCR_ILCRB);
ctrl_outw(0, BCR_ILCRC);
ctrl_outw(0, BCR_ILCRD);
ctrl_outw(0, BCR_ILCRE);
ctrl_outw(0, BCR_ILCRF);
ctrl_outw(0, BCR_ILCRG);
register_ipr_controller(&ipr_irq_desc);
}
static struct sh_machine_vector mv_polaris __initmv = {
.mv_name = "Polaris",
.mv_nr_irqs = 61,
.mv_init_irq = init_polaris_irq,
};
......@@ -275,7 +275,18 @@ void __init init_sh7785lcr_IRQ(void)
static void sh7785lcr_power_off(void)
{
ctrl_outb(0x01, P2SEGADDR(PLD_POFCR));
unsigned char *p;
p = ioremap(PLD_POFCR, PLD_POFCR + 1);
if (!p) {
printk(KERN_ERR "%s: ioremap error.\n", __func__);
return;
}
*p = 0x01;
iounmap(p);
set_bl_bit();
while (1)
cpu_relax();
}
/* Initialize the board */
......
/*
* Renesas Technology Corp. SH7786 Urquell Support.
*
* Copyright (C) 2008 Kuninori Morimoto <morimoto.kuninori@renesas.com>
* Copyright (C) 2008 Yoshihiro Shimoda
*
* 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/init.h>
#include <linux/platform_device.h>
#include <linux/fb.h>
#include <linux/smc91x.h>
#include <linux/mtd/physmap.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <mach/urquell.h>
#include <cpu/sh7786.h>
#include <asm/heartbeat.h>
#include <asm/sizes.h>
static struct resource heartbeat_resources[] = {
[0] = {
.start = BOARDREG(SLEDR),
.end = BOARDREG(SLEDR),
.flags = IORESOURCE_MEM,
},
};
static struct heartbeat_data heartbeat_data = {
.regsize = 16,
};
static struct platform_device heartbeat_device = {
.name = "heartbeat",
.id = -1,
.dev = {
.platform_data = &heartbeat_data,
},
.num_resources = ARRAY_SIZE(heartbeat_resources),
.resource = heartbeat_resources,
};
static struct smc91x_platdata smc91x_info = {
.flags = SMC91X_USE_16BIT | SMC91X_NOWAIT,
};
static struct resource smc91x_eth_resources[] = {
[0] = {
.name = "SMC91C111" ,
.start = 0x05800300,
.end = 0x0580030f,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 11,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device smc91x_eth_device = {
.name = "smc91x",
.num_resources = ARRAY_SIZE(smc91x_eth_resources),
.resource = smc91x_eth_resources,
.dev = {
.platform_data = &smc91x_info,
},
};
static struct mtd_partition nor_flash_partitions[] = {
{
.name = "loader",
.offset = 0x00000000,
.size = SZ_512K,
.mask_flags = MTD_WRITEABLE, /* Read-only */
},
{
.name = "bootenv",
.offset = MTDPART_OFS_APPEND,
.size = SZ_512K,
.mask_flags = MTD_WRITEABLE, /* Read-only */
},
{
.name = "kernel",
.offset = MTDPART_OFS_APPEND,
.size = SZ_4M,
},
{
.name = "data",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
},
};
static struct physmap_flash_data nor_flash_data = {
.width = 2,
.parts = nor_flash_partitions,
.nr_parts = ARRAY_SIZE(nor_flash_partitions),
};
static struct resource nor_flash_resources[] = {
[0] = {
.start = NOR_FLASH_ADDR,
.end = NOR_FLASH_ADDR + NOR_FLASH_SIZE - 1,
.flags = IORESOURCE_MEM,
}
};
static struct platform_device nor_flash_device = {
.name = "physmap-flash",
.dev = {
.platform_data = &nor_flash_data,
},
.num_resources = ARRAY_SIZE(nor_flash_resources),
.resource = nor_flash_resources,
};
static struct platform_device *urquell_devices[] __initdata = {
&heartbeat_device,
&smc91x_eth_device,
&nor_flash_device,
};
static int __init urquell_devices_setup(void)
{
/* USB */
gpio_request(GPIO_FN_USB_OVC0, NULL);
gpio_request(GPIO_FN_USB_PENC0, NULL);
return platform_add_devices(urquell_devices,
ARRAY_SIZE(urquell_devices));
}
device_initcall(urquell_devices_setup);
static void urquell_power_off(void)
{
__raw_writew(0xa5a5, UBOARDREG(SRSTR));
}
static void __init urquell_init_irq(void)
{
plat_irq_setup_pins(IRQ_MODE_IRL3210_MASK);
}
/* Initialize the board */
static void __init urquell_setup(char **cmdline_p)
{
printk(KERN_INFO "Renesas Technology Corp. Urquell support.\n");
pm_power_off = urquell_power_off;
}
/*
* The Machine Vector
*/
static struct sh_machine_vector mv_urquell __initmv = {
.mv_name = "Urquell",
.mv_setup = urquell_setup,
.mv_init_irq = urquell_init_irq,
};
......@@ -18,7 +18,7 @@ config SH_R7780MP
config SH_R7785RP
bool "R7785RP board support"
depends on CPU_SUBTYPE_SH7785
select GENERIC_GPIO
select ARCH_REQUIRE_GPIOLIB
endchoice
......
......@@ -10,47 +10,32 @@
#include <linux/linkage.h>
#include <cpu/mmu_context.h>
#define k0 r0
#define k1 r1
#define k2 r2
#define k3 r3
#define k4 r4
/*
* Kernel mode register usage:
* k0 scratch
* k1 scratch
* k2 scratch (Exception code)
* k3 scratch (Return address)
* k4 scratch
* k5 reserved
* k6 Global Interrupt Mask (0--15 << 4)
* k7 CURRENT_THREAD_INFO (pointer to current thread info)
* For more details, please have a look at entry.S
*/
#define k0 r0
#define k1 r1
ENTRY(wakeup_start)
! clear STBY bit
mov #-126, k2
mov #-126, k1
and #127, k0
mov.b k0, @k2
mov.b k0, @k1
! enable refresh
mov.l 5f, k1
mov.w 6f, k0
mov.w k0, @k1
! jump to handler
mov.l 2f, k2
mov.l 3f, k3
mov.l @k2, k2
mov.l 4f, k1
jmp @k1
nop
nop
.align 2
1: .long EXPEVT
2: .long INTEVT
3: .long ret_from_irq
4: .long handle_exception
4: .long handle_interrupt
5: .long 0xffffff68
6: .word 0x0524
......
......@@ -115,7 +115,6 @@ static struct sh_machine_vector mv_hp6xx __initmv = {
.mv_setup = hp6xx_setup,
/* IRQ's : CPU(64) + CCHIP(16) + FREE_TO_USE(6) */
.mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM + 6,
.mv_irq_demux = hd64461_irq_demux,
/* Enable IRQ0 -> IRQ3 in IRQ_MODE */
.mv_init_irq = hp6xx_init_irq,
};
......@@ -450,6 +450,14 @@ static struct spi_board_info migor_spi_devices[] = {
static int __init migor_devices_setup(void)
{
#ifdef CONFIG_PM
/* Let D11 LED show STATUS0 */
gpio_request(GPIO_FN_STATUS0, NULL);
/* Lit D12 LED show PDSTATUS */
gpio_request(GPIO_FN_PDSTATUS, NULL);
#else
/* Lit D11 LED */
gpio_request(GPIO_PTJ7, NULL);
gpio_direction_output(GPIO_PTJ7, 1);
......@@ -459,6 +467,7 @@ static int __init migor_devices_setup(void)
gpio_request(GPIO_PTJ5, NULL);
gpio_direction_output(GPIO_PTJ5, 1);
gpio_export(GPIO_PTJ5, 0);
#endif
/* SMC91C111 - Enable IRQ0, Setup CS4 for 16-bit fast access */
gpio_request(GPIO_FN_IRQ0, NULL);
......
......@@ -10,7 +10,7 @@ config SH_RSK7201
config SH_RSK7203
bool "RSK7203"
select GENERIC_GPIO
select ARCH_REQUIRE_GPIOLIB
depends on CPU_SUBTYPE_SH7203
endchoice
......
......@@ -63,15 +63,19 @@ static struct platform_device sh7763rdp_nor_flash_device = {
},
};
/* SH-Ether */
/*
* SH-Ether
*
* SH Ether of SH7763 has multi IRQ handling.
* (57,58,59 -> 57)
*/
static struct resource sh_eth_resources[] = {
{
.start = 0xFEE00800, /* use eth1 */
.end = 0xFEE00F7C - 1,
.flags = IORESOURCE_MEM,
}, {
.start = 58, /* irq number */
.end = 58,
.start = 57, /* irq number */
.flags = IORESOURCE_IRQ,
},
};
......
......@@ -33,20 +33,24 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
$(obj)/compressed/vmlinux: FORCE
$(Q)$(MAKE) $(build)=$(obj)/compressed $@
ifeq ($(CONFIG_32BIT),y)
KERNEL_LOAD := $(shell /bin/bash -c 'printf "0x%08x" \
$$[$(CONFIG_PAGE_OFFSET) + \
$(CONFIG_ZERO_PAGE_OFFSET)]')
else
KERNEL_MEMORY := 0x00000000
ifeq ($(CONFIG_PMB_FIXED),y)
KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \
$$[$(CONFIG_MEMORY_START) & 0x1fffffff]')
endif
ifeq ($(CONFIG_29BIT),y)
KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \
$$[$(CONFIG_MEMORY_START)]')
endif
KERNEL_LOAD := $(shell /bin/bash -c 'printf "0x%08x" \
$$[$(CONFIG_PAGE_OFFSET) + \
$(CONFIG_MEMORY_START) + \
$(KERNEL_MEMORY) + \
$(CONFIG_ZERO_PAGE_OFFSET)]')
endif
KERNEL_ENTRY := $(shell /bin/bash -c 'printf "0x%08x" \
$$[$(CONFIG_PAGE_OFFSET) + \
$(CONFIG_MEMORY_START) + \
$(KERNEL_MEMORY) + \
$(CONFIG_ZERO_PAGE_OFFSET) + $(CONFIG_ENTRY_OFFSET)]')
quiet_cmd_uimage = UIMAGE $@
......
......@@ -53,21 +53,22 @@ static struct irq_chip hd64461_irq_chip = {
.unmask = hd64461_unmask_irq,
};
int hd64461_irq_demux(int irq)
static void hd64461_irq_demux(unsigned int irq, struct irq_desc *desc)
{
if (irq == CONFIG_HD64461_IRQ) {
unsigned short bit;
unsigned short nirr = inw(HD64461_NIRR);
unsigned short nimr = inw(HD64461_NIMR);
int i;
nirr &= ~nimr;
for (bit = 1, i = 0; i < 16; bit <<= 1, i++)
if (nirr & bit)
break;
irq = HD64461_IRQBASE + i;
unsigned short intv = ctrl_inw(HD64461_NIRR);
struct irq_desc *ext_desc;
unsigned int ext_irq = HD64461_IRQBASE;
intv &= (1 << HD64461_IRQ_NUM) - 1;
while (intv) {
if (intv & 1) {
ext_desc = irq_desc + ext_irq;
handle_level_irq(ext_irq, ext_desc);
}
intv >>= 1;
ext_irq++;
}
return irq;
}
int __init setup_hd64461(void)
......@@ -93,6 +94,9 @@ int __init setup_hd64461(void)
set_irq_chip_and_handler(i, &hd64461_irq_chip,
handle_level_irq);
set_irq_chained_handler(CONFIG_HD64461_IRQ, hd64461_irq_demux);
set_irq_type(CONFIG_HD64461_IRQ, IRQ_TYPE_LEVEL_LOW);
#ifdef CONFIG_HD64461_ENABLER
printk(KERN_INFO "HD64461: enabling PCMCIA devices\n");
__raw_writeb(0x4c, HD64461_PCC1CSCIER);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -9,13 +9,21 @@ config SH_DMA
select SH_DMA_API
default n
config SH_DMA_IRQ_MULTI
bool
depends on SH_DMA
default y if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7751 || \
CPU_SUBTYPE_SH7750S || CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R || \
CPU_SUBTYPE_SH7091 || CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7764 || \
CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
config NR_ONCHIP_DMA_CHANNELS
int
depends on SH_DMA
default "6" if CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721
default "8" if CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R
default "12" if CPU_SUBTYPE_SH7780
default "4"
default "4" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7750S
default "8" if CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R || CPU_SUBTYPE_SH7760
default "12" if CPU_SUBTYPE_SH7723 || CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
default "6"
help
This allows you to specify the number of channels that the on-chip
DMAC supports. This will be 4 for SH7750/SH7751 and 8 for the
......@@ -46,4 +54,28 @@ config SH_DMABRG
of the SH7760.
Say Y if you want to use Audio/USB DMA on your SH7760 board.
config PVR2_DMA
tristate "PowerVR 2 DMAC support"
depends on SH_DREAMCAST && SH_DMA
help
Selecting this will enable support for the PVR2 DMA controller.
As this chains off of the on-chip DMAC, that must also be
enabled by default.
This is primarily used by the pvr2fb framebuffer driver for
certain optimizations, but is not necessary for functionality.
If in doubt, say N.
config G2_DMA
tristate "G2 Bus DMA support"
depends on SH_DREAMCAST
select SH_DMA_API
help
This enables support for the DMA controller for the Dreamcast's
G2 bus. Drivers that want this will generally enable this on
their own.
If in doubt, say N.
endmenu
......@@ -4,5 +4,6 @@
obj-$(CONFIG_SH_DMA_API) += dma-api.o dma-sysfs.o
obj-$(CONFIG_SH_DMA) += dma-sh.o
obj-$(CONFIG_SH_DREAMCAST) += dma-pvr2.o dma-g2.o
obj-$(CONFIG_PVR2_DMA) += dma-pvr2.o
obj-$(CONFIG_G2_DMA) += dma-g2.o
obj-$(CONFIG_SH_DMABRG) += dmabrg.o
......@@ -17,28 +17,16 @@
#include <mach-dreamcast/mach/dma.h>
#include <asm/dma.h>
#include <asm/io.h>
#include "dma-sh.h"
static int dmte_irq_map[] = {
DMTE0_IRQ,
DMTE1_IRQ,
DMTE2_IRQ,
DMTE3_IRQ,
#if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
defined(CONFIG_CPU_SUBTYPE_SH7721) || \
defined(CONFIG_CPU_SUBTYPE_SH7751R) || \
defined(CONFIG_CPU_SUBTYPE_SH7760) || \
defined(CONFIG_CPU_SUBTYPE_SH7709) || \
defined(CONFIG_CPU_SUBTYPE_SH7780)
DMTE4_IRQ,
DMTE5_IRQ,
#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7751R) || \
defined(CONFIG_CPU_SUBTYPE_SH7760) || \
defined(CONFIG_CPU_SUBTYPE_SH7780)
DMTE6_IRQ,
DMTE7_IRQ,
#include <asm/dma-sh.h>
#if defined(DMAE1_IRQ)
#define NR_DMAE 2
#else
#define NR_DMAE 1
#endif
static const char *dmae_name[] = {
"DMAC Address Error0", "DMAC Address Error1"
};
static inline unsigned int get_dmte_irq(unsigned int chan)
......@@ -46,7 +34,14 @@ static inline unsigned int get_dmte_irq(unsigned int chan)
unsigned int irq = 0;
if (chan < ARRAY_SIZE(dmte_irq_map))
irq = dmte_irq_map[chan];
#if defined(CONFIG_SH_DMA_IRQ_MULTI)
if (irq > DMTE6_IRQ)
return DMTE6_IRQ;
return DMTE0_IRQ;
#else
return irq;
#endif
}
/*
......@@ -59,7 +54,7 @@ static inline unsigned int get_dmte_irq(unsigned int chan)
*/
static inline unsigned int calc_xmit_shift(struct dma_channel *chan)
{
u32 chcr = ctrl_inl(CHCR[chan->chan]);
u32 chcr = ctrl_inl(dma_base_addr[chan->chan] + CHCR);
return ts_shift[(chcr & CHCR_TS_MASK)>>CHCR_TS_SHIFT];
}
......@@ -75,13 +70,13 @@ static irqreturn_t dma_tei(int irq, void *dev_id)
struct dma_channel *chan = dev_id;
u32 chcr;
chcr = ctrl_inl(CHCR[chan->chan]);
chcr = ctrl_inl(dma_base_addr[chan->chan] + CHCR);
if (!(chcr & CHCR_TE))
return IRQ_NONE;
chcr &= ~(CHCR_IE | CHCR_DE);
ctrl_outl(chcr, CHCR[chan->chan]);
ctrl_outl(chcr, (dma_base_addr[chan->chan] + CHCR));
wake_up(&chan->wait_queue);
......@@ -94,7 +89,12 @@ static int sh_dmac_request_dma(struct dma_channel *chan)
return 0;
return request_irq(get_dmte_irq(chan->chan), dma_tei,
IRQF_DISABLED, chan->dev_id, chan);
#if defined(CONFIG_SH_DMA_IRQ_MULTI)
IRQF_SHARED,
#else
IRQF_DISABLED,
#endif
chan->dev_id, chan);
}
static void sh_dmac_free_dma(struct dma_channel *chan)
......@@ -115,7 +115,7 @@ sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr)
chan->flags &= ~DMA_TEI_CAPABLE;
}
ctrl_outl(chcr, CHCR[chan->chan]);
ctrl_outl(chcr, (dma_base_addr[chan->chan] + CHCR));
chan->flags |= DMA_CONFIGURED;
return 0;
......@@ -126,13 +126,13 @@ static void sh_dmac_enable_dma(struct dma_channel *chan)
int irq;
u32 chcr;
chcr = ctrl_inl(CHCR[chan->chan]);
chcr = ctrl_inl(dma_base_addr[chan->chan] + CHCR);
chcr |= CHCR_DE;
if (chan->flags & DMA_TEI_CAPABLE)
chcr |= CHCR_IE;
ctrl_outl(chcr, CHCR[chan->chan]);
ctrl_outl(chcr, (dma_base_addr[chan->chan] + CHCR));
if (chan->flags & DMA_TEI_CAPABLE) {
irq = get_dmte_irq(chan->chan);
......@@ -150,9 +150,9 @@ static void sh_dmac_disable_dma(struct dma_channel *chan)
disable_irq(irq);
}
chcr = ctrl_inl(CHCR[chan->chan]);
chcr = ctrl_inl(dma_base_addr[chan->chan] + CHCR);
chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE);
ctrl_outl(chcr, CHCR[chan->chan]);
ctrl_outl(chcr, (dma_base_addr[chan->chan] + CHCR));
}
static int sh_dmac_xfer_dma(struct dma_channel *chan)
......@@ -183,12 +183,13 @@ static int sh_dmac_xfer_dma(struct dma_channel *chan)
*/
if (chan->sar || (mach_is_dreamcast() &&
chan->chan == PVR2_CASCADE_CHAN))
ctrl_outl(chan->sar, SAR[chan->chan]);
ctrl_outl(chan->sar, (dma_base_addr[chan->chan]+SAR));
if (chan->dar || (mach_is_dreamcast() &&
chan->chan == PVR2_CASCADE_CHAN))
ctrl_outl(chan->dar, DAR[chan->chan]);
ctrl_outl(chan->dar, (dma_base_addr[chan->chan] + DAR));
ctrl_outl(chan->count >> calc_xmit_shift(chan), DMATCR[chan->chan]);
ctrl_outl(chan->count >> calc_xmit_shift(chan),
(dma_base_addr[chan->chan] + TCR));
sh_dmac_enable_dma(chan);
......@@ -197,36 +198,26 @@ static int sh_dmac_xfer_dma(struct dma_channel *chan)
static int sh_dmac_get_dma_residue(struct dma_channel *chan)
{
if (!(ctrl_inl(CHCR[chan->chan]) & CHCR_DE))
if (!(ctrl_inl(dma_base_addr[chan->chan] + CHCR) & CHCR_DE))
return 0;
return ctrl_inl(DMATCR[chan->chan]) << calc_xmit_shift(chan);
return ctrl_inl(dma_base_addr[chan->chan] + TCR)
<< calc_xmit_shift(chan);
}
#if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
defined(CONFIG_CPU_SUBTYPE_SH7721) || \
defined(CONFIG_CPU_SUBTYPE_SH7780) || \
defined(CONFIG_CPU_SUBTYPE_SH7709)
#define dmaor_read_reg() ctrl_inw(DMAOR)
#define dmaor_write_reg(data) ctrl_outw(data, DMAOR)
#else
#define dmaor_read_reg() ctrl_inl(DMAOR)
#define dmaor_write_reg(data) ctrl_outl(data, DMAOR)
#endif
static inline int dmaor_reset(void)
static inline int dmaor_reset(int no)
{
unsigned long dmaor = dmaor_read_reg();
unsigned long dmaor = dmaor_read_reg(no);
/* Try to clear the error flags first, incase they are set */
dmaor &= ~(DMAOR_NMIF | DMAOR_AE);
dmaor_write_reg(dmaor);
dmaor_write_reg(no, dmaor);
dmaor |= DMAOR_INIT;
dmaor_write_reg(dmaor);
dmaor_write_reg(no, dmaor);
/* See if we got an error again */
if ((dmaor_read_reg() & (DMAOR_AE | DMAOR_NMIF))) {
if ((dmaor_read_reg(no) & (DMAOR_AE | DMAOR_NMIF))) {
printk(KERN_ERR "dma-sh: Can't initialize DMAOR.\n");
return -EINVAL;
}
......@@ -237,10 +228,33 @@ static inline int dmaor_reset(void)
#if defined(CONFIG_CPU_SH4)
static irqreturn_t dma_err(int irq, void *dummy)
{
dmaor_reset();
#if defined(CONFIG_SH_DMA_IRQ_MULTI)
int cnt = 0;
switch (irq) {
#if defined(DMTE6_IRQ) && defined(DMAE1_IRQ)
case DMTE6_IRQ:
cnt++;
#endif
case DMTE0_IRQ:
if (dmaor_read_reg(cnt) & (DMAOR_NMIF | DMAOR_AE)) {
disable_irq(irq);
/* DMA multi and error IRQ */
return IRQ_HANDLED;
}
default:
return IRQ_NONE;
}
#else
dmaor_reset(0);
#if defined(CONFIG_CPU_SUBTYPE_SH7723) || \
defined(CONFIG_CPU_SUBTYPE_SH7780) || \
defined(CONFIG_CPU_SUBTYPE_SH7785)
dmaor_reset(1);
#endif
disable_irq(irq);
return IRQ_HANDLED;
#endif
}
#endif
......@@ -259,24 +273,59 @@ static struct dma_info sh_dmac_info = {
.flags = DMAC_CHANNELS_TEI_CAPABLE,
};
#ifdef CONFIG_CPU_SH4
static unsigned int get_dma_error_irq(int n)
{
#if defined(CONFIG_SH_DMA_IRQ_MULTI)
return (n == 0) ? get_dmte_irq(0) : get_dmte_irq(6);
#else
return (n == 0) ? DMAE0_IRQ :
#if defined(DMAE1_IRQ)
DMAE1_IRQ;
#else
-1;
#endif
#endif
}
#endif
static int __init sh_dmac_init(void)
{
struct dma_info *info = &sh_dmac_info;
int i;
#ifdef CONFIG_CPU_SH4
i = request_irq(DMAE_IRQ, dma_err, IRQF_DISABLED, "DMAC Address Error", 0);
if (unlikely(i < 0))
return i;
int n;
for (n = 0; n < NR_DMAE; n++) {
i = request_irq(get_dma_error_irq(n), dma_err,
#if defined(CONFIG_SH_DMA_IRQ_MULTI)
IRQF_SHARED,
#else
IRQF_DISABLED,
#endif
dmae_name[n], (void *)dmae_name[n]);
if (unlikely(i < 0)) {
printk(KERN_ERR "%s request_irq fail\n", dmae_name[n]);
return i;
}
}
#endif /* CONFIG_CPU_SH4 */
/*
* Initialize DMAOR, and clean up any error flags that may have
* been set.
*/
i = dmaor_reset();
i = dmaor_reset(0);
if (unlikely(i != 0))
return i;
#if defined(CONFIG_CPU_SUBTYPE_SH7723) || \
defined(CONFIG_CPU_SUBTYPE_SH7780) || \
defined(CONFIG_CPU_SUBTYPE_SH7785)
i = dmaor_reset(1);
if (unlikely(i != 0))
return i;
#endif
return register_dmac(info);
}
......@@ -284,8 +333,12 @@ static int __init sh_dmac_init(void)
static void __exit sh_dmac_exit(void)
{
#ifdef CONFIG_CPU_SH4
free_irq(DMAE_IRQ, 0);
#endif
int n;
for (n = 0; n < NR_DMAE; n++) {
free_irq(get_dma_error_irq(n), (void *)dmae_name[n]);
}
#endif /* CONFIG_CPU_SH4 */
unregister_dmac(&sh_dmac_info);
}
......
......@@ -127,8 +127,8 @@ int __init sh7780_pcic_init(struct sh4_pci_address_map *map)
pci_write_reg(word, SH4_PCILSR0);
pci_write_reg(0x00000001, SH4_PCILSR1);
/* Set the values on window 0 PCI config registers */
word = (CONFIG_MEMORY_SIZE > 0x08000000) ? 0x10000000 : 0x08000000;
pci_write_reg(word | 0xa0000000, SH4_PCILAR0);
word = CONFIG_MEMORY_START | (CONFIG_MEMORY_SIZE - 0x01000000);
pci_write_reg(word, SH4_PCILAR0);
pci_write_reg(word, SH7780_PCIMBAR0);
/* Set the values on window 1 PCI config registers */
pci_write_reg(0x00000000, SH4_PCILAR1);
......
......@@ -31,7 +31,7 @@
/* Returns the physical address of a PnSEG (n=1,2) address */
#define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff)
#ifdef CONFIG_29BIT
#if defined(CONFIG_29BIT) || defined(CONFIG_PMB_FIXED)
/*
* Map an address to a certain privileged segment
*/
......@@ -43,7 +43,7 @@
((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P3SEG))
#define P4SEGADDR(a) \
((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P4SEG))
#endif /* 29BIT */
#endif /* 29BIT || PMB_FIXED */
#endif /* P1SEG */
/* Check if an address can be reached in 29 bits */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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