code:
// SPDX-License-Identifier: GPL-2.0+
//
// Copyright (c) 2004-2005 Simtec Electronics
//	http://www.simtec.co.uk/products/SWLINUX/
//	Ben Dooks <ben@simtec.co.uk>
//
// Common code for S3C24XX machines

#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <clocksource/samsung_pwm.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/platform_data/clk-s3c2410.h>
#include <linux/platform_data/dma-s3c24xx.h>
#include <linux/dmaengine.h>
#include <linux/clk/samsung.h>

#include "hardware-s3c24xx.h"
#include "map.h"
#include "regs-clock.h"
#include <asm/irq.h>
#include <asm/cacheflush.h>
#include <asm/system_info.h>
#include <asm/system_misc.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>

#include "regs-gpio.h"
#include "dma-s3c24xx.h"

#include "cpu.h"
#include "devs.h"
#include "pwm-core.h"

#include "s3c24xx.h"

/* table of supported CPUs */

static const char name_s3c2410[]  = "S3C2410";
static const char name_s3c2412[]  = "S3C2412";
static const char name_s3c2416[]  = "S3C2416/S3C2450";
static const char name_s3c2440[]  = "S3C2440";
static const char name_s3c2442[]  = "S3C2442";
static const char name_s3c2442b[]  = "S3C2442B";
static const char name_s3c2443[]  = "S3C2443";
static const char name_s3c2410a[] = "S3C2410A";
static const char name_s3c2440a[] = "S3C2440A";

static struct cpu_table cpu_ids[] __initdata = {
	{
		.idcode		= 0x32410000,
		.idmask		= 0xffffffff,
		.map_io		= s3c2410_map_io,
		.init_uarts	= s3c2410_init_uarts,
		.init		= s3c2410_init,
		.name		= name_s3c2410
	},
	{
		.idcode		= 0x32410002,
		.idmask		= 0xffffffff,
		.map_io		= s3c2410_map_io,
		.init_uarts	= s3c2410_init_uarts,
		.init		= s3c2410a_init,
		.name		= name_s3c2410a
	},
	{
		.idcode		= 0x32440000,
		.idmask		= 0xffffffff,
		.map_io		= s3c2440_map_io,
		.init_uarts	= s3c244x_init_uarts,
		.init		= s3c2440_init,
		.name		= name_s3c2440
	},
	{
		.idcode		= 0x32440001,
		.idmask		= 0xffffffff,
		.map_io		= s3c2440_map_io,
		.init_uarts	= s3c244x_init_uarts,
		.init		= s3c2440_init,
		.name		= name_s3c2440a
	},
	{
		.idcode		= 0x32440aaa,
		.idmask		= 0xffffffff,
		.map_io		= s3c2442_map_io,
		.init_uarts	= s3c244x_init_uarts,
		.init		= s3c2442_init,
		.name		= name_s3c2442
	},
	{
		.idcode		= 0x32440aab,
		.idmask		= 0xffffffff,
		.map_io		= s3c2442_map_io,
		.init_uarts	= s3c244x_init_uarts,
		.init		= s3c2442_init,
		.name		= name_s3c2442b
	},
	{
		.idcode		= 0x32412001,
		.idmask		= 0xffffffff,
		.map_io		= s3c2412_map_io,
		.init_uarts	= s3c2412_init_uarts,
		.init		= s3c2412_init,
		.name		= name_s3c2412,
	},
	{			/* a newer version of the s3c2412 */
		.idcode		= 0x32412003,
		.idmask		= 0xffffffff,
		.map_io		= s3c2412_map_io,
		.init_uarts	= s3c2412_init_uarts,
		.init		= s3c2412_init,
		.name		= name_s3c2412,
	},
	{			/* a strange version of the s3c2416 */
		.idcode		= 0x32450003,
		.idmask		= 0xffffffff,
		.map_io		= s3c2416_map_io,
		.init_uarts	= s3c2416_init_uarts,
		.init		= s3c2416_init,
		.name		= name_s3c2416,
	},
	{
		.idcode		= 0x32443001,
		.idmask		= 0xffffffff,
		.map_io		= s3c2443_map_io,
		.init_uarts	= s3c2443_init_uarts,
		.init		= s3c2443_init,
		.name		= name_s3c2443,
	},
};

/* minimal IO mapping */

static struct map_desc s3c_iodesc[] __initdata __maybe_unused = {
	IODESC_ENT(GPIO),
	IODESC_ENT(IRQ),
	IODESC_ENT(MEMCTRL),
	IODESC_ENT(UART)
};

/* read cpu identification code */

static unsigned long s3c24xx_read_idcode_v5(void)
{
#if defined(CONFIG_CPU_S3C2416)
	/* s3c2416 is v5, with S3C24XX_GSTATUS1 instead of S3C2412_GSTATUS1 */

	u32 gs = __raw_readl(S3C24XX_GSTATUS1);

	/* test for s3c2416 or similar device */
	if ((gs >> 16) == 0x3245)
		return gs;
#endif

#if defined(CONFIG_CPU_S3C2412)
	return __raw_readl(S3C2412_GSTATUS1);
#else
	return 1UL;	/* don't look like an 2400 */
#endif
}

static unsigned long s3c24xx_read_idcode_v4(void)
{
	return __raw_readl(S3C2410_GSTATUS1);
}

static void s3c24xx_default_idle(void)
{
	unsigned long tmp = 0;
	int i;

	/* idle the system by using the idle mode which will wait for an
	 * interrupt to happen before restarting the system.
	 */

	/* Warning: going into idle state upsets jtag scanning */

	__raw_writel(__raw_readl(S3C2410_CLKCON) | S3C2410_CLKCON_IDLE,
		     S3C2410_CLKCON);

	/* the samsung port seems to do a loop and then unset idle.. */
	for (i = 0; i < 50; i++)
		tmp += __raw_readl(S3C2410_CLKCON); /* ensure loop not optimised out */

	/* this bit is not cleared on re-start... */

	__raw_writel(__raw_readl(S3C2410_CLKCON) & ~S3C2410_CLKCON_IDLE,
		     S3C2410_CLKCON);
}

static struct samsung_pwm_variant s3c24xx_pwm_variant = {
	.bits		= 16,
	.div_base	= 1,
	.has_tint_cstat	= false,
	.tclk_mask	= (1 << 4),
};

void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
{
	arm_pm_idle = s3c24xx_default_idle;

	/* initialise the io descriptors we need for initialisation */
	iotable_init(mach_desc, size);
	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));

	if (cpu_architecture() >= CPU_ARCH_ARMv5) {
		samsung_cpu_id = s3c24xx_read_idcode_v5();
	} else {
		samsung_cpu_id = s3c24xx_read_idcode_v4();
	}

	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));

	samsung_pwm_set_platdata(&s3c24xx_pwm_variant);
}

void __init s3c24xx_set_timer_source(unsigned int event, unsigned int source)
{
	s3c24xx_pwm_variant.output_mask = BIT(SAMSUNG_PWM_NUM) - 1;
	s3c24xx_pwm_variant.output_mask &= ~(BIT(event) | BIT(source));
}

void __init s3c24xx_timer_init(void)
{
	unsigned int timer_irqs[SAMSUNG_PWM_NUM] = {
		IRQ_TIMER0, IRQ_TIMER1, IRQ_TIMER2, IRQ_TIMER3, IRQ_TIMER4,
	};

	samsung_pwm_clocksource_init(S3C_VA_TIMER,
					timer_irqs, &s3c24xx_pwm_variant);
}

/* Serial port registrations */

#define S3C2410_PA_UART0      (S3C24XX_PA_UART)
#define S3C2410_PA_UART1      (S3C24XX_PA_UART + 0x4000 )
#define S3C2410_PA_UART2      (S3C24XX_PA_UART + 0x8000 )
#define S3C2443_PA_UART3      (S3C24XX_PA_UART + 0xC000 )

static struct resource s3c2410_uart0_resource[] = {
	[0] = DEFINE_RES_MEM(S3C2410_PA_UART0, SZ_16K),
	[1] = DEFINE_RES_NAMED(IRQ_S3CUART_RX0, \
			IRQ_S3CUART_ERR0 - IRQ_S3CUART_RX0 + 1, \
			NULL, IORESOURCE_IRQ)
};

static struct resource s3c2410_uart1_resource[] = {
	[0] = DEFINE_RES_MEM(S3C2410_PA_UART1, SZ_16K),
	[1] = DEFINE_RES_NAMED(IRQ_S3CUART_RX1, \
			IRQ_S3CUART_ERR1 - IRQ_S3CUART_RX1 + 1, \
			NULL, IORESOURCE_IRQ)
};

static struct resource s3c2410_uart2_resource[] = {
	[0] = DEFINE_RES_MEM(S3C2410_PA_UART2, SZ_16K),
	[1] = DEFINE_RES_NAMED(IRQ_S3CUART_RX2, \
			IRQ_S3CUART_ERR2 - IRQ_S3CUART_RX2 + 1, \
			NULL, IORESOURCE_IRQ)
};

static struct resource s3c2410_uart3_resource[] = {
	[0] = DEFINE_RES_MEM(S3C2443_PA_UART3, SZ_16K),
	[1] = DEFINE_RES_NAMED(IRQ_S3CUART_RX3, \
			IRQ_S3CUART_ERR3 - IRQ_S3CUART_RX3 + 1, \
			NULL, IORESOURCE_IRQ)
};

struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = {
	[0] = {
		.resources	= s3c2410_uart0_resource,
		.nr_resources	= ARRAY_SIZE(s3c2410_uart0_resource),
	},
	[1] = {
		.resources	= s3c2410_uart1_resource,
		.nr_resources	= ARRAY_SIZE(s3c2410_uart1_resource),
	},
	[2] = {
		.resources	= s3c2410_uart2_resource,
		.nr_resources	= ARRAY_SIZE(s3c2410_uart2_resource),
	},
	[3] = {
		.resources	= s3c2410_uart3_resource,
		.nr_resources	= ARRAY_SIZE(s3c2410_uart3_resource),
	},
};

#define s3c24xx_device_dma_mask (*((u64[]) { DMA_BIT_MASK(32) }))

#if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \
	defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
static struct resource s3c2410_dma_resource[] = {
	[0] = DEFINE_RES_MEM(S3C24XX_PA_DMA, S3C24XX_SZ_DMA),
	[1] = DEFINE_RES_IRQ(IRQ_DMA0),
	[2] = DEFINE_RES_IRQ(IRQ_DMA1),
	[3] = DEFINE_RES_IRQ(IRQ_DMA2),
	[4] = DEFINE_RES_IRQ(IRQ_DMA3),
};
#endif

#if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2442)
static struct s3c24xx_dma_channel s3c2410_dma_channels[DMACH_MAX] = {
	[DMACH_XD0] = { S3C24XX_DMA_AHB, true, S3C24XX_DMA_CHANREQ(0, 0), },
	[DMACH_XD1] = { S3C24XX_DMA_AHB, true, S3C24XX_DMA_CHANREQ(0, 1), },
	[DMACH_SDI] = { S3C24XX_DMA_APB, false, S3C24XX_DMA_CHANREQ(2, 0) |
						S3C24XX_DMA_CHANREQ(2, 2) |
						S3C24XX_DMA_CHANREQ(1, 3),
	},
	[DMACH_SPI0] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(3, 1), },
	[DMACH_SPI1] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(2, 3), },
	[DMACH_UART0] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(1, 0), },
	[DMACH_UART1] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(1, 1), },
	[DMACH_UART2] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(0, 3), },
	[DMACH_TIMER] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(3, 0) |
						 S3C24XX_DMA_CHANREQ(3, 2) |
						 S3C24XX_DMA_CHANREQ(3, 3),
	},
	[DMACH_I2S_IN] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(2, 1) |
						  S3C24XX_DMA_CHANREQ(1, 2),
	},
	[DMACH_I2S_OUT] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(0, 2), },
	[DMACH_USB_EP1] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(4, 0), },
	[DMACH_USB_EP2] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(4, 1), },
	[DMACH_USB_EP3] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(4, 2), },
	[DMACH_USB_EP4] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(4, 3), },
};

static const struct dma_slave_map s3c2410_dma_slave_map[] = {
	{ "s3c2410-sdi", "rx-tx", (void *)DMACH_SDI },
	{ "s3c2410-spi.0", "rx", (void *)DMACH_SPI0_RX },
	{ "s3c2410-spi.0", "tx", (void *)DMACH_SPI0_TX },
	{ "s3c2410-spi.1", "rx", (void *)DMACH_SPI1_RX },
	{ "s3c2410-spi.1", "tx", (void *)DMACH_SPI1_TX },
	/*
	 * The DMA request source[1] (DMACH_UARTx_SRC2) are
	 * not used in the UART driver.
	 */
	{ "s3c2410-uart.0", "rx", (void *)DMACH_UART0 },
	{ "s3c2410-uart.0", "tx", (void *)DMACH_UART0 },
	{ "s3c2410-uart.1", "rx", (void *)DMACH_UART1 },
	{ "s3c2410-uart.1", "tx", (void *)DMACH_UART1 },
	{ "s3c2410-uart.2", "rx", (void *)DMACH_UART2 },
	{ "s3c2410-uart.2", "tx", (void *)DMACH_UART2 },
	{ "s3c24xx-iis", "rx", (void *)DMACH_I2S_IN },
	{ "s3c24xx-iis", "tx", (void *)DMACH_I2S_OUT },
	{ "s3c-hsudc", "rx0", (void *)DMACH_USB_EP1 },
	{ "s3c-hsudc", "tx0", (void *)DMACH_USB_EP1 },
	{ "s3c-hsudc", "rx1", (void *)DMACH_USB_EP2 },
	{ "s3c-hsudc", "tx1", (void *)DMACH_USB_EP2 },
	{ "s3c-hsudc", "rx2", (void *)DMACH_USB_EP3 },
	{ "s3c-hsudc", "tx2", (void *)DMACH_USB_EP3 },
	{ "s3c-hsudc", "rx3", (void *)DMACH_USB_EP4 },
	{ "s3c-hsudc", "tx3", (void *)DMACH_USB_EP4 }
};

static struct s3c24xx_dma_platdata s3c2410_dma_platdata = {
	.num_phy_channels = 4,
	.channels = s3c2410_dma_channels,
	.num_channels = DMACH_MAX,
	.slave_map = s3c2410_dma_slave_map,
	.slavecnt = ARRAY_SIZE(s3c2410_dma_slave_map),
};

struct platform_device s3c2410_device_dma = {
	.name		= "s3c2410-dma",
	.id		= 0,
	.num_resources	= ARRAY_SIZE(s3c2410_dma_resource),
	.resource	= s3c2410_dma_resource,
	.dev	= {
		.dma_mask = &s3c24xx_device_dma_mask,
		.coherent_dma_mask = DMA_BIT_MASK(32),
		.platform_data = &s3c2410_dma_platdata,
	},
};
#endif

#ifdef CONFIG_CPU_S3C2412
static struct s3c24xx_dma_channel s3c2412_dma_channels[DMACH_MAX] = {
	[DMACH_XD0] = { S3C24XX_DMA_AHB, true, 17 },
	[DMACH_XD1] = { S3C24XX_DMA_AHB, true, 18 },
	[DMACH_SDI] = { S3C24XX_DMA_APB, false, 10 },
	[DMACH_SPI0_RX] = { S3C24XX_DMA_APB, true, 1 },
	[DMACH_SPI0_TX] = { S3C24XX_DMA_APB, true, 0 },
	[DMACH_SPI1_RX] = { S3C24XX_DMA_APB, true, 3 },
	[DMACH_SPI1_TX] = { S3C24XX_DMA_APB, true, 2 },
	[DMACH_UART0] = { S3C24XX_DMA_APB, true, 19 },
	[DMACH_UART1] = { S3C24XX_DMA_APB, true, 21 },
	[DMACH_UART2] = { S3C24XX_DMA_APB, true, 23 },
	[DMACH_UART0_SRC2] = { S3C24XX_DMA_APB, true, 20 },
	[DMACH_UART1_SRC2] = { S3C24XX_DMA_APB, true, 22 },
	[DMACH_UART2_SRC2] = { S3C24XX_DMA_APB, true, 24 },
	[DMACH_TIMER] = { S3C24XX_DMA_APB, true, 9 },
	[DMACH_I2S_IN] = { S3C24XX_DMA_APB, true, 5 },
	[DMACH_I2S_OUT] = { S3C24XX_DMA_APB, true, 4 },
	[DMACH_USB_EP1] = { S3C24XX_DMA_APB, true, 13 },
	[DMACH_USB_EP2] = { S3C24XX_DMA_APB, true, 14 },
	[DMACH_USB_EP3] = { S3C24XX_DMA_APB, true, 15 },
	[DMACH_USB_EP4] = { S3C24XX_DMA_APB, true, 16 },
};

static const struct dma_slave_map s3c2412_dma_slave_map[] = {
	{ "s3c2412-sdi", "rx-tx", (void *)DMACH_SDI },
	{ "s3c2412-spi.0", "rx", (void *)DMACH_SPI0_RX },
	{ "s3c2412-spi.0", "tx", (void *)DMACH_SPI0_TX },
	{ "s3c2412-spi.1", "rx", (void *)DMACH_SPI1_RX },
	{ "s3c2412-spi.1", "tx", (void *)DMACH_SPI1_TX },
	{ "s3c2440-uart.0", "rx", (void *)DMACH_UART0 },
	{ "s3c2440-uart.0", "tx", (void *)DMACH_UART0 },
	{ "s3c2440-uart.1", "rx", (void *)DMACH_UART1 },
	{ "s3c2440-uart.1", "tx", (void *)DMACH_UART1 },
	{ "s3c2440-uart.2", "rx", (void *)DMACH_UART2 },
	{ "s3c2440-uart.2", "tx", (void *)DMACH_UART2 },
	{ "s3c2412-iis", "rx", (void *)DMACH_I2S_IN },
	{ "s3c2412-iis", "tx", (void *)DMACH_I2S_OUT },
	{ "s3c-hsudc", "rx0", (void *)DMACH_USB_EP1 },
	{ "s3c-hsudc", "tx0", (void *)DMACH_USB_EP1 },
	{ "s3c-hsudc", "rx1", (void *)DMACH_USB_EP2 },
	{ "s3c-hsudc", "tx1", (void *)DMACH_USB_EP2 },
	{ "s3c-hsudc", "rx2", (void *)DMACH_USB_EP3 },
	{ "s3c-hsudc", "tx2", (void *)DMACH_USB_EP3 },
	{ "s3c-hsudc", "rx3", (void *)DMACH_USB_EP4 },
	{ "s3c-hsudc", "tx3", (void *)DMACH_USB_EP4 }
};

static struct s3c24xx_dma_platdata s3c2412_dma_platdata = {
	.num_phy_channels = 4,
	.channels = s3c2412_dma_channels,
	.num_channels = DMACH_MAX,
	.slave_map = s3c2412_dma_slave_map,
	.slavecnt = ARRAY_SIZE(s3c2412_dma_slave_map),
};

struct platform_device s3c2412_device_dma = {
	.name		= "s3c2412-dma",
	.id		= 0,
	.num_resources	= ARRAY_SIZE(s3c2410_dma_resource),
	.resource	= s3c2410_dma_resource,
	.dev	= {
		.dma_mask = &s3c24xx_device_dma_mask,
		.coherent_dma_mask = DMA_BIT_MASK(32),
		.platform_data = &s3c2412_dma_platdata,
	},
};
#endif

#if defined(CONFIG_CPU_S3C2440)
static struct s3c24xx_dma_channel s3c2440_dma_channels[DMACH_MAX] = {
	[DMACH_XD0] = { S3C24XX_DMA_AHB, true, S3C24XX_DMA_CHANREQ(0, 0), },
	[DMACH_XD1] = { S3C24XX_DMA_AHB, true, S3C24XX_DMA_CHANREQ(0, 1), },
	[DMACH_SDI] = { S3C24XX_DMA_APB, false, S3C24XX_DMA_CHANREQ(2, 0) |
						S3C24XX_DMA_CHANREQ(6, 1) |
						S3C24XX_DMA_CHANREQ(2, 2) |
						S3C24XX_DMA_CHANREQ(1, 3),
	},
	[DMACH_SPI0] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(3, 1), },
	[DMACH_SPI1] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(2, 3), },
	[DMACH_UART0] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(1, 0), },
	[DMACH_UART1] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(1, 1), },
	[DMACH_UART2] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(0, 3), },
	[DMACH_TIMER] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(3, 0) |
						 S3C24XX_DMA_CHANREQ(3, 2) |
						 S3C24XX_DMA_CHANREQ(3, 3),
	},
	[DMACH_I2S_IN] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(2, 1) |
						  S3C24XX_DMA_CHANREQ(1, 2),
	},
	[DMACH_I2S_OUT] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(5, 0) |
						   S3C24XX_DMA_CHANREQ(0, 2),
	},
	[DMACH_PCM_IN] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(6, 0) |
						  S3C24XX_DMA_CHANREQ(5, 2),
	},
	[DMACH_PCM_OUT] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(5, 1) |
						  S3C24XX_DMA_CHANREQ(6, 3),
	},
	[DMACH_MIC_IN] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(6, 2) |
						  S3C24XX_DMA_CHANREQ(5, 3),
	},
	[DMACH_USB_EP1] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(4, 0), },
	[DMACH_USB_EP2] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(4, 1), },
	[DMACH_USB_EP3] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(4, 2), },
	[DMACH_USB_EP4] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(4, 3), },
};

static const struct dma_slave_map s3c2440_dma_slave_map[] = {
	/* TODO: DMACH_XD0 */
	/* TODO: DMACH_XD1 */
	{ "s3c2440-sdi", "rx-tx", (void *)DMACH_SDI },
	{ "s3c2410-spi.0", "rx", (void *)DMACH_SPI0 },
	{ "s3c2410-spi.0", "tx", (void *)DMACH_SPI0 },
	{ "s3c2410-spi.1", "rx", (void *)DMACH_SPI1 },
	{ "s3c2410-spi.1", "tx", (void *)DMACH_SPI1 },
	{ "s3c2440-uart.0", "rx", (void *)DMACH_UART0 },
	{ "s3c2440-uart.0", "tx", (void *)DMACH_UART0 },
	{ "s3c2440-uart.1", "rx", (void *)DMACH_UART1 },
	{ "s3c2440-uart.1", "tx", (void *)DMACH_UART1 },
	{ "s3c2440-uart.2", "rx", (void *)DMACH_UART2 },
	{ "s3c2440-uart.2", "tx", (void *)DMACH_UART2 },
	{ "s3c2440-uart.3", "rx", (void *)DMACH_UART3 },
	{ "s3c2440-uart.3", "tx", (void *)DMACH_UART3 },
	/* TODO: DMACH_TIMER */
	{ "s3c24xx-iis", "rx", (void *)DMACH_I2S_IN },
	{ "s3c24xx-iis", "tx", (void *)DMACH_I2S_OUT },
	{ "samsung-ac97", "rx", (void *)DMACH_PCM_IN },
	{ "samsung-ac97", "tx", (void *)DMACH_PCM_OUT },
	{ "samsung-ac97", "rx", (void *)DMACH_MIC_IN },
	{ "s3c-hsudc", "rx0", (void *)DMACH_USB_EP1 },
	{ "s3c-hsudc", "rx1", (void *)DMACH_USB_EP2 },
	{ "s3c-hsudc", "rx2", (void *)DMACH_USB_EP3 },
	{ "s3c-hsudc", "rx3", (void *)DMACH_USB_EP4 },
	{ "s3c-hsudc", "tx0", (void *)DMACH_USB_EP1 },
	{ "s3c-hsudc", "tx1", (void *)DMACH_USB_EP2 },
	{ "s3c-hsudc", "tx2", (void *)DMACH_USB_EP3 },
	{ "s3c-hsudc", "tx3", (void *)DMACH_USB_EP4 }
};

static struct s3c24xx_dma_platdata s3c2440_dma_platdata = {
	.num_phy_channels = 4,
	.channels = s3c2440_dma_channels,
	.num_channels = DMACH_MAX,
	.slave_map = s3c2440_dma_slave_map,
	.slavecnt = ARRAY_SIZE(s3c2440_dma_slave_map),
};

struct platform_device s3c2440_device_dma = {
	.name		= "s3c2410-dma",
	.id		= 0,
	.num_resources	= ARRAY_SIZE(s3c2410_dma_resource),
	.resource	= s3c2410_dma_resource,
	.dev	= {
		.dma_mask = &s3c24xx_device_dma_mask,
		.coherent_dma_mask = DMA_BIT_MASK(32),
		.platform_data = &s3c2440_dma_platdata,
	},
};
#endif

#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2416)
static struct resource s3c2443_dma_resource[] = {
	[0] = DEFINE_RES_MEM(S3C24XX_PA_DMA, S3C24XX_SZ_DMA),
	[1] = DEFINE_RES_IRQ(IRQ_S3C2443_DMA0),
	[2] = DEFINE_RES_IRQ(IRQ_S3C2443_DMA1),
	[3] = DEFINE_RES_IRQ(IRQ_S3C2443_DMA2),
	[4] = DEFINE_RES_IRQ(IRQ_S3C2443_DMA3),
	[5] = DEFINE_RES_IRQ(IRQ_S3C2443_DMA4),
	[6] = DEFINE_RES_IRQ(IRQ_S3C2443_DMA5),
};

static struct s3c24xx_dma_channel s3c2443_dma_channels[DMACH_MAX] = {
	[DMACH_XD0] = { S3C24XX_DMA_AHB, true, 17 },
	[DMACH_XD1] = { S3C24XX_DMA_AHB, true, 18 },
	[DMACH_SDI] = { S3C24XX_DMA_APB, false, 10 },
	[DMACH_SPI0_RX] = { S3C24XX_DMA_APB, true, 1 },
	[DMACH_SPI0_TX] = { S3C24XX_DMA_APB, true, 0 },
	[DMACH_SPI1_RX] = { S3C24XX_DMA_APB, true, 3 },
	[DMACH_SPI1_TX] = { S3C24XX_DMA_APB, true, 2 },
	[DMACH_UART0] = { S3C24XX_DMA_APB, true, 19 },
	[DMACH_UART1] = { S3C24XX_DMA_APB, true, 21 },
	[DMACH_UART2] = { S3C24XX_DMA_APB, true, 23 },
	[DMACH_UART3] = { S3C24XX_DMA_APB, true, 25 },
	[DMACH_UART0_SRC2] = { S3C24XX_DMA_APB, true, 20 },
	[DMACH_UART1_SRC2] = { S3C24XX_DMA_APB, true, 22 },
	[DMACH_UART2_SRC2] = { S3C24XX_DMA_APB, true, 24 },
	[DMACH_UART3_SRC2] = { S3C24XX_DMA_APB, true, 26 },
	[DMACH_TIMER] = { S3C24XX_DMA_APB, true, 9 },
	[DMACH_I2S_IN] = { S3C24XX_DMA_APB, true, 5 },
	[DMACH_I2S_OUT] = { S3C24XX_DMA_APB, true, 4 },
	[DMACH_PCM_IN] = { S3C24XX_DMA_APB, true, 28 },
	[DMACH_PCM_OUT] = { S3C24XX_DMA_APB, true, 27 },
	[DMACH_MIC_IN] = { S3C24XX_DMA_APB, true, 29 },
};

static const struct dma_slave_map s3c2443_dma_slave_map[] = {
	{ "s3c2440-sdi", "rx-tx", (void *)DMACH_SDI },
	{ "s3c2443-spi.0", "rx", (void *)DMACH_SPI0_RX },
	{ "s3c2443-spi.0", "tx", (void *)DMACH_SPI0_TX },
	{ "s3c2443-spi.1", "rx", (void *)DMACH_SPI1_RX },
	{ "s3c2443-spi.1", "tx", (void *)DMACH_SPI1_TX },
	{ "s3c2440-uart.0", "rx", (void *)DMACH_UART0 },
	{ "s3c2440-uart.0", "tx", (void *)DMACH_UART0 },
	{ "s3c2440-uart.1", "rx", (void *)DMACH_UART1 },
	{ "s3c2440-uart.1", "tx", (void *)DMACH_UART1 },
	{ "s3c2440-uart.2", "rx", (void *)DMACH_UART2 },
	{ "s3c2440-uart.2", "tx", (void *)DMACH_UART2 },
	{ "s3c2440-uart.3", "rx", (void *)DMACH_UART3 },
	{ "s3c2440-uart.3", "tx", (void *)DMACH_UART3 },
	{ "s3c24xx-iis", "rx", (void *)DMACH_I2S_IN },
	{ "s3c24xx-iis", "tx", (void *)DMACH_I2S_OUT },
};

static struct s3c24xx_dma_platdata s3c2443_dma_platdata = {
	.num_phy_channels = 6,
	.channels = s3c2443_dma_channels,
	.num_channels = DMACH_MAX,
	.slave_map = s3c2443_dma_slave_map,
	.slavecnt = ARRAY_SIZE(s3c2443_dma_slave_map),
};

struct platform_device s3c2443_device_dma = {
	.name		= "s3c2443-dma",
	.id		= 0,
	.num_resources	= ARRAY_SIZE(s3c2443_dma_resource),
	.resource	= s3c2443_dma_resource,
	.dev	= {
		.dma_mask = &s3c24xx_device_dma_mask,
		.coherent_dma_mask = DMA_BIT_MASK(32),
		.platform_data = &s3c2443_dma_platdata,
	},
};
#endif

#if defined(CONFIG_COMMON_CLK) && defined(CONFIG_CPU_S3C2410)
void __init s3c2410_init_clocks(int xtal)
{
	s3c2410_common_clk_init(NULL, xtal, 0, S3C24XX_VA_CLKPWR);
}
#endif

#ifdef CONFIG_CPU_S3C2412
void __init s3c2412_init_clocks(int xtal)
{
	s3c2412_common_clk_init(NULL, xtal, 0, S3C24XX_VA_CLKPWR);
}
#endif

#ifdef CONFIG_CPU_S3C2416
void __init s3c2416_init_clocks(int xtal)
{
	s3c2443_common_clk_init(NULL, xtal, 0, S3C24XX_VA_CLKPWR);
}
#endif

#if defined(CONFIG_COMMON_CLK) && defined(CONFIG_CPU_S3C2440)
void __init s3c2440_init_clocks(int xtal)
{
	s3c2410_common_clk_init(NULL, xtal, 1, S3C24XX_VA_CLKPWR);
}
#endif

#if defined(CONFIG_COMMON_CLK) && defined(CONFIG_CPU_S3C2442)
void __init s3c2442_init_clocks(int xtal)
{
	s3c2410_common_clk_init(NULL, xtal, 2, S3C24XX_VA_CLKPWR);
}
#endif

#ifdef CONFIG_CPU_S3C2443
void __init s3c2443_init_clocks(int xtal)
{
	s3c2443_common_clk_init(NULL, xtal, 1, S3C24XX_VA_CLKPWR);
}
#endif

#if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2440) || \
	defined(CONFIG_CPU_S3C2442)
static struct resource s3c2410_dclk_resource[] = {
	[0] = DEFINE_RES_MEM(0x56000084, 0x4),
};

static struct s3c2410_clk_platform_data s3c_clk_platform_data = {
	.modify_misccr = s3c2410_modify_misccr,
};

struct platform_device s3c2410_device_dclk = {
	.name		= "s3c2410-dclk",
	.id		= 0,
	.num_resources	= ARRAY_SIZE(s3c2410_dclk_resource),
	.resource	= s3c2410_dclk_resource,
	.dev		= {
		.platform_data = &s3c_clk_platform_data,
	},
};
#endif

#ifndef CONFIG_COMPILE_TEST
#pragma message "The platform is deprecated and scheduled for removal. " \
		"Please reach to the maintainers of the platform " \
		"and linux-samsung-soc@vger.kernel.org if you still use it." \
		"Without such feedback, the platform will be removed after 2022."
#endif


code:
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
 *		http://www.samsung.com
 *
 * Common Header for S3C24XX SoCs
 */

#ifndef __ARCH_ARM_MACH_S3C24XX_COMMON_H
#define __ARCH_ARM_MACH_S3C24XX_COMMON_H __FILE__

#include <linux/reboot.h>
#include "irqs.h"

struct s3c2410_uartcfg;

#ifdef CONFIG_CPU_S3C2410
extern  int s3c2410_init(void);
extern  int s3c2410a_init(void);
extern void s3c2410_map_io(void);
extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
extern void s3c2410_init_clocks(int xtal);
extern void s3c2410_init_irq(void);
#else
#define s3c2410_init_clocks NULL
#define s3c2410_init_uarts NULL
#define s3c2410_map_io NULL
#define s3c2410_init NULL
#define s3c2410a_init NULL
#endif

#ifdef CONFIG_CPU_S3C2412
extern  int s3c2412_init(void);
extern void s3c2412_map_io(void);
extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no);
extern void s3c2412_init_clocks(int xtal);
extern  int s3c2412_baseclk_add(void);
extern void s3c2412_init_irq(void);
#else
#define s3c2412_init_clocks NULL
#define s3c2412_init_uarts NULL
#define s3c2412_map_io NULL
#define s3c2412_init NULL
#endif

#ifdef CONFIG_CPU_S3C2416
extern  int s3c2416_init(void);
extern void s3c2416_map_io(void);
extern void s3c2416_init_uarts(struct s3c2410_uartcfg *cfg, int no);
extern void s3c2416_init_clocks(int xtal);
extern  int s3c2416_baseclk_add(void);
extern void s3c2416_init_irq(void);

extern struct syscore_ops s3c2416_irq_syscore_ops;
#else
#define s3c2416_init_clocks NULL
#define s3c2416_init_uarts NULL
#define s3c2416_map_io NULL
#define s3c2416_init NULL
#endif

#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
extern void s3c244x_map_io(void);
extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no);
#else
#define s3c244x_init_uarts NULL
#endif

#ifdef CONFIG_CPU_S3C2440
extern  int s3c2440_init(void);
extern void s3c2440_map_io(void);
extern void s3c2440_init_clocks(int xtal);
extern void s3c2440_init_irq(void);
#else
#define s3c2440_init NULL
#define s3c2440_map_io NULL
#endif

#ifdef CONFIG_CPU_S3C2442
extern  int s3c2442_init(void);
extern void s3c2442_map_io(void);
extern void s3c2442_init_clocks(int xtal);
extern void s3c2442_init_irq(void);
#else
#define s3c2442_init NULL
#define s3c2442_map_io NULL
#endif

#ifdef CONFIG_CPU_S3C2443
extern  int s3c2443_init(void);
extern void s3c2443_map_io(void);
extern void s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no);
extern void s3c2443_init_clocks(int xtal);
extern  int s3c2443_baseclk_add(void);
extern void s3c2443_init_irq(void);
#else
#define s3c2443_init_clocks NULL
#define s3c2443_init_uarts NULL
#define s3c2443_map_io NULL
#define s3c2443_init NULL
#endif

extern struct syscore_ops s3c24xx_irq_syscore_ops;

extern struct platform_device s3c2410_device_dma;
extern struct platform_device s3c2412_device_dma;
extern struct platform_device s3c2440_device_dma;
extern struct platform_device s3c2443_device_dma;

extern struct platform_device s3c2410_device_dclk;

enum s3c24xx_timer_mode {
	S3C24XX_PWM0,
	S3C24XX_PWM1,
	S3C24XX_PWM2,
	S3C24XX_PWM3,
	S3C24XX_PWM4,
};

extern void __init s3c24xx_set_timer_source(enum s3c24xx_timer_mode event,
					    enum s3c24xx_timer_mode source);
extern void __init s3c24xx_timer_init(void);

#endif /* __ARCH_ARM_MACH_S3C24XX_COMMON_H */

repo_name: angery/linux


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright 2009 Simtec Electronics
//	Ben Dooks <ben@simtec.co.uk>
//	http://armlinux.simtec.co.uk/

/*
 * NOTE: Code in this file is not used when booting with Device Tree support.
 */

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/device.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/platform_device.h>
#include <linux/of.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>

#include <asm/irq.h>

#include "regs-clock.h"

#include "cpu.h"
#include "devs.h"
#include "sdhci.h"
#include "iic-core.h"

#include "s3c64xx.h"
#include "onenand-core-s3c64xx.h"

void __init s3c6400_map_io(void)
{
	/* setup SDHCI */

	s3c6400_default_sdhci0();
	s3c6400_default_sdhci1();
	s3c6400_default_sdhci2();

	/* the i2c devices are directly compatible with s3c2440 */
	s3c_i2c0_setname("s3c2440-i2c");

	s3c_device_nand.name = "s3c6400-nand";

	s3c_onenand_setname("s3c6400-onenand");
	s3c64xx_onenand1_setname("s3c6400-onenand");
}

void __init s3c6400_init_irq(void)
{
	/* VIC0 does not have IRQS 5..7,
	 * VIC1 is fully populated. */
	s3c64xx_init_irq(~0 & ~(0xf << 5), ~0);
}

static struct bus_type s3c6400_subsys = {
	.name		= "s3c6400-core",
	.dev_name	= "s3c6400-core",
};

static struct device s3c6400_dev = {
	.bus	= &s3c6400_subsys,
};

static int __init s3c6400_core_init(void)
{
	/* Not applicable when using DT. */
	if (of_have_populated_dt() || soc_is_s3c64xx())
		return 0;

	return subsys_system_register(&s3c6400_subsys, NULL);
}

core_initcall(s3c6400_core_init);

int __init s3c6400_init(void)
{
	printk("S3C6400: Initialising architecture\n");

	return device_register(&s3c6400_dev);
}


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright 2008 Simtec Electronics
// Copyright 2008 Simtec Electronics
//	Ben Dooks <ben@simtec.co.uk>
//	http://armlinux.simtec.co.uk/

/*
 * NOTE: Code in this file is not used when booting with Device Tree support.
 */

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/device.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/platform_device.h>
#include <linux/of.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>

#include <asm/irq.h>

#include <linux/soc/samsung/s3c-pm.h>
#include "regs-clock.h"

#include "cpu.h"
#include "devs.h"
#include "sdhci.h"
#include "adc-core.h"
#include "iic-core.h"

#include "ata-core-s3c64xx.h"
#include "s3c64xx.h"
#include "onenand-core-s3c64xx.h"

void __init s3c6410_map_io(void)
{
	/* initialise device information early */
	s3c6410_default_sdhci0();
	s3c6410_default_sdhci1();
	s3c6410_default_sdhci2();

	/* the i2c devices are directly compatible with s3c2440 */
	s3c_i2c0_setname("s3c2440-i2c");
	s3c_i2c1_setname("s3c2440-i2c");

	s3c_adc_setname("s3c64xx-adc");
	s3c_device_nand.name = "s3c6400-nand";
	s3c_onenand_setname("s3c6410-onenand");
	s3c64xx_onenand1_setname("s3c6410-onenand");
	s3c_cfcon_setname("s3c64xx-pata");
}

void __init s3c6410_init_irq(void)
{
	/* VIC0 is missing IRQ7, VIC1 is fully populated. */
	s3c64xx_init_irq(~0 & ~(1 << 7), ~0);
}

struct bus_type s3c6410_subsys = {
	.name		= "s3c6410-core",
	.dev_name	= "s3c6410-core",
};

static struct device s3c6410_dev = {
	.bus	= &s3c6410_subsys,
};

static int __init s3c6410_core_init(void)
{
	/* Not applicable when using DT. */
	if (of_have_populated_dt() || !soc_is_s3c64xx())
		return 0;

	return subsys_system_register(&s3c6410_subsys, NULL);
}

core_initcall(s3c6410_core_init);

int __init s3c6410_init(void)
{
	printk("S3C6410: Initialising architecture\n");

	return device_register(&s3c6410_dev);
}


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2011 Samsung Electronics Co., Ltd.
//		http://www.samsung.com
//
// Copyright 2008 Openmoko, Inc.
// Copyright 2008 Simtec Electronics
//	Ben Dooks <ben@simtec.co.uk>
//	http://armlinux.simtec.co.uk/
//
// Common Codes for S3C64XX machines

/*
 * NOTE: Code in this file is not used when booting with Device Tree support.
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/io.h>
#include <linux/clk/samsung.h>
#include <linux/dma-mapping.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/irqchip/arm-vic.h>
#include <clocksource/samsung_pwm.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/system_misc.h>

#include "map.h"
#include "irqs.h"
#include "regs-gpio.h"
#include "gpio-samsung.h"

#include "cpu.h"
#include "devs.h"
#include "pm.h"
#include "gpio-cfg.h"
#include "pwm-core.h"
#include "regs-irqtype.h"
#include "s3c64xx.h"
#include "irq-uart-s3c64xx.h"

/* External clock frequency */
static unsigned long xtal_f __ro_after_init = 12000000;
static unsigned long xusbxti_f __ro_after_init = 48000000;

void __init s3c64xx_set_xtal_freq(unsigned long freq)
{
	xtal_f = freq;
}

void __init s3c64xx_set_xusbxti_freq(unsigned long freq)
{
	xusbxti_f = freq;
}

/* uart registration process */

static void __init s3c64xx_init_uarts(struct s3c2410_uartcfg *cfg, int no)
{
	s3c24xx_init_uartdevs("s3c6400-uart", s3c64xx_uart_resources, cfg, no);
}

/* table of supported CPUs */

static const char name_s3c6400[] = "S3C6400";
static const char name_s3c6410[] = "S3C6410";

static struct cpu_table cpu_ids[] __initdata = {
	{
		.idcode		= S3C6400_CPU_ID,
		.idmask		= S3C64XX_CPU_MASK,
		.map_io		= s3c6400_map_io,
		.init_uarts	= s3c64xx_init_uarts,
		.init		= s3c6400_init,
		.name		= name_s3c6400,
	}, {
		.idcode		= S3C6410_CPU_ID,
		.idmask		= S3C64XX_CPU_MASK,
		.map_io		= s3c6410_map_io,
		.init_uarts	= s3c64xx_init_uarts,
		.init		= s3c6410_init,
		.name		= name_s3c6410,
	},
};

/* minimal IO mapping */

/*
 * note, for the boot process to work we have to keep the UART
 * virtual address aligned to an 1MiB boundary for the L1
 * mapping the head code makes. We keep the UART virtual address
 * aligned and add in the offset when we load the value here.
 */
#define UART_OFFS (S3C_PA_UART & 0xfffff)

static struct map_desc s3c_iodesc[] __initdata = {
	{
		.virtual	= (unsigned long)S3C_VA_SYS,
		.pfn		= __phys_to_pfn(S3C64XX_PA_SYSCON),
		.length		= SZ_4K,
		.type		= MT_DEVICE,
	}, {
		.virtual	= (unsigned long)S3C_VA_MEM,
		.pfn		= __phys_to_pfn(S3C64XX_PA_SROM),
		.length		= SZ_4K,
		.type		= MT_DEVICE,
	}, {
		.virtual	= (unsigned long)(S3C_VA_UART + UART_OFFS),
		.pfn		= __phys_to_pfn(S3C_PA_UART),
		.length		= SZ_4K,
		.type		= MT_DEVICE,
	}, {
		.virtual	= (unsigned long)VA_VIC0,
		.pfn		= __phys_to_pfn(S3C64XX_PA_VIC0),
		.length		= SZ_16K,
		.type		= MT_DEVICE,
	}, {
		.virtual	= (unsigned long)VA_VIC1,
		.pfn		= __phys_to_pfn(S3C64XX_PA_VIC1),
		.length		= SZ_16K,
		.type		= MT_DEVICE,
	}, {
		.virtual	= (unsigned long)S3C_VA_TIMER,
		.pfn		= __phys_to_pfn(S3C_PA_TIMER),
		.length		= SZ_16K,
		.type		= MT_DEVICE,
	}, {
		.virtual	= (unsigned long)S3C64XX_VA_GPIO,
		.pfn		= __phys_to_pfn(S3C64XX_PA_GPIO),
		.length		= SZ_4K,
		.type		= MT_DEVICE,
	}, {
		.virtual	= (unsigned long)S3C64XX_VA_MODEM,
		.pfn		= __phys_to_pfn(S3C64XX_PA_MODEM),
		.length		= SZ_4K,
		.type		= MT_DEVICE,
	}, {
		.virtual	= (unsigned long)S3C_VA_WATCHDOG,
		.pfn		= __phys_to_pfn(S3C64XX_PA_WATCHDOG),
		.length		= SZ_4K,
		.type		= MT_DEVICE,
	}, {
		.virtual	= (unsigned long)S3C_VA_USB_HSPHY,
		.pfn		= __phys_to_pfn(S3C64XX_PA_USB_HSPHY),
		.length		= SZ_1K,
		.type		= MT_DEVICE,
	},
};

static struct bus_type s3c64xx_subsys = {
	.name		= "s3c64xx-core",
	.dev_name	= "s3c64xx-core",
};

static struct device s3c64xx_dev = {
	.bus	= &s3c64xx_subsys,
};

static struct samsung_pwm_variant s3c64xx_pwm_variant = {
	.bits		= 32,
	.div_base	= 0,
	.has_tint_cstat	= true,
	.tclk_mask	= (1 << 7) | (1 << 6) | (1 << 5),
};

void __init s3c64xx_set_timer_source(unsigned int event, unsigned int source)
{
	s3c64xx_pwm_variant.output_mask = BIT(SAMSUNG_PWM_NUM) - 1;
	s3c64xx_pwm_variant.output_mask &= ~(BIT(event) | BIT(source));
}

void __init s3c64xx_timer_init(void)
{
	unsigned int timer_irqs[SAMSUNG_PWM_NUM] = {
		IRQ_TIMER0_VIC, IRQ_TIMER1_VIC, IRQ_TIMER2_VIC,
		IRQ_TIMER3_VIC, IRQ_TIMER4_VIC,
	};

	samsung_pwm_clocksource_init(S3C_VA_TIMER,
					timer_irqs, &s3c64xx_pwm_variant);
}

/* read cpu identification code */

void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
{
	/* initialise the io descriptors we need for initialisation */
	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
	iotable_init(mach_desc, size);

	/* detect cpu id */
	s3c64xx_init_cpu();

	s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));

	samsung_pwm_set_platdata(&s3c64xx_pwm_variant);
}

static __init int s3c64xx_dev_init(void)
{
	/* Not applicable when using DT. */
	if (of_have_populated_dt() || !soc_is_s3c64xx())
		return 0;

	subsys_system_register(&s3c64xx_subsys, NULL);
	return device_register(&s3c64xx_dev);
}
core_initcall(s3c64xx_dev_init);

/*
 * setup the sources the vic should advertise resume
 * for, even though it is not doing the wake
 * (set_irq_wake needs to be valid)
 */
#define IRQ_VIC0_RESUME (1 << (IRQ_RTC_TIC - IRQ_VIC0_BASE))
#define IRQ_VIC1_RESUME (1 << (IRQ_RTC_ALARM - IRQ_VIC1_BASE) |	\
			 1 << (IRQ_PENDN - IRQ_VIC1_BASE) |	\
			 1 << (IRQ_HSMMC0 - IRQ_VIC1_BASE) |	\
			 1 << (IRQ_HSMMC1 - IRQ_VIC1_BASE) |	\
			 1 << (IRQ_HSMMC2 - IRQ_VIC1_BASE))

void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
{
	s3c64xx_clk_init(NULL, xtal_f, xusbxti_f, soc_is_s3c6400(), S3C_VA_SYS);

	printk(KERN_DEBUG "%s: initialising interrupts\n", __func__);

	/* initialise the pair of VICs */
	vic_init(VA_VIC0, IRQ_VIC0_BASE, vic0_valid, IRQ_VIC0_RESUME);
	vic_init(VA_VIC1, IRQ_VIC1_BASE, vic1_valid, IRQ_VIC1_RESUME);
}

#define eint_offset(irq)	((irq) - IRQ_EINT(0))
#define eint_irq_to_bit(irq)	((u32)(1 << eint_offset(irq)))

static inline void s3c_irq_eint_mask(struct irq_data *data)
{
	u32 mask;

	mask = __raw_readl(S3C64XX_EINT0MASK);
	mask |= (u32)data->chip_data;
	__raw_writel(mask, S3C64XX_EINT0MASK);
}

static void s3c_irq_eint_unmask(struct irq_data *data)
{
	u32 mask;

	mask = __raw_readl(S3C64XX_EINT0MASK);
	mask &= ~((u32)data->chip_data);
	__raw_writel(mask, S3C64XX_EINT0MASK);
}

static inline void s3c_irq_eint_ack(struct irq_data *data)
{
	__raw_writel((u32)data->chip_data, S3C64XX_EINT0PEND);
}

static void s3c_irq_eint_maskack(struct irq_data *data)
{
	/* compiler should in-line these */
	s3c_irq_eint_mask(data);
	s3c_irq_eint_ack(data);
}

static int s3c_irq_eint_set_type(struct irq_data *data, unsigned int type)
{
	int offs = eint_offset(data->irq);
	int pin, pin_val;
	int shift;
	u32 ctrl, mask;
	u32 newvalue = 0;
	void __iomem *reg;

	if (offs > 27)
		return -EINVAL;

	if (offs <= 15)
		reg = S3C64XX_EINT0CON0;
	else
		reg = S3C64XX_EINT0CON1;

	switch (type) {
	case IRQ_TYPE_NONE:
		printk(KERN_WARNING "No edge setting!\n");
		break;

	case IRQ_TYPE_EDGE_RISING:
		newvalue = S3C2410_EXTINT_RISEEDGE;
		break;

	case IRQ_TYPE_EDGE_FALLING:
		newvalue = S3C2410_EXTINT_FALLEDGE;
		break;

	case IRQ_TYPE_EDGE_BOTH:
		newvalue = S3C2410_EXTINT_BOTHEDGE;
		break;

	case IRQ_TYPE_LEVEL_LOW:
		newvalue = S3C2410_EXTINT_LOWLEV;
		break;

	case IRQ_TYPE_LEVEL_HIGH:
		newvalue = S3C2410_EXTINT_HILEV;
		break;

	default:
		printk(KERN_ERR "No such irq type %d", type);
		return -1;
	}

	if (offs <= 15)
		shift = (offs / 2) * 4;
	else
		shift = ((offs - 16) / 2) * 4;
	mask = 0x7 << shift;

	ctrl = __raw_readl(reg);
	ctrl &= ~mask;
	ctrl |= newvalue << shift;
	__raw_writel(ctrl, reg);

	/* set the GPIO pin appropriately */

	if (offs < 16) {
		pin = S3C64XX_GPN(offs);
		pin_val = S3C_GPIO_SFN(2);
	} else if (offs < 23) {
		pin = S3C64XX_GPL(offs + 8 - 16);
		pin_val = S3C_GPIO_SFN(3);
	} else {
		pin = S3C64XX_GPM(offs - 23);
		pin_val = S3C_GPIO_SFN(3);
	}

	s3c_gpio_cfgpin(pin, pin_val);

	return 0;
}

static struct irq_chip s3c_irq_eint = {
	.name		= "s3c-eint",
	.irq_mask	= s3c_irq_eint_mask,
	.irq_unmask	= s3c_irq_eint_unmask,
	.irq_mask_ack	= s3c_irq_eint_maskack,
	.irq_ack	= s3c_irq_eint_ack,
	.irq_set_type	= s3c_irq_eint_set_type,
	.irq_set_wake	= s3c_irqext_wake,
};

/* s3c_irq_demux_eint
 *
 * This function demuxes the IRQ from the group0 external interrupts,
 * from IRQ_EINT(0) to IRQ_EINT(27). It is designed to be inlined into
 * the specific handlers s3c_irq_demux_eintX_Y.
 */
static inline void s3c_irq_demux_eint(unsigned int start, unsigned int end)
{
	u32 status = __raw_readl(S3C64XX_EINT0PEND);
	u32 mask = __raw_readl(S3C64XX_EINT0MASK);
	unsigned int irq;

	status &= ~mask;
	status >>= start;
	status &= (1 << (end - start + 1)) - 1;

	for (irq = IRQ_EINT(start); irq <= IRQ_EINT(end); irq++) {
		if (status & 1)
			generic_handle_irq(irq);

		status >>= 1;
	}
}

static void s3c_irq_demux_eint0_3(struct irq_desc *desc)
{
	s3c_irq_demux_eint(0, 3);
}

static void s3c_irq_demux_eint4_11(struct irq_desc *desc)
{
	s3c_irq_demux_eint(4, 11);
}

static void s3c_irq_demux_eint12_19(struct irq_desc *desc)
{
	s3c_irq_demux_eint(12, 19);
}

static void s3c_irq_demux_eint20_27(struct irq_desc *desc)
{
	s3c_irq_demux_eint(20, 27);
}

static int __init s3c64xx_init_irq_eint(void)
{
	int irq;

	/* On DT-enabled systems EINTs are handled by pinctrl-s3c64xx driver. */
	if (of_have_populated_dt() || !soc_is_s3c64xx())
		return -ENODEV;

	for (irq = IRQ_EINT(0); irq <= IRQ_EINT(27); irq++) {
		irq_set_chip_and_handler(irq, &s3c_irq_eint, handle_level_irq);
		irq_set_chip_data(irq, (void *)eint_irq_to_bit(irq));
		irq_clear_status_flags(irq, IRQ_NOREQUEST);
	}

	irq_set_chained_handler(IRQ_EINT0_3, s3c_irq_demux_eint0_3);
	irq_set_chained_handler(IRQ_EINT4_11, s3c_irq_demux_eint4_11);
	irq_set_chained_handler(IRQ_EINT12_19, s3c_irq_demux_eint12_19);
	irq_set_chained_handler(IRQ_EINT20_27, s3c_irq_demux_eint20_27);

	return 0;
}
arch_initcall(s3c64xx_init_irq_eint);

#ifndef CONFIG_COMPILE_TEST
#pragma message "The platform is deprecated and scheduled for removal. " \
		"Please reach to the maintainers of the platform " \
		"and linux-samsung-soc@vger.kernel.org if you still use it." \
		"Without such feedback, the platform will be removed after 2024."
#endif


code:
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
 *		http://www.samsung.com
 *
 * Copyright 2008 Openmoko, Inc.
 * Copyright 2008 Simtec Electronics
 *	Ben Dooks <ben@simtec.co.uk>
 *	http://armlinux.simtec.co.uk/
 *
 * Common Header for S3C64XX machines
 */

#ifndef __ARCH_ARM_MACH_S3C64XX_COMMON_H
#define __ARCH_ARM_MACH_S3C64XX_COMMON_H

#include <linux/reboot.h>

void s3c64xx_init_irq(u32 vic0, u32 vic1);
void s3c64xx_init_io(struct map_desc *mach_desc, int size);

struct device_node;
void s3c64xx_set_xtal_freq(unsigned long freq);
void s3c64xx_set_xusbxti_freq(unsigned long freq);

#ifdef CONFIG_CPU_S3C6400

extern  int s3c6400_init(void);
extern void s3c6400_init_irq(void);
extern void s3c6400_map_io(void);

#else
#define s3c6400_map_io NULL
#define s3c6400_init NULL
#endif

#ifdef CONFIG_CPU_S3C6410

extern  int s3c6410_init(void);
extern void s3c6410_init_irq(void);
extern void s3c6410_map_io(void);

#else
#define s3c6410_map_io NULL
#define s3c6410_init NULL
#endif

#ifdef CONFIG_S3C64XX_PL080
extern struct pl08x_platform_data s3c64xx_dma0_plat_data;
extern struct pl08x_platform_data s3c64xx_dma1_plat_data;
#endif

/* Samsung HR-Timer Clock mode */
enum s3c64xx_timer_mode {
	S3C64XX_PWM0,
	S3C64XX_PWM1,
	S3C64XX_PWM2,
	S3C64XX_PWM3,
	S3C64XX_PWM4,
};

extern void __init s3c64xx_set_timer_source(enum s3c64xx_timer_mode event,
					    enum s3c64xx_timer_mode source);
extern void __init s3c64xx_timer_init(void);

#endif /* __ARCH_ARM_MACH_S3C64XX_COMMON_H */


code:
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
 *		http://www.samsung.com
 *
 * Copyright 2008 Openmoko, Inc.
 * Copyright 2008 Simtec Electronics
 *	http://armlinux.simtec.co.uk/
 *	Ben Dooks <ben@simtec.co.uk>
 *
 * S3C Platform - SDHCI (HSMMC) platform data definitions
 */

#ifndef __PLAT_S3C_SDHCI_H
#define __PLAT_S3C_SDHCI_H __FILE__

#include <linux/platform_data/mmc-sdhci-s3c.h>
#include "devs.h"

/* s3c_sdhci_set_platdata() - common helper for setting SDHCI platform data
 * @pd: The default platform data for this device.
 * @set: Pointer to the platform data to fill in.
 */
extern void s3c_sdhci_set_platdata(struct s3c_sdhci_platdata *pd,
				    struct s3c_sdhci_platdata *set);

/**
 * s3c_sdhci0_set_platdata - Set platform data for S3C SDHCI device.
 * @pd: Platform data to register to device.
 *
 * Register the given platform data for use withe S3C SDHCI device.
 * The call will copy the platform data, so the board definitions can
 * make the structure itself __initdata.
 */
extern void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd);
extern void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd);
extern void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd);
extern void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd);

/* Default platform data, exported so that per-cpu initialisation can
 * set the correct one when there are more than one cpu type selected.
*/

extern struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata;
extern struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata;
extern struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata;
extern struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata;

/* Helper function availability */

extern void s3c2416_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
extern void s3c2416_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
extern void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
extern void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
extern void s3c64xx_setup_sdhci2_cfg_gpio(struct platform_device *, int w);

/* S3C2416 SDHCI setup */

#ifdef CONFIG_S3C2416_SETUP_SDHCI
static inline void s3c2416_default_sdhci0(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC
	s3c_hsmmc0_def_platdata.cfg_gpio = s3c2416_setup_sdhci0_cfg_gpio;
#endif /* CONFIG_S3C_DEV_HSMMC */
}

static inline void s3c2416_default_sdhci1(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC1
	s3c_hsmmc1_def_platdata.cfg_gpio = s3c2416_setup_sdhci1_cfg_gpio;
#endif /* CONFIG_S3C_DEV_HSMMC1 */
}

#else
static inline void s3c2416_default_sdhci0(void) { }
static inline void s3c2416_default_sdhci1(void) { }

#endif /* CONFIG_S3C2416_SETUP_SDHCI */

/* S3C64XX SDHCI setup */

#ifdef CONFIG_S3C64XX_SETUP_SDHCI
static inline void s3c6400_default_sdhci0(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC
	s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
#endif
}

static inline void s3c6400_default_sdhci1(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC1
	s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
#endif
}

static inline void s3c6400_default_sdhci2(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC2
	s3c_hsmmc2_def_platdata.cfg_gpio = s3c64xx_setup_sdhci2_cfg_gpio;
#endif
}

static inline void s3c6410_default_sdhci0(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC
	s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
#endif
}

static inline void s3c6410_default_sdhci1(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC1
	s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
#endif
}

static inline void s3c6410_default_sdhci2(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC2
	s3c_hsmmc2_def_platdata.cfg_gpio = s3c64xx_setup_sdhci2_cfg_gpio;
#endif
}

#else
static inline void s3c6410_default_sdhci0(void) { }
static inline void s3c6410_default_sdhci1(void) { }
static inline void s3c6410_default_sdhci2(void) { }
static inline void s3c6400_default_sdhci0(void) { }
static inline void s3c6400_default_sdhci1(void) { }
static inline void s3c6400_default_sdhci2(void) { }

#endif /* CONFIG_S3C64XX_SETUP_SDHCI */

static inline void s3c_sdhci_setname(int id, char *name)
{
	switch (id) {
#ifdef CONFIG_S3C_DEV_HSMMC
	case 0:
		s3c_device_hsmmc0.name = name;
		break;
#endif
#ifdef CONFIG_S3C_DEV_HSMMC1
	case 1:
		s3c_device_hsmmc1.name = name;
		break;
#endif
#ifdef CONFIG_S3C_DEV_HSMMC2
	case 2:
		s3c_device_hsmmc2.name = name;
		break;
#endif
#ifdef CONFIG_S3C_DEV_HSMMC3
	case 3:
		s3c_device_hsmmc3.name = name;
		break;
#endif
	default:
		break;
	}
}
#endif /* __PLAT_S3C_SDHCI_H */


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright 2008 Openmoko, Inc.
// Copyright 2008 Simtec Electronics
//	Ben Dooks <ben@simtec.co.uk>
//	http://armlinux.simtec.co.uk/
//
// Base S3C64XX setup information for 24bpp LCD framebuffer

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fb.h>
#include <linux/gpio.h>

#include "fb.h"
#include "gpio-cfg.h"
#include "gpio-samsung.h"

void s3c64xx_fb_gpio_setup_24bpp(void)
{
	s3c_gpio_cfgrange_nopull(S3C64XX_GPI(0), 16, S3C_GPIO_SFN(2));
	s3c_gpio_cfgrange_nopull(S3C64XX_GPJ(0), 12, S3C_GPIO_SFN(2));
}


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright 2008 Simtec Electronics
//	Ben Dooks <ben@simtec.co.uk>
//
// S3C24XX Base setup for i2c device

#include <linux/kernel.h>
#include <linux/gpio.h>

struct platform_device;

#include <linux/platform_data/i2c-s3c2410.h>

#include "gpio-cfg.h"
#include "regs-gpio.h"
#include "gpio-samsung.h"

void s3c_i2c0_cfg_gpio(struct platform_device *dev)
{
	s3c_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPE15_IICSDA);
	s3c_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPE14_IICSCL);
}


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright 2008 Openmoko, Inc.
// Copyright 2008 Simtec Electronics
//	Ben Dooks <ben@simtec.co.uk>
//	http://armlinux.simtec.co.uk/
//
// Base S3C64XX I2C bus 0 gpio configuration

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/gpio.h>

struct platform_device; /* don't need the contents */

#include <linux/platform_data/i2c-s3c2410.h>
#include "gpio-cfg.h"
#include "gpio-samsung.h"

void s3c_i2c0_cfg_gpio(struct platform_device *dev)
{
	s3c_gpio_cfgall_range(S3C64XX_GPB(5), 2,
			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
}


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright 2008 Openmoko, Inc.
// Copyright 2008 Simtec Electronics
//	Ben Dooks <ben@simtec.co.uk>
//	http://armlinux.simtec.co.uk/
//
// Base S3C64XX I2C bus 1 gpio configuration

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/gpio.h>

struct platform_device; /* don't need the contents */

#include <linux/platform_data/i2c-s3c2410.h>
#include "gpio-cfg.h"
#include "gpio-samsung.h"

void s3c_i2c1_cfg_gpio(struct platform_device *dev)
{
	s3c_gpio_cfgall_range(S3C64XX_GPB(2), 2,
			      S3C_GPIO_SFN(6), S3C_GPIO_PULL_UP);
}


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2010 Samsung Electronics Co., Ltd.
//		http://www.samsung.com/
//
// S3C64XX setup information for IDE

#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/io.h>

#include <linux/platform_data/ata-samsung_cf.h>

#include "map.h"
#include "regs-clock.h"
#include "gpio-cfg.h"
#include "gpio-samsung.h"

void s3c64xx_ide_setup_gpio(void)
{
	u32 reg;

	reg = readl(S3C_MEM_SYS_CFG) & (~0x3f);

	/* Independent CF interface, CF chip select configuration */
	writel(reg | MEM_SYS_CFG_INDEP_CF |
		MEM_SYS_CFG_EBI_FIX_PRI_CFCON, S3C_MEM_SYS_CFG);

	s3c_gpio_cfgpin(S3C64XX_GPB(4), S3C_GPIO_SFN(4));

	/* Set XhiDATA[15:0] pins as CF Data[15:0] */
	s3c_gpio_cfgpin_range(S3C64XX_GPK(0), 16, S3C_GPIO_SFN(5));

	/* Set XhiADDR[2:0] pins as CF ADDR[2:0] */
	s3c_gpio_cfgpin_range(S3C64XX_GPL(0), 3, S3C_GPIO_SFN(6));

	/* Set Xhi ctrl pins as CF ctrl pins(IORDY, IOWR, IORD, CE[0:1]) */
	s3c_gpio_cfgpin(S3C64XX_GPM(5), S3C_GPIO_SFN(1));
	s3c_gpio_cfgpin_range(S3C64XX_GPM(0), 5, S3C_GPIO_SFN(6));
}


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2010 Samsung Electronics Co., Ltd.
//		http://www.samsung.com/
//
// GPIO configuration for S3C64XX KeyPad device

#include <linux/gpio.h>
#include "gpio-cfg.h"
#include "keypad.h"
#include "gpio-samsung.h"

void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols)
{
	/* Set all the necessary GPK pins to special-function 3: KP_ROW[x] */
	s3c_gpio_cfgrange_nopull(S3C64XX_GPK(8), rows, S3C_GPIO_SFN(3));

	/* Set all the necessary GPL pins to special-function 3: KP_COL[x] */
	s3c_gpio_cfgrange_nopull(S3C64XX_GPL(0), cols, S3C_GPIO_SFN(3));
}


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright 2010 Promwad Innovation Company
//	Yauhen Kharuzhy <yauhen.kharuzhy@promwad.com>
//
// S3C2416 - Helper functions for setting up SDHCI device(s) GPIO (HSMMC)
//
// Based on mach-s3c64xx/setup-sdhci-gpio.c

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio.h>

#include "regs-gpio.h"
#include "gpio-samsung.h"
#include "gpio-cfg.h"
#include "sdhci.h"

void s3c2416_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
{
	s3c_gpio_cfgrange_nopull(S3C2410_GPE(5), 2 + width, S3C_GPIO_SFN(2));
}

void s3c2416_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
{
	s3c_gpio_cfgrange_nopull(S3C2410_GPL(0), width, S3C_GPIO_SFN(2));
	s3c_gpio_cfgrange_nopull(S3C2410_GPL(8), 2, S3C_GPIO_SFN(2));
}


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright 2008 Simtec Electronics
//	Ben Dooks <ben@simtec.co.uk>
//	http://armlinux.simtec.co.uk/
//
// S3C64XX - Helper functions for setting up SDHCI device(s) GPIO (HSMMC)

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio.h>

#include "gpio-cfg.h"
#include "sdhci.h"
#include "gpio-samsung.h"

void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
{
	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;

	/* Set all the necessary GPG pins to special-function 2 */
	s3c_gpio_cfgrange_nopull(S3C64XX_GPG(0), 2 + width, S3C_GPIO_SFN(2));

	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
		s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
		s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(2));
	}
}

void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
{
	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;

	/* Set all the necessary GPH pins to special-function 2 */
	s3c_gpio_cfgrange_nopull(S3C64XX_GPH(0), 2 + width, S3C_GPIO_SFN(2));

	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
		s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
		s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(3));
	}
}

void s3c64xx_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
{
	/* Set all the necessary GPH pins to special-function 3 */
	s3c_gpio_cfgrange_nopull(S3C64XX_GPH(6), width, S3C_GPIO_SFN(3));

	/* Set all the necessary GPC pins to special-function 3 */
	s3c_gpio_cfgrange_nopull(S3C64XX_GPC(4), 2, S3C_GPIO_SFN(3));
}


code:
// SPDX-License-Identifier: GPL-2.0
//
// HS-SPI device setup for S3C2443/S3C2416
//
// Copyright (C) 2011 Samsung Electronics Ltd.
//		http://www.samsung.com/

#include <linux/gpio.h>
#include <linux/platform_device.h>

#include "gpio-cfg.h"

#include "hardware-s3c24xx.h"
#include "regs-gpio.h"

#ifdef CONFIG_S3C64XX_DEV_SPI0
int s3c64xx_spi0_cfg_gpio(void)
{
	/* enable hsspi bit in misccr */
	s3c2410_modify_misccr(S3C2416_MISCCR_HSSPI_EN2, 1);

	s3c_gpio_cfgall_range(S3C2410_GPE(11), 3,
			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);

	return 0;
}
#endif


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (C) 2011 Samsung Electronics Ltd.
//		http://www.samsung.com/

#include <linux/gpio.h>
#include <linux/platform_data/spi-s3c64xx.h>
#include "gpio-cfg.h"
#include "gpio-samsung.h"

#ifdef CONFIG_S3C64XX_DEV_SPI0
int s3c64xx_spi0_cfg_gpio(void)
{
	s3c_gpio_cfgall_range(S3C64XX_GPC(0), 3,
				S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
	return 0;
}
#endif


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2010 Samsung Electronics Co., Ltd.
//                     http://www.samsung.com/
//
// Based on S3C24XX setup for i2c device

#include <linux/kernel.h>
#include <linux/gpio.h>

struct platform_device; /* don't need the contents */

#include <linux/platform_data/touchscreen-s3c2410.h>

#include "gpio-cfg.h"
#include "gpio-samsung.h"

/**
 * s3c24xx_ts_cfg_gpio - configure gpio for s3c2410 systems
 * @dev: Device to configure GPIO for (ignored)
 *
 * Configure the GPIO for the S3C2410 system, where we have external FETs
 * connected to the device (later systems such as the S3C2440 integrate
 * these into the device).
 */
void s3c24xx_ts_cfg_gpio(struct platform_device *dev)
{
	s3c_gpio_cfgpin_range(S3C2410_GPG(12), 4, S3C_GPIO_SFN(3));
}


code:
// SPDX-License-Identifier: GPL-2.0+
//
// Copyright (C) 2011 Samsung Electronics Co.Ltd
// Author: Joonyoung Shim <jy0922.shim@samsung.com>

#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include "map.h"
#include "cpu.h"
#include "usb-phy.h"

#include "regs-sys-s3c64xx.h"
#include "regs-usb-hsotg-phy-s3c64xx.h"

enum samsung_usb_phy_type {
	USB_PHY_TYPE_DEVICE,
	USB_PHY_TYPE_HOST,
};

static int s3c_usb_otgphy_init(struct platform_device *pdev)
{
	struct clk *xusbxti;
	u32 phyclk;

	writel(readl(S3C64XX_OTHERS) | S3C64XX_OTHERS_USBMASK, S3C64XX_OTHERS);

	/* set clock frequency for PLL */
	phyclk = readl(S3C_PHYCLK) & ~S3C_PHYCLK_CLKSEL_MASK;

	xusbxti = clk_get(&pdev->dev, "xusbxti");
	if (!IS_ERR(xusbxti)) {
		switch (clk_get_rate(xusbxti)) {
		case 12 * MHZ:
			phyclk |= S3C_PHYCLK_CLKSEL_12M;
			break;
		case 24 * MHZ:
			phyclk |= S3C_PHYCLK_CLKSEL_24M;
			break;
		default:
		case 48 * MHZ:
			/* default reference clock */
			break;
		}
		clk_put(xusbxti);
	}

	/* TODO: select external clock/oscillator */
	writel(phyclk | S3C_PHYCLK_CLK_FORCE, S3C_PHYCLK);

	/* set to normal OTG PHY */
	writel((readl(S3C_PHYPWR) & ~S3C_PHYPWR_NORMAL_MASK), S3C_PHYPWR);
	mdelay(1);

	/* reset OTG PHY and Link */
	writel(S3C_RSTCON_PHY | S3C_RSTCON_HCLK | S3C_RSTCON_PHYCLK,
			S3C_RSTCON);
	udelay(20);	/* at-least 10uS */
	writel(0, S3C_RSTCON);

	return 0;
}

static int s3c_usb_otgphy_exit(struct platform_device *pdev)
{
	writel((readl(S3C_PHYPWR) | S3C_PHYPWR_ANALOG_POWERDOWN |
				S3C_PHYPWR_OTG_DISABLE), S3C_PHYPWR);

	writel(readl(S3C64XX_OTHERS) & ~S3C64XX_OTHERS_USBMASK, S3C64XX_OTHERS);

	return 0;
}

int s3c_usb_phy_init(struct platform_device *pdev, int type)
{
	if (type == USB_PHY_TYPE_DEVICE)
		return s3c_usb_otgphy_init(pdev);

	return -EINVAL;
}

int s3c_usb_phy_exit(struct platform_device *pdev, int type)
{
	if (type == USB_PHY_TYPE_DEVICE)
		return s3c_usb_otgphy_exit(pdev);

	return -EINVAL;
}


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2009 Simtec Electronics
//	http://armlinux.simtec.co.uk/
//	Ben Dooks <ben@simtec.co.uk>
//
// Audio setup for various Simtec S3C24XX implementations

#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/io.h>

#include "regs-gpio.h"
#include "gpio-samsung.h"
#include "gpio-cfg.h"

#include <linux/platform_data/asoc-s3c24xx_simtec.h>
#include "devs.h"

#include "bast.h"
#include "simtec.h"

/* platform ops for audio */

static void simtec_audio_startup_lrroute(void)
{
	unsigned int tmp;
	unsigned long flags;

	local_irq_save(flags);

	tmp = __raw_readb(BAST_VA_CTRL1);
	tmp &= ~BAST_CPLD_CTRL1_LRMASK;
	tmp |= BAST_CPLD_CTRL1_LRCDAC;
	__raw_writeb(tmp, BAST_VA_CTRL1);

	local_irq_restore(flags);
}

static struct s3c24xx_audio_simtec_pdata simtec_audio_platdata;
static char our_name[32];

static struct platform_device simtec_audio_dev = {
	.name	= our_name,
	.id	= -1,
	.dev	= {
		.parent		= &s3c_device_iis.dev,
		.platform_data	= &simtec_audio_platdata,
	},
};

int __init simtec_audio_add(const char *name, bool has_lr_routing,
			    struct s3c24xx_audio_simtec_pdata *spd)
{
	if (!name)
		name = "tlv320aic23";

	snprintf(our_name, sizeof(our_name)-1, "s3c24xx-simtec-%s", name);

	/* copy platform data so the source can be __initdata */
	if (spd)
		simtec_audio_platdata = *spd;

	if (has_lr_routing)
		simtec_audio_platdata.startup = simtec_audio_startup_lrroute;

	/* Configure the I2S pins (GPE0...GPE4) in correct mode */
	s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2),
			      S3C_GPIO_PULL_NONE);

	platform_device_register(&s3c_device_iis);
	platform_device_register(&simtec_audio_dev);
	return 0;
}


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2008 Simtec Electronics
//	http://armlinux.simtec.co.uk/
//	Ben Dooks <ben@simtec.co.uk>
//
// Simtec NOR mapping

#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>

#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/physmap.h>
#include <linux/mtd/partitions.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>

#include "map.h"

#include "bast.h"
#include "simtec.h"

static void simtec_nor_vpp(struct platform_device *pdev, int vpp)
{
	unsigned int val;

	val = __raw_readb(BAST_VA_CTRL3);

	printk(KERN_DEBUG "%s(%d)\n", __func__, vpp);

	if (vpp)
		val |= BAST_CPLD_CTRL3_ROMWEN;
	else
		val &= ~BAST_CPLD_CTRL3_ROMWEN;

	__raw_writeb(val, BAST_VA_CTRL3);
}

static struct physmap_flash_data simtec_nor_pdata = {
	.width		= 2,
	.set_vpp	= simtec_nor_vpp,
	.nr_parts	= 0,
};

static struct resource simtec_nor_resource[] = {
	[0] = DEFINE_RES_MEM(S3C2410_CS1 + 0x4000000, SZ_8M),
};

static struct platform_device simtec_device_nor = {
	.name		= "physmap-flash",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(simtec_nor_resource),
	.resource	= simtec_nor_resource,
	.dev		= {
		.platform_data = &simtec_nor_pdata,
	},
};

void __init nor_simtec_init(void)
{
	int ret;

	ret = platform_device_register(&simtec_device_nor);
	if (ret < 0)
		printk(KERN_ERR "failed to register physmap-flash device\n");
	else
		simtec_nor_vpp(NULL, 1);
}


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright 2004 Simtec Electronics
//	Ben Dooks <ben@simtec.co.uk>
//
// http://armlinux.simtec.co.uk/
//
// Power Management helpers for Simtec S3C24XX implementations

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/io.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>

#include "map.h"
#include "regs-gpio.h"

#include <asm/mach-types.h>

#include "pm.h"

#include "regs-mem-s3c24xx.h"

#define COPYRIGHT ", Copyright 2005 Simtec Electronics"

/* pm_simtec_init
 *
 * enable the power management functions
*/

static __init int pm_simtec_init(void)
{
	unsigned long gstatus4;

	/* check which machine we are running on */

	if (!machine_is_bast() && !machine_is_vr1000() &&
	    !machine_is_anubis() && !machine_is_osiris() &&
	    !machine_is_aml_m5900())
		return 0;

	printk(KERN_INFO "Simtec Board Power Management" COPYRIGHT "\n");

	gstatus4  = (__raw_readl(S3C2410_BANKCON7) & 0x3) << 30;
	gstatus4 |= (__raw_readl(S3C2410_BANKCON6) & 0x3) << 28;
	gstatus4 |= (__raw_readl(S3C2410_BANKSIZE) & S3C2410_BANKSIZE_MASK);

	__raw_writel(gstatus4, S3C2410_GSTATUS4);

	return s3c_pm_init();
}

arch_initcall(pm_simtec_init);


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright 2004-2005 Simtec Electronics
//   Ben Dooks <ben@simtec.co.uk>
//
// http://www.simtec.co.uk/products/EB2410ITX/
//
// Simtec BAST and Thorcom VR1000 USB port support functions

#define DEBUG

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/gpio.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/io.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>

#include "gpio-samsung.h"
#include "irqs.h"
#include <asm/irq.h>

#include <linux/platform_data/usb-ohci-s3c2410.h>
#include "devs.h"

#include "bast.h"
#include "simtec.h"

/* control power and monitor over-current events on various Simtec
 * designed boards.
*/

static unsigned int power_state[2];

static void
usb_simtec_powercontrol(int port, int to)
{
	pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to);

	power_state[port] = to;

	if (power_state[0] && power_state[1])
		gpio_set_value(S3C2410_GPB(4), 0);
	else
		gpio_set_value(S3C2410_GPB(4), 1);
}

static irqreturn_t
usb_simtec_ocirq(int irq, void *pw)
{
	struct s3c2410_hcd_info *info = pw;

	if (gpio_get_value(S3C2410_GPG(10)) == 0) {
		pr_debug("usb_simtec: over-current irq (oc detected)\n");
		s3c2410_usb_report_oc(info, 3);
	} else {
		pr_debug("usb_simtec: over-current irq (oc cleared)\n");
		s3c2410_usb_report_oc(info, 0);
	}

	return IRQ_HANDLED;
}

static void usb_simtec_enableoc(struct s3c2410_hcd_info *info, int on)
{
	int ret;

	if (on) {
		ret = request_irq(BAST_IRQ_USBOC, usb_simtec_ocirq,
				  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
				  "USB Over-current", info);
		if (ret != 0) {
			printk(KERN_ERR "failed to request usb oc irq\n");
		}
	} else {
		free_irq(BAST_IRQ_USBOC, info);
	}
}

static struct s3c2410_hcd_info usb_simtec_info __initdata = {
	.port[0]	= {
		.flags	= S3C_HCDFLG_USED
	},
	.port[1]	= {
		.flags	= S3C_HCDFLG_USED
	},

	.power_control	= usb_simtec_powercontrol,
	.enable_oc	= usb_simtec_enableoc,
};

int __init usb_simtec_init(void)
{
	int ret;

	printk("USB Power Control, Copyright 2004 Simtec Electronics\n");

	ret = gpio_request(S3C2410_GPB(4), "USB power control");
	if (ret < 0) {
		pr_err("%s: failed to get GPB4\n", __func__);
		return ret;
	}

	ret = gpio_request(S3C2410_GPG(10), "USB overcurrent");
	if (ret < 0) {
		pr_err("%s: failed to get GPG10\n", __func__);
		gpio_free(S3C2410_GPB(4));
		return ret;
	}

	/* turn power on */
	gpio_direction_output(S3C2410_GPB(4), 1);
	gpio_direction_input(S3C2410_GPG(10));

	s3c_ohci_set_platdata(&usb_simtec_info);
	return 0;
}


code:
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2008 Simtec Electronics
 *	http://armlinux.simtec.co.uk/
 *	Ben Dooks <ben@simtec.co.uk>
 *
 * Simtec common functions
 */

struct s3c24xx_audio_simtec_pdata;

extern void nor_simtec_init(void);

extern int usb_simtec_init(void);

extern int simtec_audio_add(const char *codec_name, bool has_lr_routing,
			    struct s3c24xx_audio_simtec_pdata *pdata);


code:
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Copyright (c) 2004 Simtec Electronics
 *	Ben Dooks <ben@simtec.co.uk>
 *
 * S3C2410 Power Manager (Suspend-To-RAM) support
 *
 * Based on PXA/SA1100 sleep code by:
 *	Nicolas Pitre, (c) 2002 Monta Vista Software Inc
 *	Cliff Brake, (c) 2001
 */

#include <linux/linkage.h>
#include <linux/serial_s3c.h>
#include <asm/assembler.h>
#include "map.h"

#include "regs-gpio.h"
#include "regs-clock.h"

#include "regs-mem-s3c24xx.h"

	/* s3c2410_cpu_suspend
	 *
	 * put the cpu into sleep mode
	*/

ENTRY(s3c2410_cpu_suspend)
	@@ prepare cpu to sleep

	ldr	r4, =S3C2410_REFRESH
	ldr	r5, =S3C24XX_MISCCR
	ldr	r6, =S3C2410_CLKCON
	ldr	r7, [r4]		@ get REFRESH (and ensure in TLB)
	ldr	r8, [r5]		@ get MISCCR (and ensure in TLB)
	ldr	r9, [r6]		@ get CLKCON (and ensure in TLB)

	orr	r7, r7, #S3C2410_REFRESH_SELF	@ SDRAM sleep command
	orr	r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
	orr	r9, r9, #S3C2410_CLKCON_POWER	@ power down command

	teq	pc, #0			@ first as a trial-run to load cache
	bl	s3c2410_do_sleep
	teq	r0, r0			@ now do it for real
	b	s3c2410_do_sleep	@

	@@ align next bit of code to cache line
	.align	5
s3c2410_do_sleep:
	streq	r7, [r4]			@ SDRAM sleep command
	streq	r8, [r5]			@ SDRAM power-down config
	streq	r9, [r6]			@ CPU sleep
1:	beq	1b
	ret	lr


code:
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Copyright (c) 2007 Simtec Electronics
 *	Ben Dooks <ben@simtec.co.uk>
 *
 * S3C2412 Power Manager low-level sleep support
 */

#include <linux/linkage.h>
#include <asm/assembler.h>
#include "map.h"

#include "regs-irq.h"

	.text

	.global	s3c2412_sleep_enter

s3c2412_sleep_enter:
	mov	r0, #0			/* argument for coprocessors */
	ldr	r1, =S3C2410_INTPND
	ldr	r2, =S3C2410_SRCPND
	ldr	r3, =S3C2410_EINTPEND

	teq	r0, r0
	bl	s3c2412_sleep_enter1
	teq	pc, r0
	bl	s3c2412_sleep_enter1

	.align	5

	/* this is called twice, first with the Z flag to ensure that the
	 * instructions have been loaded into the cache, and the second
	 * time to try and suspend the system.
	*/
s3c2412_sleep_enter1:
	mcr	p15, 0, r0, c7, c10, 4
	mcrne	p15, 0, r0, c7, c0, 4

	/* if we return from here, it is because an interrupt was
	 * active when we tried to shutdown. Try and ack the IRQ and
	 * retry, as simply returning causes the system to lock.
	*/

	ldrne	r9, [r1]
	strne	r9, [r1]
	ldrne	r9, [r2]
	strne	r9, [r2]
	ldrne	r9, [r3]
	strne	r9, [r3]
	bne	s3c2412_sleep_enter1

	ret	lr


code:
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Copyright (c) 2004 Simtec Electronics
 *	Ben Dooks <ben@simtec.co.uk>
 *
 * S3C2410 Power Manager (Suspend-To-RAM) support
 *
 * Based on PXA/SA1100 sleep code by:
 *	Nicolas Pitre, (c) 2002 Monta Vista Software Inc
 *	Cliff Brake, (c) 2001
 */

#include <linux/linkage.h>
#include <linux/serial_s3c.h>
#include <asm/assembler.h>
#include "map.h"

#include "regs-gpio.h"
#include "regs-clock.h"

/*
 * S3C24XX_DEBUG_RESUME is dangerous if your bootloader does not
 * reset the UART configuration, only enable if you really need this!
 */
//#define S3C24XX_DEBUG_RESUME

	.text

	/* sleep magic, to allow the bootloader to check for an valid
	 * image to resume to. Must be the first word before the
	 * s3c_cpu_resume entry.
	*/

	.word	0x2bedf00d

	/* s3c_cpu_resume
	 *
	 * resume code entry for bootloader to call
	*/

ENTRY(s3c_cpu_resume)
	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
	msr	cpsr_c, r0

	@@ load UART to allow us to print the two characters for
	@@ resume debug

	mov	r2, #S3C24XX_PA_UART & 0xff000000
	orr	r2, r2, #S3C24XX_PA_UART & 0xff000

#if 0
	/* SMDK2440 LED set */
	mov	r14, #S3C24XX_PA_GPIO
	ldr	r12, [ r14, #0x54 ]
	bic	r12, r12, #3<<4
	orr	r12, r12, #1<<7
	str	r12, [ r14, #0x54 ]
#endif

#ifdef S3C24XX_DEBUG_RESUME
	mov	r3, #'L'
	strb	r3, [ r2, #S3C2410_UTXH ]
1001:
	ldrb	r14, [ r3, #S3C2410_UTRSTAT ]
	tst	r14, #S3C2410_UTRSTAT_TXE
	beq	1001b
#endif /* S3C24XX_DEBUG_RESUME */

	b	cpu_resume


code:
/* SPDX-License-Identifier: GPL-2.0 */
/* linux/arch/arm/plat-s3c64xx/sleep.S
 *
 * Copyright 2008 Openmoko, Inc.
 * Copyright 2008 Simtec Electronics
 *	Ben Dooks <ben@simtec.co.uk>
 *	http://armlinux.simtec.co.uk/
 *
 * S3C64XX CPU sleep code
 */

#include <linux/linkage.h>
#include <asm/assembler.h>
#include "map.h"

#undef S3C64XX_VA_GPIO
#define S3C64XX_VA_GPIO (0x0)

#include "regs-gpio.h"

#define LL_UART (S3C_PA_UART + (0x400 * CONFIG_S3C_LOWLEVEL_UART_PORT))

	.text

	/* Sleep magic, the word before the resume entry point so that the
	 * bootloader can check for a resumeable image. */

	.word	0x2bedf00d

	/* s3c_cpu_reusme
	 *
	 * This is the entry point, stored by whatever method the bootloader
	 * requires to get the kernel runnign again. This code expects to be
	 * entered with no caches live and the MMU disabled. It will then
	 * restore the MMU and other basic CP registers saved and restart
	 * the kernel C code to finish the resume code.
	*/

ENTRY(s3c_cpu_resume)
	msr	cpsr_c, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
	ldr	r2, =LL_UART		/* for debug */

#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK

#define S3C64XX_GPNCON			(S3C64XX_GPN_BASE + 0x00)
#define S3C64XX_GPNDAT			(S3C64XX_GPN_BASE + 0x04)

#define S3C64XX_GPN_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
#define S3C64XX_GPN_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))

	/* Initialise the GPIO state if we are debugging via the SMDK LEDs,
	 * as the uboot version supplied resets these to inputs during the
	 * resume checks.
	*/

	ldr	r3, =S3C64XX_PA_GPIO
	ldr	r0, [ r3, #S3C64XX_GPNCON ]
	bic	r0, r0, #(S3C64XX_GPN_CONMASK(12) | S3C64XX_GPN_CONMASK(13) | \
			  S3C64XX_GPN_CONMASK(14) | S3C64XX_GPN_CONMASK(15))
	orr	r0, r0, #(S3C64XX_GPN_OUTPUT(12) | S3C64XX_GPN_OUTPUT(13) | \
			  S3C64XX_GPN_OUTPUT(14) | S3C64XX_GPN_OUTPUT(15))
	str	r0, [ r3, #S3C64XX_GPNCON ]

	ldr	r0, [ r3, #S3C64XX_GPNDAT ]
	bic	r0, r0, #0xf << 12			@ GPN12..15
	orr	r0, r0, #1 << 15			@ GPN15
	str	r0, [ r3, #S3C64XX_GPNDAT ]
#endif
	b	cpu_resume


code:
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de>
 */

#ifndef __PLAT_S3C_SPI_CORE_S3C24XX_H
#define __PLAT_S3C_SPI_CORE_S3C24XX_H

/* These functions are only for use with the core support code, such as
 * the cpu specific initialisation code
 */

/* re-define device name depending on support. */
static inline void s3c24xx_spi_setname(char *name)
{
#ifdef CONFIG_S3C64XX_DEV_SPI0
	s3c64xx_device_spi0.name = name;
#endif
}

#endif /* __PLAT_S3C_SPI_CORE_S3C24XX_H */


code:
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Copyright (C) 2011 Samsung Electronics Co.Ltd
 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
 */

#ifndef __PLAT_SAMSUNG_USB_PHY_H
#define __PLAT_SAMSUNG_USB_PHY_H __FILE__

extern int s3c_usb_phy_init(struct platform_device *pdev, int type);
extern int s3c_usb_phy_exit(struct platform_device *pdev, int type);

#endif /* __PLAT_SAMSUNG_USB_PHY_H */


code:
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2003 Simtec Electronics
 *	Ben Dooks <ben@simtec.co.uk>
 *
 * VR1000 - CPLD control constants
 * Machine VR1000 - IRQ Number definitions
 * Machine VR1000 - Memory map definitions
 */

#ifndef __MACH_S3C24XX_VR1000_H
#define __MACH_S3C24XX_VR1000_H __FILE__

#define VR1000_CPLD_CTRL2_RAMWEN	(0x04)	/* SRAM Write Enable */

/* irq numbers to onboard peripherals */

#define VR1000_IRQ_USBOC		IRQ_EINT19
#define VR1000_IRQ_IDE0			IRQ_EINT16
#define VR1000_IRQ_IDE1			IRQ_EINT17
#define VR1000_IRQ_SERIAL		IRQ_EINT12
#define VR1000_IRQ_DM9000A		IRQ_EINT10
#define VR1000_IRQ_DM9000N		IRQ_EINT9
#define VR1000_IRQ_SMALERT		IRQ_EINT8

/* map */

#define VR1000_IOADDR(x)		(S3C2410_ADDR((x) + 0x01300000))

/* we put the CPLD registers next, to get them out of the way */

#define VR1000_VA_CTRL1			VR1000_IOADDR(0x00000000) /* 0x01300000 */
#define VR1000_PA_CTRL1			(S3C2410_CS5 | 0x7800000)

#define VR1000_VA_CTRL2			VR1000_IOADDR(0x00100000) /* 0x01400000 */
#define VR1000_PA_CTRL2			(S3C2410_CS1 | 0x6000000)

#define VR1000_VA_CTRL3			VR1000_IOADDR(0x00200000) /* 0x01500000 */
#define VR1000_PA_CTRL3			(S3C2410_CS1 | 0x6800000)

#define VR1000_VA_CTRL4			VR1000_IOADDR(0x00300000) /* 0x01600000 */
#define VR1000_PA_CTRL4			(S3C2410_CS1 | 0x7000000)

/* next, we have the PC104 ISA interrupt registers */

#define VR1000_PA_PC104_IRQREQ		(S3C2410_CS5 | 0x6000000) /* 0x01700000 */
#define VR1000_VA_PC104_IRQREQ		VR1000_IOADDR(0x00400000)

#define VR1000_PA_PC104_IRQRAW		(S3C2410_CS5 | 0x6800000) /* 0x01800000 */
#define VR1000_VA_PC104_IRQRAW		VR1000_IOADDR(0x00500000)

#define VR1000_PA_PC104_IRQMASK		(S3C2410_CS5 | 0x7000000) /* 0x01900000 */
#define VR1000_VA_PC104_IRQMASK		VR1000_IOADDR(0x00600000)

/*
 * 0xE0000000 contains the IO space that is split by speed and
 * whether the access is for 8 or 16bit IO... this ensures that
 * the correct access is made
 *
 * 0x10000000 of space, partitioned as so:
 *
 * 0x00000000 to 0x04000000  8bit,  slow
 * 0x04000000 to 0x08000000  16bit, slow
 * 0x08000000 to 0x0C000000  16bit, net
 * 0x0C000000 to 0x10000000  16bit, fast
 *
 * each of these spaces has the following in:
 *
 * 0x02000000 to 0x02100000 1MB  IDE primary channel
 * 0x02100000 to 0x02200000 1MB  IDE primary channel aux
 * 0x02200000 to 0x02400000 1MB  IDE secondary channel
 * 0x02300000 to 0x02400000 1MB  IDE secondary channel aux
 * 0x02500000 to 0x02600000 1MB  Davicom DM9000 ethernet controllers
 * 0x02600000 to 0x02700000 1MB
 *
 * the phyiscal layout of the zones are:
 *  nGCS2 - 8bit, slow
 *  nGCS3 - 16bit, slow
 *  nGCS4 - 16bit, net
 *  nGCS5 - 16bit, fast
 */

#define VR1000_VA_MULTISPACE	(0xE0000000)

#define VR1000_VA_ISAIO		(VR1000_VA_MULTISPACE + 0x00000000)
#define VR1000_VA_ISAMEM	(VR1000_VA_MULTISPACE + 0x01000000)
#define VR1000_VA_IDEPRI	(VR1000_VA_MULTISPACE + 0x02000000)
#define VR1000_VA_IDEPRIAUX	(VR1000_VA_MULTISPACE + 0x02100000)
#define VR1000_VA_IDESEC	(VR1000_VA_MULTISPACE + 0x02200000)
#define VR1000_VA_IDESECAUX	(VR1000_VA_MULTISPACE + 0x02300000)
#define VR1000_VA_ASIXNET	(VR1000_VA_MULTISPACE + 0x02400000)
#define VR1000_VA_DM9000	(VR1000_VA_MULTISPACE + 0x02500000)
#define VR1000_VA_SUPERIO	(VR1000_VA_MULTISPACE + 0x02600000)

/* physical offset addresses for the peripherals */

#define VR1000_PA_IDEPRI	(0x02000000)
#define VR1000_PA_IDEPRIAUX	(0x02800000)
#define VR1000_PA_IDESEC	(0x03000000)
#define VR1000_PA_IDESECAUX	(0x03800000)
#define VR1000_PA_DM9000	(0x05000000)

#define VR1000_PA_SERIAL	(0x11800000)
#define VR1000_VA_SERIAL	(VR1000_IOADDR(0x00700000))

/* VR1000 ram is in CS1, with A26..A24 = 2_101 */
#define VR1000_PA_SRAM		(S3C2410_CS1 | 0x05000000)

/* some configurations for the peripherals */

#define VR1000_DM9000_CS	VR1000_VAM_CS4

#endif /* __MACH_S3C24XX_VR1000_H */


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright 2010 Ben Dooks <ben-linux@fluff.org>
//
// Support for wakeup mask interrupts on newer SoCs

#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/device.h>
#include <linux/types.h>
#include <linux/irq.h>
#include <linux/io.h>

#include "wakeup-mask.h"
#include "pm.h"

void samsung_sync_wakemask(void __iomem *reg,
			   const struct samsung_wakeup_mask *mask, int nr_mask)
{
	struct irq_data *data;
	u32 val;

	val = __raw_readl(reg);

	for (; nr_mask > 0; nr_mask--, mask++) {
		if (mask->irq == NO_WAKEUP_IRQ) {
			val |= mask->bit;
			continue;
		}

		data = irq_get_irq_data(mask->irq);

		/* bit of a liberty to read this directly from irq_data. */
		if (irqd_is_wakeup_set(data))
			val &= ~mask->bit;
		else
			val |= mask->bit;
	}

	printk(KERN_INFO "wakemask %08x => %08x\n", __raw_readl(reg), val);
	__raw_writel(val, reg);
}


code:
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright 2010 Ben Dooks <ben-linux@fluff.org>
 *
 * Support for wakeup mask interrupts on newer SoCs
 */

#ifndef __PLAT_WAKEUP_MASK_H
#define __PLAT_WAKEUP_MASK_H __file__

/* if no irq yet defined, but still want to mask */
#define NO_WAKEUP_IRQ (0x90000000)

/**
 * struct samsung_wakeup_mask - wakeup mask information
 * @irq: The interrupt associated with this wakeup.
 * @bit: The bit, as a (1 << bitno) controlling this source.
 */
struct samsung_wakeup_mask {
	unsigned int	irq;
	u32		bit;
};

/**
 * samsung_sync_wakemask - sync wakeup mask information for pm
 * @reg: The register that is used.
 * @masks: The list of masks to use.
 * @nr_masks: The number of entries pointed to buy @masks.
 *
 * Synchronise the wakeup mask information at suspend time from the list
 * of interrupts and control bits in @masks. We do this at suspend time
 * as overriding the relevant irq chips is harder and the register is only
 * required to be correct before we enter sleep.
 */
extern void samsung_sync_wakemask(void __iomem *reg,
				  const struct samsung_wakeup_mask *masks,
				  int nr_masks);

#endif /* __PLAT_WAKEUP_MASK_H */


code:
# SPDX-License-Identifier: GPL-2.0
#
# Copyright (c) 2010 Samsung Electronics Co., Ltd.
#		http://www.samsung.com/

# Configuration options for the S5PV210/S5PC110

config ARCH_S5PV210
	bool "Samsung S5PV210/S5PC110"
	depends on ARCH_MULTI_V7
	select ARM_VIC
	select CLKSRC_SAMSUNG_PWM
	select COMMON_CLK_SAMSUNG
	select GPIOLIB
	select PINCTRL
	select PINCTRL_EXYNOS
	select SOC_SAMSUNG
	help
	  Samsung S5PV210/S5PC110 series based systems

if ARCH_S5PV210

config CPU_S5PV210
	def_bool y
	select ARM_AMBA
	select PL330_DMA if DMADEVICES
	help
	  Enable S5PV210 CPU support

endif


code:
# SPDX-License-Identifier: GPL-2.0
#
# Copyright (c) 2010 Samsung Electronics Co., Ltd.
# 		http://www.samsung.com/

obj-$(CONFIG_PM_SLEEP)		+= pm.o sleep.o
obj-y				+= s5pv210.o


code:
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
 *		http://www.samsung.com
 *
 * Common Header for S5PV210 machines
 */

#ifndef __ARCH_ARM_MACH_S5PV210_COMMON_H
#define __ARCH_ARM_MACH_S5PV210_COMMON_H

#ifdef CONFIG_PM_SLEEP
void s5pv210_cpu_resume(void);
void s5pv210_pm_init(void);
#else
static inline void s5pv210_pm_init(void) {}
#endif

#endif /* __ARCH_ARM_MACH_S5PV210_COMMON_H */


code:
// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2010-2014 Samsung Electronics Co., Ltd.
//		http://www.samsung.com
//
// S5PV210 - Power Management support
//
// Based on arch/arm/mach-s3c2410/pm.c
// Copyright (c) 2006 Simtec Electronics
//	Ben Dooks <ben@simtec.co.uk>

#include <linux/init.h>
#include <linux/suspend.h>
#include <linux/syscore_ops.h>
#include <linux/io.h>
#include <linux/soc/samsung/s3c-pm.h>

#include <asm/cacheflush.h>
#include <asm/suspend.h>

#include "common.h"
#include "regs-clock.h"

/* helper functions to save and restore register state */
struct sleep_save {
	void __iomem	*reg;
	unsigned long	val;
};

#define SAVE_ITEM(x) \
	{ .reg = (x) }

/**
 * s3c_pm_do_save() - save a set of registers for restoration on resume.
 * @ptr: Pointer to an array of registers.
 * @count: Size of the ptr array.
 *
 * Run through the list of registers given, saving their contents in the
 * array for later restoration when we wakeup.
 */
static void s3c_pm_do_save(struct sleep_save *ptr, int count)
{
	for (; count > 0; count--, ptr++) {
		ptr->val = readl_relaxed(ptr->reg);
		S3C_PMDBG("saved %p value %08lx\n", ptr->reg, ptr->val);
	}
}

/**
 * s3c_pm_do_restore() - restore register values from the save list.
 * @ptr: Pointer to an array of registers.
 * @count: Size of the ptr array.
 *
 * Restore the register values saved from s3c_pm_do_save().
 *
 * WARNING: Do not put any debug in here that may effect memory or use
 * peripherals, as things may be changing!
*/

static void s3c_pm_do_restore_core(const struct sleep_save *ptr, int count)
{
	for (; count > 0; count--, ptr++)
		writel_relaxed(ptr->val, ptr->reg);
}

static struct sleep_save s5pv210_core_save[] = {
	/* Clock ETC */
	SAVE_ITEM(S5P_MDNIE_SEL),
};

/*
 * VIC wake-up support (TODO)
 */
static u32 s5pv210_irqwake_intmask = 0xffffffff;

static u32 s5pv210_read_eint_wakeup_mask(void)
{
	return __raw_readl(S5P_EINT_WAKEUP_MASK);
}

/*
 * Suspend helpers.
 */
static int s5pv210_cpu_suspend(unsigned long arg)
{
	unsigned long tmp;

	/* issue the standby signal into the pm unit. Note, we
	 * issue a write-buffer drain just in case */

	tmp = 0;

	asm("b 1f\n\t"
	    ".align 5\n\t"
	    "1:\n\t"
	    "mcr p15, 0, %0, c7, c10, 5\n\t"
	    "mcr p15, 0, %0, c7, c10, 4\n\t"
	    "wfi" : : "r" (tmp));

	pr_info("Failed to suspend the system\n");
	return 1; /* Aborting suspend */
}

static void s5pv210_pm_prepare(void)
{
	unsigned int tmp;

	/*
	 * Set wake-up mask registers
	 * S5P_EINT_WAKEUP_MASK is set by pinctrl driver in late suspend.
	 */
	__raw_writel(s5pv210_irqwake_intmask, S5P_WAKEUP_MASK);

	/* ensure at least INFORM0 has the resume address */
	__raw_writel(__pa_symbol(s5pv210_cpu_resume), S5P_INFORM0);

	tmp = __raw_readl(S5P_SLEEP_CFG);
	tmp &= ~(S5P_SLEEP_CFG_OSC_EN | S5P_SLEEP_CFG_USBOSC_EN);
	__raw_writel(tmp, S5P_SLEEP_CFG);

	/* WFI for SLEEP mode configuration by SYSCON */
	tmp = __raw_readl(S5P_PWR_CFG);
	tmp &= S5P_CFG_WFI_CLEAN;
	tmp |= S5P_CFG_WFI_SLEEP;
	__raw_writel(tmp, S5P_PWR_CFG);

	/* SYSCON interrupt handling disable */
	tmp = __raw_readl(S5P_OTHERS);
	tmp |= S5P_OTHER_SYSC_INTOFF;
	__raw_writel(tmp, S5P_OTHERS);

	s3c_pm_do_save(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save));
}

/*
 * Suspend operations.
 */
static int s5pv210_suspend_enter(suspend_state_t state)
{
	u32 eint_wakeup_mask = s5pv210_read_eint_wakeup_mask();
	int ret;

	S3C_PMDBG("%s: suspending the system...\n", __func__);

	S3C_PMDBG("%s: wakeup masks: %08x,%08x\n", __func__,
			s5pv210_irqwake_intmask, eint_wakeup_mask);

	if (s5pv210_irqwake_intmask == -1U
	    && eint_wakeup_mask == -1U) {
		pr_err("%s: No wake-up sources!\n", __func__);
		pr_err("%s: Aborting sleep\n", __func__);
		return -EINVAL;
	}

	s3c_pm_save_uarts(false);
	s5pv210_pm_prepare();
	flush_cache_all();
	s3c_pm_check_store();

	ret = cpu_suspend(0, s5pv210_cpu_suspend);
	if (ret)
		return ret;

	s3c_pm_restore_uarts(false);

	S3C_PMDBG("%s: wakeup stat: %08x\n", __func__,
			__raw_readl(S5P_WAKEUP_STAT));

	s3c_pm_check_restore();

	S3C_PMDBG("%s: resuming the system...\n", __func__);

	return 0;
}

static int s5pv210_suspend_prepare(void)
{
	s3c_pm_check_prepare();

	return 0;
}

static void s5pv210_suspend_finish(void)
{
	s3c_pm_check_cleanup();
}

static const struct platform_suspend_ops s5pv210_suspend_ops = {
	.enter		= s5pv210_suspend_enter,
	.prepare	= s5pv210_suspend_prepare,
	.finish		= s5pv210_suspend_finish,
	.valid		= suspend_valid_only_mem,
};

/*
 * Syscore operations used to delay restore of certain registers.
 */
static void s5pv210_pm_resume(void)
{
	s3c_pm_do_restore_core(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save));
}

static struct syscore_ops s5pv210_pm_syscore_ops = {
	.resume		= s5pv210_pm_resume,
};

/*
 * Initialization entry point.
 */
void __init s5pv210_pm_init(void)
{
	register_syscore_ops(&s5pv210_pm_syscore_ops);
	suspend_set_ops(&s5pv210_suspend_ops);
}


code:
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
 *		http://www.samsung.com/
 *
 * S5PV210 - Clock register definitions
 */

#ifndef __ASM_ARCH_REGS_CLOCK_H
#define __ASM_ARCH_REGS_CLOCK_H __FILE__

#define S3C_ADDR_BASE		0xF6000000
#define S3C_ADDR(x)		((void __iomem __force *)S3C_ADDR_BASE + (x))
#define S3C_VA_SYS		S3C_ADDR(0x00100000)

#define S5P_CLKREG(x)		(S3C_VA_SYS + (x))

#define S5P_APLL_LOCK		S5P_CLKREG(0x00)
#define S5P_MPLL_LOCK		S5P_CLKREG(0x08)
#define S5P_EPLL_LOCK		S5P_CLKREG(0x10)
#define S5P_VPLL_LOCK		S5P_CLKREG(0x20)

#define S5P_APLL_CON		S5P_CLKREG(0x100)
#define S5P_MPLL_CON		S5P_CLKREG(0x108)
#define S5P_EPLL_CON		S5P_CLKREG(0x110)
#define S5P_EPLL_CON1		S5P_CLKREG(0x114)
#define S5P_VPLL_CON		S5P_CLKREG(0x120)

#define S5P_CLK_SRC0		S5P_CLKREG(0x200)
#define S5P_CLK_SRC1		S5P_CLKREG(0x204)
#define S5P_CLK_SRC2		S5P_CLKREG(0x208)
#define S5P_CLK_SRC3		S5P_CLKREG(0x20C)
#define S5P_CLK_SRC4		S5P_CLKREG(0x210)
#define S5P_CLK_SRC5		S5P_CLKREG(0x214)
#define S5P_CLK_SRC6		S5P_CLKREG(0x218)

#define S5P_CLK_SRC_MASK0	S5P_CLKREG(0x280)
#define S5P_CLK_SRC_MASK1	S5P_CLKREG(0x284)

#define S5P_CLK_DIV0		S5P_CLKREG(0x300)
#define S5P_CLK_DIV1		S5P_CLKREG(0x304)
#define S5P_CLK_DIV2		S5P_CLKREG(0x308)
#define S5P_CLK_DIV3		S5P_CLKREG(0x30C)
#define S5P_CLK_DIV4		S5P_CLKREG(0x310)
#define S5P_CLK_DIV5		S5P_CLKREG(0x314)
#define S5P_CLK_DIV6		S5P_CLKREG(0x318)
#define S5P_CLK_DIV7		S5P_CLKREG(0x31C)

#define S5P_CLKGATE_MAIN0	S5P_CLKREG(0x400)
#define S5P_CLKGATE_MAIN1	S5P_CLKREG(0x404)
#define S5P_CLKGATE_MAIN2	S5P_CLKREG(0x408)

#define S5P_CLKGATE_PERI0	S5P_CLKREG(0x420)
#define S5P_CLKGATE_PERI1	S5P_CLKREG(0x424)

#define S5P_CLKGATE_SCLK0	S5P_CLKREG(0x440)
#define S5P_CLKGATE_SCLK1	S5P_CLKREG(0x444)
#define S5P_CLKGATE_IP0		S5P_CLKREG(0x460)
#define S5P_CLKGATE_IP1		S5P_CLKREG(0x464)
#define S5P_CLKGATE_IP2		S5P_CLKREG(0x468)
#define S5P_CLKGATE_IP3		S5P_CLKREG(0x46C)
#define S5P_CLKGATE_IP4		S5P_CLKREG(0x470)

#define S5P_CLKGATE_BLOCK	S5P_CLKREG(0x480)
#define S5P_CLKGATE_BUS0	S5P_CLKREG(0x484)
#define S5P_CLKGATE_BUS1	S5P_CLKREG(0x488)
#define S5P_CLK_OUT		S5P_CLKREG(0x500)

/* DIV/MUX STATUS */
#define S5P_CLKDIV_STAT0	S5P_CLKREG(0x1000)
#define S5P_CLKDIV_STAT1	S5P_CLKREG(0x1004)
#define S5P_CLKMUX_STAT0	S5P_CLKREG(0x1100)
#define S5P_CLKMUX_STAT1	S5P_CLKREG(0x1104)

/* CLKSRC0 */
#define S5P_CLKSRC0_MUX200_SHIFT	(16)
#define S5P_CLKSRC0_MUX200_MASK		(0x1 << S5P_CLKSRC0_MUX200_SHIFT)
#define S5P_CLKSRC0_MUX166_MASK		(0x1<<20)
#define S5P_CLKSRC0_MUX133_MASK		(0x1<<24)

/* CLKSRC2 */
#define S5P_CLKSRC2_G3D_SHIFT           (0)
#define S5P_CLKSRC2_G3D_MASK            (0x3 << S5P_CLKSRC2_G3D_SHIFT)
#define S5P_CLKSRC2_MFC_SHIFT           (4)
#define S5P_CLKSRC2_MFC_MASK            (0x3 << S5P_CLKSRC2_MFC_SHIFT)

/* CLKSRC6*/
#define S5P_CLKSRC6_ONEDRAM_SHIFT       (24)
#define S5P_CLKSRC6_ONEDRAM_MASK        (0x3 << S5P_CLKSRC6_ONEDRAM_SHIFT)

/* CLKDIV0 */
#define S5P_CLKDIV0_APLL_SHIFT		(0)
#define S5P_CLKDIV0_APLL_MASK		(0x7 << S5P_CLKDIV0_APLL_SHIFT)
#define S5P_CLKDIV0_A2M_SHIFT		(4)
#define S5P_CLKDIV0_A2M_MASK		(0x7 << S5P_CLKDIV0_A2M_SHIFT)
#define S5P_CLKDIV0_HCLK200_SHIFT	(8)
#define S5P_CLKDIV0_HCLK200_MASK	(0x7 << S5P_CLKDIV0_HCLK200_SHIFT)
#define S5P_CLKDIV0_PCLK100_SHIFT	(12)
#define S5P_CLKDIV0_PCLK100_MASK	(0x7 << S5P_CLKDIV0_PCLK100_SHIFT)
#define S5P_CLKDIV0_HCLK166_SHIFT	(16)
#define S5P_CLKDIV0_HCLK166_MASK	(0xF << S5P_CLKDIV0_HCLK166_SHIFT)
#define S5P_CLKDIV0_PCLK83_SHIFT	(20)
#define S5P_CLKDIV0_PCLK83_MASK		(0x7 << S5P_CLKDIV0_PCLK83_SHIFT)
#define S5P_CLKDIV0_HCLK133_SHIFT	(24)
#define S5P_CLKDIV0_HCLK133_MASK	(0xF << S5P_CLKDIV0_HCLK133_SHIFT)
#define S5P_CLKDIV0_PCLK66_SHIFT	(28)
#define S5P_CLKDIV0_PCLK66_MASK		(0x7 << S5P_CLKDIV0_PCLK66_SHIFT)

/* CLKDIV2 */
#define S5P_CLKDIV2_G3D_SHIFT           (0)
#define S5P_CLKDIV2_G3D_MASK            (0xF << S5P_CLKDIV2_G3D_SHIFT)
#define S5P_CLKDIV2_MFC_SHIFT           (4)
#define S5P_CLKDIV2_MFC_MASK            (0xF << S5P_CLKDIV2_MFC_SHIFT)

/* CLKDIV6 */
#define S5P_CLKDIV6_ONEDRAM_SHIFT       (28)
#define S5P_CLKDIV6_ONEDRAM_MASK        (0xF << S5P_CLKDIV6_ONEDRAM_SHIFT)

#define S5P_SWRESET		S5P_CLKREG(0x2000)

#define S5P_ARM_MCS_CON		S5P_CLKREG(0x6100)

/* Registers related to power management */
#define S5P_PWR_CFG		S5P_CLKREG(0xC000)
#define S5P_EINT_WAKEUP_MASK	S5P_CLKREG(0xC004)
#define S5P_WAKEUP_MASK		S5P_CLKREG(0xC008)
#define S5P_PWR_MODE		S5P_CLKREG(0xC00C)
#define S5P_NORMAL_CFG		S5P_CLKREG(0xC010)
#define S5P_IDLE_CFG		S5P_CLKREG(0xC020)
#define S5P_STOP_CFG		S5P_CLKREG(0xC030)
#define S5P_STOP_MEM_CFG	S5P_CLKREG(0xC034)
#define S5P_SLEEP_CFG		S5P_CLKREG(0xC040)

#define S5P_OSC_FREQ		S5P_CLKREG(0xC100)
#define S5P_OSC_STABLE		S5P_CLKREG(0xC104)
#define S5P_PWR_STABLE		S5P_CLKREG(0xC108)
#define S5P_MTC_STABLE		S5P_CLKREG(0xC110)
#define S5P_CLAMP_STABLE	S5P_CLKREG(0xC114)

#define S5P_WAKEUP_STAT		S5P_CLKREG(0xC200)
#define S5P_BLK_PWR_STAT	S5P_CLKREG(0xC204)

#define S5P_OTHERS		S5P_CLKREG(0xE000)
#define S5P_OM_STAT		S5P_CLKREG(0xE100)
#define S5P_HDMI_PHY_CONTROL	S5P_CLKREG(0xE804)
#define S5P_USB_PHY_CONTROL	S5P_CLKREG(0xE80C)
#define S5P_DAC_PHY_CONTROL	S5P_CLKREG(0xE810)

#define S5P_INFORM0		S5P_CLKREG(0xF000)
#define S5P_INFORM1		S5P_CLKREG(0xF004)
#define S5P_INFORM2		S5P_CLKREG(0xF008)
#define S5P_INFORM3		S5P_CLKREG(0xF00C)
#define S5P_INFORM4		S5P_CLKREG(0xF010)
#define S5P_INFORM5		S5P_CLKREG(0xF014)
#define S5P_INFORM6		S5P_CLKREG(0xF018)
#define S5P_INFORM7		S5P_CLKREG(0xF01C)

#define S5P_RST_STAT		S5P_CLKREG(0xA000)
#define S5P_OSC_CON		S5P_CLKREG(0x8000)
#define S5P_MDNIE_SEL		S5P_CLKREG(0x7008)
#define S5P_MIPI_PHY_CON0	S5P_CLKREG(0x7200)
#define S5P_MIPI_PHY_CON1	S5P_CLKREG(0x7204)

#define S5P_IDLE_CFG_TL_MASK	(3 << 30)
#define S5P_IDLE_CFG_TM_MASK	(3 << 28)
#define S5P_IDLE_CFG_TL_ON	(2 << 30)
#define S5P_IDLE_CFG_TM_ON	(2 << 28)
#define S5P_IDLE_CFG_DIDLE	(1 << 0)

#define S5P_CFG_WFI_CLEAN		(~(3 << 8))
#define S5P_CFG_WFI_IDLE		(1 << 8)
#define S5P_CFG_WFI_STOP		(2 << 8)
#define S5P_CFG_WFI_SLEEP		(3 << 8)

#define S5P_OTHER_SYS_INT		24
#define S5P_OTHER_STA_TYPE		23
#define S5P_OTHER_SYSC_INTOFF		(1 << 0)
#define STA_TYPE_EXPON			0
#define STA_TYPE_SFR			1

#define S5P_PWR_STA_EXP_SCALE		0
#define S5P_PWR_STA_CNT			4

#define S5P_PWR_STABLE_COUNT		85500

#define S5P_SLEEP_CFG_OSC_EN		(1 << 0)
#define S5P_SLEEP_CFG_USBOSC_EN		(1 << 1)

/* OTHERS Resgister */
#define S5P_OTHERS_USB_SIG_MASK		(1 << 16)

/* S5P_DAC_CONTROL */
#define S5P_DAC_ENABLE			(1)
#define S5P_DAC_DISABLE			(0)

#endif /* __ASM_ARCH_REGS_CLOCK_H */


code:
// SPDX-License-Identifier: GPL-2.0
//
// Samsung's S5PC110/S5PV210 flattened device tree enabled machine.
//
// Copyright (c) 2013-2014 Samsung Electronics Co., Ltd.
// Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
// Tomasz Figa <t.figa@samsung.com>

#include <linux/of_fdt.h>
#include <linux/of_platform.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/system_misc.h>

#include "common.h"
#include "regs-clock.h"

static int __init s5pv210_fdt_map_sys(unsigned long node, const char *uname,
					int depth, void *data)
{
	struct map_desc iodesc;
	const __be32 *reg;
	int len;

	if (!of_flat_dt_is_compatible(node, "samsung,s5pv210-clock"))
		return 0;

	reg = of_get_flat_dt_prop(node, "reg", &len);
	if (reg == NULL || len != (sizeof(unsigned long) * 2))
		return 0;

	iodesc.pfn = __phys_to_pfn(be32_to_cpu(reg[0]));
	iodesc.length = be32_to_cpu(reg[1]) - 1;
	iodesc.virtual = (unsigned long)S3C_VA_SYS;
	iodesc.type = MT_DEVICE;
	iotable_init(&iodesc, 1);

	return 1;
}

static void __init s5pv210_dt_map_io(void)
{
	debug_ll_io_init();

	of_scan_flat_dt(s5pv210_fdt_map_sys, NULL);
}

static void s5pv210_dt_restart(enum reboot_mode mode, const char *cmd)
{
	__raw_writel(0x1, S5P_SWRESET);
}

static void __init s5pv210_dt_init_late(void)
{
	platform_device_register_simple("s5pv210-cpufreq", -1, NULL, 0);
	s5pv210_pm_init();
}

static char const *const s5pv210_dt_compat[] __initconst = {
	"samsung,s5pc110",
	"samsung,s5pv210",
	NULL
};

DT_MACHINE_START(S5PV210_DT, "Samsung S5PC110/S5PV210-based board")
	.dt_compat = s5pv210_dt_compat,
	.map_io = s5pv210_dt_map_io,
	.restart = s5pv210_dt_restart,
	.init_late = s5pv210_dt_init_late,
MACHINE_END


code:
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
 *		http://www.samsung.com
 *
 * S5PV210 Sleep Code
 * Based on S3C64XX sleep code by:
 *	Ben Dooks, (c) 2008 Simtec Electronics
 */

#include <linux/linkage.h>

	.text
	.align

	/*
	 * sleep magic, to allow the bootloader to check for an valid
	 * image to resume to. Must be the first word before the
	 * s3c_cpu_resume entry.
	 */

	.word	0x2bedf00d

	/*
	 * s3c_cpu_resume
	 *
	 * resume code entry for bootloader to call
	 */

ENTRY(s5pv210_cpu_resume)
	b	cpu_resume
ENDPROC(s5pv210_cpu_resume)


code:
# SPDX-License-Identifier: GPL-2.0-only
menuconfig ARCH_SA1100
	bool "SA11x0 Implementations"
	depends on ARCH_MULTI_V4 && !(ARCH_MULTI_V4T || ARCH_MULTI_V5)
	depends on !(ARCH_MOXART || ARCH_GEMINI)
	depends on ATAGS
	depends on CPU_LITTLE_ENDIAN
	depends on MMU
	select ARCH_NO_SG_CHAIN
	select ARCH_MTD_XIP
	select CLKSRC_MMIO
	select CLKSRC_PXA
	select CPU_FREQ
	select CPU_SA1100
	select GPIOLIB
	select IRQ_DOMAIN
	select ISA
	select NEED_MACH_MEMORY_H
	help
	  Support for StrongARM 11x0 based boards.

if ARCH_SA1100

config SA1100_ASSABET
	bool "Assabet"
	select ARM_SA1110_CPUFREQ
	select GPIO_REG
	select LEDS_GPIO_REGISTER
	select REGULATOR
	select REGULATOR_FIXED_VOLTAGE
	help
	  Say Y here if you are using the Intel(R) StrongARM(R) SA-1110
	  Microprocessor Development Board (also known as the Assabet).

config ASSABET_NEPONSET
	bool "Include support for Neponset"
	depends on SA1100_ASSABET
	select SA1111
	help
	  Say Y here if you are using the Intel(R) StrongARM(R) SA-1110
	  Microprocessor Development Board (Assabet)  with the SA-1111
	  Development Board (Nepon).

config SA1100_CERF
	bool "CerfBoard"
	depends on UNUSED_BOARD_FILES
	select ARM_SA1110_CPUFREQ
	select LEDS_GPIO_REGISTER
	help
	  The Intrinsyc CerfBoard is based on the StrongARM 1110 (Discontinued).
	  More information is available at:
	  <http://www.intrinsyc.com/products/cerfboard/>.

	  Say Y if configuring for an Intrinsyc CerfBoard.
	  Say N otherwise.

choice
	prompt "Cerf Flash available"
	depends on SA1100_CERF
	default SA1100_CERF_FLASH_8MB

config SA1100_CERF_FLASH_8MB
	bool "8MB"

config SA1100_CERF_FLASH_16MB
	bool "16MB"

config SA1100_CERF_FLASH_32MB
	bool "32MB"

endchoice

config SA1100_COLLIE
	bool "Sharp Zaurus SL5500"
	# FIXME: select ARM_SA11x0_CPUFREQ
	select SHARP_LOCOMO
	select SHARP_PARAM
	select SHARP_SCOOP
	help
	  Say Y here to support the Sharp Zaurus SL5500 PDAs.

config SA1100_H3100
	bool "Compaq iPAQ H3100"
	depends on UNUSED_BOARD_FILES
	select ARM_SA1110_CPUFREQ
	select HTC_EGPIO
	select MFD_IPAQ_MICRO
	help
	  Say Y here if you intend to run this kernel on the Compaq iPAQ
	  H3100 handheld computer.

config SA1100_H3600
	bool "Compaq iPAQ H3600/H3700"
	select ARM_SA1110_CPUFREQ
	select HTC_EGPIO
	select MFD_IPAQ_MICRO
	help
	  Say Y here if you intend to run this kernel on the Compaq iPAQ
	  H3600 and H3700 handheld computers.

config SA1100_BADGE4
	bool "HP Labs BadgePAD 4"
	depends on UNUSED_BOARD_FILES
	select ARM_SA1100_CPUFREQ
	select SA1111
	help
	  Say Y here if you want to build a kernel for the HP Laboratories
	  BadgePAD 4.

config SA1100_JORNADA720
	bool "HP Jornada 720"
	depends on UNUSED_BOARD_FILES
	# FIXME: select ARM_SA11x0_CPUFREQ
	select SA1111
	help
	  Say Y here if you want to build a kernel for the HP Jornada 720
	  handheld computer.  See
	  <http://h10025.www1.hp.com/ewfrf/wc/product?product=61677&cc=us&lc=en&dlc=en&product=61677#>

config SA1100_JORNADA720_SSP
	bool "HP Jornada 720 Extended SSP driver"
	depends on SA1100_JORNADA720
	select SA1100_SSP
	help
	  Say Y here if you have a HP Jornada 7xx handheld computer and you
	  want to access devices connected to the MCU. Those include the
	  keyboard, touchscreen, backlight and battery. This driver also activates
	  the generic SSP which it extends.

config SA1100_HACKKIT
	bool "HackKit Core CPU Board"
	depends on UNUSED_BOARD_FILES
	select ARM_SA1100_CPUFREQ
	help
	  Say Y here to support the HackKit Core CPU Board
	  <http://hackkit.eletztrick.de>;

config SA1100_LART
	bool "LART"
	depends on UNUSED_BOARD_FILES
	select ARM_SA1100_CPUFREQ
	help
	  Say Y here if you are using the Linux Advanced Radio Terminal
	  (also known as the LART).  See <http://www.lartmaker.nl/> for
	  information on the LART.

config SA1100_NANOENGINE
	bool "nanoEngine"
	depends on UNUSED_BOARD_FILES
	select ARM_SA1110_CPUFREQ
	select FORCE_PCI
	select PCI_NANOENGINE
	help
	  Say Y here if you are using the Bright Star Engineering nanoEngine.
	  See <http://www.brightstareng.com/arm/nanoeng.htm> for information
	  on the BSE nanoEngine.

config SA1100_PLEB
	bool "PLEB"
	depends on UNUSED_BOARD_FILES
	select ARM_SA1100_CPUFREQ
	help
	  Say Y here if you are using version 1 of the Portable Linux
	  Embedded Board (also known as PLEB).
	  See <http://www.disy.cse.unsw.edu.au/Hardware/PLEB/>
	  for more information.

config SA1100_SHANNON
	bool "Shannon"
	depends on UNUSED_BOARD_FILES
	select ARM_SA1100_CPUFREQ
	select REGULATOR
	select REGULATOR_FIXED_VOLTAGE
	help
	  The Shannon (also known as a Tuxscreen, and also as a IS2630) was a
	  limited edition webphone produced by Philips. The Shannon is a SA1100
	  platform with a 640x480 LCD, touchscreen, CIR keyboard, PCMCIA slots,
	  and a telco interface.

config SA1100_SIMPAD
	bool "Simpad"
	depends on UNUSED_BOARD_FILES
	select ARM_SA1110_CPUFREQ
	help
	  The SIEMENS webpad SIMpad is based on the StrongARM 1110. There
	  are two different versions CL4 and SL4. CL4 has 32MB RAM and 16MB
	  FLASH. The SL4 version got 64 MB RAM and 32 MB FLASH and a
	  PCMCIA-Slot. The version for the Germany Telecom (DTAG) is the same
	  like CL4 in additional it has a PCMCIA-Slot. For more information
	  visit <http://www.usa.siemens.com/> or <http://www.siemens.ch/>.

config SA1100_SSP
	tristate "Generic PIO SSP"
	depends on UNUSED_BOARD_FILES
	help
	  Say Y here to enable support for the generic PIO SSP driver.
	  This isn't for audio support, but for attached sensors and
	  other devices, eg for BadgePAD 4 sensor support.

endif


code:
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for the linux kernel.
#

# Common support
obj-y := clock.o generic.o #nmi-oopser.o

# Specific board support
obj-$(CONFIG_SA1100_ASSABET)		+= assabet.o
obj-$(CONFIG_ASSABET_NEPONSET)		+= neponset.o

obj-$(CONFIG_SA1100_BADGE4)		+= badge4.o

obj-$(CONFIG_SA1100_CERF)		+= cerf.o

obj-$(CONFIG_SA1100_COLLIE)		+= collie.o

obj-$(CONFIG_SA1100_H3100)		+= h3100.o h3xxx.o
obj-$(CONFIG_SA1100_H3600)		+= h3600.o h3xxx.o

obj-$(CONFIG_SA1100_HACKKIT)		+= hackkit.o

obj-$(CONFIG_SA1100_JORNADA720)		+= jornada720.o
obj-$(CONFIG_SA1100_JORNADA720_SSP)	+= jornada720_ssp.o

obj-$(CONFIG_SA1100_LART)		+= lart.o

obj-$(CONFIG_SA1100_NANOENGINE)		+= nanoengine.o
obj-$(CONFIG_PCI_NANOENGINE)		+= pci-nanoengine.o

obj-$(CONFIG_SA1100_PLEB)		+= pleb.o

obj-$(CONFIG_SA1100_SHANNON)		+= shannon.o

obj-$(CONFIG_SA1100_SIMPAD)		+= simpad.o

# Miscellaneous functions
obj-$(CONFIG_PM)			+= pm.o sleep.o
obj-$(CONFIG_SA1100_SSP)		+= ssp.o