提交 e11c910b 编写于 作者: R Russell King 提交者: Russell King

Merge S3C24xx branch

......@@ -81,6 +81,12 @@ config SMDK2440_CPU2442
depends on ARCH_S3C2440
select CPU_S3C2442
config MACH_SMDK2413
bool "SMDK2413"
select CPU_S3C2412
select MACH_SMDK
help
Say Y here if you are using an SMDK2413
config MACH_VR1000
bool "Thorcom VR1000"
......@@ -127,6 +133,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)
......
......@@ -24,6 +24,11 @@ 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
obj-$(CONFIG_CPU_S3C2412) += s3c2412-clock.o
#
# S3C244X support
obj-$(CONFIG_CPU_S3C244X) += s3c244x.o
......@@ -57,6 +62,7 @@ obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o
obj-$(CONFIG_ARCH_H1940) += mach-h1940.o
obj-$(CONFIG_MACH_N30) += mach-n30.o
obj-$(CONFIG_ARCH_SMDK2410) += mach-smdk2410.o
obj-$(CONFIG_MACH_SMDK2413) += mach-smdk2413.o
obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o
obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o
obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o
......
......@@ -213,7 +213,7 @@ EXPORT_SYMBOL(clk_set_parent);
/* base clocks */
static struct clk clk_xtal = {
struct clk clk_xtal = {
.name = "xtal",
.id = -1,
.rate = 0,
......@@ -221,6 +221,11 @@ static struct clk clk_xtal = {
.ctrlbit = 0,
};
struct clk clk_mpll = {
.name = "mpll",
.id = -1,
};
struct clk clk_upll = {
.name = "upll",
.id = -1,
......@@ -232,7 +237,7 @@ struct clk clk_f = {
.name = "fclk",
.id = -1,
.rate = 0,
.parent = NULL,
.parent = &clk_mpll,
.ctrlbit = 0,
};
......@@ -263,14 +268,14 @@ struct clk clk_usb_bus = {
static int s3c24xx_dclk_enable(struct clk *clk, int enable)
{
unsigned long dclkcon = __raw_readl(S3C2410_DCLKCON);
unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON);
if (enable)
dclkcon |= clk->ctrlbit;
else
dclkcon &= ~clk->ctrlbit;
__raw_writel(dclkcon, S3C2410_DCLKCON);
__raw_writel(dclkcon, S3C24XX_DCLKCON);
return 0;
}
......@@ -289,7 +294,7 @@ static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
clk->parent = parent;
dclkcon = __raw_readl(S3C2410_DCLKCON);
dclkcon = __raw_readl(S3C24XX_DCLKCON);
if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
if (uclk)
......@@ -303,7 +308,7 @@ static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
}
__raw_writel(dclkcon, S3C2410_DCLKCON);
__raw_writel(dclkcon, S3C24XX_DCLKCON);
return 0;
}
......@@ -413,6 +418,7 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
clk_xtal.rate = xtal;
clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
clk_mpll.rate = fclk;
clk_h.rate = hclk;
clk_p.rate = pclk;
clk_f.rate = fclk;
......@@ -424,6 +430,9 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
if (s3c24xx_register_clock(&clk_xtal) < 0)
printk(KERN_ERR "failed to register master xtal\n");
if (s3c24xx_register_clock(&clk_mpll) < 0)
printk(KERN_ERR "failed to register mpll clock\n");
if (s3c24xx_register_clock(&clk_upll) < 0)
printk(KERN_ERR "failed to register upll clock\n");
......
......@@ -42,7 +42,9 @@ extern struct clk clk_usb_bus;
extern struct clk clk_f;
extern struct clk clk_h;
extern struct clk clk_p;
extern struct clk clk_mpll;
extern struct clk clk_upll;
extern struct clk clk_xtal;
/* exports for arch/arm/mach-s3c2410
*
......
......@@ -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"
......@@ -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";
......@@ -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,
......@@ -171,6 +182,24 @@ 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;
......@@ -178,9 +207,11 @@ void __init s3c24xx_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));
#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);
......
......@@ -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;
......@@ -191,13 +191,9 @@ static struct irqchip s3c_irq_chip = {
.ack = s3c_irq_ack,
.mask = s3c_irq_mask,
.unmask = s3c_irq_unmask,
.set_wake = s3c_irq_wake
.set_wake = s3c_irq_wake
};
/* S3C2410_EINTMASK
* S3C2410_EINTPEND
*/
static void
s3c_irqext_mask(unsigned int irqno)
{
......@@ -205,9 +201,9 @@ s3c_irqext_mask(unsigned int irqno)
irqno -= EXTINT_OFF;
mask = __raw_readl(S3C2410_EINTMASK);
mask = __raw_readl(S3C24XX_EINTMASK);
mask |= ( 1UL << irqno);
__raw_writel(mask, S3C2410_EINTMASK);
__raw_writel(mask, S3C24XX_EINTMASK);
if (irqno <= (IRQ_EINT7 - EXTINT_OFF)) {
/* check to see if all need masking */
......@@ -232,11 +228,11 @@ s3c_irqext_ack(unsigned int irqno)
bit = 1UL << (irqno - EXTINT_OFF);
mask = __raw_readl(S3C2410_EINTMASK);
mask = __raw_readl(S3C24XX_EINTMASK);
__raw_writel(bit, S3C2410_EINTPEND);
__raw_writel(bit, S3C24XX_EINTPEND);
req = __raw_readl(S3C2410_EINTPEND);
req = __raw_readl(S3C24XX_EINTPEND);
req &= ~mask;
/* not sure if we should be acking the parent irq... */
......@@ -257,9 +253,9 @@ s3c_irqext_unmask(unsigned int irqno)
irqno -= EXTINT_OFF;
mask = __raw_readl(S3C2410_EINTMASK);
mask = __raw_readl(S3C24XX_EINTMASK);
mask &= ~( 1UL << irqno);
__raw_writel(mask, S3C2410_EINTMASK);
__raw_writel(mask, S3C24XX_EINTMASK);
s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23);
}
......@@ -275,28 +271,28 @@ s3c_irqext_type(unsigned int irq, unsigned int type)
if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
{
gpcon_reg = S3C2410_GPFCON;
extint_reg = S3C2410_EXTINT0;
extint_reg = S3C24XX_EXTINT0;
gpcon_offset = (irq - IRQ_EINT0) * 2;
extint_offset = (irq - IRQ_EINT0) * 4;
}
else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
{
gpcon_reg = S3C2410_GPFCON;
extint_reg = S3C2410_EXTINT0;
extint_reg = S3C24XX_EXTINT0;
gpcon_offset = (irq - (EXTINT_OFF)) * 2;
extint_offset = (irq - (EXTINT_OFF)) * 4;
}
else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
{
gpcon_reg = S3C2410_GPGCON;
extint_reg = S3C2410_EXTINT1;
extint_reg = S3C24XX_EXTINT1;
gpcon_offset = (irq - IRQ_EINT8) * 2;
extint_offset = (irq - IRQ_EINT8) * 4;
}
else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
{
gpcon_reg = S3C2410_GPGCON;
extint_reg = S3C2410_EXTINT2;
extint_reg = S3C24XX_EXTINT2;
gpcon_offset = (irq - IRQ_EINT8) * 2;
extint_offset = (irq - IRQ_EINT16) * 4;
} else
......@@ -572,6 +568,23 @@ s3c_irq_demux_uart2(unsigned int irq,
s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);
}
static void
s3c_irq_demux_extint(unsigned int irq,
struct irqdesc *desc,
struct pt_regs *regs)
{
unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
eintpnd &= ~eintmsk;
if (eintpnd) {
irq = fls(eintpnd);
irq += (IRQ_EINT4 - (4 + 1));
desc_handle_irq(irq, irq_desc + irq, regs);
}
}
/* s3c24xx_init_irq
*
......@@ -591,12 +604,12 @@ void __init s3c24xx_init_irq(void)
last = 0;
for (i = 0; i < 4; i++) {
pend = __raw_readl(S3C2410_EINTPEND);
pend = __raw_readl(S3C24XX_EINTPEND);
if (pend == 0 || pend == last)
break;
__raw_writel(pend, S3C2410_EINTPEND);
__raw_writel(pend, S3C24XX_EINTPEND);
printk("irq: clearing pending ext status %08x\n", (int)pend);
last = pend;
}
......@@ -630,12 +643,14 @@ void __init s3c24xx_init_irq(void)
irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
for (irqno = IRQ_BATT_FLT; irqno <= IRQ_ADCPARENT; irqno++) {
for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
/* set all the s3c2410 internal irqs */
switch (irqno) {
/* deal with the special IRQs (cascaded) */
case IRQ_EINT4t7:
case IRQ_EINT8t23:
case IRQ_UART0:
case IRQ_UART1:
case IRQ_UART2:
......@@ -659,12 +674,14 @@ void __init s3c24xx_init_irq(void)
/* setup the cascade irq handlers */
set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint);
set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint);
set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
/* external interrupts */
for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
......
/* linux/arch/arm/mach-s3c2410/mach-smdk2413.c
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* Thanks to Dimity Andric (TomTom) and Steven Ryu (Samsung) for the
* loans of SMDK2413 to work with.
*
* 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.
*/
#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/platform_device.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
#include <asm/hardware.h>
#include <asm/hardware/iomd.h>
#include <asm/setup.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
//#include <asm/debug-ll.h>
#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-lcd.h>
#include <asm/arch/idle.h>
#include <asm/arch/fb.h>
#include "s3c2410.h"
#include "s3c2412.h"
#include "clock.h"
#include "devs.h"
#include "cpu.h"
#include "common-smdk.h"
static struct map_desc smdk2413_iodesc[] __initdata = {
};
static struct s3c2410_uartcfg smdk2413_uartcfgs[] __initdata = {
[0] = {
.hwport = 0,
.flags = 0,
.ucon = 0x3c5,
.ulcon = 0x03,
.ufcon = 0x51,
},
[1] = {
.hwport = 1,
.flags = 0,
.ucon = 0x3c5,
.ulcon = 0x03,
.ufcon = 0x51,
},
/* IR port */
[2] = {
.hwport = 2,
.flags = 0,
.ucon = 0x3c5,
.ulcon = 0x43,
.ufcon = 0x51,
}
};
static struct platform_device *smdk2413_devices[] __initdata = {
&s3c_device_usb,
//&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
};
static struct s3c24xx_board smdk2413_board __initdata = {
.devices = smdk2413_devices,
.devices_count = ARRAY_SIZE(smdk2413_devices)
};
static void __init smdk2413_fixup(struct machine_desc *desc,
struct tag *tags, char **cmdline,
struct meminfo *mi)
{
if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
mi->nr_banks=1;
mi->bank[0].start = 0x30000000;
mi->bank[0].size = SZ_64M;
mi->bank[0].node = 0;
}
}
static void __init smdk2413_map_io(void)
{
s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc));
s3c24xx_init_clocks(12000000);
s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs));
s3c24xx_set_board(&smdk2413_board);
}
static void __init smdk2413_machine_init(void)
{
smdk_machine_init();
}
MACHINE_START(S3C2413, "SMDK2413")
/* Maintainer: Ben Dooks <ben@fluff.org> */
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.fixup = smdk2413_fixup,
.init_irq = s3c24xx_init_irq,
.map_io = smdk2413_map_io,
.init_machine = smdk2413_machine_init,
.timer = &s3c24xx_timer,
MACHINE_END
......@@ -48,7 +48,8 @@ static __init int pm_simtec_init(void)
/* check which machine we are running on */
if (!machine_is_bast() && !machine_is_vr1000() && !machine_is_anubis())
if (!machine_is_bast() && !machine_is_vr1000() &&
!machine_is_anubis() && !machine_is_osiris())
return 0;
printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n");
......
......@@ -182,7 +182,15 @@ static struct clk init_clocks[] = {
.id = -1,
.parent = &clk_p,
.ctrlbit = 0,
}
}, {
.name = "usb-bus-host",
.id = -1,
.parent = &clk_usb_bus,
}, {
.name = "usb-bus-gadget",
.id = -1,
.parent = &clk_usb_bus,
},
};
/* s3c2410_baseclk_add()
......
......@@ -18,9 +18,6 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Changelog
* 15-Jan-2006 LCVR Splitted from gpio.c
*/
#include <linux/kernel.h>
......@@ -38,7 +35,7 @@
int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
unsigned int config)
{
void __iomem *reg = S3C2410_EINFLT0;
void __iomem *reg = S3C24XX_EINFLT0;
unsigned long flags;
unsigned long val;
......@@ -47,7 +44,7 @@ int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
config &= 0xff;
pin -= S3C2410_GPG8_EINT16;
pin -= S3C2410_GPG8;
reg += pin & ~3;
local_irq_save(flags);
......@@ -61,10 +58,10 @@ int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
/* update filter enable */
val = __raw_readl(S3C2410_EXTINT2);
val = __raw_readl(S3C24XX_EXTINT2);
val &= ~(1 << ((pin * 4) + 3));
val |= on << ((pin * 4) + 3);
__raw_writel(val, S3C2410_EXTINT2);
__raw_writel(val, S3C24XX_EXTINT2);
local_irq_restore(flags);
......@@ -75,7 +72,7 @@ EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
int s3c2410_gpio_getirq(unsigned int pin)
{
if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15_EINT23)
if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15)
return -1; /* not valid interrupts */
if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
......
/* linux/arch/arm/mach-s3c2410/s3c2412-clock.c
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C2412,S3C2413 Clock control support
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/sysdev.h>
#include <linux/clk.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/arch/regs-clock.h>
#include <asm/arch/regs-gpio.h>
#include "clock.h"
#include "cpu.h"
/* We currently have to assume that the system is running
* from the XTPll input, and that all ***REFCLKs are being
* fed from it, as we cannot read the state of OM[4] from
* software.
*
* It would be possible for each board initialisation to
* set the correct muxing at initialisation
*/
int s3c2412_clkcon_enable(struct clk *clk, int enable)
{
unsigned int clocks = clk->ctrlbit;
unsigned long clkcon;
clkcon = __raw_readl(S3C2410_CLKCON);
if (enable)
clkcon |= clocks;
else
clkcon &= ~clocks;
__raw_writel(clkcon, S3C2410_CLKCON);
return 0;
}
static int s3c2412_upll_enable(struct clk *clk, int enable)
{
unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
unsigned long orig = upllcon;
if (!enable)
upllcon |= S3C2412_PLLCON_OFF;
else
upllcon &= ~S3C2412_PLLCON_OFF;
__raw_writel(upllcon, S3C2410_UPLLCON);
/* allow ~150uS for the PLL to settle and lock */
if (enable && (orig & S3C2412_PLLCON_OFF))
udelay(150);
return 0;
}
/* clock selections */
/* CPU EXTCLK input */
static struct clk clk_ext = {
.name = "extclk",
.id = -1,
};
static struct clk clk_erefclk = {
.name = "erefclk",
.id = -1,
};
static struct clk clk_urefclk = {
.name = "urefclk",
.id = -1,
};
static int s3c2412_setparent_usysclk(struct clk *clk, struct clk *parent)
{
unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
if (parent == &clk_urefclk)
clksrc &= ~S3C2412_CLKSRC_USYSCLK_UPLL;
else if (parent == &clk_upll)
clksrc |= S3C2412_CLKSRC_USYSCLK_UPLL;
else
return -EINVAL;
clk->parent = parent;
__raw_writel(clksrc, S3C2412_CLKSRC);
return 0;
}
static struct clk clk_usysclk = {
.name = "usysclk",
.id = -1,
.parent = &clk_xtal,
.set_parent = s3c2412_setparent_usysclk,
};
static struct clk clk_mrefclk = {
.name = "mrefclk",
.parent = &clk_xtal,
.id = -1,
};
static struct clk clk_mdivclk = {
.name = "mdivclk",
.parent = &clk_xtal,
.id = -1,
};
static int s3c2412_setparent_usbsrc(struct clk *clk, struct clk *parent)
{
unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
if (parent == &clk_usysclk)
clksrc &= ~S3C2412_CLKSRC_USBCLK_HCLK;
else if (parent == &clk_h)
clksrc |= S3C2412_CLKSRC_USBCLK_HCLK;
else
return -EINVAL;
clk->parent = parent;
__raw_writel(clksrc, S3C2412_CLKSRC);
return 0;
}
static unsigned long s3c2412_roundrate_usbsrc(struct clk *clk,
unsigned long rate)
{
unsigned long parent_rate = clk_get_rate(clk->parent);
int div;
if (rate > parent_rate)
return parent_rate;
div = parent_rate / rate;
if (div > 2)
div = 2;
return parent_rate / div;
}
static unsigned long s3c2412_getrate_usbsrc(struct clk *clk)
{
unsigned long parent_rate = clk_get_rate(clk->parent);
unsigned long div = __raw_readl(S3C2410_CLKDIVN);
return parent_rate / ((div & S3C2412_CLKDIVN_USB48DIV) ? 2 : 1);
}
static int s3c2412_setrate_usbsrc(struct clk *clk, unsigned long rate)
{
unsigned long parent_rate = clk_get_rate(clk->parent);
unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
rate = s3c2412_roundrate_usbsrc(clk, rate);
if ((parent_rate / rate) == 2)
clkdivn |= S3C2412_CLKDIVN_USB48DIV;
else
clkdivn &= ~S3C2412_CLKDIVN_USB48DIV;
__raw_writel(clkdivn, S3C2410_CLKDIVN);
return 0;
}
static struct clk clk_usbsrc = {
.name = "usbsrc",
.id = -1,
.get_rate = s3c2412_getrate_usbsrc,
.set_rate = s3c2412_setrate_usbsrc,
.round_rate = s3c2412_roundrate_usbsrc,
.set_parent = s3c2412_setparent_usbsrc,
};
static int s3c2412_setparent_msysclk(struct clk *clk, struct clk *parent)
{
unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
if (parent == &clk_mdivclk)
clksrc &= ~S3C2412_CLKSRC_MSYSCLK_MPLL;
else if (parent == &clk_upll)
clksrc |= S3C2412_CLKSRC_MSYSCLK_MPLL;
else
return -EINVAL;
clk->parent = parent;
__raw_writel(clksrc, S3C2412_CLKSRC);
return 0;
}
static struct clk clk_msysclk = {
.name = "msysclk",
.id = -1,
.set_parent = s3c2412_setparent_msysclk,
};
/* these next clocks have an divider immediately after them,
* so we can register them with their divider and leave out the
* intermediate clock stage
*/
static unsigned long s3c2412_roundrate_clksrc(struct clk *clk,
unsigned long rate)
{
unsigned long parent_rate = clk_get_rate(clk->parent);
int div;
if (rate > parent_rate)
return parent_rate;
/* note, we remove the +/- 1 calculations as they cancel out */
div = (rate / parent_rate);
if (div < 1)
div = 1;
else if (div > 16)
div = 16;
return parent_rate / div;
}
static int s3c2412_setparent_uart(struct clk *clk, struct clk *parent)
{
unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
if (parent == &clk_erefclk)
clksrc &= ~S3C2412_CLKSRC_UARTCLK_MPLL;
else if (parent == &clk_mpll)
clksrc |= S3C2412_CLKSRC_UARTCLK_MPLL;
else
return -EINVAL;
clk->parent = parent;
__raw_writel(clksrc, S3C2412_CLKSRC);
return 0;
}
static unsigned long s3c2412_getrate_uart(struct clk *clk)
{
unsigned long parent_rate = clk_get_rate(clk->parent);
unsigned long div = __raw_readl(S3C2410_CLKDIVN);
div &= S3C2412_CLKDIVN_UARTDIV_MASK;
div >>= S3C2412_CLKDIVN_UARTDIV_SHIFT;
return parent_rate / (div + 1);
}
static int s3c2412_setrate_uart(struct clk *clk, unsigned long rate)
{
unsigned long parent_rate = clk_get_rate(clk->parent);
unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
rate = s3c2412_roundrate_clksrc(clk, rate);
clkdivn &= ~S3C2412_CLKDIVN_UARTDIV_MASK;
clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_UARTDIV_SHIFT;
__raw_writel(clkdivn, S3C2410_CLKDIVN);
return 0;
}
static struct clk clk_uart = {
.name = "uartclk",
.id = -1,
.get_rate = s3c2412_getrate_uart,
.set_rate = s3c2412_setrate_uart,
.set_parent = s3c2412_setparent_uart,
.round_rate = s3c2412_roundrate_clksrc,
};
static int s3c2412_setparent_i2s(struct clk *clk, struct clk *parent)
{
unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
if (parent == &clk_erefclk)
clksrc &= ~S3C2412_CLKSRC_I2SCLK_MPLL;
else if (parent == &clk_mpll)
clksrc |= S3C2412_CLKSRC_I2SCLK_MPLL;
else
return -EINVAL;
clk->parent = parent;
__raw_writel(clksrc, S3C2412_CLKSRC);
return 0;
}
static unsigned long s3c2412_getrate_i2s(struct clk *clk)
{
unsigned long parent_rate = clk_get_rate(clk->parent);
unsigned long div = __raw_readl(S3C2410_CLKDIVN);
div &= S3C2412_CLKDIVN_I2SDIV_MASK;
div >>= S3C2412_CLKDIVN_I2SDIV_SHIFT;
return parent_rate / (div + 1);
}
static int s3c2412_setrate_i2s(struct clk *clk, unsigned long rate)
{
unsigned long parent_rate = clk_get_rate(clk->parent);
unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
rate = s3c2412_roundrate_clksrc(clk, rate);
clkdivn &= ~S3C2412_CLKDIVN_I2SDIV_MASK;
clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_I2SDIV_SHIFT;
__raw_writel(clkdivn, S3C2410_CLKDIVN);
return 0;
}
static struct clk clk_i2s = {
.name = "i2sclk",
.id = -1,
.get_rate = s3c2412_getrate_i2s,
.set_rate = s3c2412_setrate_i2s,
.set_parent = s3c2412_setparent_i2s,
.round_rate = s3c2412_roundrate_clksrc,
};
static int s3c2412_setparent_cam(struct clk *clk, struct clk *parent)
{
unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
if (parent == &clk_usysclk)
clksrc &= ~S3C2412_CLKSRC_CAMCLK_HCLK;
else if (parent == &clk_h)
clksrc |= S3C2412_CLKSRC_CAMCLK_HCLK;
else
return -EINVAL;
clk->parent = parent;
__raw_writel(clksrc, S3C2412_CLKSRC);
return 0;
}
static unsigned long s3c2412_getrate_cam(struct clk *clk)
{
unsigned long parent_rate = clk_get_rate(clk->parent);
unsigned long div = __raw_readl(S3C2410_CLKDIVN);
div &= S3C2412_CLKDIVN_CAMDIV_MASK;
div >>= S3C2412_CLKDIVN_CAMDIV_SHIFT;
return parent_rate / (div + 1);
}
static int s3c2412_setrate_cam(struct clk *clk, unsigned long rate)
{
unsigned long parent_rate = clk_get_rate(clk->parent);
unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
rate = s3c2412_roundrate_clksrc(clk, rate);
clkdivn &= ~S3C2412_CLKDIVN_CAMDIV_MASK;
clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_CAMDIV_SHIFT;
__raw_writel(clkdivn, S3C2410_CLKDIVN);
return 0;
}
static struct clk clk_cam = {
.name = "camif-upll", /* same as 2440 name */
.id = -1,
.get_rate = s3c2412_getrate_cam,
.set_rate = s3c2412_setrate_cam,
.set_parent = s3c2412_setparent_cam,
.round_rate = s3c2412_roundrate_clksrc,
};
/* standard clock definitions */
static struct clk init_clocks_disable[] = {
{
.name = "nand",
.id = -1,
.parent = &clk_h,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_NAND,
}, {
.name = "sdi",
.id = -1,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_SDI,
}, {
.name = "adc",
.id = -1,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_ADC,
}, {
.name = "i2c",
.id = -1,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_IIC,
}, {
.name = "iis",
.id = -1,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_IIS,
}, {
.name = "spi",
.id = -1,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_SPI,
}
};
static struct clk init_clocks[] = {
{
.name = "dma",
.id = 0,
.parent = &clk_h,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_DMA0,
}, {
.name = "dma",
.id = 1,
.parent = &clk_h,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_DMA1,
}, {
.name = "dma",
.id = 2,
.parent = &clk_h,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_DMA2,
}, {
.name = "dma",
.id = 3,
.parent = &clk_h,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_DMA3,
}, {
.name = "lcd",
.id = -1,
.parent = &clk_h,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_LCDC,
}, {
.name = "gpio",
.id = -1,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_GPIO,
}, {
.name = "usb-host",
.id = -1,
.parent = &clk_h,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_USBH,
}, {
.name = "usb-device",
.id = -1,
.parent = &clk_h,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_USBD,
}, {
.name = "timers",
.id = -1,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_PWMT,
}, {
.name = "uart",
.id = 0,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_UART0,
}, {
.name = "uart",
.id = 1,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_UART1,
}, {
.name = "uart",
.id = 2,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_UART2,
}, {
.name = "rtc",
.id = -1,
.parent = &clk_p,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_RTC,
}, {
.name = "watchdog",
.id = -1,
.parent = &clk_p,
.ctrlbit = 0,
}, {
.name = "usb-bus-gadget",
.id = -1,
.parent = &clk_usb_bus,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_USB_DEV48,
}, {
.name = "usb-bus-host",
.id = -1,
.parent = &clk_usb_bus,
.enable = s3c2412_clkcon_enable,
.ctrlbit = S3C2412_CLKCON_USB_HOST48,
}
};
/* clocks to add where we need to check their parentage */
struct clk_init {
struct clk *clk;
unsigned int bit;
struct clk *src_0;
struct clk *src_1;
};
struct clk_init clks_src[] __initdata = {
{
.clk = &clk_usysclk,
.bit = S3C2412_CLKSRC_USBCLK_HCLK,
.src_0 = &clk_urefclk,
.src_1 = &clk_upll,
}, {
.clk = &clk_i2s,
.bit = S3C2412_CLKSRC_I2SCLK_MPLL,
.src_0 = &clk_erefclk,
.src_1 = &clk_mpll,
}, {
.clk = &clk_cam,
.bit = S3C2412_CLKSRC_CAMCLK_HCLK,
.src_0 = &clk_usysclk,
.src_1 = &clk_h,
}, {
.clk = &clk_msysclk,
.bit = S3C2412_CLKSRC_MSYSCLK_MPLL,
.src_0 = &clk_mdivclk,
.src_1 = &clk_mpll,
}, {
.clk = &clk_uart,
.bit = S3C2412_CLKSRC_UARTCLK_MPLL,
.src_0 = &clk_erefclk,
.src_1 = &clk_mpll,
}, {
.clk = &clk_usbsrc,
.bit = S3C2412_CLKSRC_USBCLK_HCLK,
.src_0 = &clk_usysclk,
.src_1 = &clk_h,
},
};
/* s3c2412_clk_initparents
*
* Initialise the parents for the clocks that we get at start-time
*/
static void __init s3c2412_clk_initparents(void)
{
unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
struct clk_init *cip = clks_src;
struct clk *src;
int ptr;
int ret;
for (ptr = 0; ptr < ARRAY_SIZE(clks_src); ptr++, cip++) {
ret = s3c24xx_register_clock(cip->clk);
if (ret < 0) {
printk(KERN_ERR "Failed to register clock %s (%d)\n",
cip->clk->name, ret);
}
src = (clksrc & cip->bit) ? cip->src_1 : cip->src_0;
printk(KERN_INFO "%s: parent %s\n", cip->clk->name, src->name);
clk_set_parent(cip->clk, src);
}
}
/* clocks to add straight away */
struct clk *clks[] __initdata = {
&clk_ext,
&clk_usb_bus,
&clk_erefclk,
&clk_urefclk,
&clk_mrefclk,
};
int __init s3c2412_baseclk_add(void)
{
unsigned long clkcon = __raw_readl(S3C2410_CLKCON);
struct clk *clkp;
int ret;
int ptr;
clk_upll.enable = s3c2412_upll_enable;
clk_usb_bus.parent = &clk_usbsrc;
clk_usb_bus.rate = 0x0;
s3c2412_clk_initparents();
for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
clkp = clks[ptr];
ret = s3c24xx_register_clock(clkp);
if (ret < 0) {
printk(KERN_ERR "Failed to register clock %s (%d)\n",
clkp->name, ret);
}
}
/* ensure usb bus clock is within correct rate of 48MHz */
if (clk_get_rate(&clk_usb_bus) != (48 * 1000 * 1000)) {
printk(KERN_INFO "Warning: USB bus clock not at 48MHz\n");
/* for the moment, let's use the UPLL, and see if we can
* get 48MHz */
clk_set_parent(&clk_usysclk, &clk_upll);
clk_set_parent(&clk_usbsrc, &clk_usysclk);
clk_set_rate(&clk_usbsrc, 48*1000*1000);
}
printk("S3C2412: upll %s, %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
(__raw_readl(S3C2410_UPLLCON) & S3C2412_PLLCON_OFF) ? "off":"on",
print_mhz(clk_get_rate(&clk_upll)),
print_mhz(clk_get_rate(&clk_usb_bus)));
/* register clocks from clock array */
clkp = init_clocks;
for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
/* ensure that we note the clock state */
clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
ret = s3c24xx_register_clock(clkp);
if (ret < 0) {
printk(KERN_ERR "Failed to register clock %s (%d)\n",
clkp->name, ret);
}
}
/* We must be careful disabling the clocks we are not intending to
* be using at boot time, as subsytems such as the LCD which do
* their own DMA requests to the bus can cause the system to lockup
* if they where in the middle of requesting bus access.
*
* Disabling the LCD clock if the LCD is active is very dangerous,
* and therefore the bootloader should be careful to not enable
* the LCD clock if it is not needed.
*/
/* install (and disable) the clocks we do not need immediately */
clkp = init_clocks_disable;
for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
ret = s3c24xx_register_clock(clkp);
if (ret < 0) {
printk(KERN_ERR "Failed to register clock %s (%d)\n",
clkp->name, ret);
}
s3c2412_clkcon_enable(clkp, 0);
}
return 0;
}
/* 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);
}
/* 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
......@@ -61,9 +61,9 @@ config CPU_ARM720T
# ARM920T
config CPU_ARM920T
bool "Support ARM920T processor" if !ARCH_S3C2410
depends on ARCH_EP93XX || ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200
default y if ARCH_S3C2410 || ARCH_AT91RM9200
bool "Support ARM920T processor"
depends on ARCH_EP93XX || ARCH_INTEGRATOR || CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200
default y if CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_AT91RM9200
select CPU_32v4
select CPU_ABRT_EV4T
select CPU_CACHE_V4WT
......@@ -121,8 +121,8 @@ config CPU_ARM925T
# ARM926T
config CPU_ARM926T
bool "Support ARM926T processor"
depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX
default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX
depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412
default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412
select CPU_32v5
select CPU_ABRT_EV5TJ
select CPU_CACHE_VIVT
......
......@@ -354,21 +354,24 @@ config SERIAL_CLPS711X_CONSOLE
kernel at boot time.)
config SERIAL_S3C2410
tristate "Samsung S3C2410 Serial port support"
tristate "Samsung S3C2410/S3C2440/S3C2442/S3C2412 Serial port support"
depends on ARM && ARCH_S3C2410
select SERIAL_CORE
help
Support for the on-chip UARTs on the Samsung S3C2410X CPU,
Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
providing /dev/ttySAC0, 1 and 2 (note, some machines may not
provide all of these ports, depending on how the serial port
pins are configured.
Currently this driver supports the UARTS on the S3C2410, S3C2440,
S3C2442, S3C2412 and S3C2413 CPUs.
config SERIAL_S3C2410_CONSOLE
bool "Support for console on S3C2410 serial port"
depends on SERIAL_S3C2410=y
select SERIAL_CORE_CONSOLE
help
Allow selection of the S3C2410 on-board serial ports for use as
Allow selection of the S3C24XX on-board serial ports for use as
an virtual console.
Even if you say Y here, the currently visible virtual console
......
......@@ -872,6 +872,8 @@ static const char *s3c24xx_serial_type(struct uart_port *port)
return "S3C2410";
case PORT_S3C2440:
return "S3C2440";
case PORT_S3C2412:
return "S3C2412";
default:
return NULL;
}
......@@ -1528,6 +1530,141 @@ static inline void s3c2440_serial_exit(void)
#define s3c2440_uart_inf_at NULL
#endif /* CONFIG_CPU_S3C2440 */
#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
static int s3c2412_serial_setsource(struct uart_port *port,
struct s3c24xx_uart_clksrc *clk)
{
unsigned long ucon = rd_regl(port, S3C2410_UCON);
ucon &= ~S3C2412_UCON_CLKMASK;
if (strcmp(clk->name, "uclk") == 0)
ucon |= S3C2440_UCON_UCLK;
else if (strcmp(clk->name, "pclk") == 0)
ucon |= S3C2440_UCON_PCLK;
else if (strcmp(clk->name, "usysclk") == 0)
ucon |= S3C2412_UCON_USYSCLK;
else {
printk(KERN_ERR "unknown clock source %s\n", clk->name);
return -EINVAL;
}
wr_regl(port, S3C2410_UCON, ucon);
return 0;
}
static int s3c2412_serial_getsource(struct uart_port *port,
struct s3c24xx_uart_clksrc *clk)
{
unsigned long ucon = rd_regl(port, S3C2410_UCON);
switch (ucon & S3C2412_UCON_CLKMASK) {
case S3C2412_UCON_UCLK:
clk->divisor = 1;
clk->name = "uclk";
break;
case S3C2412_UCON_PCLK:
case S3C2412_UCON_PCLK2:
clk->divisor = 1;
clk->name = "pclk";
break;
case S3C2412_UCON_USYSCLK:
clk->divisor = 1;
clk->name = "usysclk";
break;
}
return 0;
}
static int s3c2412_serial_resetport(struct uart_port *port,
struct s3c2410_uartcfg *cfg)
{
unsigned long ucon = rd_regl(port, S3C2410_UCON);
dbg("%s: port=%p (%08lx), cfg=%p\n",
__FUNCTION__, port, port->mapbase, cfg);
/* ensure we don't change the clock settings... */
ucon &= S3C2412_UCON_CLKMASK;
wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
wr_regl(port, S3C2410_ULCON, cfg->ulcon);
/* reset both fifos */
wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
wr_regl(port, S3C2410_UFCON, cfg->ufcon);
return 0;
}
static struct s3c24xx_uart_info s3c2412_uart_inf = {
.name = "Samsung S3C2412 UART",
.type = PORT_S3C2412,
.fifosize = 64,
.rx_fifomask = S3C2440_UFSTAT_RXMASK,
.rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
.rx_fifofull = S3C2440_UFSTAT_RXFULL,
.tx_fifofull = S3C2440_UFSTAT_TXFULL,
.tx_fifomask = S3C2440_UFSTAT_TXMASK,
.tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
.get_clksrc = s3c2412_serial_getsource,
.set_clksrc = s3c2412_serial_setsource,
.reset_port = s3c2412_serial_resetport,
};
/* device management */
static int s3c2412_serial_probe(struct platform_device *dev)
{
dbg("s3c2440_serial_probe: dev=%p\n", dev);
return s3c24xx_serial_probe(dev, &s3c2440_uart_inf);
}
static struct platform_driver s3c2412_serial_drv = {
.probe = s3c2412_serial_probe,
.remove = s3c24xx_serial_remove,
.suspend = s3c24xx_serial_suspend,
.resume = s3c24xx_serial_resume,
.driver = {
.name = "s3c2412-uart",
.owner = THIS_MODULE,
},
};
static inline int s3c2412_serial_init(void)
{
return s3c24xx_serial_init(&s3c2412_serial_drv, &s3c2412_uart_inf);
}
static inline void s3c2412_serial_exit(void)
{
platform_driver_unregister(&s3c2412_serial_drv);
}
#define s3c2412_uart_inf_at &s3c2412_uart_inf
#else
static inline int s3c2412_serial_init(void)
{
return 0;
}
static inline void s3c2412_serial_exit(void)
{
}
#define s3c2412_uart_inf_at NULL
#endif /* CONFIG_CPU_S3C2440 */
/* module initialisation code */
static int __init s3c24xx_serial_modinit(void)
......@@ -1542,6 +1679,7 @@ static int __init s3c24xx_serial_modinit(void)
s3c2400_serial_init();
s3c2410_serial_init();
s3c2412_serial_init();
s3c2440_serial_init();
return 0;
......@@ -1551,6 +1689,7 @@ static void __exit s3c24xx_serial_modexit(void)
{
s3c2400_serial_exit();
s3c2410_serial_exit();
s3c2412_serial_exit();
s3c2440_serial_exit();
uart_unregister_driver(&s3c24xx_uart_drv);
......@@ -1773,6 +1912,8 @@ static int s3c24xx_serial_initconsole(void)
info = s3c2410_uart_inf_at;
} else if (strcmp(dev->name, "s3c2440-uart") == 0) {
info = s3c2440_uart_inf_at;
} else if (strcmp(dev->name, "s3c2412-uart") == 0) {
info = s3c2412_uart_inf_at;
} else {
printk(KERN_ERR "s3c24xx: no driver for %s\n", dev->name);
return 0;
......@@ -1796,4 +1937,4 @@ console_initcall(s3c24xx_serial_initconsole);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
MODULE_DESCRIPTION("Samsung S3C2410/S3C2440 Serial port driver");
MODULE_DESCRIPTION("Samsung S3C2410/S3C2440/S3C2412 Serial port driver");
......@@ -33,7 +33,7 @@
.endm
.macro senduart,rd,rx
str \rd, [\rx, # S3C2410_UTXH ]
strb \rd, [\rx, # S3C2410_UTXH ]
.endm
.macro busyuart, rd, rx
......@@ -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)
......@@ -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
......
......@@ -18,8 +18,6 @@
#define INTPND (0x10)
#define INTOFFSET (0x14)
#define EXTINTPEND (0xa8)
#define EXTINTMASK (0xa4)
#include <asm/hardware.h>
#include <asm/arch/irqs.h>
......@@ -28,37 +26,23 @@
mov \base, #S3C24XX_VA_IRQ
ldr \irqstat, [ \base, #INTPND]
bics \irqnr, \irqstat, #3<<4 @@ only an GPIO IRQ
beq 2000f
@@ try the interrupt offset register, since it is there
ldr \irqstat, [ \base, #INTPND ]
teq \irqstat, #0
beq 1002f
ldr \irqnr, [ \base, #INTOFFSET ]
mov \tmp, #1
tst \irqstat, \tmp, lsl \irqnr
addne \irqnr, \irqnr, #IRQ_EINT0
bne 1001f
@@ the number specified is not a valid irq, so try
@@ and work it out for ourselves
mov \irqnr, #IRQ_EINT0 @@ start here
b 3000f
2000:
@@ load the GPIO interrupt register, and check it
add \tmp, \base, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ
ldr \irqstat, [ \tmp, # EXTINTPEND ]
ldr \irqnr, [ \tmp, # EXTINTMASK ]
bics \irqstat, \irqstat, \irqnr
beq 1001f
mov \irqnr, #(IRQ_EINT4 - 4)
mov \irqnr, #0 @@ start here
@@ work out which irq (if any) we got
3000:
movs \tmp, \irqstat, lsl#16
addeq \irqnr, \irqnr, #16
moveq \irqstat, \irqstat, lsr#16
......@@ -75,9 +59,9 @@
addeq \irqnr, \irqnr, #1
@@ we have the value
movs \irqnr, \irqnr
1001:
adds \irqnr, \irqnr, #IRQ_EINT0
1002:
@@ exit here, Z flag unset if IRQ
.endm
......
......@@ -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 */
/* linux/include/asm/arch-s3c2410/regs-clock.h
*
* Copyright (c) 2003,2004,2005 Simtec Electronics <linux@simtec.co.uk>
* Copyright (c) 2003,2004,2005,2006 Simtec Electronics <linux@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* This program is free software; you can redistribute it and/or modify
......@@ -140,5 +140,66 @@ s3c2410_get_pll(unsigned int pllval, unsigned int baseclk)
#endif /* CONFIG_CPU_S3C2440 or CONFIG_CPU_S3C2442 */
#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
#define S3C2412_OSCSET S3C2410_CLKREG(0x18)
#define S3C2412_CLKSRC S3C2410_CLKREG(0x1C)
#define S3C2412_PLLCON_OFF (1<<20)
#define S3C2412_CLKDIVN_PDIVN (1<<2)
#define S3C2412_CLKDIVN_HDIVN_MASK (3<<0)
#define S3C2421_CLKDIVN_ARMDIVN (1<<3)
#define S3C2412_CLKDIVN_USB48DIV (1<<6)
#define S3C2412_CLKDIVN_UARTDIV_MASK (15<<8)
#define S3C2412_CLKDIVN_UARTDIV_SHIFT (8)
#define S3C2412_CLKDIVN_I2SDIV_MASK (15<<12)
#define S3C2412_CLKDIVN_I2SDIV_SHIFT (12)
#define S3C2412_CLKDIVN_CAMDIV_MASK (15<<16)
#define S3C2412_CLKDIVN_CAMDIV_SHIFT (16)
#define S3C2412_CLKCON_WDT (1<<28)
#define S3C2412_CLKCON_SPI (1<<27)
#define S3C2412_CLKCON_IIS (1<<26)
#define S3C2412_CLKCON_IIC (1<<25)
#define S3C2412_CLKCON_ADC (1<<24)
#define S3C2412_CLKCON_RTC (1<<23)
#define S3C2412_CLKCON_GPIO (1<<22)
#define S3C2412_CLKCON_UART2 (1<<21)
#define S3C2412_CLKCON_UART1 (1<<20)
#define S3C2412_CLKCON_UART0 (1<<19)
#define S3C2412_CLKCON_SDI (1<<18)
#define S3C2412_CLKCON_PWMT (1<<17)
#define S3C2412_CLKCON_USBD (1<<16)
#define S3C2412_CLKCON_CAMCLK (1<<15)
#define S3C2412_CLKCON_UARTCLK (1<<14)
/* missing 13 */
#define S3C2412_CLKCON_USB_HOST48 (1<<12)
#define S3C2412_CLKCON_USB_DEV48 (1<<11)
#define S3C2412_CLKCON_HCLKdiv2 (1<<10)
#define S3C2412_CLKCON_HCLKx2 (1<<9)
#define S3C2412_CLKCON_SDRAM (1<<8)
/* missing 7 */
#define S3C2412_CLKCON_USBH S3C2410_CLKCON_USBH
#define S3C2412_CLKCON_LCDC S3C2410_CLKCON_LCDC
#define S3C2412_CLKCON_NAND S3C2410_CLKCON_NAND
#define S3C2412_CLKCON_DMA3 (1<<3)
#define S3C2412_CLKCON_DMA2 (1<<2)
#define S3C2412_CLKCON_DMA1 (1<<1)
#define S3C2412_CLKCON_DMA0 (1<<0)
/* clock sourec controls */
#define S3C2412_CLKSRC_EXTCLKDIV_MASK (7 << 0)
#define S3C2412_CLKSRC_EXTCLKDIV_SHIFT (0)
#define S3C2412_CLKSRC_MDIVCLK_EXTCLKDIV (1<<3)
#define S3C2412_CLKSRC_MSYSCLK_MPLL (1<<4)
#define S3C2412_CLKSRC_USYSCLK_UPLL (1<<5)
#define S3C2412_CLKSRC_UARTCLK_MPLL (1<<8)
#define S3C2412_CLKSRC_I2SCLK_MPLL (1<<9)
#define S3C2412_CLKSRC_USBCLK_HCLK (1<<10)
#define S3C2412_CLKSRC_CAMCLK_HCLK (1<<11)
#endif /* CONFIG_CPU_S3C2412 | CONFIG_CPU_S3C2413 */
#endif /* __ASM_ARM_REGS_CLOCK */
......@@ -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)
......
......@@ -45,7 +45,7 @@
#define S3C24XX_MISCCR S3C2400_MISCCR
#else
#define S3C24XX_GPIO_BASE(x) S3C2410_GPIO_BASE(x)
#define S3C24XX_MISCCR S3C2410_MISCCR
#define S3C24XX_MISCCR S3C24XX_GPIOREG2(0x80)
#endif /* CONFIG_CPU_S3C2400 */
......@@ -73,9 +73,15 @@
#define S3C2410_GPIO_SFN2 (0xFFFFFFF2) /* not available on A */
#define S3C2410_GPIO_SFN3 (0xFFFFFFF3) /* not available on A */
/* configure GPIO ports A..G */
/* register address for the GPIO registers.
* S3C24XX_GPIOREG2 is for the second set of registers in the
* GPIO which move between s3c2410 and s3c2412 type systems */
#define S3C2410_GPIOREG(x) ((x) + S3C24XX_VA_GPIO)
#define S3C24XX_GPIOREG2(x) ((x) + S3C24XX_VA_GPIO2)
/* configure GPIO ports A..G */
/* port A - S3C2410: 22bits, zero in bit X makes pin X output
* S3C2400: 18bits, zero in bit X makes pin X output
......@@ -953,11 +959,18 @@
#define S3C2410_GPH10_OUTP (0x01 << 20)
#define S3C2410_GPH10_CLKOUT1 (0x02 << 20)
/* The S3C2412 and S3C2413 move the GPJ register set to after
* GPH, which means all registers after 0x80 are now offset by 0x10
* for the 2412/2413 from the 2410/2440/2442
*/
/* miscellaneous control */
#define S3C2400_MISCCR S3C2410_GPIOREG(0x54)
#define S3C2410_MISCCR S3C2410_GPIOREG(0x80)
#define S3C2410_DCLKCON S3C2410_GPIOREG(0x84)
#define S3C24XX_DCLKCON S3C24XX_GPIOREG2(0x84)
/* see clock.h for dclk definitions */
/* pullup control on databus */
......@@ -985,6 +998,8 @@
#define S3C2410_MISCCR_CLK0_DCLK0 (5<<4)
#define S3C2410_MISCCR_CLK0_MASK (7<<4)
#define S3C2412_MISCCR_CLK0_RTC (2<<4)
#define S3C2410_MISCCR_CLK1_MPLL (0<<8)
#define S3C2410_MISCCR_CLK1_UPLL (1<<8)
#define S3C2410_MISCCR_CLK1_FCLK (2<<8)
......@@ -993,6 +1008,8 @@
#define S3C2410_MISCCR_CLK1_DCLK1 (5<<8)
#define S3C2410_MISCCR_CLK1_MASK (7<<8)
#define S3C2412_MISCCR_CLK1_CLKsrc (0<<8)
#define S3C2410_MISCCR_USBSUSPND0 (1<<12)
#define S3C2410_MISCCR_USBSUSPND1 (1<<13)
......@@ -1000,7 +1017,7 @@
#define S3C2410_MISCCR_nEN_SCLK0 (1<<17)
#define S3C2410_MISCCR_nEN_SCLK1 (1<<18)
#define S3C2410_MISCCR_nEN_SCLKE (1<<19)
#define S3C2410_MISCCR_nEN_SCLKE (1<<19) /* not 2412 */
#define S3C2410_MISCCR_SDSLEEP (7<<17)
/* external interrupt control... */
......@@ -1017,6 +1034,10 @@
#define S3C2410_EXTINT1 S3C2410_GPIOREG(0x8C)
#define S3C2410_EXTINT2 S3C2410_GPIOREG(0x90)
#define S3C24XX_EXTINT0 S3C24XX_GPIOREG2(0x88)
#define S3C24XX_EXTINT1 S3C24XX_GPIOREG2(0x8C)
#define S3C24XX_EXTINT2 S3C24XX_GPIOREG2(0x90)
/* values for S3C2410_EXTINT0/1/2 */
#define S3C2410_EXTINT_LOWLEV (0x00)
#define S3C2410_EXTINT_HILEV (0x01)
......@@ -1030,6 +1051,11 @@
#define S3C2410_EINFLT2 S3C2410_GPIOREG(0x9C)
#define S3C2410_EINFLT3 S3C2410_GPIOREG(0xA0)
#define S3C24XX_EINFLT0 S3C24XX_GPIOREG2(0x94)
#define S3C24XX_EINFLT1 S3C24XX_GPIOREG2(0x98)
#define S3C24XX_EINFLT2 S3C24XX_GPIOREG2(0x9C)
#define S3C24XX_EINFLT3 S3C24XX_GPIOREG2(0xA0)
/* values for interrupt filtering */
#define S3C2410_EINTFLT_PCLK (0x00)
#define S3C2410_EINTFLT_EXTCLK (1<<7)
......@@ -1039,6 +1065,7 @@
/* GSTATUS have miscellaneous information in them
*
* These move between s3c2410 and s3c2412 style systems.
*/
#define S3C2410_GSTATUS0 S3C2410_GPIOREG(0x0AC)
......@@ -1047,6 +1074,18 @@
#define S3C2410_GSTATUS3 S3C2410_GPIOREG(0x0B8)
#define S3C2410_GSTATUS4 S3C2410_GPIOREG(0x0BC)
#define S3C2412_GSTATUS0 S3C2410_GPIOREG(0x0BC)
#define S3C2412_GSTATUS1 S3C2410_GPIOREG(0x0C0)
#define S3C2412_GSTATUS2 S3C2410_GPIOREG(0x0C4)
#define S3C2412_GSTATUS3 S3C2410_GPIOREG(0x0C8)
#define S3C2412_GSTATUS4 S3C2410_GPIOREG(0x0CC)
#define S3C24XX_GSTATUS0 S3C24XX_GPIOREG2(0x0AC)
#define S3C24XX_GSTATUS1 S3C24XX_GPIOREG2(0x0B0)
#define S3C24XX_GSTATUS2 S3C24XX_GPIOREG2(0x0B4)
#define S3C24XX_GSTATUS3 S3C24XX_GPIOREG2(0x0B8)
#define S3C24XX_GSTATUS4 S3C24XX_GPIOREG2(0x0BC)
#define S3C2410_GSTATUS0_nWAIT (1<<3)
#define S3C2410_GSTATUS0_NCON (1<<2)
#define S3C2410_GSTATUS0_RnB (1<<1)
......@@ -1054,6 +1093,7 @@
#define S3C2410_GSTATUS1_IDMASK (0xffff0000)
#define S3C2410_GSTATUS1_2410 (0x32410000)
#define S3C2410_GSTATUS1_2412 (0x32412001)
#define S3C2410_GSTATUS1_2440 (0x32440000)
#define S3C2410_GSTATUS1_2442 (0x32440aaa)
......@@ -1077,5 +1117,22 @@
#define S3C2400_OPENCR_OPC_MOSIDIS (0<<5)
#define S3C2400_OPENCR_OPC_MOSIEN (1<<5)
/* 2412/2413 sleep configuration registers */
#define S3C2412_GPBSLPCON S3C2410_GPIOREG(0x1C)
#define S3C2412_GPCSLPCON S3C2410_GPIOREG(0x2C)
#define S3C2412_GPDSLPCON S3C2410_GPIOREG(0x3C)
#define S3C2412_GPESLPCON S3C2410_GPIOREG(0x4C)
#define S3C2412_GPFSLPCON S3C2410_GPIOREG(0x5C)
#define S3C2412_GPGSLPCON S3C2410_GPIOREG(0x6C)
#define S3C2412_GPHSLPCON S3C2410_GPIOREG(0x7C)
/* definitions for each pin bit */
#define S3C2412_SLPCON_LOW(x) ( 0x00 << ((x) * 2))
#define S3C2412_SLPCON_HI(x) ( 0x01 << ((x) * 2))
#define S3C2412_SLPCON_IN(x) ( 0x02 << ((x) * 2))
#define S3C2412_SLPCON_PDWN(x) ( 0x03 << ((x) * 2))
#define S3C2412_SLPCON_MASK(x) ( 0x03 << ((x) * 2))
#endif /* __ASM_ARCH_REGS_GPIO_H */
......@@ -32,6 +32,11 @@
#define S3C2440_GPJDAT S3C2410_GPIOREG(0xd4)
#define S3C2440_GPJUP S3C2410_GPIOREG(0xd8)
#define S3C2413_GPJCON S3C2410_GPIOREG(0x80)
#define S3C2413_GPJDAT S3C2410_GPIOREG(0x84)
#define S3C2413_GPJUP S3C2410_GPIOREG(0x88)
#define S3C2413_GPJSLPCON S3C2410_GPIOREG(0x8C)
#define S3C2440_GPJ0 S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 0)
#define S3C2440_GPJ0_INP (0x00 << 0)
#define S3C2440_GPJ0_OUTP (0x01 << 0)
......
......@@ -23,6 +23,7 @@
#define S3C2410_IRQREG(x) ((x) + S3C24XX_VA_IRQ)
#define S3C2410_EINTREG(x) ((x) + S3C24XX_VA_GPIO)
#define S3C24XX_EINTREG(x) ((x) + S3C24XX_VA_GPIO2)
#define S3C2410_SRCPND S3C2410_IRQREG(0x000)
#define S3C2410_INTMOD S3C2410_IRQREG(0x004)
......@@ -40,5 +41,10 @@
#define S3C2410_EINTMASK S3C2410_EINTREG(0x0A4)
#define S3C2410_EINTPEND S3C2410_EINTREG(0X0A8)
#define S3C2412_EINTMASK S3C2410_EINTREG(0x0B4)
#define S3C2412_EINTPEND S3C2410_EINTREG(0X0B8)
#define S3C24XX_EINTMASK S3C24XX_EINTREG(0x0A4)
#define S3C24XX_EINTPEND S3C24XX_EINTREG(0X0A8)
#endif /* ___ASM_ARCH_REGS_IRQ_H */
......@@ -82,6 +82,12 @@
#define S3C2440_UCON2_DIVMASK (7 << 12)
#define S3C2440_UCON_DIVSHIFT (12)
#define S3C2412_UCON_CLKMASK (3<<10)
#define S3C2412_UCON_UCLK (1<<10)
#define S3C2412_UCON_USYSCLK (3<<10)
#define S3C2412_UCON_PCLK (0<<10)
#define S3C2412_UCON_PCLK2 (2<<10)
#define S3C2410_UCON_UCLK (1<<10)
#define S3C2410_UCON_SBREAK (1<<4)
......@@ -124,6 +130,15 @@
#define S3C2410_UMCOM_AFC (1<<4)
#define S3C2410_UMCOM_RTS_LOW (1<<0)
#define S3C2412_UMCON_AFC_63 (0<<5)
#define S3C2412_UMCON_AFC_56 (1<<5)
#define S3C2412_UMCON_AFC_48 (2<<5)
#define S3C2412_UMCON_AFC_40 (3<<5)
#define S3C2412_UMCON_AFC_32 (4<<5)
#define S3C2412_UMCON_AFC_24 (5<<5)
#define S3C2412_UMCON_AFC_16 (6<<5)
#define S3C2412_UMCON_AFC_8 (7<<5)
#define S3C2410_UFSTAT_TXFULL (1<<9)
#define S3C2410_UFSTAT_RXFULL (1<<8)
#define S3C2410_UFSTAT_TXMASK (15<<4)
......
......@@ -130,6 +130,9 @@
/* SUN4V Hypervisor Console */
#define PORT_SUNHV 72
#define PORT_S3C2412 73
#ifdef __KERNEL__
#include <linux/compiler.h>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册