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

* master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6: (68 commits)
  sh: sh-rtc support for SH7709.
  sh: Revert __xdiv64_32 size change.
  sh: Update r7785rp defconfig.
  sh: Export div symbols for GCC 4.2 and ST GCC.
  sh: fix race in parallel out-of-tree build
  sh: Kill off dead mach.c for hp6xx.
  sh: hd64461.h cleanup and added comments.
  sh: Update the alignment when 4K stacks are used.
  sh: Add a .bss.page_aligned section for 4K stacks.
  sh: Don't let SH-4A clobber SH-4 CFLAGS.
  sh: Add parport stub for SuperIO ports.
  sh: Drop -Wa,-dsp for DSP tuning.
  sh: Update dreamcast defconfig.
  fb: pvr2fb: A few more __devinit annotations for PCI.
  fb: pvr2fb: Fix up section mismatch warnings.
  sh: Select IPR-IRQ for SH7091.
  sh: Correct __xdiv64_32/div64_32 return value size.
  sh: Fix timer-tmu build for SH-3.
  sh: Add cpu and mach links to CLEAN_FILES.
  sh: Preliminary support for the SH-X3 CPU.
  ...
This commit is contained in:
Linus Torvalds
2007-07-16 10:32:02 -07:00
132 changed files with 4928 additions and 2875 deletions

View File

@@ -4,10 +4,9 @@
extra-y := head.o init_task.o vmlinux.lds
obj-y := process.o signal.o traps.o irq.o \
ptrace.o setup.o time.o sys_sh.o semaphore.o \
io.o io_generic.o sh_ksyms.o syscalls.o \
debugtraps.o
obj-y := debugtraps.o io.o io_generic.o irq.o machvec.o process.o ptrace.o \
semaphore.o setup.o signal.o sys_sh.o syscalls.o \
time.o topology.o traps.o
obj-y += cpu/ timers/
obj-$(CONFIG_VSYSCALL) += vsyscall/
@@ -17,7 +16,7 @@ obj-$(CONFIG_CF_ENABLER) += cf-enabler.o
obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o
obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o
obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_MODULES) += sh_ksyms.o module.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o

View File

@@ -75,11 +75,7 @@ static int __init cf_init_default(void)
#if defined(CONFIG_CPU_SH4)
allocate_cf_area();
#endif
#if defined(CONFIG_SH_UNKNOWN)
/* This should be done in each board's init_xxx_irq. */
make_imask_irq(14);
disable_irq(14);
#endif
return 0;
}

View File

@@ -21,8 +21,7 @@
#include <asm/cacheflush.h>
#include <asm/cache.h>
#include <asm/io.h>
extern void detect_cpu_and_cache_system(void);
#include <asm/ubc.h>
/*
* Generic wrapper for command line arguments to disable on-chip
@@ -152,15 +151,6 @@ static void __init cache_init(void)
flags |= CCR_CACHE_CB;
#endif
#ifdef CONFIG_SH_OCRAM
/* Turn on OCRAM -- halve the OC */
flags |= CCR_CACHE_ORA;
current_cpu_data.dcache.sets >>= 1;
current_cpu_data.dcache.way_size = current_cpu_data.dcache.sets *
current_cpu_data.dcache.linesz;
#endif
ctrl_outl(flags, CCR);
back_to_P1();
}
@@ -269,7 +259,6 @@ asmlinkage void __init sh_cpu_init(void)
}
#endif
#ifdef CONFIG_UBC_WAKEUP
/*
* Some brain-damaged loaders decided it would be a good idea to put
* the UBC to sleep. This causes some issues when it comes to things
@@ -277,7 +266,5 @@ asmlinkage void __init sh_cpu_init(void)
* we wake it up and hope that all is well.
*/
ubc_wakeup();
#endif
speculative_execution_init();
}

View File

@@ -13,36 +13,31 @@
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <asm/smp.h>
#if defined(CONFIG_CPU_SUBTYPE_SH7760)
#define INTC2_BASE 0xfe080000
#define INTC2_INTMSK (INTC2_BASE + 0x40)
#define INTC2_INTMSKCLR (INTC2_BASE + 0x60)
#elif defined(CONFIG_CPU_SUBTYPE_SH7780) || \
defined(CONFIG_CPU_SUBTYPE_SH7785)
#define INTC2_BASE 0xffd40000
#define INTC2_INTMSK (INTC2_BASE + 0x38)
#define INTC2_INTMSKCLR (INTC2_BASE + 0x3c)
#endif
static inline struct intc2_desc *get_intc2_desc(unsigned int irq)
{
struct irq_chip *chip = get_irq_chip(irq);
return (void *)((char *)chip - offsetof(struct intc2_desc, chip));
}
static void disable_intc2_irq(unsigned int irq)
{
struct intc2_data *p = get_irq_chip_data(irq);
ctrl_outl(1 << p->msk_shift, INTC2_INTMSK + p->msk_offset);
struct intc2_desc *d = get_intc2_desc(irq);
ctrl_outl(1 << p->msk_shift, d->msk_base + p->msk_offset +
(hard_smp_processor_id() * 4));
}
static void enable_intc2_irq(unsigned int irq)
{
struct intc2_data *p = get_irq_chip_data(irq);
ctrl_outl(1 << p->msk_shift, INTC2_INTMSKCLR + p->msk_offset);
}
struct intc2_desc *d = get_intc2_desc(irq);
static struct irq_chip intc2_irq_chip = {
.name = "INTC2",
.mask = disable_intc2_irq,
.unmask = enable_intc2_irq,
.mask_ack = disable_intc2_irq,
};
ctrl_outl(1 << p->msk_shift, d->mskclr_base + p->msk_offset +
(hard_smp_processor_id() * 4));
}
/*
* Setup an INTC2 style interrupt.
@@ -56,30 +51,36 @@ static struct irq_chip intc2_irq_chip = {
*
* in the intc2_data table.
*/
void make_intc2_irq(struct intc2_data *table, unsigned int nr_irqs)
void register_intc2_controller(struct intc2_desc *desc)
{
int i;
for (i = 0; i < nr_irqs; i++) {
desc->chip.mask = disable_intc2_irq;
desc->chip.unmask = enable_intc2_irq;
desc->chip.mask_ack = disable_intc2_irq;
for (i = 0; i < desc->nr_irqs; i++) {
unsigned long ipr, flags;
struct intc2_data *p = table + i;
struct intc2_data *p = desc->intc2_data + i;
disable_irq_nosync(p->irq);
/* Set the priority level */
local_irq_save(flags);
if (desc->prio_base) {
/* Set the priority level */
local_irq_save(flags);
ipr = ctrl_inl(INTC2_BASE + p->ipr_offset);
ipr &= ~(0xf << p->ipr_shift);
ipr |= p->priority << p->ipr_shift;
ctrl_outl(ipr, INTC2_BASE + p->ipr_offset);
ipr = ctrl_inl(desc->prio_base + p->ipr_offset);
ipr &= ~(0xf << p->ipr_shift);
ipr |= p->priority << p->ipr_shift;
ctrl_outl(ipr, desc->prio_base + p->ipr_offset);
local_irq_restore(flags);
local_irq_restore(flags);
}
set_irq_chip_and_handler_name(p->irq, &intc2_irq_chip,
set_irq_chip_and_handler_name(p->irq, &desc->chip,
handle_level_irq, "level");
set_irq_chip_data(p->irq, p);
enable_intc2_irq(p->irq);
disable_intc2_irq(p->irq);
}
}

View File

@@ -22,58 +22,57 @@
#include <linux/io.h>
#include <linux/interrupt.h>
static inline struct ipr_desc *get_ipr_desc(unsigned int irq)
{
struct irq_chip *chip = get_irq_chip(irq);
return (void *)((char *)chip - offsetof(struct ipr_desc, chip));
}
static void disable_ipr_irq(unsigned int irq)
{
struct ipr_data *p = get_irq_chip_data(irq);
unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx];
/* Set the priority in IPR to 0 */
ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
ctrl_outw(ctrl_inw(addr) & (0xffff ^ (0xf << p->shift)), addr);
}
static void enable_ipr_irq(unsigned int irq)
{
struct ipr_data *p = get_irq_chip_data(irq);
unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx];
/* Set priority in IPR back to original value */
ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
ctrl_outw(ctrl_inw(addr) | (p->priority << p->shift), addr);
}
static struct irq_chip ipr_irq_chip = {
.name = "IPR",
.mask = disable_ipr_irq,
.unmask = enable_ipr_irq,
.mask_ack = disable_ipr_irq,
};
/*
* The shift value is now the number of bits to shift, not the number of
* bits/4. This is to make it easier to read the value directly from the
* datasheets. The IPR address is calculated using the ipr_offset table.
*/
unsigned int map_ipridx_to_addr(int idx) __attribute__ ((weak));
unsigned int map_ipridx_to_addr(int idx)
{
return 0;
}
void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs)
void register_ipr_controller(struct ipr_desc *desc)
{
int i;
for (i = 0; i < nr_irqs; i++) {
unsigned int irq = table[i].irq;
desc->chip.mask = disable_ipr_irq;
desc->chip.unmask = enable_ipr_irq;
desc->chip.mask_ack = disable_ipr_irq;
if (!irq)
irq = table[i].irq = i;
for (i = 0; i < desc->nr_irqs; i++) {
struct ipr_data *p = desc->ipr_data + i;
/* could the IPR index be mapped, if not we ignore this */
if (!table[i].addr) {
table[i].addr = map_ipridx_to_addr(table[i].ipr_idx);
if (!table[i].addr)
continue;
}
BUG_ON(p->ipr_idx >= desc->nr_offsets);
BUG_ON(!desc->ipr_offsets[p->ipr_idx]);
disable_irq_nosync(irq);
set_irq_chip_and_handler_name(irq, &ipr_irq_chip,
disable_irq_nosync(p->irq);
set_irq_chip_and_handler_name(p->irq, &desc->chip,
handle_level_irq, "level");
set_irq_chip_data(irq, &table[i]);
enable_ipr_irq(irq);
set_irq_chip_data(p->irq, p);
disable_ipr_irq(p->irq);
}
}
EXPORT_SYMBOL(make_ipr_irq);
EXPORT_SYMBOL(register_ipr_controller);
#if !defined(CONFIG_CPU_HAS_PINT_IRQ)
int ipr_irq_demux(int irq)

View File

@@ -311,6 +311,7 @@ restore_all:
rte
nop
.align 2
#ifdef CONFIG_TRACE_IRQFLAGS
1: .long trace_hardirqs_off
#endif

View File

@@ -9,23 +9,14 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/init.h>
#include <linux/smp.h>
#include <asm/processor.h>
#include <asm/cache.h>
int __init detect_cpu_and_cache_system(void)
{
#if defined(CONFIG_CPU_SUBTYPE_SH7604)
current_cpu_data.type = CPU_SH7604;
current_cpu_data.dcache.ways = 4;
current_cpu_data.dcache.way_incr = (1<<10);
current_cpu_data.dcache.sets = 64;
current_cpu_data.dcache.entry_shift = 4;
current_cpu_data.dcache.linesz = L1_CACHE_BYTES;
current_cpu_data.dcache.flags = 0;
#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
#if defined(CONFIG_CPU_SUBTYPE_SH7619)
current_cpu_data.type = CPU_SH7619;
current_cpu_data.dcache.ways = 4;
current_cpu_data.dcache.way_incr = (1<<12);

View File

@@ -52,7 +52,7 @@ static int __init sh7619_devices_setup(void)
}
__initcall(sh7619_devices_setup);
static struct ipr_data sh7619_ipr_map[] = {
static struct ipr_data ipr_irq_table[] = {
{ 86, 0, 4, 2 }, /* CMI0 */
{ 88, 1, 12, 3 }, /* SCIF0_ERI */
{ 89, 1, 12, 3 }, /* SCIF0_RXI */
@@ -68,7 +68,7 @@ static struct ipr_data sh7619_ipr_map[] = {
{ 99, 1, 4, 3 }, /* SCIF2_TXI */
};
static unsigned int ipr_offsets[] = {
static unsigned long ipr_offsets[] = {
0xf8080000, /* IPRC */
0xf8080002, /* IPRD */
0xf8080004, /* IPRE */
@@ -76,15 +76,19 @@ static unsigned int ipr_offsets[] = {
0xf8080008, /* IPRG */
};
/* given the IPR index return the address of the IPR register */
unsigned int map_ipridx_to_addr(int idx)
{
if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
return 0;
return ipr_offsets[idx];
}
static struct ipr_desc ipr_irq_desc = {
.ipr_offsets = ipr_offsets,
.nr_offsets = ARRAY_SIZE(ipr_offsets),
.ipr_data = ipr_irq_table,
.nr_irqs = ARRAY_SIZE(ipr_irq_table),
.chip = {
.name = "IPR-sh7619",
},
};
void __init init_IRQ_ipr(void)
{
make_ipr_irq(sh7619_ipr_map, ARRAY_SIZE(sh7619_ipr_map));
register_ipr_controller(&ipr_irq_desc);
}

View File

@@ -57,7 +57,7 @@ static int __init sh7206_devices_setup(void)
}
__initcall(sh7206_devices_setup);
static struct ipr_data sh7206_ipr_map[] = {
static struct ipr_data ipr_irq_table[] = {
{ 140, 7, 12, 2 }, /* CMI0 */
{ 164, 8, 4, 2 }, /* MTU2_TGI1A */
{ 240, 13, 12, 3 }, /* SCIF0_BRI */
@@ -78,7 +78,7 @@ static struct ipr_data sh7206_ipr_map[] = {
{ 255, 13, 0, 3 }, /* SCIF3_TXI */
};
static unsigned int ipr_offsets[] = {
static unsigned long ipr_offsets[] = {
0xfffe0818, /* IPR01 */
0xfffe081a, /* IPR02 */
0, /* unused */
@@ -95,15 +95,19 @@ static unsigned int ipr_offsets[] = {
0xfffe0c10, /* IPR14 */
};
/* given the IPR index return the address of the IPR register */
unsigned int map_ipridx_to_addr(int idx)
{
if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
return 0;
return ipr_offsets[idx];
}
static struct ipr_desc ipr_irq_desc = {
.ipr_offsets = ipr_offsets,
.nr_offsets = ARRAY_SIZE(ipr_offsets),
.ipr_data = ipr_irq_table,
.nr_irqs = ARRAY_SIZE(ipr_irq_table),
.chip = {
.name = "IPR-sh7206",
},
};
void __init init_IRQ_ipr(void)
{
make_ipr_irq(sh7206_ipr_map, ARRAY_SIZE(sh7206_ipr_map));
register_ipr_controller(&ipr_irq_desc);
}

View File

@@ -340,8 +340,27 @@ ENTRY(vbr_base)
general_exception:
mov.l 1f, k2
mov.l 2f, k3
#ifdef CONFIG_CPU_SUBTYPE_SHX3
mov.l @k2, k2
! Is EXPEVT larger than 0x800?
mov #0x8, k0
shll8 k0
cmp/hs k0, k2
bf 0f
! then add 0x580 (k2 is 0xd80 or 0xda0)
mov #0x58, k0
shll2 k0
shll2 k0
add k0, k2
0:
bra handle_exception
nop
#else
bra handle_exception
mov.l @k2, k2
#endif
.align 2
1: .long EXPEVT
2: .long ret_from_exception

View File

@@ -48,7 +48,7 @@ static int __init sh7705_devices_setup(void)
}
__initcall(sh7705_devices_setup);
static struct ipr_data sh7705_ipr_map[] = {
static struct ipr_data ipr_irq_table[] = {
/* IRQ, IPR-idx, shift, priority */
{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
{ 17, 0, 8, 2 }, /* TMU1 TUNI */
@@ -70,25 +70,29 @@ static struct ipr_data sh7705_ipr_map[] = {
};
static unsigned long ipr_offsets[] = {
0xFFFFFEE2 /* 0: IPRA */
, 0xFFFFFEE4 /* 1: IPRB */
, 0xA4000016 /* 2: IPRC */
, 0xA4000018 /* 3: IPRD */
, 0xA400001A /* 4: IPRE */
, 0xA4080000 /* 5: IPRF */
, 0xA4080002 /* 6: IPRG */
, 0xA4080004 /* 7: IPRH */
0xFFFFFEE2, /* 0: IPRA */
0xFFFFFEE4, /* 1: IPRB */
0xA4000016, /* 2: IPRC */
0xA4000018, /* 3: IPRD */
0xA400001A, /* 4: IPRE */
0xA4080000, /* 5: IPRF */
0xA4080002, /* 6: IPRG */
0xA4080004, /* 7: IPRH */
};
/* given the IPR index return the address of the IPR register */
unsigned int map_ipridx_to_addr(int idx)
{
if (idx >= ARRAY_SIZE(ipr_offsets))
return 0;
return ipr_offsets[idx];
}
static struct ipr_desc ipr_irq_desc = {
.ipr_offsets = ipr_offsets,
.nr_offsets = ARRAY_SIZE(ipr_offsets),
void __init init_IRQ_ipr()
.ipr_data = ipr_irq_table,
.nr_irqs = ARRAY_SIZE(ipr_irq_table),
.chip = {
.name = "IPR-sh7705",
},
};
void __init init_IRQ_ipr(void)
{
make_ipr_irq(sh7705_ipr_map, ARRAY_SIZE(sh7705_ipr_map));
register_ipr_controller(&ipr_irq_desc);
}

View File

@@ -12,6 +12,26 @@
#include <linux/serial.h>
#include <asm/sci.h>
static struct resource rtc_resources[] = {
[0] = {
.start = 0xfffffec0,
.end = 0xfffffec0 + 0x1e,
.flags = IORESOURCE_IO,
},
[1] = {
.start = 20,
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = 21,
.flags = IORESOURCE_IRQ,
},
[3] = {
.start = 22,
.flags = IORESOURCE_IRQ,
},
};
static struct plat_sci_port sci_platform_data[] = {
{
.mapbase = 0xfffffe80,
@@ -41,8 +61,16 @@ static struct platform_device sci_device = {
},
};
static struct platform_device rtc_device = {
.name = "sh-rtc",
.id = -1,
.num_resources = ARRAY_SIZE(rtc_resources),
.resource = rtc_resources,
};
static struct platform_device *sh7709_devices[] __initdata = {
&sci_device,
&rtc_device,
};
static int __init sh7709_devices_setup(void)
@@ -52,32 +80,66 @@ static int __init sh7709_devices_setup(void)
}
__initcall(sh7709_devices_setup);
#define IPRx(A,N) .addr=A, .shift=N
#define IPRA(N) IPRx(0xfffffee2UL,N)
#define IPRB(N) IPRx(0xfffffee4UL,N)
#define IPRC(N) IPRx(0xa4000016UL,N)
#define IPRD(N) IPRx(0xa4000018UL,N)
#define IPRE(N) IPRx(0xa400001aUL,N)
static struct ipr_data ipr_irq_table[] = {
{ 16, 0, 12, 2 }, /* TMU TUNI0 */
{ 17, 0, 8, 4 }, /* TMU TUNI1 */
{ 18, 0, 4, 1 }, /* TMU TUNI1 */
{ 19, 0, 4, 1 }, /* TMU TUNI1 */
{ 20, 0, 0, 2 }, /* RTC CUI */
{ 21, 0, 0, 2 }, /* RTC CUI */
{ 22, 0, 0, 2 }, /* RTC CUI */
static struct ipr_data sh7709_ipr_map[] = {
[16] = { IPRA(12), 2 }, /* TMU TUNI0 */
[17] = { IPRA(8), 4 }, /* TMU TUNI1 */
[18 ... 19] = { IPRA(4), 1 }, /* TMU TUNI1 */
[20 ... 22] = { IPRA(0), 2 }, /* RTC CUI */
[23 ... 26] = { IPRB(4), 3 }, /* SCI */
[27] = { IPRB(12), 2 }, /* WDT ITI */
[32] = { IPRC(0), 1 }, /* IRQ 0 */
[33] = { IPRC(4), 1 }, /* IRQ 1 */
[34] = { IPRC(8), 1 }, /* IRQ 2 APM */
[35] = { IPRC(12), 1 }, /* IRQ 3 TOUCHSCREEN */
[36] = { IPRD(0), 1 }, /* IRQ 4 */
[37] = { IPRD(4), 1 }, /* IRQ 5 */
[48 ... 51] = { IPRE(12), 7 }, /* DMA */
[52 ... 55] = { IPRE(8), 3 }, /* IRDA */
[56 ... 59] = { IPRE(4), 3 }, /* SCIF */
{ 23, 1, 4, 3 }, /* SCI */
{ 24, 1, 4, 3 }, /* SCI */
{ 25, 1, 4, 3 }, /* SCI */
{ 26, 1, 4, 3 }, /* SCI */
{ 27, 1, 12, 3 }, /* WDT ITI */
{ 32, 2, 0, 1 }, /* IRQ 0 */
{ 33, 2, 4, 1 }, /* IRQ 1 */
{ 34, 2, 8, 1 }, /* IRQ 2 APM */
{ 35, 2, 12, 1 }, /* IRQ 3 TOUCHSCREEN */
{ 36, 3, 0, 1 }, /* IRQ 4 */
{ 37, 3, 4, 1 }, /* IRQ 5 */
{ 48, 4, 12, 7 }, /* DMA */
{ 49, 4, 12, 7 }, /* DMA */
{ 50, 4, 12, 7 }, /* DMA */
{ 51, 4, 12, 7 }, /* DMA */
{ 52, 4, 8, 3 }, /* IRDA */
{ 53, 4, 8, 3 }, /* IRDA */
{ 54, 4, 8, 3 }, /* IRDA */
{ 55, 4, 8, 3 }, /* IRDA */
{ 56, 4, 4, 3 }, /* SCIF */
{ 57, 4, 4, 3 }, /* SCIF */
{ 58, 4, 4, 3 }, /* SCIF */
{ 59, 4, 4, 3 }, /* SCIF */
};
void __init init_IRQ_ipr()
static unsigned long ipr_offsets[] = {
0xfffffee2, /* 0: IPRA */
0xfffffee4, /* 1: IPRB */
0xa4000016, /* 2: IPRC */
0xa4000018, /* 3: IPRD */
0xa400001a, /* 4: IPRE */
};
static struct ipr_desc ipr_irq_desc = {
.ipr_offsets = ipr_offsets,
.nr_offsets = ARRAY_SIZE(ipr_offsets),
.ipr_data = ipr_irq_table,
.nr_irqs = ARRAY_SIZE(ipr_irq_table),
.chip = {
.name = "IPR-sh7709",
},
};
void __init init_IRQ_ipr(void)
{
make_ipr_irq(sh7709_ipr_map, ARRAY_SIZE(sh7709_ipr_map));
register_ipr_controller(&ipr_irq_desc);
}

View File

@@ -49,7 +49,7 @@ static int __init sh7710_devices_setup(void)
}
__initcall(sh7710_devices_setup);
static struct ipr_data sh7710_ipr_map[] = {
static struct ipr_data ipr_irq_table[] = {
/* IRQ, IPR-idx, shift, priority */
{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
{ 17, 0, 8, 2 }, /* TMU1 TUNI */
@@ -78,26 +78,30 @@ static struct ipr_data sh7710_ipr_map[] = {
};
static unsigned long ipr_offsets[] = {
0xA414FEE2 /* 0: IPRA */
, 0xA414FEE4 /* 1: IPRB */
, 0xA4140016 /* 2: IPRC */
, 0xA4140018 /* 3: IPRD */
, 0xA414001A /* 4: IPRE */
, 0xA4080000 /* 5: IPRF */
, 0xA4080002 /* 6: IPRG */
, 0xA4080004 /* 7: IPRH */
, 0xA4080006 /* 8: IPRI */
0xA414FEE2, /* 0: IPRA */
0xA414FEE4, /* 1: IPRB */
0xA4140016, /* 2: IPRC */
0xA4140018, /* 3: IPRD */
0xA414001A, /* 4: IPRE */
0xA4080000, /* 5: IPRF */
0xA4080002, /* 6: IPRG */
0xA4080004, /* 7: IPRH */
0xA4080006, /* 8: IPRI */
};
/* given the IPR index return the address of the IPR register */
unsigned int map_ipridx_to_addr(int idx)
{
if (idx >= ARRAY_SIZE(ipr_offsets))
return 0;
return ipr_offsets[idx];
}
static struct ipr_desc ipr_irq_desc = {
.ipr_offsets = ipr_offsets,
.nr_offsets = ARRAY_SIZE(ipr_offsets),
void __init init_IRQ_ipr()
.ipr_data = ipr_irq_table,
.nr_irqs = ARRAY_SIZE(ipr_irq_table),
.chip = {
.name = "IPR-sh7710",
},
};
void __init init_IRQ_ipr(void)
{
make_ipr_irq(sh7710_ipr_map, ARRAY_SIZE(sh7710_ipr_map));
register_ipr_controller(&ipr_irq_desc);
}

View File

@@ -10,7 +10,11 @@ obj-$(CONFIG_SH_STORE_QUEUES) += sq.o
# CPU subtype setup
obj-$(CONFIG_CPU_SUBTYPE_SH7750) += setup-sh7750.o
obj-$(CONFIG_CPU_SUBTYPE_SH7750R) += setup-sh7750.o
obj-$(CONFIG_CPU_SUBTYPE_SH7750S) += setup-sh7750.o
obj-$(CONFIG_CPU_SUBTYPE_SH7091) += setup-sh7750.o
obj-$(CONFIG_CPU_SUBTYPE_SH7751) += setup-sh7750.o
obj-$(CONFIG_CPU_SUBTYPE_SH7751R) += setup-sh7750.o
obj-$(CONFIG_CPU_SUBTYPE_SH7760) += setup-sh7760.o
obj-$(CONFIG_CPU_SUBTYPE_SH4_202) += setup-sh4-202.o

View File

@@ -141,6 +141,14 @@ int __init detect_cpu_and_cache_system(void)
current_cpu_data.flags |= CPU_HAS_LLSC;
}
break;
case 0x4000: /* 1st cut */
case 0x4001: /* 2nd cut */
current_cpu_data.type = CPU_SHX3;
current_cpu_data.icache.ways = 4;
current_cpu_data.dcache.ways = 4;
current_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
CPU_HAS_LLSC;
break;
case 0x8000:
current_cpu_data.type = CPU_ST40RA;
current_cpu_data.flags |= CPU_HAS_FPU;

View File

@@ -82,7 +82,7 @@ static int __init sh7750_devices_setup(void)
}
__initcall(sh7750_devices_setup);
static struct ipr_data sh7750_ipr_map[] = {
static struct ipr_data ipr_irq_table[] = {
/* IRQ, IPR-idx, shift, priority */
{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
{ 17, 0, 12, 2 }, /* TMU1 TUNI */
@@ -106,8 +106,27 @@ static struct ipr_data sh7750_ipr_map[] = {
{ 38, 2, 8, 7 }, /* DMAC DMAE */
};
static unsigned long ipr_offsets[] = {
0xffd00004UL, /* 0: IPRA */
0xffd00008UL, /* 1: IPRB */
0xffd0000cUL, /* 2: IPRC */
0xffd00010UL, /* 3: IPRD */
};
static struct ipr_desc ipr_irq_desc = {
.ipr_offsets = ipr_offsets,
.nr_offsets = ARRAY_SIZE(ipr_offsets),
.ipr_data = ipr_irq_table,
.nr_irqs = ARRAY_SIZE(ipr_irq_table),
.chip = {
.name = "IPR-sh7750",
},
};
#ifdef CONFIG_CPU_SUBTYPE_SH7751
static struct ipr_data sh7751_ipr_map[] = {
static struct ipr_data ipr_irq_table_sh7751[] = {
{ 44, 2, 8, 7 }, /* DMAC DMTE4 */
{ 45, 2, 8, 7 }, /* DMAC DMTE5 */
{ 46, 2, 8, 7 }, /* DMAC DMTE6 */
@@ -118,21 +137,26 @@ static struct ipr_data sh7751_ipr_map[] = {
/*{ 72, INTPRI00, 8, ? },*/ /* TMU3 TUNI */
/*{ 76, INTPRI00, 12, ? },*/ /* TMU4 TUNI */
};
static struct ipr_desc ipr_irq_desc_sh7751 = {
.ipr_offsets = ipr_offsets,
.nr_offsets = ARRAY_SIZE(ipr_offsets),
.ipr_data = ipr_irq_table_sh7751,
.nr_irqs = ARRAY_SIZE(ipr_irq_table_sh7751),
.chip = {
.name = "IPR-sh7751",
},
};
#endif
static unsigned long ipr_offsets[] = {
0xffd00004UL, /* 0: IPRA */
0xffd00008UL, /* 1: IPRB */
0xffd0000cUL, /* 2: IPRC */
0xffd00010UL, /* 3: IPRD */
};
/* given the IPR index return the address of the IPR register */
unsigned int map_ipridx_to_addr(int idx)
void __init init_IRQ_ipr(void)
{
if (idx >= ARRAY_SIZE(ipr_offsets))
return 0;
return ipr_offsets[idx];
register_ipr_controller(&ipr_irq_desc);
#ifdef CONFIG_CPU_SUBTYPE_SH7751
register_ipr_controller(&ipr_irq_desc_sh7751);
#endif
}
#define INTC_ICR 0xffd00000UL
@@ -143,11 +167,3 @@ void ipr_irq_enable_irlm(void)
{
ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
}
void __init init_IRQ_ipr()
{
make_ipr_irq(sh7750_ipr_map, ARRAY_SIZE(sh7750_ipr_map));
#ifdef CONFIG_CPU_SUBTYPE_SH7751
make_ipr_irq(sh7751_ipr_map, ARRAY_SIZE(sh7751_ipr_map));
#endif
}

View File

@@ -96,7 +96,25 @@ static struct intc2_data intc2_irq_table[] = {
{109,12, 0, 4, 0, 3}, /* CMTI */
};
static struct ipr_data sh7760_ipr_map[] = {
static struct intc2_desc intc2_irq_desc __read_mostly = {
.prio_base = 0xfe080000,
.msk_base = 0xfe080040,
.mskclr_base = 0xfe080060,
.intc2_data = intc2_irq_table,
.nr_irqs = ARRAY_SIZE(intc2_irq_table),
.chip = {
.name = "INTC2-sh7760",
},
};
void __init init_IRQ_intc2(void)
{
register_intc2_controller(&intc2_irq_desc);
}
static struct ipr_data ipr_irq_table[] = {
/* IRQ, IPR-idx, shift, priority */
{ 16, 0, 12, 2 }, /* TMU0 TUNI*/
{ 17, 0, 8, 2 }, /* TMU1 TUNI */
@@ -133,20 +151,19 @@ static unsigned long ipr_offsets[] = {
0xffd00010UL, /* 3: IPRD */
};
/* given the IPR index return the address of the IPR register */
unsigned int map_ipridx_to_addr(int idx)
{
if (idx >= ARRAY_SIZE(ipr_offsets))
return 0;
return ipr_offsets[idx];
}
static struct ipr_desc ipr_irq_desc = {
.ipr_offsets = ipr_offsets,
.nr_offsets = ARRAY_SIZE(ipr_offsets),
void __init init_IRQ_intc2(void)
{
make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
}
.ipr_data = ipr_irq_table,
.nr_irqs = ARRAY_SIZE(ipr_irq_table),
void __init init_IRQ_ipr(void)
.chip = {
.name = "IPR-sh7760",
},
};
void __init init_IRQ_ipr(void)
{
make_ipr_irq(sh7760_ipr_map, ARRAY_SIZE(sh7760_ipr_map));
register_ipr_controller(&ipr_irq_desc);
}

View File

@@ -9,6 +9,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7785) += setup-sh7785.o
obj-$(CONFIG_CPU_SUBTYPE_SH73180) += setup-sh73180.o
obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o
obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o
obj-$(CONFIG_CPU_SUBTYPE_SHX3) += setup-shx3.o
# Primary on-chip clocks (common)
clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o
@@ -17,5 +18,6 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o
clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o
clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o
clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o
clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o
obj-y += $(clock-y)

View File

@@ -0,0 +1,135 @@
/*
* arch/sh/kernel/cpu/sh4/clock-shx3.c
*
* SH-X3 support for the clock framework
*
* Copyright (C) 2006-2007 Renesas Technology Corp.
* Copyright (C) 2006-2007 Renesas Solutions Corp.
* Copyright (C) 2006-2007 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <asm/clock.h>
#include <asm/freq.h>
#include <asm/io.h>
static int ifc_divisors[] = { 1, 2, 4 ,6 };
static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18, 24, 32, 36, 48 };
static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 18, 24, 32, 36, 48 };
static int cfc_divisors[] = { 1, 1, 4, 6 };
#define IFC_POS 28
#define IFC_MSK 0x0003
#define BFC_MSK 0x000f
#define PFC_MSK 0x000f
#define CFC_MSK 0x0003
#define BFC_POS 16
#define PFC_POS 0
#define CFC_POS 20
static void master_clk_init(struct clk *clk)
{
clk->rate *= pfc_divisors[(ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK];
}
static struct clk_ops shx3_master_clk_ops = {
.init = master_clk_init,
};
static void module_clk_recalc(struct clk *clk)
{
int idx = ((ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK);
clk->rate = clk->parent->rate / pfc_divisors[idx];
}
static struct clk_ops shx3_module_clk_ops = {
.recalc = module_clk_recalc,
};
static void bus_clk_recalc(struct clk *clk)
{
int idx = ((ctrl_inl(FRQCR) >> BFC_POS) & BFC_MSK);
clk->rate = clk->parent->rate / bfc_divisors[idx];
}
static struct clk_ops shx3_bus_clk_ops = {
.recalc = bus_clk_recalc,
};
static void cpu_clk_recalc(struct clk *clk)
{
int idx = ((ctrl_inl(FRQCR) >> IFC_POS) & IFC_MSK);
clk->rate = clk->parent->rate / ifc_divisors[idx];
}
static struct clk_ops shx3_cpu_clk_ops = {
.recalc = cpu_clk_recalc,
};
static struct clk_ops *shx3_clk_ops[] = {
&shx3_master_clk_ops,
&shx3_module_clk_ops,
&shx3_bus_clk_ops,
&shx3_cpu_clk_ops,
};
void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
{
if (idx < ARRAY_SIZE(shx3_clk_ops))
*ops = shx3_clk_ops[idx];
}
static void shyway_clk_recalc(struct clk *clk)
{
int idx = ((ctrl_inl(FRQCR) >> CFC_POS) & CFC_MSK);
clk->rate = clk->parent->rate / cfc_divisors[idx];
}
static struct clk_ops shx3_shyway_clk_ops = {
.recalc = shyway_clk_recalc,
};
static struct clk shx3_shyway_clk = {
.name = "shyway_clk",
.flags = CLK_ALWAYS_ENABLED,
.ops = &shx3_shyway_clk_ops,
};
/*
* Additional SHx3-specific on-chip clocks that aren't already part of the
* clock framework
*/
static struct clk *shx3_onchip_clocks[] = {
&shx3_shyway_clk,
};
static int __init shx3_clk_init(void)
{
struct clk *clk = clk_get(NULL, "master_clk");
int i;
for (i = 0; i < ARRAY_SIZE(shx3_onchip_clocks); i++) {
struct clk *clkp = shx3_onchip_clocks[i];
clkp->parent = clk;
clk_register(clkp);
clk_enable(clkp);
}
/*
* Now that we have the rest of the clocks registered, we need to
* force the parent clock to propagate so that these clocks will
* automatically figure out their rate. We cheat by handing the
* parent clock its current rate and forcing child propagation.
*/
clk_set_rate(clk, clk_get_rate(clk));
clk_put(clk);
return 0;
}
arch_initcall(shx3_clk_init);

View File

@@ -1,7 +1,7 @@
/*
* SH7722 Setup
*
* Copyright (C) 2006 Paul Mundt
* Copyright (C) 2006 - 2007 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -10,6 +10,8 @@
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/mm.h>
#include <asm/mmzone.h>
#include <asm/sci.h>
static struct plat_sci_port sci_platform_data[] = {
@@ -42,7 +44,7 @@ static int __init sh7722_devices_setup(void)
}
__initcall(sh7722_devices_setup);
static struct ipr_data sh7722_ipr_map[] = {
static struct ipr_data ipr_irq_table[] = {
/* IRQ, IPR-idx, shift, prio */
{ 16, 0, 12, 2 }, /* TMU0 */
{ 17, 0, 8, 2 }, /* TMU1 */
@@ -67,14 +69,25 @@ static unsigned long ipr_offsets[] = {
0xa408002c, /* 11: IPRL */
};
unsigned int map_ipridx_to_addr(int idx)
{
if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
return 0;
return ipr_offsets[idx];
}
static struct ipr_desc ipr_irq_desc = {
.ipr_offsets = ipr_offsets,
.nr_offsets = ARRAY_SIZE(ipr_offsets),
.ipr_data = ipr_irq_table,
.nr_irqs = ARRAY_SIZE(ipr_irq_table),
.chip = {
.name = "IPR-sh7722",
},
};
void __init init_IRQ_ipr(void)
{
make_ipr_irq(sh7722_ipr_map, ARRAY_SIZE(sh7722_ipr_map));
register_ipr_controller(&ipr_irq_desc);
}
void __init plat_mem_setup(void)
{
/* Register the URAM space as Node 1 */
setup_bootmem_node(1, 0x055f0000, 0x05610000);
}

View File

@@ -102,7 +102,20 @@ static struct intc2_data intc2_irq_table[] = {
{ 68, 0x14, 8, 0, 18, 2 }, /* PCIC4 */
};
static struct intc2_desc intc2_irq_desc __read_mostly = {
.prio_base = 0xffd40000,
.msk_base = 0xffd40038,
.mskclr_base = 0xffd4003c,
.intc2_data = intc2_irq_table,
.nr_irqs = ARRAY_SIZE(intc2_irq_table),
.chip = {
.name = "INTC2-sh7780",
},
};
void __init init_IRQ_intc2(void)
{
make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
register_intc2_controller(&intc2_irq_desc);
}

View File

@@ -97,7 +97,21 @@ static struct intc2_data intc2_irq_table[] = {
{ 60, 12, 16, 0, 7, 3 }, /* SCIF5 ERI, RXI, BRI, TXI */
};
static struct intc2_desc intc2_irq_desc __read_mostly = {
.prio_base = 0xffd40000,
.msk_base = 0xffd40038,
.mskclr_base = 0xffd4003c,
.intc2_data = intc2_irq_table,
.nr_irqs = ARRAY_SIZE(intc2_irq_table),
.chip = {
.name = "INTC2-sh7785",
},
};
void __init init_IRQ_intc2(void)
{
make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
register_intc2_controller(&intc2_irq_desc);
}

View File

@@ -0,0 +1,85 @@
/*
* SH-X3 Setup
*
* Copyright (C) 2007 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/io.h>
#include <asm/sci.h>
static struct plat_sci_port sci_platform_data[] = {
{
.mapbase = 0xffc30000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 40, 41, 43, 42 },
}, {
.mapbase = 0xffc40000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 44, 45, 47, 46 },
}, {
.mapbase = 0xffc50000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 48, 49, 51, 50 },
}, {
.mapbase = 0xffc60000,
.flags = UPF_BOOT_AUTOCONF,
.type = PORT_SCIF,
.irqs = { 52, 53, 55, 54 },
}, {
.flags = 0,
}
};
static struct platform_device sci_device = {
.name = "sh-sci",
.id = -1,
.dev = {
.platform_data = sci_platform_data,
},
};
static struct platform_device *shx3_devices[] __initdata = {
&sci_device,
};
static int __init shx3_devices_setup(void)
{
return platform_add_devices(shx3_devices,
ARRAY_SIZE(shx3_devices));
}
__initcall(shx3_devices_setup);
static struct intc2_data intc2_irq_table[] = {
{ 16, 0, 0, 0, 1, 2 }, /* TMU0 */
{ 40, 4, 0, 0x20, 0, 3 }, /* SCIF0 ERI */
{ 41, 4, 0, 0x20, 1, 3 }, /* SCIF0 RXI */
{ 42, 4, 0, 0x20, 2, 3 }, /* SCIF0 BRI */
{ 43, 4, 0, 0x20, 3, 3 }, /* SCIF0 TXI */
};
static struct intc2_desc intc2_irq_desc __read_mostly = {
.prio_base = 0xfe410000,
.msk_base = 0xfe410820,
.mskclr_base = 0xfe410850,
.intc2_data = intc2_irq_table,
.nr_irqs = ARRAY_SIZE(intc2_irq_table),
.chip = {
.name = "INTC2-SHX3",
},
};
void __init init_IRQ_intc2(void)
{
register_intc2_controller(&intc2_irq_desc);
}

View File

@@ -158,15 +158,11 @@ asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs)
}
#ifdef CONFIG_4KSTACKS
/*
* These should really be __section__(".bss.page_aligned") as well, but
* gcc's 3.0 and earlier don't handle that correctly.
*/
static char softirq_stack[NR_CPUS * THREAD_SIZE]
__attribute__((__aligned__(THREAD_SIZE)));
__attribute__((__section__(".bss.page_aligned")));
static char hardirq_stack[NR_CPUS * THREAD_SIZE]
__attribute__((__aligned__(THREAD_SIZE)));
__attribute__((__section__(".bss.page_aligned")));
/*
* allocate per-cpu stacks for hardirq and for softirq processing

130
arch/sh/kernel/machvec.c Normal file
View File

@@ -0,0 +1,130 @@
/*
* arch/sh/kernel/machvec.c
*
* The SuperH machine vector setup handlers, yanked from setup.c
*
* Copyright (C) 1999 Niibe Yutaka
* Copyright (C) 2002 - 2007 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/init.h>
#include <linux/string.h>
#include <asm/machvec.h>
#include <asm/sections.h>
#include <asm/io.h>
#include <asm/irq.h>
#define MV_NAME_SIZE 32
#define for_each_mv(mv) \
for ((mv) = (struct sh_machine_vector *)&__machvec_start; \
(mv) && (unsigned long)(mv) < (unsigned long)&__machvec_end; \
(mv)++)
static struct sh_machine_vector * __init get_mv_byname(const char *name)
{
struct sh_machine_vector *mv;
for_each_mv(mv)
if (strcasecmp(name, mv->mv_name) == 0)
return mv;
return NULL;
}
static unsigned int __initdata machvec_selected;
static int __init early_parse_mv(char *from)
{
char mv_name[MV_NAME_SIZE] = "";
char *mv_end;
char *mv_comma;
int mv_len;
struct sh_machine_vector *mvp;
mv_end = strchr(from, ' ');
if (mv_end == NULL)
mv_end = from + strlen(from);
mv_comma = strchr(from, ',');
mv_len = mv_end - from;
if (mv_len > (MV_NAME_SIZE-1))
mv_len = MV_NAME_SIZE-1;
memcpy(mv_name, from, mv_len);
mv_name[mv_len] = '\0';
from = mv_end;
machvec_selected = 1;
/* Boot with the generic vector */
if (strcmp(mv_name, "generic") == 0)
return 0;
mvp = get_mv_byname(mv_name);
if (unlikely(!mvp)) {
printk("Available vectors:\n\n\t'%s', ", sh_mv.mv_name);
for_each_mv(mvp)
printk("'%s', ", mvp->mv_name);
printk("\n\n");
panic("Failed to select machvec '%s' -- halting.\n",
mv_name);
} else
sh_mv = *mvp;
return 0;
}
early_param("sh_mv", early_parse_mv);
void __init sh_mv_setup(void)
{
/*
* Only overload the machvec if one hasn't been selected on
* the command line with sh_mv=
*/
if (!machvec_selected) {
unsigned long machvec_size;
machvec_size = ((unsigned long)&__machvec_end -
(unsigned long)&__machvec_start);
/*
* If the machvec hasn't been preselected, use the first
* vector (usually the only one) from .machvec.init.
*/
if (machvec_size >= sizeof(struct sh_machine_vector))
sh_mv = *(struct sh_machine_vector *)&__machvec_start;
}
printk(KERN_NOTICE "Booting machvec: %s\n", get_system_type());
/*
* Manually walk the vec, fill in anything that the board hasn't yet
* by hand, wrapping to the generic implementation.
*/
#define mv_set(elem) do { \
if (!sh_mv.mv_##elem) \
sh_mv.mv_##elem = generic_##elem; \
} while (0)
mv_set(inb); mv_set(inw); mv_set(inl);
mv_set(outb); mv_set(outw); mv_set(outl);
mv_set(inb_p); mv_set(inw_p); mv_set(inl_p);
mv_set(outb_p); mv_set(outw_p); mv_set(outl_p);
mv_set(insb); mv_set(insw); mv_set(insl);
mv_set(outsb); mv_set(outsw); mv_set(outsl);
mv_set(readb); mv_set(readw); mv_set(readl);
mv_set(writeb); mv_set(writew); mv_set(writel);
mv_set(ioport_map);
mv_set(ioport_unmap);
mv_set(irq_demux);
if (!sh_mv.mv_nr_irqs)
sh_mv.mv_nr_irqs = NR_IRQS;
}

View File

@@ -17,6 +17,7 @@
#include <linux/kexec.h>
#include <linux/kdebug.h>
#include <linux/tick.h>
#include <linux/reboot.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
#include <asm/pgalloc.h>
@@ -319,9 +320,7 @@ static void ubc_set_tracing(int asid, unsigned long pc)
ctrl_outl(pc, UBC_BARA);
#ifdef CONFIG_MMU
/* We don't have any ASID settings for the SH-2! */
if (current_cpu_data.type != CPU_SH7604)
ctrl_outb(asid, UBC_BASRA);
ctrl_outb(asid, UBC_BASRA);
#endif
ctrl_outl(0, UBC_BAMRA);
@@ -405,8 +404,8 @@ asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs __regs)
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
#ifdef CONFIG_MMU
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL);
#else
/* fork almost works, enough to trick you into looking elsewhere :-( */
@@ -449,23 +448,20 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
/*
* sys_execve() executes a new program.
*/
asmlinkage int sys_execve(char *ufilename, char **uargv,
char **uenvp, unsigned long r7,
asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv,
char __user * __user *uenvp, unsigned long r7,
struct pt_regs __regs)
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
int error;
char *filename;
filename = getname((char __user *)ufilename);
filename = getname(ufilename);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename,
(char __user * __user *)uargv,
(char __user * __user *)uenvp,
regs);
error = do_execve(filename, uargv, uenvp, regs);
if (error == 0) {
task_lock(current);
current->ptrace &= ~PT_DTRACE;

View File

@@ -99,7 +99,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = -EIO;
if (copied != sizeof(tmp))
break;
ret = put_user(tmp,(unsigned long *) data);
ret = put_user(tmp,(unsigned long __user *) data);
break;
}
@@ -128,7 +128,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
tmp = !!tsk_used_math(child);
else
tmp = 0;
ret = put_user(tmp, (unsigned long *)data);
ret = put_user(tmp, (unsigned long __user *)data);
break;
}
@@ -196,7 +196,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_SINGLESTEP: { /* set the trap flag. */
long pc;
struct pt_regs *dummy = NULL;
struct pt_regs *regs = NULL;
ret = -EIO;
if (!valid_signal(data))
@@ -207,7 +207,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
child->ptrace |= PT_DTRACE;
}
pc = get_stack_long(child, (long)&dummy->pc);
pc = get_stack_long(child, (long)&regs->pc);
/* Next scheduling will set up UBC */
if (child->thread.ubc_pc == 0)

View File

@@ -23,6 +23,7 @@
#include <linux/kexec.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/page.h>
#include <asm/sections.h>
#include <asm/irq.h>
#include <asm/setup.h>
@@ -41,20 +42,19 @@ extern void * __rd_start, * __rd_end;
* The bigger value means no problem.
*/
struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 10000000, };
/*
* The machine vector. First entry in .machvec.init, or clobbered by
* sh_mv= on the command line, prior to .machvec.init teardown.
*/
struct sh_machine_vector sh_mv = { .mv_name = "generic", };
#ifdef CONFIG_VT
struct screen_info screen_info;
#endif
#if defined(CONFIG_SH_UNKNOWN)
struct sh_machine_vector sh_mv;
#endif
extern int root_mountflags;
#define MV_NAME_SIZE 32
static struct sh_machine_vector* __init get_mv_byname(const char* name);
/*
* This is set up by the setup-routine at boot-time
*/
@@ -80,131 +80,17 @@ static struct resource data_resource = { .name = "Kernel data", };
unsigned long memory_start, memory_end;
static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
struct sh_machine_vector** mvp,
unsigned long *mv_io_base)
static int __init early_parse_mem(char *p)
{
char c = ' ', *to = command_line, *from = COMMAND_LINE;
int len = 0;
/* Save unparsed command line copy for /proc/cmdline */
memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
unsigned long size;
memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START;
memory_end = memory_start + __MEMORY_SIZE;
for (;;) {
/*
* "mem=XXX[kKmM]" defines a size of memory.
*/
if (c == ' ' && !memcmp(from, "mem=", 4)) {
if (to != command_line)
to--;
{
unsigned long mem_size;
mem_size = memparse(from+4, &from);
memory_end = memory_start + mem_size;
}
}
if (c == ' ' && !memcmp(from, "sh_mv=", 6)) {
char* mv_end;
char* mv_comma;
int mv_len;
if (to != command_line)
to--;
from += 6;
mv_end = strchr(from, ' ');
if (mv_end == NULL)
mv_end = from + strlen(from);
mv_comma = strchr(from, ',');
if ((mv_comma != NULL) && (mv_comma < mv_end)) {
int ints[3];
get_options(mv_comma+1, ARRAY_SIZE(ints), ints);
*mv_io_base = ints[1];
mv_len = mv_comma - from;
} else {
mv_len = mv_end - from;
}
if (mv_len > (MV_NAME_SIZE-1))
mv_len = MV_NAME_SIZE-1;
memcpy(mv_name, from, mv_len);
mv_name[mv_len] = '\0';
from = mv_end;
*mvp = get_mv_byname(mv_name);
}
c = *(from++);
if (!c)
break;
if (COMMAND_LINE_SIZE <= ++len)
break;
*(to++) = c;
}
*to = '\0';
*cmdline_p = command_line;
}
static int __init sh_mv_setup(char **cmdline_p)
{
#ifdef CONFIG_SH_UNKNOWN
extern struct sh_machine_vector mv_unknown;
#endif
struct sh_machine_vector *mv = NULL;
char mv_name[MV_NAME_SIZE] = "";
unsigned long mv_io_base = 0;
parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base);
#ifdef CONFIG_SH_UNKNOWN
if (mv == NULL) {
mv = &mv_unknown;
if (*mv_name != '\0') {
printk("Warning: Unsupported machine %s, using unknown\n",
mv_name);
}
}
sh_mv = *mv;
#endif
/*
* Manually walk the vec, fill in anything that the board hasn't yet
* by hand, wrapping to the generic implementation.
*/
#define mv_set(elem) do { \
if (!sh_mv.mv_##elem) \
sh_mv.mv_##elem = generic_##elem; \
} while (0)
mv_set(inb); mv_set(inw); mv_set(inl);
mv_set(outb); mv_set(outw); mv_set(outl);
mv_set(inb_p); mv_set(inw_p); mv_set(inl_p);
mv_set(outb_p); mv_set(outw_p); mv_set(outl_p);
mv_set(insb); mv_set(insw); mv_set(insl);
mv_set(outsb); mv_set(outsw); mv_set(outsl);
mv_set(readb); mv_set(readw); mv_set(readl);
mv_set(writeb); mv_set(writew); mv_set(writel);
mv_set(ioport_map);
mv_set(ioport_unmap);
mv_set(irq_demux);
#ifdef CONFIG_SH_UNKNOWN
__set_io_port_base(mv_io_base);
#endif
if (!sh_mv.mv_nr_irqs)
sh_mv.mv_nr_irqs = NR_IRQS;
size = memparse(p, &p);
memory_end = memory_start + size;
return 0;
}
early_param("mem", early_parse_mem);
/*
* Register fully available low RAM pages with the bootmem allocator.
@@ -230,7 +116,7 @@ static void __init register_bootmem_low_pages(void)
free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages));
}
void __init setup_bootmem_allocator(unsigned long start_pfn)
void __init setup_bootmem_allocator(unsigned long free_pfn)
{
unsigned long bootmap_size;
@@ -239,9 +125,10 @@ void __init setup_bootmem_allocator(unsigned long start_pfn)
* bootstrap step all allocations (until the page allocator
* is intact) must be done via bootmem_alloc().
*/
bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
bootmap_size = init_bootmem_node(NODE_DATA(0), free_pfn,
min_low_pfn, max_low_pfn);
add_active_range(0, min_low_pfn, max_low_pfn);
register_bootmem_low_pages();
node_set_online(0);
@@ -254,7 +141,7 @@ void __init setup_bootmem_allocator(unsigned long start_pfn)
* an invalid RAM area.
*/
reserve_bootmem(__MEMORY_START+PAGE_SIZE,
(PFN_PHYS(start_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START);
(PFN_PHYS(free_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START);
/*
* reserve physical page 0 - it's a special BIOS page on many boxes,
@@ -262,6 +149,8 @@ void __init setup_bootmem_allocator(unsigned long start_pfn)
*/
reserve_bootmem(__MEMORY_START, PAGE_SIZE);
sparse_memory_present_with_active_regions(0);
#ifdef CONFIG_BLK_DEV_INITRD
ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
if (&__rd_start != &__rd_end) {
@@ -315,10 +204,6 @@ void __init setup_arch(char **cmdline_p)
{
enable_mmu();
#ifdef CONFIG_CMDLINE_BOOL
strcpy(COMMAND_LINE, CONFIG_CMDLINE);
#endif
ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
#ifdef CONFIG_BLK_DEV_RAM
@@ -339,9 +224,22 @@ void __init setup_arch(char **cmdline_p)
data_resource.start = virt_to_phys(_etext);
data_resource.end = virt_to_phys(_edata)-1;
memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START;
memory_end = memory_start + __MEMORY_SIZE;
#ifdef CONFIG_CMDLINE_BOOL
strlcpy(command_line, CONFIG_CMDLINE, sizeof(command_line));
#else
strlcpy(command_line, COMMAND_LINE, sizeof(command_line));
#endif
/* Save unparsed command line copy for /proc/cmdline */
memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
*cmdline_p = command_line;
parse_early_param();
sh_mv_setup(cmdline_p);
sh_mv_setup();
/*
* Find the highest page frame number we have available
@@ -355,8 +253,9 @@ void __init setup_arch(char **cmdline_p)
min_low_pfn = __MEMORY_START >> PAGE_SHIFT;
nodes_clear(node_online_map);
/* Setup bootmem with available RAM */
setup_memory();
paging_init();
sparse_init();
#ifdef CONFIG_DUMMY_CONSOLE
@@ -366,46 +265,13 @@ void __init setup_arch(char **cmdline_p)
/* Perform the machine specific initialisation */
if (likely(sh_mv.mv_setup))
sh_mv.mv_setup(cmdline_p);
paging_init();
}
struct sh_machine_vector* __init get_mv_byname(const char* name)
{
extern long __machvec_start, __machvec_end;
struct sh_machine_vector *all_vecs =
(struct sh_machine_vector *)&__machvec_start;
int i, n = ((unsigned long)&__machvec_end
- (unsigned long)&__machvec_start)/
sizeof(struct sh_machine_vector);
for (i = 0; i < n; ++i) {
struct sh_machine_vector *mv = &all_vecs[i];
if (mv == NULL)
continue;
if (strcasecmp(name, get_system_type()) == 0) {
return mv;
}
}
return NULL;
}
static struct cpu cpu[NR_CPUS];
static int __init topology_init(void)
{
int cpu_id;
for_each_possible_cpu(cpu_id)
register_cpu(&cpu[cpu_id], cpu_id);
return 0;
}
subsys_initcall(topology_init);
static const char *cpu_name[] = {
[CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619",
[CPU_SH7604] = "SH7604", [CPU_SH7300] = "SH7300",
[CPU_SH7300] = "SH7300",
[CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706",
[CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708",
[CPU_SH7709] = "SH7709", [CPU_SH7710] = "SH7710",
@@ -419,7 +285,7 @@ static const char *cpu_name[] = {
[CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780",
[CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343",
[CPU_SH7785] = "SH7785", [CPU_SH7722] = "SH7722",
[CPU_SH_NONE] = "Unknown"
[CPU_SHX3] = "SH-X3", [CPU_SH_NONE] = "Unknown"
};
const char *get_cpu_subtype(struct sh_cpuinfo *c)

View File

@@ -78,6 +78,16 @@ DECLARE_EXPORT(__movstr);
DECLARE_EXPORT(__movmem_i4_even);
DECLARE_EXPORT(__movmem_i4_odd);
DECLARE_EXPORT(__movmemSI12_i4);
#if (__GNUC_MINOR__ == 2 || defined(__GNUC_STM_RELEASE__))
/*
* GCC 4.2 emits these for division, as do GCC 4.1.x versions of the ST
* compiler which include backported patches.
*/
DECLARE_EXPORT(__sdivsi3_i4i);
DECLARE_EXPORT(__udiv_qrnnd_16);
DECLARE_EXPORT(__udivsi3_i4i);
#endif
#else /* GCC 3.x */
DECLARE_EXPORT(__movstr_i4_even);
DECLARE_EXPORT(__movstr_i4_odd);

View File

@@ -23,6 +23,7 @@
#include <linux/personality.h>
#include <linux/binfmts.h>
#include <linux/freezer.h>
#include <linux/io.h>
#include <asm/system.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
@@ -261,7 +262,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
goto badframe;
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
do_sigaltstack(&st, NULL, regs->regs[15]);
do_sigaltstack((const stack_t __user *)&st, NULL, (unsigned long)frame);
return r0;

View File

@@ -308,9 +308,9 @@ ENTRY(sys_call_table)
.long sys_utimes
.long sys_fadvise64_64_wrapper
.long sys_ni_syscall /* Reserved for vserver */
.long sys_ni_syscall /* Reserved for mbind */
.long sys_ni_syscall /* 275 - get_mempolicy */
.long sys_ni_syscall /* set_mempolicy */
.long sys_mbind
.long sys_get_mempolicy /* 275 */
.long sys_set_mempolicy
.long sys_mq_open
.long sys_mq_unlink
.long sys_mq_timedsend

View File

@@ -30,7 +30,7 @@
static int tmu_timer_start(void)
{
ctrl_outb(ctrl_inb(TMU_TSTR) | 0x3, TMU_TSTR);
ctrl_outb(ctrl_inb(TMU_012_TSTR) | 0x3, TMU_012_TSTR);
return 0;
}
@@ -52,7 +52,7 @@ static void tmu0_timer_set_interval(unsigned long interval, unsigned int reload)
static int tmu_timer_stop(void)
{
ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x3, TMU_TSTR);
ctrl_outb(ctrl_inb(TMU_012_TSTR) & ~0x3, TMU_012_TSTR);
return 0;
}
@@ -174,7 +174,8 @@ static int tmu_timer_init(void)
#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \
!defined(CONFIG_CPU_SUBTYPE_SH7760) && \
!defined(CONFIG_CPU_SUBTYPE_SH7785)
!defined(CONFIG_CPU_SUBTYPE_SH7785) && \
!defined(CONFIG_CPU_SUBTYPE_SHX3)
ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
#endif

49
arch/sh/kernel/topology.c Normal file
View File

@@ -0,0 +1,49 @@
/*
* arch/sh/kernel/topology.c
*
* Copyright (C) 2007 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/cpu.h>
#include <linux/cpumask.h>
#include <linux/init.h>
#include <linux/percpu.h>
#include <linux/node.h>
#include <linux/nodemask.h>
static DEFINE_PER_CPU(struct cpu, cpu_devices);
static int __init topology_init(void)
{
int i, ret;
#ifdef CONFIG_NEED_MULTIPLE_NODES
for_each_online_node(i)
register_one_node(i);
#endif
for_each_present_cpu(i) {
ret = register_cpu(&per_cpu(cpu_devices, i), i);
if (unlikely(ret))
printk(KERN_WARNING "%s: register_cpu %d failed (%d)\n",
__FUNCTION__, i, ret);
}
#if defined(CONFIG_NUMA) && !defined(CONFIG_SMP)
/*
* In the UP case, make sure the CPU association is still
* registered under each node. Without this, sysfs fails
* to make the connection between nodes other than node0
* and cpu0.
*/
for_each_online_node(i)
if (i != numa_node_id())
register_cpu_under_node(raw_smp_processor_id(), i);
#endif
return 0;
}
subsys_initcall(topology_init);

View File

@@ -584,7 +584,7 @@ uspace_segv:
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = si_code;
info.si_addr = (void *) address;
info.si_addr = (void __user *)address;
force_sig_info(SIGBUS, &info, current);
} else {
if (regs->pc & 1)
@@ -617,7 +617,7 @@ uspace_segv:
*/
int is_dsp_inst(struct pt_regs *regs)
{
unsigned short inst;
unsigned short inst = 0;
/*
* Safe guard if DSP mode is already enabled or we're lacking
@@ -645,7 +645,6 @@ asmlinkage void do_divide_error(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs __regs)
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
siginfo_t info;
switch (r4) {

View File

@@ -97,18 +97,20 @@ SECTIONS
__initramfs_end = .;
#endif
. = ALIGN(4);
__machvec_start = .;
.init.machvec : { *(.init.machvec) }
.machvec.init : { *(.machvec.init) }
__machvec_end = .;
. = ALIGN(PAGE_SIZE);
__init_end = .;
. = ALIGN(4);
__bss_start = .; /* BSS */
.bss : { *(.bss) }
. = ALIGN(4);
_end = . ;
.bss : {
__init_end = .;
__bss_start = .; /* BSS */
*(.bss.page_aligned)
*(.bss)
. = ALIGN(4);
_end = . ;
}
/* When something in the kernel is NOT compiled as a module, the
* module cleanup code and data are put into these segments. Both