Skip to content

Commit

Permalink
[ARM] 3635/1: S3C24XX: Add S3C2412 core cpu support
Browse files Browse the repository at this point in the history
Patch from Ben Dooks

Add support for the Samsung S3C2412 and S3C2413 range
of SoCs. This patch contains the core identification,
debug macros, and basic register updates to get these
to build.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Ben Dooks authored and Russell King committed Jun 24, 2006
1 parent a3ff550 commit 68d9ab3
Show file tree
Hide file tree
Showing 11 changed files with 369 additions and 8 deletions.
14 changes: 14 additions & 0 deletions arch/arm/mach-s3c2410/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,20 @@ config CPU_S3C2410
Support for S3C2410 and S3C2410A family from the S3C24XX line
of Samsung Mobile CPUs.

# internal node to signify if we are only dealing with an S3C2412

config CPU_S3C2412_ONLY
bool
depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
!CPU_S3C2440 && !CPU_S3C2442 && CPU_S3C2412
default y if CPU_S3C2412

config CPU_S3C2412
bool
depends on ARCH_S3C2410
help
Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line

config CPU_S3C244X
bool
depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
Expand Down
4 changes: 4 additions & 0 deletions arch/arm/mach-s3c2410/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ obj-$(CONFIG_S3C2410_DMA) += dma.o
obj-$(CONFIG_PM) += pm.o sleep.o
obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o

# S3C2412 support
obj-$(CONFIG_CPU_S3C2412) += s3c2412.o

#
# S3C244X support

obj-$(CONFIG_CPU_S3C244X) += s3c244x.o
Expand Down
37 changes: 34 additions & 3 deletions arch/arm/mach-s3c2410/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "clock.h"
#include "s3c2400.h"
#include "s3c2410.h"
#include "s3c2412.h"
#include "s3c244x.h"
#include "s3c2440.h"
#include "s3c2442.h"
Expand All @@ -62,6 +63,7 @@ struct cpu_table {

static const char name_s3c2400[] = "S3C2400";
static const char name_s3c2410[] = "S3C2410";
static const char name_s3c2412[] = "S3C2412";
static const char name_s3c2440[] = "S3C2440";
static const char name_s3c2442[] = "S3C2442";
static const char name_s3c2410a[] = "S3C2410A";
Expand Down Expand Up @@ -113,6 +115,15 @@ static struct cpu_table cpu_ids[] __initdata = {
.init = s3c2442_init,
.name = name_s3c2442
},
{
.idcode = 0x32412001,
.idmask = 0xffffffff,
.map_io = s3c2412_map_io,
.init_clocks = s3c2412_init_clocks,
.init_uarts = s3c2412_init_uarts,
.init = s3c2412_init,
.name = name_s3c2412,
},
{
.idcode = 0x0, /* S3C2400 doesn't have an idcode */
.idmask = 0xffffffff,
Expand Down Expand Up @@ -171,16 +182,36 @@ void s3c24xx_set_board(struct s3c24xx_board *b)

static struct cpu_table *cpu;

static unsigned long s3c24xx_read_idcode_v5(void)
{
#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
return __raw_readl(S3C2412_GSTATUS1);
#else
return 1UL; /* don't look like an 2400 */
#endif
}

static unsigned long s3c24xx_read_idcode_v4(void)
{
#ifndef CONFIG_CPU_S3C2400
return __raw_readl(S3C2410_GSTATUS1);
#else
return 0UL;
#endif
}

void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
{
unsigned long idcode = 0x0;

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

#ifndef CONFIG_CPU_S3C2400
idcode = __raw_readl(S3C2410_GSTATUS1);
#endif
if (cpu_architecture() >= CPU_ARCH_ARMv5) {
idcode = s3c24xx_read_idcode_v5();
} else {
idcode = s3c24xx_read_idcode_v4();
}

cpu = s3c_lookup_cpu(idcode);

Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-s3c2410/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,6 @@ extern struct sys_timer s3c24xx_timer;
/* system device classes */

extern struct sysdev_class s3c2410_sysclass;
extern struct sysdev_class s3c2412_sysclass;
extern struct sysdev_class s3c2440_sysclass;
extern struct sysdev_class s3c2442_sysclass;
195 changes: 195 additions & 0 deletions arch/arm/mach-s3c2410/s3c2412.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
/* linux/arch/arm/mach-s3c2410/s3c2412.c
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* http://armlinux.simtec.co.uk/.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Modifications:
* 16-May-2003 BJD Created initial version
* 16-Aug-2003 BJD Fixed header files and copyright, added URL
* 05-Sep-2003 BJD Moved to kernel v2.6
* 18-Jan-2004 BJD Added serial port configuration
* 21-Aug-2004 BJD Added new struct s3c2410_board handler
* 28-Sep-2004 BJD Updates for new serial port bits
* 04-Nov-2004 BJD Updated UART configuration process
* 10-Jan-2005 BJD Removed s3c2410_clock_tick_rate
* 13-Aug-2005 DA Removed UART from initial I/O mappings
*/

#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/sysdev.h>
#include <linux/platform_device.h>

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

#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>

#include <asm/arch/regs-clock.h>
#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-gpioj.h>
#include <asm/arch/regs-dsc.h>

#include "s3c2412.h"
#include "cpu.h"
#include "devs.h"
#include "clock.h"
#include "pm.h"

#ifndef CONFIG_CPU_S3C2412_ONLY
void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO;
#endif

/* Initial IO mappings */

static struct map_desc s3c2412_iodesc[] __initdata = {
IODESC_ENT(CLKPWR),
IODESC_ENT(LCD),
IODESC_ENT(TIMER),
IODESC_ENT(ADC),
IODESC_ENT(WATCHDOG),
};

/* uart registration process */

void __init s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no)
{
s3c24xx_init_uartdevs("s3c2412-uart", s3c2410_uart_resources, cfg, no);

/* rename devices that are s3c2412/s3c2413 specific */
s3c_device_sdi.name = "s3c2412-sdi";
s3c_device_nand.name = "s3c2412-nand";
}

/* s3c2412_map_io
*
* register the standard cpu IO areas, and any passed in from the
* machine specific initialisation.
*/

void __init s3c2412_map_io(struct map_desc *mach_desc, int mach_size)
{
/* move base of IO */

s3c24xx_va_gpio2 = S3C24XX_VA_GPIO + 0x10;

/* register our io-tables */

iotable_init(s3c2412_iodesc, ARRAY_SIZE(s3c2412_iodesc));
iotable_init(mach_desc, mach_size);
}

void __init s3c2412_init_clocks(int xtal)
{
unsigned long tmp;
unsigned long fclk;
unsigned long hclk;
unsigned long pclk;

/* now we've got our machine bits initialised, work out what
* clocks we've got */

fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal*2);

tmp = __raw_readl(S3C2410_CLKDIVN);

/* work out clock scalings */

hclk = fclk / ((tmp & S3C2412_CLKDIVN_HDIVN_MASK) + 1);
hclk /= ((tmp & S3C2421_CLKDIVN_ARMDIVN) ? 2 : 1);
pclk = hclk / ((tmp & S3C2412_CLKDIVN_PDIVN) ? 2 : 1);

/* print brieft summary of clocks, etc */

printk("S3C2412: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));

/* initialise the clocks here, to allow other things like the
* console to use them
*/

s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
s3c2412_baseclk_add();
}

/* need to register class before we actually register the device, and
* we also need to ensure that it has been initialised before any of the
* drivers even try to use it (even if not on an s3c2412 based system)
* as a driver which may support both 2410 and 2440 may try and use it.
*/

#ifdef CONFIG_PM
static struct sleep_save s3c2412_sleep[] = {
SAVE_ITEM(S3C2412_DSC0),
SAVE_ITEM(S3C2412_DSC1),
SAVE_ITEM(S3C2413_GPJDAT),
SAVE_ITEM(S3C2413_GPJCON),
SAVE_ITEM(S3C2413_GPJUP),

/* save the sleep configuration anyway, just in case these
* get damaged during wakeup */

SAVE_ITEM(S3C2412_GPBSLPCON),
SAVE_ITEM(S3C2412_GPCSLPCON),
SAVE_ITEM(S3C2412_GPDSLPCON),
SAVE_ITEM(S3C2412_GPESLPCON),
SAVE_ITEM(S3C2412_GPFSLPCON),
SAVE_ITEM(S3C2412_GPGSLPCON),
SAVE_ITEM(S3C2412_GPHSLPCON),
SAVE_ITEM(S3C2413_GPJSLPCON),
};

static int s3c2412_suspend(struct sys_device *dev, pm_message_t state)
{
s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
return 0;
}

static int s3c2412_resume(struct sys_device *dev)
{
s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
return 0;
}

#else
#define s3c2412_suspend NULL
#define s3c2412_resume NULL
#endif

struct sysdev_class s3c2412_sysclass = {
set_kset_name("s3c2412-core"),
.suspend = s3c2412_suspend,
.resume = s3c2412_resume
};

static int __init s3c2412_core_init(void)
{
return sysdev_class_register(&s3c2412_sysclass);
}

core_initcall(s3c2412_core_init);

static struct sys_device s3c2412_sysdev = {
.cls = &s3c2412_sysclass,
};

int __init s3c2412_init(void)
{
printk("S3C2412: Initialising architecture\n");

return sysdev_register(&s3c2412_sysdev);
}
29 changes: 29 additions & 0 deletions arch/arm/mach-s3c2410/s3c2412.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* arch/arm/mach-s3c2410/s3c2412.h
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* Header file for s3c2412 cpu support
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/

#ifdef CONFIG_CPU_S3C2412

extern int s3c2412_init(void);

extern void s3c2412_map_io(struct map_desc *mach_desc, int size);

extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no);

extern void s3c2412_init_clocks(int xtal);

extern int s3c2412_baseclk_add(void);
#else
#define s3c2412_init_clocks NULL
#define s3c2412_init_uarts NULL
#define s3c2412_map_io NULL
#define s3c2412_init NULL
#endif
10 changes: 8 additions & 2 deletions include/asm-arm/arch-s3c2410/debug-macro.S
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
.endm

.macro senduart,rd,rx
str \rd, [\rx, # S3C2410_UTXH ]
strb \rd, [\rx, # S3C2410_UTXH ]
.endm

.macro busyuart, rd, rx
Expand All @@ -42,6 +42,12 @@
beq 1001f @
@ FIFO enabled...
1003:
@ check for arm920 vs arm926. currently assume all arm926
@ devices have an 64 byte FIFO identical to the s3c2440
mrc p15, 0, \rd, c0, c0
and \rd, \rd, #0xff0
teq \rd, #0x260
beq 1004f
mrc p15, 0, \rd, c1, c0
tst \rd, #1
addeq \rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART)
Expand All @@ -50,7 +56,7 @@
ldr \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
and \rd, \rd, #0x00ff0000
teq \rd, #0x00440000 @ is it 2440?

1004:
ldr \rd, [ \rx, # S3C2410_UFSTAT ]
moveq \rd, \rd, lsr #SHIFT_2440TXF
tst \rd, #S3C2410_UFSTAT_TXFULL
Expand Down
16 changes: 16 additions & 0 deletions include/asm-arm/arch-s3c2410/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,4 +236,20 @@
#define S3C24XX_PA_SPI S3C2410_PA_SPI
#endif

/* deal with the registers that move under the 2412/2413 */

#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
#ifndef __ASSEMBLY__
extern void __iomem *s3c24xx_va_gpio2;
#endif
#ifdef CONFIG_CPU_S3C2412_ONLY
#define S3C24XX_VA_GPIO2 (S3C24XX_VA_GPIO + 0x10)
#else
#define S3C24XX_VA_GPIO2 s3c24xx_va_gpio2
#endif
#else
#define s3c24xx_va_gpio2 S3C24XX_VA_GPIO
#define S3C24XX_VA_GPIO2 S3C24XX_VA_GPIO
#endif

#endif /* __ASM_ARCH_MAP_H */
3 changes: 3 additions & 0 deletions include/asm-arm/arch-s3c2410/regs-dsc.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
#define S3C2440_DSC0 S3C2410_GPIOREG(0xc4)
#define S3C2440_DSC1 S3C2410_GPIOREG(0xc8)

#define S3C2412_DSC0 S3C2410_GPIOREG(0xdc)
#define S3C2412_DSC1 S3C2410_GPIOREG(0xe0)

#define S3C2440_SELECT_DSC0 (0)
#define S3C2440_SELECT_DSC1 (1<<31)

Expand Down
Loading

0 comments on commit 68d9ab3

Please sign in to comment.