提交 2f284c84 编写于 作者: L Linus Torvalds

Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm

* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (35 commits)
  ARM: Update (and cut down) mach-types
  ARM: 6771/1: vexpress: add support for multiple core tiles
  ARM: 6797/1: hw_breakpoint: Fix newlines in WARNings
  ARM: 6751/1: vexpress: select applicable errata workarounds in Kconfig
  ARM: 6753/1: omap4: Enable ARM local timers with OMAP4430 es1.0 exception
  ARM: 6759/1: smp: Select local timers vs broadcast timer support runtime
  ARM: pgtable: add pud-level code
  ARM: 6673/1: LPAE: use phys_addr_t instead of unsigned long for start of membanks
  ARM: Use long long format when printing meminfo physical addresses
  ARM: integrator: add Integrator/CP sched_clock support
  ARM: realview/vexpress: consolidate SMP bringup code
  ARM: realview/vexpress: consolidate localtimer support
  ARM: integrator/versatile: consolidate FPGA IRQ handling code
  ARM: rationalize versatile family Kconfig/Makefile
  ARM: realview: remove old AMBA device DMA definitions
  ARM: versatile: remove old AMBA device DMA definitions
  ARM: vexpress: use new init_early for clock tree and sched_clock init
  ARM: realview: use new init_early for clock tree and sched_clock init
  ARM: versatile: use new init_early for clock tree and sched_clock init
  ARM: integrator: use new init_early for clock tree init
  ...
......@@ -235,6 +235,7 @@ config ARCH_INTEGRATOR
select ICST
select GENERIC_CLOCKEVENTS
select PLAT_VERSATILE
select PLAT_VERSATILE_FPGA_IRQ
help
Support for ARM's Integrator platform.
......@@ -242,11 +243,11 @@ config ARCH_REALVIEW
bool "ARM Ltd. RealView family"
select ARM_AMBA
select CLKDEV_LOOKUP
select HAVE_SCHED_CLOCK
select ICST
select GENERIC_CLOCKEVENTS
select ARCH_WANT_OPTIONAL_GPIOLIB
select PLAT_VERSATILE
select PLAT_VERSATILE_CLCD
select ARM_TIMER_SP804
select GPIO_PL061 if GPIOLIB
help
......@@ -257,11 +258,12 @@ config ARCH_VERSATILE
select ARM_AMBA
select ARM_VIC
select CLKDEV_LOOKUP
select HAVE_SCHED_CLOCK
select ICST
select GENERIC_CLOCKEVENTS
select ARCH_WANT_OPTIONAL_GPIOLIB
select PLAT_VERSATILE
select PLAT_VERSATILE_CLCD
select PLAT_VERSATILE_FPGA_IRQ
select ARM_TIMER_SP804
help
This enables support for ARM Ltd Versatile board.
......@@ -274,9 +276,10 @@ config ARCH_VEXPRESS
select CLKDEV_LOOKUP
select GENERIC_CLOCKEVENTS
select HAVE_CLK
select HAVE_SCHED_CLOCK
select HAVE_PATA_PLATFORM
select ICST
select PLAT_VERSATILE
select PLAT_VERSATILE_CLCD
help
This enables support for the ARM Ltd Versatile Express boards.
......@@ -1011,6 +1014,7 @@ source "arch/arm/mach-ux500/Kconfig"
source "arch/arm/mach-versatile/Kconfig"
source "arch/arm/mach-vexpress/Kconfig"
source "arch/arm/plat-versatile/Kconfig"
source "arch/arm/mach-vt8500/Kconfig"
......
......@@ -44,8 +44,14 @@ int local_timer_ack(void);
/*
* Setup a local timer interrupt for a CPU.
*/
void local_timer_setup(struct clock_event_device *);
int local_timer_setup(struct clock_event_device *);
#else
static inline int local_timer_setup(struct clock_event_device *evt)
{
return -ENXIO;
}
#endif
#endif
......@@ -21,6 +21,8 @@
#ifndef __ASM_OUTERCACHE_H
#define __ASM_OUTERCACHE_H
#include <linux/types.h>
struct outer_cache_fns {
void (*inv_range)(unsigned long, unsigned long);
void (*clean_range)(unsigned long, unsigned long);
......@@ -38,17 +40,17 @@ struct outer_cache_fns {
extern struct outer_cache_fns outer_cache;
static inline void outer_inv_range(unsigned long start, unsigned long end)
static inline void outer_inv_range(phys_addr_t start, phys_addr_t end)
{
if (outer_cache.inv_range)
outer_cache.inv_range(start, end);
}
static inline void outer_clean_range(unsigned long start, unsigned long end)
static inline void outer_clean_range(phys_addr_t start, phys_addr_t end)
{
if (outer_cache.clean_range)
outer_cache.clean_range(start, end);
}
static inline void outer_flush_range(unsigned long start, unsigned long end)
static inline void outer_flush_range(phys_addr_t start, phys_addr_t end)
{
if (outer_cache.flush_range)
outer_cache.flush_range(start, end);
......@@ -74,11 +76,11 @@ static inline void outer_disable(void)
#else
static inline void outer_inv_range(unsigned long start, unsigned long end)
static inline void outer_inv_range(phys_addr_t start, phys_addr_t end)
{ }
static inline void outer_clean_range(unsigned long start, unsigned long end)
static inline void outer_clean_range(phys_addr_t start, phys_addr_t end)
{ }
static inline void outer_flush_range(unsigned long start, unsigned long end)
static inline void outer_flush_range(phys_addr_t start, phys_addr_t end)
{ }
static inline void outer_flush_all(void) { }
static inline void outer_inv_all(void) { }
......
......@@ -301,6 +301,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
#define pgd_present(pgd) (1)
#define pgd_clear(pgdp) do { } while (0)
#define set_pgd(pgd,pgdp) do { } while (0)
#define set_pud(pud,pudp) do { } while (0)
/* Find an entry in the second-level page table.. */
......@@ -351,7 +352,7 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
#define pte_unmap(pte) __pte_unmap(pte)
#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
#define pfn_pte(pfn,prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
#define pfn_pte(pfn,prot) __pte(__pfn_to_phys(pfn) | pgprot_val(prot))
#define pte_page(pte) pfn_to_page(pte_pfn(pte))
#define mk_pte(page,prot) pfn_pte(page_to_pfn(page), prot)
......
......@@ -195,7 +195,7 @@ static struct tagtable __tagtable_##fn __tag = { tag, fn }
#define NR_BANKS 8
struct membank {
unsigned long start;
phys_addr_t start;
unsigned long size;
unsigned int highmem;
};
......
......@@ -238,8 +238,8 @@ static int enable_monitor_mode(void)
ARM_DBG_READ(c1, 0, dscr);
/* Ensure that halting mode is disabled. */
if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN, "halting debug mode enabled."
"Unable to access hardware resources.")) {
if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN,
"halting debug mode enabled. Unable to access hardware resources.\n")) {
ret = -EPERM;
goto out;
}
......@@ -377,7 +377,7 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
}
}
if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot")) {
if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n")) {
ret = -EBUSY;
goto out;
}
......@@ -423,7 +423,7 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp)
}
}
if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot"))
if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n"))
return;
/* Reset the control register. */
......@@ -635,7 +635,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
if (WARN_ONCE(!bp->overflow_handler &&
(arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_brps()
|| !bp->hw.bp_target),
"overflow handler required but none found")) {
"overflow handler required but none found\n")) {
ret = -EINVAL;
}
out:
......@@ -936,8 +936,8 @@ static int __init arch_hw_breakpoint_init(void)
ARM_DBG_READ(c1, 0, dscr);
if (dscr & ARM_DSCR_HDBGEN) {
max_watchpoint_len = 4;
pr_warning("halting debug mode enabled. Assuming maximum "
"watchpoint size of %u bytes.", max_watchpoint_len);
pr_warning("halting debug mode enabled. Assuming maximum watchpoint size of %u bytes.\n",
max_watchpoint_len);
} else {
/* Work out the maximum supported watchpoint length. */
max_watchpoint_len = get_max_wp_len();
......
......@@ -466,13 +466,13 @@ static struct machine_desc * __init setup_machine(unsigned int nr)
/* can't use cpu_relax() here as it may require MMU setup */;
}
static int __init arm_add_memory(unsigned long start, unsigned long size)
static int __init arm_add_memory(phys_addr_t start, unsigned long size)
{
struct membank *bank = &meminfo.bank[meminfo.nr_banks];
if (meminfo.nr_banks >= NR_BANKS) {
printk(KERN_CRIT "NR_BANKS too low, "
"ignoring memory at %#lx\n", start);
"ignoring memory at 0x%08llx\n", (long long)start);
return -EINVAL;
}
......@@ -502,7 +502,8 @@ static int __init arm_add_memory(unsigned long start, unsigned long size)
static int __init early_mem(char *p)
{
static int usermem __initdata = 0;
unsigned long size, start;
unsigned long size;
phys_addr_t start;
char *endp;
/*
......
......@@ -474,13 +474,12 @@ static void smp_timer_broadcast(const struct cpumask *mask)
#define smp_timer_broadcast NULL
#endif
#ifndef CONFIG_LOCAL_TIMERS
static void broadcast_timer_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
}
static void local_timer_setup(struct clock_event_device *evt)
static void broadcast_timer_setup(struct clock_event_device *evt)
{
evt->name = "dummy_timer";
evt->features = CLOCK_EVT_FEAT_ONESHOT |
......@@ -492,7 +491,6 @@ static void local_timer_setup(struct clock_event_device *evt)
clockevents_register_device(evt);
}
#endif
void __cpuinit percpu_timer_setup(void)
{
......@@ -502,7 +500,8 @@ void __cpuinit percpu_timer_setup(void)
evt->cpumask = cpumask_of(cpu);
evt->broadcast = smp_timer_broadcast;
local_timer_setup(evt);
if (local_timer_setup(evt))
broadcast_timer_setup(evt);
}
#ifdef CONFIG_HOTPLUG_CPU
......
......@@ -712,17 +712,17 @@ EXPORT_SYMBOL(__readwrite_bug);
void __pte_error(const char *file, int line, pte_t pte)
{
printk("%s:%d: bad pte %08lx.\n", file, line, pte_val(pte));
printk("%s:%d: bad pte %08llx.\n", file, line, (long long)pte_val(pte));
}
void __pmd_error(const char *file, int line, pmd_t pmd)
{
printk("%s:%d: bad pmd %08lx.\n", file, line, pmd_val(pmd));
printk("%s:%d: bad pmd %08llx.\n", file, line, (long long)pmd_val(pmd));
}
void __pgd_error(const char *file, int line, pgd_t pgd)
{
printk("%s:%d: bad pgd %08lx.\n", file, line, pgd_val(pgd));
printk("%s:%d: bad pgd %08llx.\n", file, line, (long long)pgd_val(pgd));
}
asmlinkage void __div0(void)
......
......@@ -27,13 +27,18 @@ pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
pud_t *pud;
spinlock_t *ptl;
pgd = pgd_offset(current->mm, addr);
if (unlikely(pgd_none(*pgd) || pgd_bad(*pgd)))
return 0;
pmd = pmd_offset(pgd, addr);
pud = pud_offset(pgd, addr);
if (unlikely(pud_none(*pud) || pud_bad(*pud)))
return 0;
pmd = pmd_offset(pud, addr);
if (unlikely(pmd_none(*pmd) || pmd_bad(*pmd)))
return 0;
......
......@@ -18,8 +18,9 @@
/*
* Setup the local clock events for a CPU.
*/
void __cpuinit local_timer_setup(struct clock_event_device *evt)
int __cpuinit local_timer_setup(struct clock_event_device *evt)
{
evt->irq = IRQ_LOCALTIMER;
twd_timer_setup(evt);
return 0;
}
......@@ -13,6 +13,7 @@ config ARCH_INTEGRATOR_CP
bool "Support Integrator/CP platform"
select ARCH_CINTEGRATOR
select ARM_TIMER_SP804
select PLAT_VERSATILE_CLCD
help
Include support for the ARM(R) Integrator CP platform.
......
void integrator_init_early(void);
void integrator_reserve(void);
......@@ -144,12 +144,15 @@ static struct clk_lookup lookups[] = {
}
};
void __init integrator_init_early(void)
{
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
}
static int __init integrator_init(void)
{
int i;
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
struct amba_device *d = amba_devs[i];
amba_device_register(d, &iomem_resource);
......
......@@ -121,6 +121,7 @@ static struct clcd_panel vga = {
.height = -1,
.tim2 = TIM2_BCD | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
.caps = CLCD_CAP_5551,
.connector = IMPD1_CTRL_DISP_VGA,
.bpp = 16,
.grayscale = 0,
......@@ -149,6 +150,7 @@ static struct clcd_panel svga = {
.tim2 = TIM2_BCD,
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
.connector = IMPD1_CTRL_DISP_VGA,
.caps = CLCD_CAP_5551,
.bpp = 16,
.grayscale = 0,
};
......@@ -175,6 +177,7 @@ static struct clcd_panel prospector = {
.height = -1,
.tim2 = TIM2_BCD,
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
.caps = CLCD_CAP_5551,
.fixedtimings = 1,
.connector = IMPD1_CTRL_DISP_LCD,
.bpp = 16,
......@@ -206,6 +209,7 @@ static struct clcd_panel ltm10c209 = {
.height = -1,
.tim2 = TIM2_BCD,
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
.caps = CLCD_CAP_5551,
.fixedtimings = 1,
.connector = IMPD1_CTRL_DISP_LCD,
.bpp = 16,
......@@ -279,6 +283,7 @@ static void impd1fb_clcd_remove(struct clcd_fb *fb)
static struct clcd_board impd1_clcd_data = {
.name = "IM-PD/1",
.caps = CLCD_CAP_5551 | CLCD_CAP_888,
.check = clcdfb_check,
.decode = clcdfb_decode,
.disable = impd1fb_clcd_disable,
......
......@@ -24,9 +24,9 @@ void cm_control(u32, u32);
#define CM_CTRL_LCDBIASDN (1 << 10)
#define CM_CTRL_LCDMUXSEL_MASK (7 << 11)
#define CM_CTRL_LCDMUXSEL_GENLCD (1 << 11)
#define CM_CTRL_LCDMUXSEL_VGA_16BPP (2 << 11)
#define CM_CTRL_LCDMUXSEL_VGA565_TFT555 (2 << 11)
#define CM_CTRL_LCDMUXSEL_SHARPLCD (3 << 11)
#define CM_CTRL_LCDMUXSEL_VGA_8421BPP (4 << 11)
#define CM_CTRL_LCDMUXSEL_VGA555_TFT555 (4 << 11)
#define CM_CTRL_LCDEN0 (1 << 14)
#define CM_CTRL_LCDEN1 (1 << 15)
#define CM_CTRL_STATIC1 (1 << 16)
......
......@@ -48,6 +48,8 @@
#include <asm/mach/map.h>
#include <asm/mach/time.h>
#include <plat/fpga-irq.h>
#include "common.h"
/*
......@@ -57,10 +59,10 @@
* Setup a VA for the Integrator interrupt controller (for header #0,
* just for now).
*/
#define VA_IC_BASE IO_ADDRESS(INTEGRATOR_IC_BASE)
#define VA_SC_BASE IO_ADDRESS(INTEGRATOR_SC_BASE)
#define VA_EBI_BASE IO_ADDRESS(INTEGRATOR_EBI_BASE)
#define VA_CMIC_BASE IO_ADDRESS(INTEGRATOR_HDR_IC)
#define VA_IC_BASE __io_address(INTEGRATOR_IC_BASE)
#define VA_SC_BASE __io_address(INTEGRATOR_SC_BASE)
#define VA_EBI_BASE __io_address(INTEGRATOR_EBI_BASE)
#define VA_CMIC_BASE __io_address(INTEGRATOR_HDR_IC)
/*
* Logical Physical
......@@ -156,27 +158,14 @@ static void __init ap_map_io(void)
#define INTEGRATOR_SC_VALID_INT 0x003fffff
static void sc_mask_irq(struct irq_data *d)
{
writel(1 << d->irq, VA_IC_BASE + IRQ_ENABLE_CLEAR);
}
static void sc_unmask_irq(struct irq_data *d)
{
writel(1 << d->irq, VA_IC_BASE + IRQ_ENABLE_SET);
}
static struct irq_chip sc_chip = {
.name = "SC",
.irq_ack = sc_mask_irq,
.irq_mask = sc_mask_irq,
.irq_unmask = sc_unmask_irq,
static struct fpga_irq_data sc_irq_data = {
.base = VA_IC_BASE,
.irq_start = 0,
.chip.name = "SC",
};
static void __init ap_init_irq(void)
{
unsigned int i;
/* Disable all interrupts initially. */
/* Do the core module ones */
writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
......@@ -185,13 +174,7 @@ static void __init ap_init_irq(void)
writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
for (i = 0; i < NR_IRQS; i++) {
if (((1 << i) & INTEGRATOR_SC_VALID_INT) != 0) {
set_irq_chip(i, &sc_chip);
set_irq_handler(i, handle_level_irq);
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
}
}
fpga_irq_init(-1, INTEGRATOR_SC_VALID_INT, &sc_irq_data);
}
#ifdef CONFIG_PM
......@@ -282,7 +265,7 @@ static void ap_flash_exit(void)
static void ap_flash_set_vpp(int on)
{
unsigned long reg = on ? SC_CTRLS : SC_CTRLC;
void __iomem *reg = on ? SC_CTRLS : SC_CTRLC;
writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg);
}
......@@ -499,8 +482,9 @@ static struct sys_timer ap_timer = {
MACHINE_START(INTEGRATOR, "ARM-Integrator")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
.boot_params = 0x00000100,
.map_io = ap_map_io,
.reserve = integrator_reserve,
.map_io = ap_map_io,
.init_early = integrator_init_early,
.init_irq = ap_init_irq,
.timer = &ap_timer,
.init_machine = ap_init,
......
......@@ -42,6 +42,10 @@
#include <asm/hardware/timer-sp.h>
#include <plat/clcd.h>
#include <plat/fpga-irq.h>
#include <plat/sched_clock.h>
#include "common.h"
#define INTCP_PA_FLASH_BASE 0x24000000
......@@ -49,9 +53,9 @@
#define INTCP_PA_CLCD_BASE 0xc0000000
#define INTCP_VA_CIC_BASE IO_ADDRESS(INTEGRATOR_HDR_BASE + 0x40)
#define INTCP_VA_PIC_BASE IO_ADDRESS(INTEGRATOR_IC_BASE)
#define INTCP_VA_SIC_BASE IO_ADDRESS(INTEGRATOR_CP_SIC_BASE)
#define INTCP_VA_CIC_BASE __io_address(INTEGRATOR_HDR_BASE + 0x40)
#define INTCP_VA_PIC_BASE __io_address(INTEGRATOR_IC_BASE)
#define INTCP_VA_SIC_BASE __io_address(INTEGRATOR_CP_SIC_BASE)
#define INTCP_ETH_SIZE 0x10
......@@ -139,129 +143,48 @@ static void __init intcp_map_io(void)
iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc));
}
#define cic_writel __raw_writel
#define cic_readl __raw_readl
#define pic_writel __raw_writel
#define pic_readl __raw_readl
#define sic_writel __raw_writel
#define sic_readl __raw_readl
static void cic_mask_irq(struct irq_data *d)
{
unsigned int irq = d->irq - IRQ_CIC_START;
cic_writel(1 << irq, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
}
static void cic_unmask_irq(struct irq_data *d)
{
unsigned int irq = d->irq - IRQ_CIC_START;
cic_writel(1 << irq, INTCP_VA_CIC_BASE + IRQ_ENABLE_SET);
}
static struct irq_chip cic_chip = {
.name = "CIC",
.irq_ack = cic_mask_irq,
.irq_mask = cic_mask_irq,
.irq_unmask = cic_unmask_irq,
static struct fpga_irq_data cic_irq_data = {
.base = INTCP_VA_CIC_BASE,
.irq_start = IRQ_CIC_START,
.chip.name = "CIC",
};
static void pic_mask_irq(struct irq_data *d)
{
unsigned int irq = d->irq - IRQ_PIC_START;
pic_writel(1 << irq, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);
}
static void pic_unmask_irq(struct irq_data *d)
{
unsigned int irq = d->irq - IRQ_PIC_START;
pic_writel(1 << irq, INTCP_VA_PIC_BASE + IRQ_ENABLE_SET);
}
static struct irq_chip pic_chip = {
.name = "PIC",
.irq_ack = pic_mask_irq,
.irq_mask = pic_mask_irq,
.irq_unmask = pic_unmask_irq,
static struct fpga_irq_data pic_irq_data = {
.base = INTCP_VA_PIC_BASE,
.irq_start = IRQ_PIC_START,
.chip.name = "PIC",
};
static void sic_mask_irq(struct irq_data *d)
{
unsigned int irq = d->irq - IRQ_SIC_START;
sic_writel(1 << irq, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
}
static void sic_unmask_irq(struct irq_data *d)
{
unsigned int irq = d->irq - IRQ_SIC_START;
sic_writel(1 << irq, INTCP_VA_SIC_BASE + IRQ_ENABLE_SET);
}
static struct irq_chip sic_chip = {
.name = "SIC",
.irq_ack = sic_mask_irq,
.irq_mask = sic_mask_irq,
.irq_unmask = sic_unmask_irq,
static struct fpga_irq_data sic_irq_data = {
.base = INTCP_VA_SIC_BASE,
.irq_start = IRQ_SIC_START,
.chip.name = "SIC",
};
static void
sic_handle_irq(unsigned int irq, struct irq_desc *desc)
{
unsigned long status = sic_readl(INTCP_VA_SIC_BASE + IRQ_STATUS);
if (status == 0) {
do_bad_IRQ(irq, desc);
return;
}
do {
irq = ffs(status) - 1;
status &= ~(1 << irq);
irq += IRQ_SIC_START;
generic_handle_irq(irq);
} while (status);
}
static void __init intcp_init_irq(void)
{
unsigned int i;
u32 pic_mask, sic_mask;
pic_mask = ~((~0u) << (11 - IRQ_PIC_START));
pic_mask |= (~((~0u) << (29 - 22))) << 22;
sic_mask = ~((~0u) << (1 + IRQ_SIC_END - IRQ_SIC_START));
/*
* Disable all interrupt sources
*/
pic_writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);
pic_writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR);
for (i = IRQ_PIC_START; i <= IRQ_PIC_END; i++) {
if (i == 11)
i = 22;
if (i == 29)
break;
set_irq_chip(i, &pic_chip);
set_irq_handler(i, handle_level_irq);
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
}
writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);
writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR);
writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR);
writel(sic_mask, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
writel(sic_mask, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR);
cic_writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
cic_writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR);
fpga_irq_init(-1, pic_mask, &pic_irq_data);
for (i = IRQ_CIC_START; i <= IRQ_CIC_END; i++) {
set_irq_chip(i, &cic_chip);
set_irq_handler(i, handle_level_irq);
set_irq_flags(i, IRQF_VALID);
}
sic_writel(0x00000fff, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
sic_writel(0x00000fff, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR);
for (i = IRQ_SIC_START; i <= IRQ_SIC_END; i++) {
set_irq_chip(i, &sic_chip);
set_irq_handler(i, handle_level_irq);
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
}
fpga_irq_init(-1, ~((~0u) << (1 + IRQ_CIC_END - IRQ_CIC_START)),
&cic_irq_data);
set_irq_chained_handler(IRQ_CP_CPPLDINT, sic_handle_irq);
fpga_irq_init(IRQ_CP_CPPLDINT, sic_mask, &sic_irq_data);
}
/*
......@@ -449,43 +372,21 @@ static struct amba_device aaci_device = {
/*
* CLCD support
*/
static struct clcd_panel vga = {
.mode = {
.name = "VGA",
.refresh = 60,
.xres = 640,
.yres = 480,
.pixclock = 39721,
.left_margin = 40,
.right_margin = 24,
.upper_margin = 32,
.lower_margin = 11,
.hsync_len = 96,
.vsync_len = 2,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
.bpp = 16,
.grayscale = 0,
};
/*
* Ensure VGA is selected.
*/
static void cp_clcd_enable(struct clcd_fb *fb)
{
u32 val;
struct fb_var_screeninfo *var = &fb->fb.var;
u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2;
if (fb->fb.var.bits_per_pixel <= 8)
val = CM_CTRL_LCDMUXSEL_VGA_8421BPP;
if (var->bits_per_pixel <= 8 ||
(var->bits_per_pixel == 16 && var->green.length == 5))
/* Pseudocolor, RGB555, BGR555 */
val |= CM_CTRL_LCDMUXSEL_VGA555_TFT555;
else if (fb->fb.var.bits_per_pixel <= 16)
val = CM_CTRL_LCDMUXSEL_VGA_16BPP
| CM_CTRL_LCDEN0 | CM_CTRL_LCDEN1
| CM_CTRL_STATIC1 | CM_CTRL_STATIC2;
/* truecolor RGB565 */
val |= CM_CTRL_LCDMUXSEL_VGA565_TFT555;
else
val = 0; /* no idea for this, don't trust the docs */
......@@ -498,49 +399,24 @@ static void cp_clcd_enable(struct clcd_fb *fb)
CM_CTRL_n24BITEN, val);
}
static unsigned long framesize = SZ_1M;
static int cp_clcd_setup(struct clcd_fb *fb)
{
dma_addr_t dma;
fb->panel = &vga;
fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
&dma, GFP_KERNEL);
if (!fb->fb.screen_base) {
printk(KERN_ERR "CLCD: unable to map framebuffer\n");
return -ENOMEM;
}
fb->fb.fix.smem_start = dma;
fb->fb.fix.smem_len = framesize;
return 0;
}
static int cp_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
{
return dma_mmap_writecombine(&fb->dev->dev, vma,
fb->fb.screen_base,
fb->fb.fix.smem_start,
fb->fb.fix.smem_len);
}
fb->panel = versatile_clcd_get_panel("VGA");
if (!fb->panel)
return -EINVAL;
static void cp_clcd_remove(struct clcd_fb *fb)
{
dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
fb->fb.screen_base, fb->fb.fix.smem_start);
return versatile_clcd_setup_dma(fb, SZ_1M);
}
static struct clcd_board clcd_data = {
.name = "Integrator/CP",
.caps = CLCD_CAP_5551 | CLCD_CAP_RGB565 | CLCD_CAP_888,
.check = clcdfb_check,
.decode = clcdfb_decode,
.enable = cp_clcd_enable,
.setup = cp_clcd_setup,
.mmap = cp_clcd_mmap,
.remove = cp_clcd_remove,
.mmap = versatile_clcd_mmap_dma,
.remove = versatile_clcd_remove_dma,
};
static struct amba_device clcd_device = {
......@@ -565,11 +441,23 @@ static struct amba_device *amba_devs[] __initdata = {
&clcd_device,
};
#define REFCOUNTER (__io_address(INTEGRATOR_HDR_BASE) + 0x28)
static void __init intcp_init_early(void)
{
clkdev_add_table(cp_lookups, ARRAY_SIZE(cp_lookups));
integrator_init_early();
#ifdef CONFIG_PLAT_VERSATILE_SCHED_CLOCK
versatile_sched_clock_init(REFCOUNTER, 24000000);
#endif
}
static void __init intcp_init(void)
{
int i;
clkdev_add_table(cp_lookups, ARRAY_SIZE(cp_lookups));
platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs));
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
......@@ -599,8 +487,9 @@ static struct sys_timer cp_timer = {
MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
.boot_params = 0x00000100,
.map_io = intcp_map_io,
.reserve = integrator_reserve,
.map_io = intcp_map_io,
.init_early = intcp_init_early,
.init_irq = intcp_init_irq,
.timer = &cp_timer,
.init_machine = intcp_init,
......
......@@ -263,7 +263,7 @@ static void __init msm_timer_init(void)
}
#ifdef CONFIG_SMP
void __cpuinit local_timer_setup(struct clock_event_device *evt)
int __cpuinit local_timer_setup(struct clock_event_device *evt)
{
struct msm_clock *clock = &msm_clocks[MSM_GLOBAL_TIMER];
......@@ -295,6 +295,7 @@ void __cpuinit local_timer_setup(struct clock_event_device *evt)
gic_enable_ppi(clock->irq.irq);
clockevents_register_device(evt);
return 0;
}
inline int local_timer_ack(void)
......
......@@ -44,6 +44,7 @@ config ARCH_OMAP4
depends on ARCH_OMAP2PLUS
select CPU_V7
select ARM_GIC
select LOCAL_TIMERS if SMP
select PL310_ERRATA_588369
select PL310_ERRATA_727915
select ARM_ERRATA_720789
......
......@@ -26,9 +26,14 @@
/*
* Setup the local clock events for a CPU.
*/
void __cpuinit local_timer_setup(struct clock_event_device *evt)
int __cpuinit local_timer_setup(struct clock_event_device *evt)
{
/* Local timers are not supprted on OMAP4430 ES1.0 */
if (omap_rev() == OMAP4430_REV_ES1_0)
return -ENXIO;
evt->irq = OMAP44XX_IRQ_LOCALTIMER;
twd_timer_setup(evt);
return 0;
}
......@@ -8,6 +8,5 @@ obj-$(CONFIG_MACH_REALVIEW_PB11MP) += realview_pb11mp.o
obj-$(CONFIG_MACH_REALVIEW_PB1176) += realview_pb1176.o
obj-$(CONFIG_MACH_REALVIEW_PBA8) += realview_pba8.o
obj-$(CONFIG_MACH_REALVIEW_PBX) += realview_pbx.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
obj-$(CONFIG_SMP) += platsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
......@@ -51,6 +51,7 @@
#include <mach/irqs.h>
#include <asm/hardware/timer-sp.h>
#include <plat/clcd.h>
#include <plat/sched_clock.h>
#include "core.h"
......@@ -359,18 +360,19 @@ static struct clk_lookup lookups[] = {
}
};
static int __init clk_init(void)
void __init realview_init_early(void)
{
void __iomem *sys = __io_address(REALVIEW_SYS_BASE);
if (machine_is_realview_pb1176())
oscvco_clk.vcoreg = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC0_OFFSET;
oscvco_clk.vcoreg = sys + REALVIEW_SYS_OSC0_OFFSET;
else
oscvco_clk.vcoreg = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC4_OFFSET;
oscvco_clk.vcoreg = sys + REALVIEW_SYS_OSC4_OFFSET;
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
return 0;
versatile_sched_clock_init(sys + REALVIEW_SYS_24MHz_OFFSET, 24000000);
}
core_initcall(clk_init);
/*
* CLCD support.
......@@ -385,157 +387,6 @@ core_initcall(clk_init);
#define SYS_CLCD_ID_SANYO_2_5 (0x07 << 8)
#define SYS_CLCD_ID_VGA (0x1f << 8)
static struct clcd_panel vga = {
.mode = {
.name = "VGA",
.refresh = 60,
.xres = 640,
.yres = 480,
.pixclock = 39721,
.left_margin = 40,
.right_margin = 24,
.upper_margin = 32,
.lower_margin = 11,
.hsync_len = 96,
.vsync_len = 2,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
.bpp = 16,
};
static struct clcd_panel xvga = {
.mode = {
.name = "XVGA",
.refresh = 60,
.xres = 1024,
.yres = 768,
.pixclock = 15748,
.left_margin = 152,
.right_margin = 48,
.upper_margin = 23,
.lower_margin = 3,
.hsync_len = 104,
.vsync_len = 4,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
.bpp = 16,
};
static struct clcd_panel sanyo_3_8_in = {
.mode = {
.name = "Sanyo QVGA",
.refresh = 116,
.xres = 320,
.yres = 240,
.pixclock = 100000,
.left_margin = 6,
.right_margin = 6,
.upper_margin = 5,
.lower_margin = 5,
.hsync_len = 6,
.vsync_len = 6,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD,
.cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
.bpp = 16,
};
static struct clcd_panel sanyo_2_5_in = {
.mode = {
.name = "Sanyo QVGA Portrait",
.refresh = 116,
.xres = 240,
.yres = 320,
.pixclock = 100000,
.left_margin = 20,
.right_margin = 10,
.upper_margin = 2,
.lower_margin = 2,
.hsync_len = 10,
.vsync_len = 2,
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_IVS | TIM2_IHS | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
.bpp = 16,
};
static struct clcd_panel epson_2_2_in = {
.mode = {
.name = "Epson QCIF",
.refresh = 390,
.xres = 176,
.yres = 220,
.pixclock = 62500,
.left_margin = 3,
.right_margin = 2,
.upper_margin = 1,
.lower_margin = 0,
.hsync_len = 3,
.vsync_len = 2,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
.bpp = 16,
};
/*
* Detect which LCD panel is connected, and return the appropriate
* clcd_panel structure. Note: we do not have any information on
* the required timings for the 8.4in panel, so we presently assume
* VGA timings.
*/
static struct clcd_panel *realview_clcd_panel(void)
{
void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET;
struct clcd_panel *vga_panel;
struct clcd_panel *panel;
u32 val;
if (machine_is_realview_eb())
vga_panel = &vga;
else
vga_panel = &xvga;
val = readl(sys_clcd) & SYS_CLCD_ID_MASK;
if (val == SYS_CLCD_ID_SANYO_3_8)
panel = &sanyo_3_8_in;
else if (val == SYS_CLCD_ID_SANYO_2_5)
panel = &sanyo_2_5_in;
else if (val == SYS_CLCD_ID_EPSON_2_2)
panel = &epson_2_2_in;
else if (val == SYS_CLCD_ID_VGA)
panel = vga_panel;
else {
printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n",
val);
panel = vga_panel;
}
return panel;
}
/*
* Disable all display connectors on the interface module.
*/
......@@ -565,56 +416,60 @@ static void realview_clcd_enable(struct clcd_fb *fb)
writel(val, sys_clcd);
}
/*
* Detect which LCD panel is connected, and return the appropriate
* clcd_panel structure. Note: we do not have any information on
* the required timings for the 8.4in panel, so we presently assume
* VGA timings.
*/
static int realview_clcd_setup(struct clcd_fb *fb)
{
void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET;
const char *panel_name, *vga_panel_name;
unsigned long framesize;
dma_addr_t dma;
u32 val;
if (machine_is_realview_eb())
if (machine_is_realview_eb()) {
/* VGA, 16bpp */
framesize = 640 * 480 * 2;
else
vga_panel_name = "VGA";
} else {
/* XVGA, 16bpp */
framesize = 1024 * 768 * 2;
fb->panel = realview_clcd_panel();
fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
&dma, GFP_KERNEL | GFP_DMA);
if (!fb->fb.screen_base) {
printk(KERN_ERR "CLCD: unable to map framebuffer\n");
return -ENOMEM;
vga_panel_name = "XVGA";
}
fb->fb.fix.smem_start = dma;
fb->fb.fix.smem_len = framesize;
return 0;
}
val = readl(sys_clcd) & SYS_CLCD_ID_MASK;
if (val == SYS_CLCD_ID_SANYO_3_8)
panel_name = "Sanyo TM38QV67A02A";
else if (val == SYS_CLCD_ID_SANYO_2_5)
panel_name = "Sanyo QVGA Portrait";
else if (val == SYS_CLCD_ID_EPSON_2_2)
panel_name = "Epson L2F50113T00";
else if (val == SYS_CLCD_ID_VGA)
panel_name = vga_panel_name;
else {
pr_err("CLCD: unknown LCD panel ID 0x%08x, using VGA\n", val);
panel_name = vga_panel_name;
}
static int realview_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
{
return dma_mmap_writecombine(&fb->dev->dev, vma,
fb->fb.screen_base,
fb->fb.fix.smem_start,
fb->fb.fix.smem_len);
}
fb->panel = versatile_clcd_get_panel(panel_name);
if (!fb->panel)
return -EINVAL;
static void realview_clcd_remove(struct clcd_fb *fb)
{
dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
fb->fb.screen_base, fb->fb.fix.smem_start);
return versatile_clcd_setup_dma(fb, framesize);
}
struct clcd_board clcd_plat_data = {
.name = "RealView",
.caps = CLCD_CAP_ALL,
.check = clcdfb_check,
.decode = clcdfb_decode,
.disable = realview_clcd_disable,
.enable = realview_clcd_enable,
.setup = realview_clcd_setup,
.mmap = realview_clcd_mmap,
.remove = realview_clcd_remove,
.mmap = versatile_clcd_mmap_dma,
.remove = versatile_clcd_remove_dma,
};
#ifdef CONFIG_LEDS
......@@ -655,12 +510,6 @@ void realview_leds_event(led_event_t ledevt)
}
#endif /* CONFIG_LEDS */
/*
* The sched_clock counter
*/
#define REFCOUNTER (__io_address(REALVIEW_SYS_BASE) + \
REALVIEW_SYS_24MHz_OFFSET)
/*
* Where is the timer (VA)?
*/
......@@ -676,8 +525,6 @@ void __init realview_timer_init(unsigned int timer_irq)
{
u32 val;
versatile_sched_clock_init(REFCOUNTER, 24000000);
/*
* set clock frequency:
* REALVIEW_REFCLK is 32KHz
......
......@@ -42,7 +42,6 @@ static struct amba_device name##_device = { \
}, \
.dma_mask = ~0, \
.irq = base##_IRQ, \
/* .dma = base##_DMA,*/ \
}
struct machine_desc;
......@@ -63,6 +62,7 @@ extern void realview_timer_init(unsigned int timer_irq);
extern int realview_flash_register(struct resource *res, u32 num);
extern int realview_eth_register(const char *name, struct resource *res);
extern int realview_usb_register(struct resource *res);
extern void realview_init_early(void);
extern void realview_fixup(struct machine_desc *mdesc, struct tag *tags,
char **from, struct meminfo *meminfo);
extern void (*realview_reset)(char);
......
/*
* linux/arch/arm/mach-realview/headsmp.S
*
* Copyright (c) 2003 ARM Limited
* All Rights Reserved
*
* 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/linkage.h>
#include <linux/init.h>
__INIT
/*
* Realview specific entry point for secondary CPUs. This provides
* a "holding pen" into which all secondary cores are held until we're
* ready for them to initialise.
*/
ENTRY(realview_secondary_startup)
mrc p15, 0, r0, c0, c0, 5
and r0, r0, #15
adr r4, 1f
ldmia r4, {r5, r6}
sub r4, r4, r5
add r6, r6, r4
pen: ldr r7, [r6]
cmp r7, r0
bne pen
/*
* we've been released from the holding pen: secondary_stack
* should now contain the SVC stack for this core
*/
b secondary_startup
.align
1: .long .
.long pen_release
/*
* linux/arch/arm/mach-realview/localtimer.c
*
* Copyright (C) 2002 ARM Ltd.
* All Rights Reserved
*
* 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/init.h>
#include <linux/smp.h>
#include <linux/clockchips.h>
#include <asm/irq.h>
#include <asm/smp_twd.h>
#include <asm/localtimer.h>
/*
* Setup the local clock events for a CPU.
*/
void __cpuinit local_timer_setup(struct clock_event_device *evt)
{
evt->irq = IRQ_LOCALTIMER;
twd_timer_setup(evt);
}
......@@ -10,44 +10,21 @@
*/
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/jiffies.h>
#include <linux/smp.h>
#include <linux/io.h>
#include <asm/cacheflush.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
#include <asm/smp_scu.h>
#include <asm/unified.h>
#include <mach/board-eb.h>
#include <mach/board-pb11mp.h>
#include <mach/board-pbx.h>
#include <asm/smp_scu.h>
#include "core.h"
extern void realview_secondary_startup(void);
/*
* control for which core is the next to come out of the secondary
* boot "holding pen"
*/
volatile int __cpuinitdata pen_release = -1;
/*
* Write pen_release in a way that is guaranteed to be visible to all
* observers, irrespective of whether they're taking part in coherency
* or not. This is necessary for the hotplug code to work reliably.
*/
static void __cpuinit write_pen_release(int val)
{
pen_release = val;
smp_wmb();
__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
}
extern void versatile_secondary_startup(void);
static void __iomem *scu_base_addr(void)
{
......@@ -62,75 +39,6 @@ static void __iomem *scu_base_addr(void)
return (void __iomem *)0;
}
static DEFINE_SPINLOCK(boot_lock);
void __cpuinit platform_secondary_init(unsigned int cpu)
{
/*
* if any interrupts are already enabled for the primary
* core (e.g. timer irq), then they will not have been enabled
* for us: do so
*/
gic_secondary_init(0);
/*
* let the primary processor know we're out of the
* pen, then head off into the C entry point
*/
write_pen_release(-1);
/*
* Synchronise with the boot thread.
*/
spin_lock(&boot_lock);
spin_unlock(&boot_lock);
}
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
{
unsigned long timeout;
/*
* set synchronisation state between this boot processor
* and the secondary one
*/
spin_lock(&boot_lock);
/*
* The secondary processor is waiting to be released from
* the holding pen - release it, then wait for it to flag
* that it has been released by resetting pen_release.
*
* Note that "pen_release" is the hardware CPU ID, whereas
* "cpu" is Linux's internal ID.
*/
write_pen_release(cpu);
/*
* Send the secondary CPU a soft interrupt, thereby causing
* the boot monitor to read the system wide flags register,
* and branch to the address found there.
*/
smp_cross_call(cpumask_of(cpu), 1);
timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) {
smp_rmb();
if (pen_release == -1)
break;
udelay(10);
}
/*
* now the secondary core is starting up let it run its
* calibrations, then wait for it to finish
*/
spin_unlock(&boot_lock);
return pen_release != -1 ? -ENOSYS : 0;
}
/*
* Initialise the CPU possible map early - this describes the CPUs
* which may be present or become present in the system.
......@@ -174,6 +82,6 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
* until it receives a soft interrupt, and then the
* secondary CPU branches to this address.
*/
__raw_writel(BSYM(virt_to_phys(realview_secondary_startup)),
__raw_writel(BSYM(virt_to_phys(versatile_secondary_startup)),
__io_address(REALVIEW_SYS_FLAGSSET));
}
......@@ -144,60 +144,39 @@ static struct pl022_ssp_controller ssp0_plat_data = {
* These devices are connected via the core APB bridge
*/
#define GPIO2_IRQ { IRQ_EB_GPIO2, NO_IRQ }
#define GPIO2_DMA { 0, 0 }
#define GPIO3_IRQ { IRQ_EB_GPIO3, NO_IRQ }
#define GPIO3_DMA { 0, 0 }
#define AACI_IRQ { IRQ_EB_AACI, NO_IRQ }
#define AACI_DMA { 0x80, 0x81 }
#define MMCI0_IRQ { IRQ_EB_MMCI0A, IRQ_EB_MMCI0B }
#define MMCI0_DMA { 0x84, 0 }
#define KMI0_IRQ { IRQ_EB_KMI0, NO_IRQ }
#define KMI0_DMA { 0, 0 }
#define KMI1_IRQ { IRQ_EB_KMI1, NO_IRQ }
#define KMI1_DMA { 0, 0 }
/*
* These devices are connected directly to the multi-layer AHB switch
*/
#define EB_SMC_IRQ { NO_IRQ, NO_IRQ }
#define EB_SMC_DMA { 0, 0 }
#define MPMC_IRQ { NO_IRQ, NO_IRQ }
#define MPMC_DMA { 0, 0 }
#define EB_CLCD_IRQ { IRQ_EB_CLCD, NO_IRQ }
#define EB_CLCD_DMA { 0, 0 }
#define DMAC_IRQ { IRQ_EB_DMA, NO_IRQ }
#define DMAC_DMA { 0, 0 }
/*
* These devices are connected via the core APB bridge
*/
#define SCTL_IRQ { NO_IRQ, NO_IRQ }
#define SCTL_DMA { 0, 0 }
#define EB_WATCHDOG_IRQ { IRQ_EB_WDOG, NO_IRQ }
#define EB_WATCHDOG_DMA { 0, 0 }
#define EB_GPIO0_IRQ { IRQ_EB_GPIO0, NO_IRQ }
#define EB_GPIO0_DMA { 0, 0 }
#define GPIO1_IRQ { IRQ_EB_GPIO1, NO_IRQ }
#define GPIO1_DMA { 0, 0 }
#define EB_RTC_IRQ { IRQ_EB_RTC, NO_IRQ }
#define EB_RTC_DMA { 0, 0 }
/*
* These devices are connected via the DMA APB bridge
*/
#define SCI_IRQ { IRQ_EB_SCI, NO_IRQ }
#define SCI_DMA { 7, 6 }
#define EB_UART0_IRQ { IRQ_EB_UART0, NO_IRQ }
#define EB_UART0_DMA { 15, 14 }
#define EB_UART1_IRQ { IRQ_EB_UART1, NO_IRQ }
#define EB_UART1_DMA { 13, 12 }
#define EB_UART2_IRQ { IRQ_EB_UART2, NO_IRQ }
#define EB_UART2_DMA { 11, 10 }
#define EB_UART3_IRQ { IRQ_EB_UART3, NO_IRQ }
#define EB_UART3_DMA { 0x86, 0x87 }
#define EB_SSP_IRQ { IRQ_EB_SSP, NO_IRQ }
#define EB_SSP_DMA { 9, 8 }
/* FPGA Primecells */
AMBA_DEVICE(aaci, "fpga:aaci", AACI, NULL);
......@@ -487,6 +466,7 @@ MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
.boot_params = PLAT_PHYS_OFFSET + 0x00000100,
.fixup = realview_fixup,
.map_io = realview_eb_map_io,
.init_early = realview_init_early,
.init_irq = gic_init_irq,
.timer = &realview_eb_timer,
.init_machine = realview_eb_init,
......
......@@ -134,47 +134,26 @@ static struct pl022_ssp_controller ssp0_plat_data = {
* RealView PB1176 AMBA devices
*/
#define GPIO2_IRQ { IRQ_PB1176_GPIO2, NO_IRQ }
#define GPIO2_DMA { 0, 0 }
#define GPIO3_IRQ { IRQ_PB1176_GPIO3, NO_IRQ }
#define GPIO3_DMA { 0, 0 }
#define AACI_IRQ { IRQ_PB1176_AACI, NO_IRQ }
#define AACI_DMA { 0x80, 0x81 }
#define MMCI0_IRQ { IRQ_PB1176_MMCI0A, IRQ_PB1176_MMCI0B }
#define MMCI0_DMA { 0x84, 0 }
#define KMI0_IRQ { IRQ_PB1176_KMI0, NO_IRQ }
#define KMI0_DMA { 0, 0 }
#define KMI1_IRQ { IRQ_PB1176_KMI1, NO_IRQ }
#define KMI1_DMA { 0, 0 }
#define PB1176_SMC_IRQ { NO_IRQ, NO_IRQ }
#define PB1176_SMC_DMA { 0, 0 }
#define MPMC_IRQ { NO_IRQ, NO_IRQ }
#define MPMC_DMA { 0, 0 }
#define PB1176_CLCD_IRQ { IRQ_DC1176_CLCD, NO_IRQ }
#define PB1176_CLCD_DMA { 0, 0 }
#define SCTL_IRQ { NO_IRQ, NO_IRQ }
#define SCTL_DMA { 0, 0 }
#define PB1176_WATCHDOG_IRQ { IRQ_DC1176_WATCHDOG, NO_IRQ }
#define PB1176_WATCHDOG_DMA { 0, 0 }
#define PB1176_GPIO0_IRQ { IRQ_PB1176_GPIO0, NO_IRQ }
#define PB1176_GPIO0_DMA { 0, 0 }
#define GPIO1_IRQ { IRQ_PB1176_GPIO1, NO_IRQ }
#define GPIO1_DMA { 0, 0 }
#define PB1176_RTC_IRQ { IRQ_DC1176_RTC, NO_IRQ }
#define PB1176_RTC_DMA { 0, 0 }
#define SCI_IRQ { IRQ_PB1176_SCI, NO_IRQ }
#define SCI_DMA { 7, 6 }
#define PB1176_UART0_IRQ { IRQ_DC1176_UART0, NO_IRQ }
#define PB1176_UART0_DMA { 15, 14 }
#define PB1176_UART1_IRQ { IRQ_DC1176_UART1, NO_IRQ }
#define PB1176_UART1_DMA { 13, 12 }
#define PB1176_UART2_IRQ { IRQ_DC1176_UART2, NO_IRQ }
#define PB1176_UART2_DMA { 11, 10 }
#define PB1176_UART3_IRQ { IRQ_DC1176_UART3, NO_IRQ }
#define PB1176_UART3_DMA { 0x86, 0x87 }
#define PB1176_UART4_IRQ { IRQ_PB1176_UART4, NO_IRQ }
#define PB1176_UART4_DMA { 0, 0 }
#define PB1176_SSP_IRQ { IRQ_DC1176_SSP, NO_IRQ }
#define PB1176_SSP_DMA { 9, 8 }
/* FPGA Primecells */
AMBA_DEVICE(aaci, "fpga:aaci", AACI, NULL);
......@@ -382,6 +361,7 @@ MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
.boot_params = PLAT_PHYS_OFFSET + 0x00000100,
.fixup = realview_pb1176_fixup,
.map_io = realview_pb1176_map_io,
.init_early = realview_init_early,
.init_irq = gic_init_irq,
.timer = &realview_pb1176_timer,
.init_machine = realview_pb1176_init,
......
......@@ -136,47 +136,26 @@ static struct pl022_ssp_controller ssp0_plat_data = {
*/
#define GPIO2_IRQ { IRQ_PB11MP_GPIO2, NO_IRQ }
#define GPIO2_DMA { 0, 0 }
#define GPIO3_IRQ { IRQ_PB11MP_GPIO3, NO_IRQ }
#define GPIO3_DMA { 0, 0 }
#define AACI_IRQ { IRQ_TC11MP_AACI, NO_IRQ }
#define AACI_DMA { 0x80, 0x81 }
#define MMCI0_IRQ { IRQ_TC11MP_MMCI0A, IRQ_TC11MP_MMCI0B }
#define MMCI0_DMA { 0x84, 0 }
#define KMI0_IRQ { IRQ_TC11MP_KMI0, NO_IRQ }
#define KMI0_DMA { 0, 0 }
#define KMI1_IRQ { IRQ_TC11MP_KMI1, NO_IRQ }
#define KMI1_DMA { 0, 0 }
#define PB11MP_SMC_IRQ { NO_IRQ, NO_IRQ }
#define PB11MP_SMC_DMA { 0, 0 }
#define MPMC_IRQ { NO_IRQ, NO_IRQ }
#define MPMC_DMA { 0, 0 }
#define PB11MP_CLCD_IRQ { IRQ_PB11MP_CLCD, NO_IRQ }
#define PB11MP_CLCD_DMA { 0, 0 }
#define DMAC_IRQ { IRQ_PB11MP_DMAC, NO_IRQ }
#define DMAC_DMA { 0, 0 }
#define SCTL_IRQ { NO_IRQ, NO_IRQ }
#define SCTL_DMA { 0, 0 }
#define PB11MP_WATCHDOG_IRQ { IRQ_PB11MP_WATCHDOG, NO_IRQ }
#define PB11MP_WATCHDOG_DMA { 0, 0 }
#define PB11MP_GPIO0_IRQ { IRQ_PB11MP_GPIO0, NO_IRQ }
#define PB11MP_GPIO0_DMA { 0, 0 }
#define GPIO1_IRQ { IRQ_PB11MP_GPIO1, NO_IRQ }
#define GPIO1_DMA { 0, 0 }
#define PB11MP_RTC_IRQ { IRQ_TC11MP_RTC, NO_IRQ }
#define PB11MP_RTC_DMA { 0, 0 }
#define SCI_IRQ { IRQ_PB11MP_SCI, NO_IRQ }
#define SCI_DMA { 7, 6 }
#define PB11MP_UART0_IRQ { IRQ_TC11MP_UART0, NO_IRQ }
#define PB11MP_UART0_DMA { 15, 14 }
#define PB11MP_UART1_IRQ { IRQ_TC11MP_UART1, NO_IRQ }
#define PB11MP_UART1_DMA { 13, 12 }
#define PB11MP_UART2_IRQ { IRQ_PB11MP_UART2, NO_IRQ }
#define PB11MP_UART2_DMA { 11, 10 }
#define PB11MP_UART3_IRQ { IRQ_PB11MP_UART3, NO_IRQ }
#define PB11MP_UART3_DMA { 0x86, 0x87 }
#define PB11MP_SSP_IRQ { IRQ_PB11MP_SSP, NO_IRQ }
#define PB11MP_SSP_DMA { 9, 8 }
/* FPGA Primecells */
AMBA_DEVICE(aaci, "fpga:aaci", AACI, NULL);
......@@ -384,6 +363,7 @@ MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
.boot_params = PLAT_PHYS_OFFSET + 0x00000100,
.fixup = realview_fixup,
.map_io = realview_pb11mp_map_io,
.init_early = realview_init_early,
.init_irq = gic_init_irq,
.timer = &realview_pb11mp_timer,
.init_machine = realview_pb11mp_init,
......
......@@ -126,47 +126,26 @@ static struct pl022_ssp_controller ssp0_plat_data = {
*/
#define GPIO2_IRQ { IRQ_PBA8_GPIO2, NO_IRQ }
#define GPIO2_DMA { 0, 0 }
#define GPIO3_IRQ { IRQ_PBA8_GPIO3, NO_IRQ }
#define GPIO3_DMA { 0, 0 }
#define AACI_IRQ { IRQ_PBA8_AACI, NO_IRQ }
#define AACI_DMA { 0x80, 0x81 }
#define MMCI0_IRQ { IRQ_PBA8_MMCI0A, IRQ_PBA8_MMCI0B }
#define MMCI0_DMA { 0x84, 0 }
#define KMI0_IRQ { IRQ_PBA8_KMI0, NO_IRQ }
#define KMI0_DMA { 0, 0 }
#define KMI1_IRQ { IRQ_PBA8_KMI1, NO_IRQ }
#define KMI1_DMA { 0, 0 }
#define PBA8_SMC_IRQ { NO_IRQ, NO_IRQ }
#define PBA8_SMC_DMA { 0, 0 }
#define MPMC_IRQ { NO_IRQ, NO_IRQ }
#define MPMC_DMA { 0, 0 }
#define PBA8_CLCD_IRQ { IRQ_PBA8_CLCD, NO_IRQ }
#define PBA8_CLCD_DMA { 0, 0 }
#define DMAC_IRQ { IRQ_PBA8_DMAC, NO_IRQ }
#define DMAC_DMA { 0, 0 }
#define SCTL_IRQ { NO_IRQ, NO_IRQ }
#define SCTL_DMA { 0, 0 }
#define PBA8_WATCHDOG_IRQ { IRQ_PBA8_WATCHDOG, NO_IRQ }
#define PBA8_WATCHDOG_DMA { 0, 0 }
#define PBA8_GPIO0_IRQ { IRQ_PBA8_GPIO0, NO_IRQ }
#define PBA8_GPIO0_DMA { 0, 0 }
#define GPIO1_IRQ { IRQ_PBA8_GPIO1, NO_IRQ }
#define GPIO1_DMA { 0, 0 }
#define PBA8_RTC_IRQ { IRQ_PBA8_RTC, NO_IRQ }
#define PBA8_RTC_DMA { 0, 0 }
#define SCI_IRQ { IRQ_PBA8_SCI, NO_IRQ }
#define SCI_DMA { 7, 6 }
#define PBA8_UART0_IRQ { IRQ_PBA8_UART0, NO_IRQ }
#define PBA8_UART0_DMA { 15, 14 }
#define PBA8_UART1_IRQ { IRQ_PBA8_UART1, NO_IRQ }
#define PBA8_UART1_DMA { 13, 12 }
#define PBA8_UART2_IRQ { IRQ_PBA8_UART2, NO_IRQ }
#define PBA8_UART2_DMA { 11, 10 }
#define PBA8_UART3_IRQ { IRQ_PBA8_UART3, NO_IRQ }
#define PBA8_UART3_DMA { 0x86, 0x87 }
#define PBA8_SSP_IRQ { IRQ_PBA8_SSP, NO_IRQ }
#define PBA8_SSP_DMA { 9, 8 }
/* FPGA Primecells */
AMBA_DEVICE(aaci, "fpga:aaci", AACI, NULL);
......@@ -334,6 +313,7 @@ MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8")
.boot_params = PLAT_PHYS_OFFSET + 0x00000100,
.fixup = realview_fixup,
.map_io = realview_pba8_map_io,
.init_early = realview_init_early,
.init_irq = gic_init_irq,
.timer = &realview_pba8_timer,
.init_machine = realview_pba8_init,
......
......@@ -148,47 +148,26 @@ static struct pl022_ssp_controller ssp0_plat_data = {
*/
#define GPIO2_IRQ { IRQ_PBX_GPIO2, NO_IRQ }
#define GPIO2_DMA { 0, 0 }
#define GPIO3_IRQ { IRQ_PBX_GPIO3, NO_IRQ }
#define GPIO3_DMA { 0, 0 }
#define AACI_IRQ { IRQ_PBX_AACI, NO_IRQ }
#define AACI_DMA { 0x80, 0x81 }
#define MMCI0_IRQ { IRQ_PBX_MMCI0A, IRQ_PBX_MMCI0B }
#define MMCI0_DMA { 0x84, 0 }
#define KMI0_IRQ { IRQ_PBX_KMI0, NO_IRQ }
#define KMI0_DMA { 0, 0 }
#define KMI1_IRQ { IRQ_PBX_KMI1, NO_IRQ }
#define KMI1_DMA { 0, 0 }
#define PBX_SMC_IRQ { NO_IRQ, NO_IRQ }
#define PBX_SMC_DMA { 0, 0 }
#define MPMC_IRQ { NO_IRQ, NO_IRQ }
#define MPMC_DMA { 0, 0 }
#define PBX_CLCD_IRQ { IRQ_PBX_CLCD, NO_IRQ }
#define PBX_CLCD_DMA { 0, 0 }
#define DMAC_IRQ { IRQ_PBX_DMAC, NO_IRQ }
#define DMAC_DMA { 0, 0 }
#define SCTL_IRQ { NO_IRQ, NO_IRQ }
#define SCTL_DMA { 0, 0 }
#define PBX_WATCHDOG_IRQ { IRQ_PBX_WATCHDOG, NO_IRQ }
#define PBX_WATCHDOG_DMA { 0, 0 }
#define PBX_GPIO0_IRQ { IRQ_PBX_GPIO0, NO_IRQ }
#define PBX_GPIO0_DMA { 0, 0 }
#define GPIO1_IRQ { IRQ_PBX_GPIO1, NO_IRQ }
#define GPIO1_DMA { 0, 0 }
#define PBX_RTC_IRQ { IRQ_PBX_RTC, NO_IRQ }
#define PBX_RTC_DMA { 0, 0 }
#define SCI_IRQ { IRQ_PBX_SCI, NO_IRQ }
#define SCI_DMA { 7, 6 }
#define PBX_UART0_IRQ { IRQ_PBX_UART0, NO_IRQ }
#define PBX_UART0_DMA { 15, 14 }
#define PBX_UART1_IRQ { IRQ_PBX_UART1, NO_IRQ }
#define PBX_UART1_DMA { 13, 12 }
#define PBX_UART2_IRQ { IRQ_PBX_UART2, NO_IRQ }
#define PBX_UART2_DMA { 11, 10 }
#define PBX_UART3_IRQ { IRQ_PBX_UART3, NO_IRQ }
#define PBX_UART3_DMA { 0x86, 0x87 }
#define PBX_SSP_IRQ { IRQ_PBX_SSP, NO_IRQ }
#define PBX_SSP_DMA { 9, 8 }
/* FPGA Primecells */
AMBA_DEVICE(aaci, "fpga:aaci", AACI, NULL);
......@@ -417,6 +396,7 @@ MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX")
.boot_params = PLAT_PHYS_OFFSET + 0x00000100,
.fixup = realview_pbx_fixup,
.map_io = realview_pbx_map_io,
.init_early = realview_init_early,
.init_irq = gic_init_irq,
.timer = &realview_pbx_timer,
.init_machine = realview_pbx_init,
......
......@@ -18,8 +18,9 @@
/*
* Setup the local clock events for a CPU.
*/
void __cpuinit local_timer_setup(struct clock_event_device *evt)
int __cpuinit local_timer_setup(struct clock_event_device *evt)
{
evt->irq = 29;
twd_timer_setup(evt);
return 0;
}
......@@ -18,8 +18,9 @@
/*
* Setup the local clock events for a CPU.
*/
void __cpuinit local_timer_setup(struct clock_event_device *evt)
int __cpuinit local_timer_setup(struct clock_event_device *evt)
{
evt->irq = IRQ_LOCALTIMER;
twd_timer_setup(evt);
return 0;
}
......@@ -21,8 +21,9 @@
/*
* Setup the local clock events for a CPU.
*/
void __cpuinit local_timer_setup(struct clock_event_device *evt)
int __cpuinit local_timer_setup(struct clock_event_device *evt)
{
evt->irq = IRQ_LOCALTIMER;
twd_timer_setup(evt);
return 0;
}
......@@ -50,6 +50,8 @@
#include <mach/platform.h>
#include <asm/hardware/timer-sp.h>
#include <plat/clcd.h>
#include <plat/fpga-irq.h>
#include <plat/sched_clock.h>
#include "core.h"
......@@ -63,47 +65,12 @@
#define VA_VIC_BASE __io_address(VERSATILE_VIC_BASE)
#define VA_SIC_BASE __io_address(VERSATILE_SIC_BASE)
static void sic_mask_irq(struct irq_data *d)
{
unsigned int irq = d->irq - IRQ_SIC_START;
writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
}
static void sic_unmask_irq(struct irq_data *d)
{
unsigned int irq = d->irq - IRQ_SIC_START;
writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_SET);
}
static struct irq_chip sic_chip = {
.name = "SIC",
.irq_ack = sic_mask_irq,
.irq_mask = sic_mask_irq,
.irq_unmask = sic_unmask_irq,
static struct fpga_irq_data sic_irq = {
.base = VA_SIC_BASE,
.irq_start = IRQ_SIC_START,
.chip.name = "SIC",
};
static void
sic_handle_irq(unsigned int irq, struct irq_desc *desc)
{
unsigned long status = readl(VA_SIC_BASE + SIC_IRQ_STATUS);
if (status == 0) {
do_bad_IRQ(irq, desc);
return;
}
do {
irq = ffs(status) - 1;
status &= ~(1 << irq);
irq += IRQ_SIC_START;
generic_handle_irq(irq);
} while (status);
}
#if 1
#define IRQ_MMCI0A IRQ_VICSOURCE22
#define IRQ_AACI IRQ_VICSOURCE24
......@@ -118,22 +85,11 @@ sic_handle_irq(unsigned int irq, struct irq_desc *desc)
void __init versatile_init_irq(void)
{
unsigned int i;
vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0);
set_irq_chained_handler(IRQ_VICSOURCE31, sic_handle_irq);
/* Do second interrupt controller */
writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
for (i = IRQ_SIC_START; i <= IRQ_SIC_END; i++) {
if ((PIC_MASK & (1 << (i - IRQ_SIC_START))) == 0) {
set_irq_chip(i, &sic_chip);
set_irq_handler(i, handle_level_irq);
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
}
}
fpga_irq_init(IRQ_VICSOURCE31, ~PIC_MASK, &sic_irq);
/*
* Interrupts on secondary controller from 0 to 8 are routed to
......@@ -476,127 +432,7 @@ static struct clk_lookup lookups[] = {
#define SYS_CLCD_ID_SANYO_2_5 (0x07 << 8)
#define SYS_CLCD_ID_VGA (0x1f << 8)
static struct clcd_panel vga = {
.mode = {
.name = "VGA",
.refresh = 60,
.xres = 640,
.yres = 480,
.pixclock = 39721,
.left_margin = 40,
.right_margin = 24,
.upper_margin = 32,
.lower_margin = 11,
.hsync_len = 96,
.vsync_len = 2,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
.bpp = 16,
};
static struct clcd_panel sanyo_3_8_in = {
.mode = {
.name = "Sanyo QVGA",
.refresh = 116,
.xres = 320,
.yres = 240,
.pixclock = 100000,
.left_margin = 6,
.right_margin = 6,
.upper_margin = 5,
.lower_margin = 5,
.hsync_len = 6,
.vsync_len = 6,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD,
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
.bpp = 16,
};
static struct clcd_panel sanyo_2_5_in = {
.mode = {
.name = "Sanyo QVGA Portrait",
.refresh = 116,
.xres = 240,
.yres = 320,
.pixclock = 100000,
.left_margin = 20,
.right_margin = 10,
.upper_margin = 2,
.lower_margin = 2,
.hsync_len = 10,
.vsync_len = 2,
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_IVS | TIM2_IHS | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
.bpp = 16,
};
static struct clcd_panel epson_2_2_in = {
.mode = {
.name = "Epson QCIF",
.refresh = 390,
.xres = 176,
.yres = 220,
.pixclock = 62500,
.left_margin = 3,
.right_margin = 2,
.upper_margin = 1,
.lower_margin = 0,
.hsync_len = 3,
.vsync_len = 2,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
.bpp = 16,
};
/*
* Detect which LCD panel is connected, and return the appropriate
* clcd_panel structure. Note: we do not have any information on
* the required timings for the 8.4in panel, so we presently assume
* VGA timings.
*/
static struct clcd_panel *versatile_clcd_panel(void)
{
void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
struct clcd_panel *panel = &vga;
u32 val;
val = readl(sys_clcd) & SYS_CLCD_ID_MASK;
if (val == SYS_CLCD_ID_SANYO_3_8)
panel = &sanyo_3_8_in;
else if (val == SYS_CLCD_ID_SANYO_2_5)
panel = &sanyo_2_5_in;
else if (val == SYS_CLCD_ID_EPSON_2_2)
panel = &epson_2_2_in;
else if (val == SYS_CLCD_ID_VGA)
panel = &vga;
else {
printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n",
val);
panel = &vga;
}
return panel;
}
static bool is_sanyo_2_5_lcd;
/*
* Disable all display connectors on the interface module.
......@@ -614,7 +450,7 @@ static void versatile_clcd_disable(struct clcd_fb *fb)
/*
* If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light off
*/
if (machine_is_versatile_ab() && fb->panel == &sanyo_2_5_in) {
if (machine_is_versatile_ab() && is_sanyo_2_5_lcd) {
void __iomem *versatile_ib2_ctrl = __io_address(VERSATILE_IB2_CTRL);
unsigned long ctrl;
......@@ -630,18 +466,22 @@ static void versatile_clcd_disable(struct clcd_fb *fb)
*/
static void versatile_clcd_enable(struct clcd_fb *fb)
{
struct fb_var_screeninfo *var = &fb->fb.var;
void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
u32 val;
val = readl(sys_clcd);
val &= ~SYS_CLCD_MODE_MASK;
switch (fb->fb.var.green.length) {
switch (var->green.length) {
case 5:
val |= SYS_CLCD_MODE_5551;
break;
case 6:
val |= SYS_CLCD_MODE_565_RLSB;
if (var->red.offset == 0)
val |= SYS_CLCD_MODE_565_RLSB;
else
val |= SYS_CLCD_MODE_565_BLSB;
break;
case 8:
val |= SYS_CLCD_MODE_888;
......@@ -663,7 +503,7 @@ static void versatile_clcd_enable(struct clcd_fb *fb)
/*
* If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light on
*/
if (machine_is_versatile_ab() && fb->panel == &sanyo_2_5_in) {
if (machine_is_versatile_ab() && is_sanyo_2_5_lcd) {
void __iomem *versatile_ib2_ctrl = __io_address(VERSATILE_IB2_CTRL);
unsigned long ctrl;
......@@ -674,50 +514,62 @@ static void versatile_clcd_enable(struct clcd_fb *fb)
#endif
}
static unsigned long framesize = SZ_1M;
/*
* Detect which LCD panel is connected, and return the appropriate
* clcd_panel structure. Note: we do not have any information on
* the required timings for the 8.4in panel, so we presently assume
* VGA timings.
*/
static int versatile_clcd_setup(struct clcd_fb *fb)
{
dma_addr_t dma;
void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
const char *panel_name;
u32 val;
fb->panel = versatile_clcd_panel();
is_sanyo_2_5_lcd = false;
fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
&dma, GFP_KERNEL);
if (!fb->fb.screen_base) {
printk(KERN_ERR "CLCD: unable to map framebuffer\n");
return -ENOMEM;
val = readl(sys_clcd) & SYS_CLCD_ID_MASK;
if (val == SYS_CLCD_ID_SANYO_3_8)
panel_name = "Sanyo TM38QV67A02A";
else if (val == SYS_CLCD_ID_SANYO_2_5) {
panel_name = "Sanyo QVGA Portrait";
is_sanyo_2_5_lcd = true;
} else if (val == SYS_CLCD_ID_EPSON_2_2)
panel_name = "Epson L2F50113T00";
else if (val == SYS_CLCD_ID_VGA)
panel_name = "VGA";
else {
printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n",
val);
panel_name = "VGA";
}
fb->fb.fix.smem_start = dma;
fb->fb.fix.smem_len = framesize;
fb->panel = versatile_clcd_get_panel(panel_name);
if (!fb->panel)
return -EINVAL;
return 0;
return versatile_clcd_setup_dma(fb, SZ_1M);
}
static int versatile_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
static void versatile_clcd_decode(struct clcd_fb *fb, struct clcd_regs *regs)
{
return dma_mmap_writecombine(&fb->dev->dev, vma,
fb->fb.screen_base,
fb->fb.fix.smem_start,
fb->fb.fix.smem_len);
}
clcdfb_decode(fb, regs);
static void versatile_clcd_remove(struct clcd_fb *fb)
{
dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
fb->fb.screen_base, fb->fb.fix.smem_start);
/* Always clear BGR for RGB565: we do the routing externally */
if (fb->fb.var.green.length == 6)
regs->cntl &= ~CNTL_BGR;
}
static struct clcd_board clcd_plat_data = {
.name = "Versatile",
.caps = CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888,
.check = clcdfb_check,
.decode = clcdfb_decode,
.decode = versatile_clcd_decode,
.disable = versatile_clcd_disable,
.enable = versatile_clcd_enable,
.setup = versatile_clcd_setup,
.mmap = versatile_clcd_mmap,
.remove = versatile_clcd_remove,
.mmap = versatile_clcd_mmap_dma,
.remove = versatile_clcd_remove_dma,
};
static struct pl061_platform_data gpio0_plat_data = {
......@@ -737,53 +589,35 @@ static struct pl022_ssp_controller ssp0_plat_data = {
};
#define AACI_IRQ { IRQ_AACI, NO_IRQ }
#define AACI_DMA { 0x80, 0x81 }
#define MMCI0_IRQ { IRQ_MMCI0A,IRQ_SIC_MMCI0B }
#define MMCI0_DMA { 0x84, 0 }
#define KMI0_IRQ { IRQ_SIC_KMI0, NO_IRQ }
#define KMI0_DMA { 0, 0 }
#define KMI1_IRQ { IRQ_SIC_KMI1, NO_IRQ }
#define KMI1_DMA { 0, 0 }
/*
* These devices are connected directly to the multi-layer AHB switch
*/
#define SMC_IRQ { NO_IRQ, NO_IRQ }
#define SMC_DMA { 0, 0 }
#define MPMC_IRQ { NO_IRQ, NO_IRQ }
#define MPMC_DMA { 0, 0 }
#define CLCD_IRQ { IRQ_CLCDINT, NO_IRQ }
#define CLCD_DMA { 0, 0 }
#define DMAC_IRQ { IRQ_DMAINT, NO_IRQ }
#define DMAC_DMA { 0, 0 }
/*
* These devices are connected via the core APB bridge
*/
#define SCTL_IRQ { NO_IRQ, NO_IRQ }
#define SCTL_DMA { 0, 0 }
#define WATCHDOG_IRQ { IRQ_WDOGINT, NO_IRQ }
#define WATCHDOG_DMA { 0, 0 }
#define GPIO0_IRQ { IRQ_GPIOINT0, NO_IRQ }
#define GPIO0_DMA { 0, 0 }
#define GPIO1_IRQ { IRQ_GPIOINT1, NO_IRQ }
#define GPIO1_DMA { 0, 0 }
#define RTC_IRQ { IRQ_RTCINT, NO_IRQ }
#define RTC_DMA { 0, 0 }
/*
* These devices are connected via the DMA APB bridge
*/
#define SCI_IRQ { IRQ_SCIINT, NO_IRQ }
#define SCI_DMA { 7, 6 }
#define UART0_IRQ { IRQ_UARTINT0, NO_IRQ }
#define UART0_DMA { 15, 14 }
#define UART1_IRQ { IRQ_UARTINT1, NO_IRQ }
#define UART1_DMA { 13, 12 }
#define UART2_IRQ { IRQ_UARTINT2, NO_IRQ }
#define UART2_DMA { 11, 10 }
#define SSP_IRQ { IRQ_SSPINT, NO_IRQ }
#define SSP_DMA { 9, 8 }
/* FPGA Primecells */
AMBA_DEVICE(aaci, "fpga:04", AACI, NULL);
......@@ -865,14 +699,21 @@ static void versatile_leds_event(led_event_t ledevt)
}
#endif /* CONFIG_LEDS */
void __init versatile_init(void)
/* Early initializations */
void __init versatile_init_early(void)
{
int i;
osc4_clk.vcoreg = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSCCLCD_OFFSET;
void __iomem *sys = __io_address(VERSATILE_SYS_BASE);
osc4_clk.vcoreg = sys + VERSATILE_SYS_OSCCLCD_OFFSET;
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
versatile_sched_clock_init(sys + VERSATILE_SYS_24MHz_OFFSET, 24000000);
}
void __init versatile_init(void)
{
int i;
platform_device_register(&versatile_flash_device);
platform_device_register(&versatile_i2c_device);
platform_device_register(&smc91x_device);
......@@ -888,12 +729,6 @@ void __init versatile_init(void)
#endif
}
/*
* The sched_clock counter
*/
#define REFCOUNTER (__io_address(VERSATILE_SYS_BASE) + \
VERSATILE_SYS_24MHz_OFFSET)
/*
* Where is the timer (VA)?
*/
......@@ -909,8 +744,6 @@ static void __init versatile_timer_init(void)
{
u32 val;
versatile_sched_clock_init(REFCOUNTER, 24000000);
/*
* set clock frequency:
* VERSATILE_REFCLK is 32KHz
......
......@@ -25,6 +25,7 @@
#include <linux/amba/bus.h>
extern void __init versatile_init(void);
extern void __init versatile_init_early(void);
extern void __init versatile_init_irq(void);
extern void __init versatile_map_io(void);
extern struct sys_timer versatile_timer;
......@@ -44,7 +45,6 @@ static struct amba_device name##_device = { \
}, \
.dma_mask = ~0, \
.irq = base##_IRQ, \
/* .dma = base##_DMA,*/ \
}
#endif
......@@ -39,6 +39,6 @@
/* macro to get at IO space when running virtually */
#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
#define __io_address(n) __io(IO_ADDRESS(n))
#define __io_address(n) ((void __iomem __force *)IO_ADDRESS(n))
#endif
......@@ -37,6 +37,7 @@ MACHINE_START(VERSATILE_AB, "ARM-Versatile AB")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
.boot_params = 0x00000100,
.map_io = versatile_map_io,
.init_early = versatile_init_early,
.init_irq = versatile_init_irq,
.timer = &versatile_timer,
.init_machine = versatile_init,
......
......@@ -59,19 +59,14 @@ static struct pl061_platform_data gpio3_plat_data = {
};
#define UART3_IRQ { IRQ_SIC_UART3, NO_IRQ }
#define UART3_DMA { 0x86, 0x87 }
#define SCI1_IRQ { IRQ_SIC_SCI3, NO_IRQ }
#define SCI1_DMA { 0x88, 0x89 }
#define MMCI1_IRQ { IRQ_MMCI1A, IRQ_SIC_MMCI1B }
#define MMCI1_DMA { 0x85, 0 }
/*
* These devices are connected via the core APB bridge
*/
#define GPIO2_IRQ { IRQ_GPIOINT2, NO_IRQ }
#define GPIO2_DMA { 0, 0 }
#define GPIO3_IRQ { IRQ_GPIOINT3, NO_IRQ }
#define GPIO3_DMA { 0, 0 }
/*
* These devices are connected via the DMA APB bridge
......@@ -110,6 +105,7 @@ MACHINE_START(VERSATILE_PB, "ARM-Versatile PB")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
.boot_params = 0x00000100,
.map_io = versatile_map_io,
.init_early = versatile_init_early,
.init_irq = versatile_init_irq,
.timer = &versatile_timer,
.init_machine = versatile_pb_init,
......
......@@ -5,5 +5,8 @@ config ARCH_VEXPRESS_CA9X4
bool "Versatile Express Cortex-A9x4 tile"
select CPU_V7
select ARM_GIC
select ARM_ERRATA_720789
select ARM_ERRATA_751472
select ARM_ERRATA_753970
endmenu
......@@ -4,6 +4,5 @@
obj-y := v2m.o
obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
obj-$(CONFIG_SMP) += platsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
......@@ -17,8 +17,3 @@ struct amba_device name##_device = { \
.irq = IRQ_##base, \
/* .dma = DMA_##base,*/ \
}
struct map_desc;
void v2m_map_io(struct map_desc *tile, size_t num);
extern struct sys_timer v2m_timer;
......@@ -10,19 +10,17 @@
#include <linux/amba/clcd.h>
#include <linux/clkdev.h>
#include <asm/pgtable.h>
#include <asm/hardware/arm_timer.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/hardware/gic.h>
#include <asm/mach-types.h>
#include <asm/pmu.h>
#include <asm/smp_scu.h>
#include <asm/smp_twd.h>
#include <mach/ct-ca9x4.h>
#include <asm/hardware/timer-sp.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>
......@@ -30,6 +28,8 @@
#include <mach/motherboard.h>
#include <plat/clcd.h>
#define V2M_PA_CS7 0x10000000
static struct map_desc ct_ca9x4_io_desc[] __initdata = {
......@@ -56,7 +56,7 @@ static void __init ct_ca9x4_map_io(void)
#ifdef CONFIG_LOCAL_TIMERS
twd_base = MMIO_P2V(A9_MPCORE_TWD);
#endif
v2m_map_io(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
}
static void __init ct_ca9x4_init_irq(void)
......@@ -80,29 +80,6 @@ static struct sys_timer ct_ca9x4_timer = {
};
#endif
static struct clcd_panel xvga_panel = {
.mode = {
.name = "XVGA",
.refresh = 60,
.xres = 1024,
.yres = 768,
.pixclock = 15384,
.left_margin = 168,
.right_margin = 8,
.upper_margin = 29,
.lower_margin = 3,
.hsync_len = 144,
.vsync_len = 6,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
.bpp = 16,
};
static void ct_ca9x4_clcd_enable(struct clcd_fb *fb)
{
v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE_DB1, 0);
......@@ -112,42 +89,23 @@ static void ct_ca9x4_clcd_enable(struct clcd_fb *fb)
static int ct_ca9x4_clcd_setup(struct clcd_fb *fb)
{
unsigned long framesize = 1024 * 768 * 2;
dma_addr_t dma;
fb->panel = &xvga_panel;
fb->panel = versatile_clcd_get_panel("XVGA");
if (!fb->panel)
return -EINVAL;
fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
&dma, GFP_KERNEL);
if (!fb->fb.screen_base) {
printk(KERN_ERR "CLCD: unable to map frame buffer\n");
return -ENOMEM;
}
fb->fb.fix.smem_start = dma;
fb->fb.fix.smem_len = framesize;
return 0;
}
static int ct_ca9x4_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
{
return dma_mmap_writecombine(&fb->dev->dev, vma, fb->fb.screen_base,
fb->fb.fix.smem_start, fb->fb.fix.smem_len);
}
static void ct_ca9x4_clcd_remove(struct clcd_fb *fb)
{
dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
fb->fb.screen_base, fb->fb.fix.smem_start);
return versatile_clcd_setup_dma(fb, framesize);
}
static struct clcd_board ct_ca9x4_clcd_data = {
.name = "CT-CA9X4",
.caps = CLCD_CAP_5551 | CLCD_CAP_565,
.check = clcdfb_check,
.decode = clcdfb_decode,
.enable = ct_ca9x4_clcd_enable,
.setup = ct_ca9x4_clcd_setup,
.mmap = ct_ca9x4_clcd_mmap,
.remove = ct_ca9x4_clcd_remove,
.mmap = versatile_clcd_mmap_dma,
.remove = versatile_clcd_remove_dma,
};
static AMBA_DEVICE(clcd, "ct:clcd", CT_CA9X4_CLCDC, &ct_ca9x4_clcd_data);
......@@ -220,6 +178,11 @@ static struct platform_device pmu_device = {
.resource = pmu_resources,
};
static void __init ct_ca9x4_init_early(void)
{
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
}
static void __init ct_ca9x4_init(void)
{
int i;
......@@ -234,22 +197,40 @@ static void __init ct_ca9x4_init(void)
l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff);
#endif
clkdev_add_table(lookups, ARRAY_SIZE(lookups));
for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++)
amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource);
platform_device_register(&pmu_device);
}
MACHINE_START(VEXPRESS, "ARM-Versatile Express CA9x4")
.boot_params = PLAT_PHYS_OFFSET + 0x00000100,
#ifdef CONFIG_SMP
static void ct_ca9x4_init_cpu_map(void)
{
int i, ncores = scu_get_core_count(MMIO_P2V(A9_MPCORE_SCU));
for (i = 0; i < ncores; ++i)
set_cpu_possible(i, true);
}
static void ct_ca9x4_smp_enable(unsigned int max_cpus)
{
int i;
for (i = 0; i < max_cpus; i++)
set_cpu_present(i, true);
scu_enable(MMIO_P2V(A9_MPCORE_SCU));
}
#endif
struct ct_desc ct_ca9x4_desc __initdata = {
.id = V2M_CT_ID_CA9,
.name = "CA9x4",
.map_io = ct_ca9x4_map_io,
.init_early = ct_ca9x4_init_early,
.init_irq = ct_ca9x4_init_irq,
#if 0
.timer = &ct_ca9x4_timer,
#else
.timer = &v2m_timer,
.init_tile = ct_ca9x4_init,
#ifdef CONFIG_SMP
.init_cpu_map = ct_ca9x4_init_cpu_map,
.smp_enable = ct_ca9x4_smp_enable,
#endif
.init_machine = ct_ca9x4_init,
MACHINE_END
};
......@@ -45,4 +45,6 @@
#define IRQ_CT_CA9X4_PMU_CPU2 94
#define IRQ_CT_CA9X4_PMU_CPU3 95
extern struct ct_desc ct_ca9x4_desc;
#endif
......@@ -118,4 +118,26 @@
int v2m_cfg_write(u32 devfn, u32 data);
int v2m_cfg_read(u32 devfn, u32 *data);
/*
* Core tile IDs
*/
#define V2M_CT_ID_CA9 0x0c000191
#define V2M_CT_ID_UNSUPPORTED 0xff000191
#define V2M_CT_ID_MASK 0xff000fff
struct ct_desc {
u32 id;
const char *name;
void (*map_io)(void);
void (*init_early)(void);
void (*init_irq)(void);
void (*init_tile)(void);
#ifdef CONFIG_SMP
void (*init_cpu_map)(void);
void (*smp_enable)(unsigned int);
#endif
};
extern struct ct_desc *ct_desc;
#endif
......@@ -10,114 +10,17 @@
*/
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/jiffies.h>
#include <linux/smp.h>
#include <linux/io.h>
#include <asm/cacheflush.h>
#include <asm/smp_scu.h>
#include <asm/unified.h>
#include <mach/ct-ca9x4.h>
#include <mach/motherboard.h>
#define V2M_PA_CS7 0x10000000
#include "core.h"
extern void vexpress_secondary_startup(void);
/*
* control for which core is the next to come out of the secondary
* boot "holding pen"
*/
volatile int __cpuinitdata pen_release = -1;
/*
* Write pen_release in a way that is guaranteed to be visible to all
* observers, irrespective of whether they're taking part in coherency
* or not. This is necessary for the hotplug code to work reliably.
*/
static void __cpuinit write_pen_release(int val)
{
pen_release = val;
smp_wmb();
__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
}
static void __iomem *scu_base_addr(void)
{
return MMIO_P2V(A9_MPCORE_SCU);
}
static DEFINE_SPINLOCK(boot_lock);
void __cpuinit platform_secondary_init(unsigned int cpu)
{
/*
* if any interrupts are already enabled for the primary
* core (e.g. timer irq), then they will not have been enabled
* for us: do so
*/
gic_secondary_init(0);
/*
* let the primary processor know we're out of the
* pen, then head off into the C entry point
*/
write_pen_release(-1);
/*
* Synchronise with the boot thread.
*/
spin_lock(&boot_lock);
spin_unlock(&boot_lock);
}
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
{
unsigned long timeout;
/*
* Set synchronisation state between this boot processor
* and the secondary one
*/
spin_lock(&boot_lock);
/*
* This is really belt and braces; we hold unintended secondary
* CPUs in the holding pen until we're ready for them. However,
* since we haven't sent them a soft interrupt, they shouldn't
* be there.
*/
write_pen_release(cpu);
/*
* Send the secondary CPU a soft interrupt, thereby causing
* the boot monitor to read the system wide flags register,
* and branch to the address found there.
*/
smp_cross_call(cpumask_of(cpu), 1);
timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) {
smp_rmb();
if (pen_release == -1)
break;
udelay(10);
}
/*
* now the secondary core is starting up let it run its
* calibrations, then wait for it to finish
*/
spin_unlock(&boot_lock);
return pen_release != -1 ? -ENOSYS : 0;
}
extern void versatile_secondary_startup(void);
/*
* Initialise the CPU possible map early - this describes the CPUs
......@@ -125,36 +28,16 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
*/
void __init smp_init_cpus(void)
{
void __iomem *scu_base = scu_base_addr();
unsigned int i, ncores;
ncores = scu_base ? scu_get_core_count(scu_base) : 1;
/* sanity check */
if (ncores > NR_CPUS) {
printk(KERN_WARNING
"vexpress: no. of cores (%d) greater than configured "
"maximum of %d - clipping\n",
ncores, NR_CPUS);
ncores = NR_CPUS;
}
for (i = 0; i < ncores; i++)
set_cpu_possible(i, true);
ct_desc->init_cpu_map();
}
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
{
int i;
/*
* Initialise the present map, which describes the set of CPUs
* actually populated at the present time.
*/
for (i = 0; i < max_cpus; i++)
set_cpu_present(i, true);
scu_enable(scu_base_addr());
ct_desc->smp_enable(max_cpus);
/*
* Write the address of secondary startup into the
......@@ -163,6 +46,6 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
* secondary CPU branches to this address.
*/
writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR));
writel(BSYM(virt_to_phys(vexpress_secondary_startup)),
writel(BSYM(virt_to_phys(versatile_secondary_startup)),
MMIO_P2V(V2M_SYS_FLAGSSET));
}
......@@ -7,13 +7,16 @@
#include <linux/io.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/ata_platform.h>
#include <linux/smsc911x.h>
#include <linux/spinlock.h>
#include <linux/sysdev.h>
#include <linux/usb/isp1760.h>
#include <linux/clkdev.h>
#include <asm/mach-types.h>
#include <asm/sizes.h>
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>
......@@ -21,6 +24,7 @@
#include <asm/hardware/timer-sp.h>
#include <asm/hardware/sp810.h>
#include <mach/ct-ca9x4.h>
#include <mach/motherboard.h>
#include <plat/sched_clock.h>
......@@ -42,19 +46,16 @@ static struct map_desc v2m_io_desc[] __initdata = {
},
};
void __init v2m_map_io(struct map_desc *tile, size_t num)
static void __init v2m_init_early(void)
{
iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
iotable_init(tile, num);
ct_desc->init_early();
versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000);
}
static void __init v2m_timer_init(void)
{
u32 scctrl;
versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000);
/* Select 1MHz TIMCLK as the reference clock for SP804 timers */
scctrl = readl(MMIO_P2V(V2M_SYSCTL + SCCTRL));
scctrl |= SCCTRL_TIMEREN0SEL_TIMCLK;
......@@ -68,7 +69,7 @@ static void __init v2m_timer_init(void)
sp804_clockevents_init(MMIO_P2V(V2M_TIMER0), IRQ_V2M_TIMER0);
}
struct sys_timer v2m_timer = {
static struct sys_timer v2m_timer = {
.init = v2m_timer_init,
};
......@@ -249,6 +250,29 @@ static struct platform_device v2m_flash_device = {
.dev.platform_data = &v2m_flash_data,
};
static struct pata_platform_info v2m_pata_data = {
.ioport_shift = 2,
};
static struct resource v2m_pata_resources[] = {
{
.start = V2M_CF,
.end = V2M_CF + 0xff,
.flags = IORESOURCE_MEM,
}, {
.start = V2M_CF + 0x100,
.end = V2M_CF + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device v2m_cf_device = {
.name = "pata_platform",
.id = -1,
.resource = v2m_pata_resources,
.num_resources = ARRAY_SIZE(v2m_pata_resources),
.dev.platform_data = &v2m_pata_data,
};
static unsigned int v2m_mmci_status(struct device *dev)
{
......@@ -354,7 +378,44 @@ static void v2m_restart(char str, const char *cmd)
printk(KERN_EMERG "Unable to reboot\n");
}
static int __init v2m_init(void)
struct ct_desc *ct_desc;
static struct ct_desc *ct_descs[] __initdata = {
#ifdef CONFIG_ARCH_VEXPRESS_CA9X4
&ct_ca9x4_desc,
#endif
};
static void __init v2m_populate_ct_desc(void)
{
int i;
u32 current_tile_id;
ct_desc = NULL;
current_tile_id = readl(MMIO_P2V(V2M_SYS_PROCID0)) & V2M_CT_ID_MASK;
for (i = 0; i < ARRAY_SIZE(ct_descs) && !ct_desc; ++i)
if (ct_descs[i]->id == current_tile_id)
ct_desc = ct_descs[i];
if (!ct_desc)
panic("vexpress: failed to populate core tile description "
"for tile ID 0x%8x\n", current_tile_id);
}
static void __init v2m_map_io(void)
{
iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
v2m_populate_ct_desc();
ct_desc->map_io();
}
static void __init v2m_init_irq(void)
{
ct_desc->init_irq();
}
static void __init v2m_init(void)
{
int i;
......@@ -363,6 +424,7 @@ static int __init v2m_init(void)
platform_device_register(&v2m_pcie_i2c_device);
platform_device_register(&v2m_ddc_i2c_device);
platform_device_register(&v2m_flash_device);
platform_device_register(&v2m_cf_device);
platform_device_register(&v2m_eth_device);
platform_device_register(&v2m_usb_device);
......@@ -372,6 +434,14 @@ static int __init v2m_init(void)
pm_power_off = v2m_power_off;
arm_pm_restart = v2m_restart;
return 0;
ct_desc->init_tile();
}
arch_initcall(v2m_init);
MACHINE_START(VEXPRESS, "ARM-Versatile Express")
.boot_params = PLAT_PHYS_OFFSET + 0x00000100,
.map_io = v2m_map_io,
.init_early = v2m_init_early,
.init_irq = v2m_init_irq,
.timer = &v2m_timer,
.init_machine = v2m_init,
MACHINE_END
......@@ -149,6 +149,7 @@ static int __init consistent_init(void)
{
int ret = 0;
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
int i = 0;
......@@ -156,7 +157,15 @@ static int __init consistent_init(void)
do {
pgd = pgd_offset(&init_mm, base);
pmd = pmd_alloc(&init_mm, pgd, base);
pud = pud_alloc(&init_mm, pgd, base);
if (!pud) {
printk(KERN_ERR "%s: no pud tables\n", __func__);
ret = -ENOMEM;
break;
}
pmd = pmd_alloc(&init_mm, pud, base);
if (!pmd) {
printk(KERN_ERR "%s: no pmd tables\n", __func__);
ret = -ENOMEM;
......
......@@ -95,6 +95,7 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address,
{
spinlock_t *ptl;
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
int ret;
......@@ -103,7 +104,11 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address,
if (pgd_none_or_clear_bad(pgd))
return 0;
pmd = pmd_offset(pgd, address);
pud = pud_offset(pgd, address);
if (pud_none_or_clear_bad(pud))
return 0;
pmd = pmd_offset(pud, address);
if (pmd_none_or_clear_bad(pmd))
return 0;
......
......@@ -76,9 +76,11 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
printk(KERN_ALERT "pgd = %p\n", mm->pgd);
pgd = pgd_offset(mm, addr);
printk(KERN_ALERT "[%08lx] *pgd=%08lx", addr, pgd_val(*pgd));
printk(KERN_ALERT "[%08lx] *pgd=%08llx",
addr, (long long)pgd_val(*pgd));
do {
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
......@@ -90,9 +92,21 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
break;
}
pmd = pmd_offset(pgd, addr);
pud = pud_offset(pgd, addr);
if (PTRS_PER_PUD != 1)
printk(", *pud=%08lx", pud_val(*pud));
if (pud_none(*pud))
break;
if (pud_bad(*pud)) {
printk("(bad)");
break;
}
pmd = pmd_offset(pud, addr);
if (PTRS_PER_PMD != 1)
printk(", *pmd=%08lx", pmd_val(*pmd));
printk(", *pmd=%08llx", (long long)pmd_val(*pmd));
if (pmd_none(*pmd))
break;
......@@ -107,8 +121,9 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
break;
pte = pte_offset_map(pmd, addr);
printk(", *pte=%08lx", pte_val(*pte));
printk(", *ppte=%08lx", pte_val(pte[PTE_HWTABLE_PTRS]));
printk(", *pte=%08llx", (long long)pte_val(*pte));
printk(", *ppte=%08llx",
(long long)pte_val(pte[PTE_HWTABLE_PTRS]));
pte_unmap(pte);
} while(0);
......@@ -388,6 +403,7 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
{
unsigned int index;
pgd_t *pgd, *pgd_k;
pud_t *pud, *pud_k;
pmd_t *pmd, *pmd_k;
if (addr < TASK_SIZE)
......@@ -406,12 +422,19 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
if (pgd_none(*pgd_k))
goto bad_area;
if (!pgd_present(*pgd))
set_pgd(pgd, *pgd_k);
pmd_k = pmd_offset(pgd_k, addr);
pmd = pmd_offset(pgd, addr);
pud = pud_offset(pgd, addr);
pud_k = pud_offset(pgd_k, addr);
if (pud_none(*pud_k))
goto bad_area;
if (!pud_present(*pud))
set_pud(pud, *pud_k);
pmd = pmd_offset(pud, addr);
pmd_k = pmd_offset(pud_k, addr);
/*
* On ARM one Linux PGD entry contains two hardware entries (see page
......
......@@ -4,10 +4,10 @@
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
static void idmap_add_pmd(pgd_t *pgd, unsigned long addr, unsigned long end,
static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end,
unsigned long prot)
{
pmd_t *pmd = pmd_offset(pgd, addr);
pmd_t *pmd = pmd_offset(pud, addr);
addr = (addr & PMD_MASK) | prot;
pmd[0] = __pmd(addr);
......@@ -16,6 +16,18 @@ static void idmap_add_pmd(pgd_t *pgd, unsigned long addr, unsigned long end,
flush_pmd_entry(pmd);
}
static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
unsigned long prot)
{
pud_t *pud = pud_offset(pgd, addr);
unsigned long next;
do {
next = pud_addr_end(addr, end);
idmap_add_pmd(pud, addr, next, prot);
} while (pud++, addr = next, addr != end);
}
void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end)
{
unsigned long prot, next;
......@@ -27,17 +39,28 @@ void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end)
pgd += pgd_index(addr);
do {
next = pgd_addr_end(addr, end);
idmap_add_pmd(pgd, addr, next, prot);
idmap_add_pud(pgd, addr, next, prot);
} while (pgd++, addr = next, addr != end);
}
#ifdef CONFIG_SMP
static void idmap_del_pmd(pgd_t *pgd, unsigned long addr, unsigned long end)
static void idmap_del_pmd(pud_t *pud, unsigned long addr, unsigned long end)
{
pmd_t *pmd = pmd_offset(pgd, addr);
pmd_t *pmd = pmd_offset(pud, addr);
pmd_clear(pmd);
}
static void idmap_del_pud(pgd_t *pgd, unsigned long addr, unsigned long end)
{
pud_t *pud = pud_offset(pgd, addr);
unsigned long next;
do {
next = pud_addr_end(addr, end);
idmap_del_pmd(pud, addr, next);
} while (pud++, addr = next, addr != end);
}
void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end)
{
unsigned long next;
......@@ -45,7 +68,7 @@ void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end)
pgd += pgd_index(addr);
do {
next = pgd_addr_end(addr, end);
idmap_del_pmd(pgd, addr, next);
idmap_del_pud(pgd, addr, next);
} while (pgd++, addr = next, addr != end);
}
#endif
......
......@@ -350,7 +350,7 @@ void __init bootmem_init(void)
*/
arm_bootmem_free(min, max_low, max_high);
high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1;
high_memory = __va(((phys_addr_t)max_low << PAGE_SHIFT) - 1) + 1;
/*
* This doesn't seem to be used by the Linux memory manager any
......@@ -398,8 +398,8 @@ free_memmap(unsigned long start_pfn, unsigned long end_pfn)
* Convert to physical addresses, and
* round start upwards and end downwards.
*/
pg = PAGE_ALIGN(__pa(start_pg));
pgend = __pa(end_pg) & PAGE_MASK;
pg = (unsigned long)PAGE_ALIGN(__pa(start_pg));
pgend = (unsigned long)__pa(end_pg) & PAGE_MASK;
/*
* If there are free pages between these,
......
......@@ -7,7 +7,7 @@ extern pmd_t *top_pmd;
static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
{
return pmd_offset(pgd, virt);
return pmd_offset(pud_offset(pgd, virt), virt);
}
static inline pmd_t *pmd_off_k(unsigned long virt)
......
......@@ -533,7 +533,7 @@ static void __init *early_alloc(unsigned long sz)
static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr, unsigned long prot)
{
if (pmd_none(*pmd)) {
pte_t *pte = early_alloc(2 * PTRS_PER_PTE * sizeof(pte_t));
pte_t *pte = early_alloc(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE);
__pmd_populate(pmd, __pa(pte), prot);
}
BUG_ON(pmd_bad(*pmd));
......@@ -551,11 +551,11 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
} while (pte++, addr += PAGE_SIZE, addr != end);
}
static void __init alloc_init_section(pgd_t *pgd, unsigned long addr,
static void __init alloc_init_section(pud_t *pud, unsigned long addr,
unsigned long end, phys_addr_t phys,
const struct mem_type *type)
{
pmd_t *pmd = pmd_offset(pgd, addr);
pmd_t *pmd = pmd_offset(pud, addr);
/*
* Try a section mapping - end, addr and phys must all be aligned
......@@ -584,6 +584,19 @@ static void __init alloc_init_section(pgd_t *pgd, unsigned long addr,
}
}
static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
unsigned long phys, const struct mem_type *type)
{
pud_t *pud = pud_offset(pgd, addr);
unsigned long next;
do {
next = pud_addr_end(addr, end);
alloc_init_section(pud, addr, next, phys, type);
phys += next - addr;
} while (pud++, addr = next, addr != end);
}
static void __init create_36bit_mapping(struct map_desc *md,
const struct mem_type *type)
{
......@@ -592,13 +605,13 @@ static void __init create_36bit_mapping(struct map_desc *md,
pgd_t *pgd;
addr = md->virtual;
phys = (unsigned long)__pfn_to_phys(md->pfn);
phys = __pfn_to_phys(md->pfn);
length = PAGE_ALIGN(md->length);
if (!(cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())) {
printk(KERN_ERR "MM: CPU does not support supersection "
"mapping for 0x%08llx at 0x%08lx\n",
__pfn_to_phys((u64)md->pfn), addr);
(long long)__pfn_to_phys((u64)md->pfn), addr);
return;
}
......@@ -611,14 +624,14 @@ static void __init create_36bit_mapping(struct map_desc *md,
if (type->domain) {
printk(KERN_ERR "MM: invalid domain in supersection "
"mapping for 0x%08llx at 0x%08lx\n",
__pfn_to_phys((u64)md->pfn), addr);
(long long)__pfn_to_phys((u64)md->pfn), addr);
return;
}
if ((addr | length | __pfn_to_phys(md->pfn)) & ~SUPERSECTION_MASK) {
printk(KERN_ERR "MM: cannot create mapping for "
"0x%08llx at 0x%08lx invalid alignment\n",
__pfn_to_phys((u64)md->pfn), addr);
printk(KERN_ERR "MM: cannot create mapping for 0x%08llx"
" at 0x%08lx invalid alignment\n",
(long long)__pfn_to_phys((u64)md->pfn), addr);
return;
}
......@@ -631,7 +644,8 @@ static void __init create_36bit_mapping(struct map_desc *md,
pgd = pgd_offset_k(addr);
end = addr + length;
do {
pmd_t *pmd = pmd_offset(pgd, addr);
pud_t *pud = pud_offset(pgd, addr);
pmd_t *pmd = pmd_offset(pud, addr);
int i;
for (i = 0; i < 16; i++)
......@@ -652,22 +666,23 @@ static void __init create_36bit_mapping(struct map_desc *md,
*/
static void __init create_mapping(struct map_desc *md)
{
unsigned long phys, addr, length, end;
unsigned long addr, length, end;
phys_addr_t phys;
const struct mem_type *type;
pgd_t *pgd;
if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
printk(KERN_WARNING "BUG: not creating mapping for "
"0x%08llx at 0x%08lx in user region\n",
__pfn_to_phys((u64)md->pfn), md->virtual);
printk(KERN_WARNING "BUG: not creating mapping for 0x%08llx"
" at 0x%08lx in user region\n",
(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
return;
}
if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) {
printk(KERN_WARNING "BUG: mapping for 0x%08llx at 0x%08lx "
"overlaps vmalloc space\n",
__pfn_to_phys((u64)md->pfn), md->virtual);
printk(KERN_WARNING "BUG: mapping for 0x%08llx"
" at 0x%08lx overlaps vmalloc space\n",
(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
}
type = &mem_types[md->type];
......@@ -681,13 +696,13 @@ static void __init create_mapping(struct map_desc *md)
}
addr = md->virtual & PAGE_MASK;
phys = (unsigned long)__pfn_to_phys(md->pfn);
phys = __pfn_to_phys(md->pfn);
length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK));
if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) {
printk(KERN_WARNING "BUG: map for 0x%08lx at 0x%08lx can not "
printk(KERN_WARNING "BUG: map for 0x%08llx at 0x%08lx can not "
"be mapped using pages, ignoring.\n",
__pfn_to_phys(md->pfn), addr);
(long long)__pfn_to_phys(md->pfn), addr);
return;
}
......@@ -696,7 +711,7 @@ static void __init create_mapping(struct map_desc *md)
do {
unsigned long next = pgd_addr_end(addr, end);
alloc_init_section(pgd, addr, next, phys, type);
alloc_init_pud(pgd, addr, next, phys, type);
phys += next - addr;
addr = next;
......@@ -794,9 +809,10 @@ static void __init sanity_check_meminfo(void)
*/
if (__va(bank->start) >= vmalloc_min ||
__va(bank->start) < (void *)PAGE_OFFSET) {
printk(KERN_NOTICE "Ignoring RAM at %.8lx-%.8lx "
printk(KERN_NOTICE "Ignoring RAM at %.8llx-%.8llx "
"(vmalloc region overlap).\n",
bank->start, bank->start + bank->size - 1);
(unsigned long long)bank->start,
(unsigned long long)bank->start + bank->size - 1);
continue;
}
......@@ -807,10 +823,11 @@ static void __init sanity_check_meminfo(void)
if (__va(bank->start + bank->size) > vmalloc_min ||
__va(bank->start + bank->size) < __va(bank->start)) {
unsigned long newsize = vmalloc_min - __va(bank->start);
printk(KERN_NOTICE "Truncating RAM at %.8lx-%.8lx "
"to -%.8lx (vmalloc region overlap).\n",
bank->start, bank->start + bank->size - 1,
bank->start + newsize - 1);
printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx "
"to -%.8llx (vmalloc region overlap).\n",
(unsigned long long)bank->start,
(unsigned long long)bank->start + bank->size - 1,
(unsigned long long)bank->start + newsize - 1);
bank->size = newsize;
}
#endif
......
......@@ -23,6 +23,7 @@
pgd_t *pgd_alloc(struct mm_struct *mm)
{
pgd_t *new_pgd, *init_pgd;
pud_t *new_pud, *init_pud;
pmd_t *new_pmd, *init_pmd;
pte_t *new_pte, *init_pte;
......@@ -46,7 +47,11 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
* On ARM, first page must always be allocated since it
* contains the machine vectors.
*/
new_pmd = pmd_alloc(mm, new_pgd, 0);
new_pud = pud_alloc(mm, new_pgd, 0);
if (!new_pud)
goto no_pud;
new_pmd = pmd_alloc(mm, new_pud, 0);
if (!new_pmd)
goto no_pmd;
......@@ -54,7 +59,8 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
if (!new_pte)
goto no_pte;
init_pmd = pmd_offset(init_pgd, 0);
init_pud = pud_offset(init_pgd, 0);
init_pmd = pmd_offset(init_pud, 0);
init_pte = pte_offset_map(init_pmd, 0);
set_pte_ext(new_pte, *init_pte, 0);
pte_unmap(init_pte);
......@@ -66,6 +72,8 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
no_pte:
pmd_free(mm, new_pmd);
no_pmd:
pud_free(mm, new_pud);
no_pud:
free_pages((unsigned long)new_pgd, 2);
no_pgd:
return NULL;
......@@ -74,6 +82,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
void pgd_free(struct mm_struct *mm, pgd_t *pgd_base)
{
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pgtable_t pte;
......@@ -84,7 +93,11 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd_base)
if (pgd_none_or_clear_bad(pgd))
goto no_pgd;
pmd = pmd_offset(pgd, 0);
pud = pud_offset(pgd, 0);
if (pud_none_or_clear_bad(pud))
goto no_pud;
pmd = pmd_offset(pud, 0);
if (pmd_none_or_clear_bad(pmd))
goto no_pmd;
......@@ -92,8 +105,11 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd_base)
pmd_clear(pmd);
pte_free(mm, pte);
no_pmd:
pgd_clear(pgd);
pud_clear(pud);
pmd_free(mm, pmd);
no_pud:
pgd_clear(pgd);
pud_free(mm, pud);
no_pgd:
free_pages((unsigned long) pgd_base, 2);
}
if PLAT_VERSATILE
config PLAT_VERSATILE_CLCD
bool
config PLAT_VERSATILE_FPGA_IRQ
bool
config PLAT_VERSATILE_LEDS
def_bool y if LEDS_CLASS
depends on ARCH_REALVIEW || ARCH_VERSATILE
config PLAT_VERSATILE_SCHED_CLOCK
def_bool y if !ARCH_INTEGRATOR_AP
select HAVE_SCHED_CLOCK
endif
obj-y := clock.o
ifneq ($(CONFIG_ARCH_INTEGRATOR),y)
obj-y += sched-clock.o
endif
ifeq ($(CONFIG_LEDS_CLASS),y)
obj-$(CONFIG_ARCH_REALVIEW) += leds.o
obj-$(CONFIG_ARCH_VERSATILE) += leds.o
endif
obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o
obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o
obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o
obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
#include <plat/clcd.h>
static struct clcd_panel vga = {
.mode = {
.name = "VGA",
.refresh = 60,
.xres = 640,
.yres = 480,
.pixclock = 39721,
.left_margin = 40,
.right_margin = 24,
.upper_margin = 32,
.lower_margin = 11,
.hsync_len = 96,
.vsync_len = 2,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
.caps = CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888,
.bpp = 16,
};
static struct clcd_panel xvga = {
.mode = {
.name = "XVGA",
.refresh = 60,
.xres = 1024,
.yres = 768,
.pixclock = 15748,
.left_margin = 152,
.right_margin = 48,
.upper_margin = 23,
.lower_margin = 3,
.hsync_len = 104,
.vsync_len = 4,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
.caps = CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888,
.bpp = 16,
};
/* Sanyo TM38QV67A02A - 3.8 inch QVGA (320x240) Color TFT */
static struct clcd_panel sanyo_tm38qv67a02a = {
.mode = {
.name = "Sanyo TM38QV67A02A",
.refresh = 116,
.xres = 320,
.yres = 240,
.pixclock = 100000,
.left_margin = 6,
.right_margin = 6,
.upper_margin = 5,
.lower_margin = 5,
.hsync_len = 6,
.vsync_len = 6,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD,
.cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
.caps = CLCD_CAP_5551,
.bpp = 16,
};
static struct clcd_panel sanyo_2_5_in = {
.mode = {
.name = "Sanyo QVGA Portrait",
.refresh = 116,
.xres = 240,
.yres = 320,
.pixclock = 100000,
.left_margin = 20,
.right_margin = 10,
.upper_margin = 2,
.lower_margin = 2,
.hsync_len = 10,
.vsync_len = 2,
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_IVS | TIM2_IHS | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
.caps = CLCD_CAP_5551,
.bpp = 16,
};
/* Epson L2F50113T00 - 2.2 inch 176x220 Color TFT */
static struct clcd_panel epson_l2f50113t00 = {
.mode = {
.name = "Epson L2F50113T00",
.refresh = 390,
.xres = 176,
.yres = 220,
.pixclock = 62500,
.left_margin = 3,
.right_margin = 2,
.upper_margin = 1,
.lower_margin = 0,
.hsync_len = 3,
.vsync_len = 2,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
.caps = CLCD_CAP_5551,
.bpp = 16,
};
static struct clcd_panel *panels[] = {
&vga,
&xvga,
&sanyo_tm38qv67a02a,
&sanyo_2_5_in,
&epson_l2f50113t00,
};
struct clcd_panel *versatile_clcd_get_panel(const char *name)
{
int i;
for (i = 0; i < ARRAY_SIZE(panels); i++)
if (strcmp(panels[i]->mode.name, name) == 0)
break;
if (i < ARRAY_SIZE(panels))
return panels[i];
pr_err("CLCD: couldn't get parameters for panel %s\n", name);
return NULL;
}
int versatile_clcd_setup_dma(struct clcd_fb *fb, unsigned long framesize)
{
dma_addr_t dma;
fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
&dma, GFP_KERNEL);
if (!fb->fb.screen_base) {
pr_err("CLCD: unable to map framebuffer\n");
return -ENOMEM;
}
fb->fb.fix.smem_start = dma;
fb->fb.fix.smem_len = framesize;
return 0;
}
int versatile_clcd_mmap_dma(struct clcd_fb *fb, struct vm_area_struct *vma)
{
return dma_mmap_writecombine(&fb->dev->dev, vma,
fb->fb.screen_base,
fb->fb.fix.smem_start,
fb->fb.fix.smem_len);
}
void versatile_clcd_remove_dma(struct clcd_fb *fb)
{
dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
fb->fb.screen_base, fb->fb.fix.smem_start);
}
/*
* Support for Versatile FPGA-based IRQ controllers
*/
#include <linux/irq.h>
#include <linux/io.h>
#include <asm/mach/irq.h>
#include <plat/fpga-irq.h>
#define IRQ_STATUS 0x00
#define IRQ_RAW_STATUS 0x04
#define IRQ_ENABLE_SET 0x08
#define IRQ_ENABLE_CLEAR 0x0c
static void fpga_irq_mask(struct irq_data *d)
{
struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
u32 mask = 1 << (d->irq - f->irq_start);
writel(mask, f->base + IRQ_ENABLE_CLEAR);
}
static void fpga_irq_unmask(struct irq_data *d)
{
struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
u32 mask = 1 << (d->irq - f->irq_start);
writel(mask, f->base + IRQ_ENABLE_SET);
}
static void fpga_irq_handle(unsigned int irq, struct irq_desc *desc)
{
struct fpga_irq_data *f = get_irq_desc_data(desc);
u32 status = readl(f->base + IRQ_STATUS);
if (status == 0) {
do_bad_IRQ(irq, desc);
return;
}
do {
irq = ffs(status) - 1;
status &= ~(1 << irq);
generic_handle_irq(irq + f->irq_start);
} while (status);
}
void __init fpga_irq_init(int parent_irq, u32 valid, struct fpga_irq_data *f)
{
unsigned int i;
f->chip.irq_ack = fpga_irq_mask;
f->chip.irq_mask = fpga_irq_mask;
f->chip.irq_unmask = fpga_irq_unmask;
if (parent_irq != -1) {
set_irq_data(parent_irq, f);
set_irq_chained_handler(parent_irq, fpga_irq_handle);
}
for (i = 0; i < 32; i++) {
if (valid & (1 << i)) {
unsigned int irq = f->irq_start + i;
set_irq_chip_data(irq, f);
set_irq_chip(irq, &f->chip);
set_irq_handler(irq, handle_level_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
}
}
/*
* linux/arch/arm/mach-vexpress/headsmp.S
* linux/arch/arm/plat-versatile/headsmp.S
*
* Copyright (c) 2003 ARM Limited
* All Rights Reserved
......@@ -14,11 +14,11 @@
__INIT
/*
* Versatile Express specific entry point for secondary CPUs. This
* provides a "holding pen" into which all secondary cores are held
* Realview/Versatile Express specific entry point for secondary CPUs.
* This provides a "holding pen" into which all secondary cores are held
* until we're ready for them to initialise.
*/
ENTRY(vexpress_secondary_startup)
ENTRY(versatile_secondary_startup)
mrc p15, 0, r0, c0, c0, 5
and r0, r0, #15
adr r4, 1f
......
#ifndef PLAT_CLCD_H
#define PLAT_CLCD_H
struct clcd_panel *versatile_clcd_get_panel(const char *);
int versatile_clcd_setup_dma(struct clcd_fb *, unsigned long);
int versatile_clcd_mmap_dma(struct clcd_fb *, struct vm_area_struct *);
void versatile_clcd_remove_dma(struct clcd_fb *);
#endif
#ifndef PLAT_FPGA_IRQ_H
#define PLAT_FPGA_IRQ_H
struct fpga_irq_data {
void __iomem *base;
unsigned int irq_start;
struct irq_chip chip;
};
void fpga_irq_init(int, u32, struct fpga_irq_data *);
#endif
/*
* linux/arch/arm/mach-vexpress/localtimer.c
* linux/arch/arm/plat-versatile/localtimer.c
*
* Copyright (C) 2002 ARM Ltd.
* All Rights Reserved
......@@ -19,8 +19,9 @@
/*
* Setup the local clock events for a CPU.
*/
void __cpuinit local_timer_setup(struct clock_event_device *evt)
int __cpuinit local_timer_setup(struct clock_event_device *evt)
{
evt->irq = IRQ_LOCALTIMER;
twd_timer_setup(evt);
return 0;
}
/*
* linux/arch/arm/plat-versatile/platsmp.c
*
* Copyright (C) 2002 ARM Ltd.
* All Rights Reserved
*
* 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/init.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/jiffies.h>
#include <linux/smp.h>
#include <asm/cacheflush.h>
/*
* control for which core is the next to come out of the secondary
* boot "holding pen"
*/
volatile int __cpuinitdata pen_release = -1;
/*
* Write pen_release in a way that is guaranteed to be visible to all
* observers, irrespective of whether they're taking part in coherency
* or not. This is necessary for the hotplug code to work reliably.
*/
static void __cpuinit write_pen_release(int val)
{
pen_release = val;
smp_wmb();
__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
}
static DEFINE_SPINLOCK(boot_lock);
void __cpuinit platform_secondary_init(unsigned int cpu)
{
/*
* if any interrupts are already enabled for the primary
* core (e.g. timer irq), then they will not have been enabled
* for us: do so
*/
gic_secondary_init(0);
/*
* let the primary processor know we're out of the
* pen, then head off into the C entry point
*/
write_pen_release(-1);
/*
* Synchronise with the boot thread.
*/
spin_lock(&boot_lock);
spin_unlock(&boot_lock);
}
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
{
unsigned long timeout;
/*
* Set synchronisation state between this boot processor
* and the secondary one
*/
spin_lock(&boot_lock);
/*
* This is really belt and braces; we hold unintended secondary
* CPUs in the holding pen until we're ready for them. However,
* since we haven't sent them a soft interrupt, they shouldn't
* be there.
*/
write_pen_release(cpu);
/*
* Send the secondary CPU a soft interrupt, thereby causing
* the boot monitor to read the system wide flags register,
* and branch to the address found there.
*/
smp_cross_call(cpumask_of(cpu), 1);
timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) {
smp_rmb();
if (pen_release == -1)
break;
udelay(10);
}
/*
* now the secondary core is starting up let it run its
* calibrations, then wait for it to finish
*/
spin_unlock(&boot_lock);
return pen_release != -1 ? -ENOSYS : 0;
}
此差异已折叠。
......@@ -120,8 +120,23 @@ static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
static int
clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
{
u32 caps;
int ret = 0;
if (fb->panel->caps && fb->board->caps)
caps = fb->panel->caps & fb->board->caps;
else {
/* Old way of specifying what can be used */
caps = fb->panel->cntl & CNTL_BGR ?
CLCD_CAP_BGR : CLCD_CAP_RGB;
/* But mask out 444 modes as they weren't supported */
caps &= ~CLCD_CAP_444;
}
/* Only TFT panels can do RGB888/BGR888 */
if (!(fb->panel->cntl & CNTL_LCDTFT))
caps &= ~CLCD_CAP_888;
memset(&var->transp, 0, sizeof(var->transp));
var->red.msb_right = 0;
......@@ -133,6 +148,13 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
case 2:
case 4:
case 8:
/* If we can't do 5551, reject */
caps &= CLCD_CAP_5551;
if (!caps) {
ret = -EINVAL;
break;
}
var->red.length = var->bits_per_pixel;
var->red.offset = 0;
var->green.length = var->bits_per_pixel;
......@@ -140,23 +162,61 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
var->blue.length = var->bits_per_pixel;
var->blue.offset = 0;
break;
case 16:
var->red.length = 5;
var->blue.length = 5;
/* If we can't do 444, 5551 or 565, reject */
if (!(caps & (CLCD_CAP_444 | CLCD_CAP_5551 | CLCD_CAP_565))) {
ret = -EINVAL;
break;
}
/*
* Green length can be 5 or 6 depending whether
* we're operating in RGB555 or RGB565 mode.
* Green length can be 4, 5 or 6 depending whether
* we're operating in 444, 5551 or 565 mode.
*/
if (var->green.length != 5 && var->green.length != 6)
var->green.length = 6;
if (var->green.length == 4 && caps & CLCD_CAP_444)
caps &= CLCD_CAP_444;
if (var->green.length == 5 && caps & CLCD_CAP_5551)
caps &= CLCD_CAP_5551;
else if (var->green.length == 6 && caps & CLCD_CAP_565)
caps &= CLCD_CAP_565;
else {
/*
* PL110 officially only supports RGB555,
* but may be wired up to allow RGB565.
*/
if (caps & CLCD_CAP_565) {
var->green.length = 6;
caps &= CLCD_CAP_565;
} else if (caps & CLCD_CAP_5551) {
var->green.length = 5;
caps &= CLCD_CAP_5551;
} else {
var->green.length = 4;
caps &= CLCD_CAP_444;
}
}
if (var->green.length >= 5) {
var->red.length = 5;
var->blue.length = 5;
} else {
var->red.length = 4;
var->blue.length = 4;
}
break;
case 32:
if (fb->panel->cntl & CNTL_LCDTFT) {
var->red.length = 8;
var->green.length = 8;
var->blue.length = 8;
/* If we can't do 888, reject */
caps &= CLCD_CAP_888;
if (!caps) {
ret = -EINVAL;
break;
}
var->red.length = 8;
var->green.length = 8;
var->blue.length = 8;
break;
default:
ret = -EINVAL;
break;
......@@ -168,7 +228,20 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
* the bitfield length defined above.
*/
if (ret == 0 && var->bits_per_pixel >= 16) {
if (fb->panel->cntl & CNTL_BGR) {
bool bgr, rgb;
bgr = caps & CLCD_CAP_BGR && var->blue.offset == 0;
rgb = caps & CLCD_CAP_RGB && var->red.offset == 0;
if (!bgr && !rgb)
/*
* The requested format was not possible, try just
* our capabilities. One of BGR or RGB must be
* supported.
*/
bgr = caps & CLCD_CAP_BGR;
if (bgr) {
var->blue.offset = 0;
var->green.offset = var->blue.offset + var->blue.length;
var->red.offset = var->green.offset + var->green.length;
......@@ -443,8 +516,8 @@ static int clcdfb_register(struct clcd_fb *fb)
fb_set_var(&fb->fb, &fb->fb.var);
printk(KERN_INFO "CLCD: %s hardware, %s display\n",
fb->board->name, fb->panel->mode.name);
dev_info(&fb->dev->dev, "%s hardware, %s display\n",
fb->board->name, fb->panel->mode.name);
ret = register_framebuffer(&fb->fb);
if (ret == 0)
......@@ -486,6 +559,10 @@ static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
fb->dev = dev;
fb->board = board;
dev_info(&fb->dev->dev, "PL%03x rev%u at 0x%08llx\n",
amba_part(dev), amba_rev(dev),
(unsigned long long)dev->res.start);
ret = fb->board->setup(fb);
if (ret)
goto free_fb;
......
......@@ -53,6 +53,7 @@
#define CNTL_LCDBPP8 (3 << 1)
#define CNTL_LCDBPP16 (4 << 1)
#define CNTL_LCDBPP16_565 (6 << 1)
#define CNTL_LCDBPP16_444 (7 << 1)
#define CNTL_LCDBPP24 (5 << 1)
#define CNTL_LCDBW (1 << 4)
#define CNTL_LCDTFT (1 << 5)
......@@ -66,6 +67,32 @@
#define CNTL_LDMAFIFOTIME (1 << 15)
#define CNTL_WATERMARK (1 << 16)
enum {
/* individual formats */
CLCD_CAP_RGB444 = (1 << 0),
CLCD_CAP_RGB5551 = (1 << 1),
CLCD_CAP_RGB565 = (1 << 2),
CLCD_CAP_RGB888 = (1 << 3),
CLCD_CAP_BGR444 = (1 << 4),
CLCD_CAP_BGR5551 = (1 << 5),
CLCD_CAP_BGR565 = (1 << 6),
CLCD_CAP_BGR888 = (1 << 7),
/* connection layouts */
CLCD_CAP_444 = CLCD_CAP_RGB444 | CLCD_CAP_BGR444,
CLCD_CAP_5551 = CLCD_CAP_RGB5551 | CLCD_CAP_BGR5551,
CLCD_CAP_565 = CLCD_CAP_RGB565 | CLCD_CAP_BGR565,
CLCD_CAP_888 = CLCD_CAP_RGB888 | CLCD_CAP_BGR888,
/* red/blue ordering */
CLCD_CAP_RGB = CLCD_CAP_RGB444 | CLCD_CAP_RGB5551 |
CLCD_CAP_RGB565 | CLCD_CAP_RGB888,
CLCD_CAP_BGR = CLCD_CAP_BGR444 | CLCD_CAP_BGR5551 |
CLCD_CAP_BGR565 | CLCD_CAP_BGR888,
CLCD_CAP_ALL = CLCD_CAP_BGR | CLCD_CAP_RGB,
};
struct clcd_panel {
struct fb_videomode mode;
signed short width; /* width in mm */
......@@ -73,6 +100,7 @@ struct clcd_panel {
u32 tim2;
u32 tim3;
u32 cntl;
u32 caps;
unsigned int bpp:8,
fixedtimings:1,
grayscale:1;
......@@ -96,6 +124,11 @@ struct clcd_fb;
struct clcd_board {
const char *name;
/*
* Optional. Hardware capability flags.
*/
u32 caps;
/*
* Optional. Check whether the var structure is acceptable
* for this display.
......@@ -155,34 +188,35 @@ struct clcd_fb {
static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs)
{
struct fb_var_screeninfo *var = &fb->fb.var;
u32 val, cpl;
/*
* Program the CLCD controller registers and start the CLCD
*/
val = ((fb->fb.var.xres / 16) - 1) << 2;
val |= (fb->fb.var.hsync_len - 1) << 8;
val |= (fb->fb.var.right_margin - 1) << 16;
val |= (fb->fb.var.left_margin - 1) << 24;
val = ((var->xres / 16) - 1) << 2;
val |= (var->hsync_len - 1) << 8;
val |= (var->right_margin - 1) << 16;
val |= (var->left_margin - 1) << 24;
regs->tim0 = val;
val = fb->fb.var.yres;
val = var->yres;
if (fb->panel->cntl & CNTL_LCDDUAL)
val /= 2;
val -= 1;
val |= (fb->fb.var.vsync_len - 1) << 10;
val |= fb->fb.var.lower_margin << 16;
val |= fb->fb.var.upper_margin << 24;
val |= (var->vsync_len - 1) << 10;
val |= var->lower_margin << 16;
val |= var->upper_margin << 24;
regs->tim1 = val;
val = fb->panel->tim2;
val |= fb->fb.var.sync & FB_SYNC_HOR_HIGH_ACT ? 0 : TIM2_IHS;
val |= fb->fb.var.sync & FB_SYNC_VERT_HIGH_ACT ? 0 : TIM2_IVS;
val |= var->sync & FB_SYNC_HOR_HIGH_ACT ? 0 : TIM2_IHS;
val |= var->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : TIM2_IVS;
cpl = fb->fb.var.xres_virtual;
cpl = var->xres_virtual;
if (fb->panel->cntl & CNTL_LCDTFT) /* TFT */
/* / 1 */;
else if (!fb->fb.var.grayscale) /* STN color */
else if (!var->grayscale) /* STN color */
cpl = cpl * 8 / 3;
else if (fb->panel->cntl & CNTL_LCDMONO8) /* STN monochrome, 8bit */
cpl /= 8;
......@@ -194,10 +228,22 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs)
regs->tim3 = fb->panel->tim3;
val = fb->panel->cntl;
if (fb->fb.var.grayscale)
if (var->grayscale)
val |= CNTL_LCDBW;
switch (fb->fb.var.bits_per_pixel) {
if (fb->panel->caps && fb->board->caps &&
var->bits_per_pixel >= 16) {
/*
* if board and panel supply capabilities, we can support
* changing BGR/RGB depending on supplied parameters
*/
if (var->red.offset == 0)
val &= ~CNTL_BGR;
else
val |= CNTL_BGR;
}
switch (var->bits_per_pixel) {
case 1:
val |= CNTL_LCDBPP1;
break;
......@@ -212,15 +258,17 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs)
break;
case 16:
/*
* PL110 cannot choose between 5551 and 565 modes in
* its control register
* PL110 cannot choose between 5551 and 565 modes in its
* control register. It is possible to use 565 with
* custom external wiring.
*/
if ((fb->dev->periphid & 0x000fffff) == 0x00041110)
if (amba_part(fb->dev) == 0x110 ||
var->green.length == 5)
val |= CNTL_LCDBPP16;
else if (fb->fb.var.green.length == 5)
val |= CNTL_LCDBPP16;
else
else if (var->green.length == 6)
val |= CNTL_LCDBPP16_565;
else
val |= CNTL_LCDBPP16_444;
break;
case 32:
val |= CNTL_LCDBPP24;
......@@ -228,7 +276,7 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs)
}
regs->cntl = val;
regs->pixclock = fb->fb.var.pixclock;
regs->pixclock = var->pixclock;
}
static inline int clcdfb_check(struct clcd_fb *fb, struct fb_var_screeninfo *var)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册