Commit ae650d87 authored by Russell King's avatar Russell King

Merge flint.arm.linux.org.uk:/usr/src/linux-bk-2.5/linux-2.5

into flint.arm.linux.org.uk:/usr/src/linux-bk-2.5/linux-2.5-rmk
parents 7ef85b9f 4cf9be2c
......@@ -165,6 +165,8 @@ source "arch/arm/mach-epxa10db/Kconfig"
source "arch/arm/mach-footbridge/Kconfig"
source "arch/arm/mach-integrator/Kconfig"
source "arch/arm/mach-iop3xx/Kconfig"
source "arch/arm/mach-pxa/Kconfig"
......@@ -1014,15 +1016,6 @@ config DEBUG_ERRORS
you are concerned with the code size or don't want to see these
messages.
config DEBUG_INFO
bool "Compile the kernel with debug info"
depends on DEBUG_KERNEL
help
If you say Y here the resulting kernel image will include
debugging info resulting in a larger kernel image.
Say Y here only if you plan to use gdb to debug the kernel.
If you don't debug the kernel, you can say N.
# These options are only for real kernel hackers who want to get their hands dirty.
config DEBUG_LL
bool "Kernel low-level debugging functions"
......
......@@ -20,10 +20,6 @@ ifeq ($(CONFIG_FRAME_POINTER),y)
CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
endif
ifeq ($(CONFIG_DEBUG_INFO),y)
CFLAGS +=-g
endif
ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
CFLAGS += -mbig-endian
AS += -EB
......
......@@ -180,7 +180,7 @@ int amba_device_register(struct amba_device *dev, struct resource *parent)
dev->dev.release = amba_device_release;
dev->dev.bus = &amba_bustype;
dev->res.name = dev->dev.name;
dev->res.name = dev->dev.bus_id;
ret = request_resource(parent, &dev->res);
if (ret == 0) {
......@@ -200,14 +200,6 @@ int amba_device_register(struct amba_device *dev, struct resource *parent)
if (cid == 0xb105f00d)
dev->periphid = pid;
if (dev->periphid)
snprintf(dev->dev.name, sizeof(dev->dev.name),
"AMBA PL%03X",
dev->periphid & 0xfff);
else
strlcpy(dev->dev.name, "AMBA unknown",
sizeof(dev->dev.name));
ret = device_register(&dev->dev);
if (ret == 0) {
device_create_file(&dev->dev, &dev_attr_id);
......
......@@ -9,7 +9,7 @@ int __init platform_add_device(struct platform_device *dev)
for (i = 0; i < dev->num_resources; i++) {
struct resource *r = &dev->resource[i];
r->name = dev->dev.name;
r->name = dev->dev.bus_id;
if (r->flags & IORESOURCE_MEM &&
request_resource(&iomem_resource, r)) {
......
......@@ -55,9 +55,6 @@ struct sa1111 {
static struct sa1111 *g_sa1111;
static struct sa1111_dev usb_dev = {
.dev = {
.name = "Intel Corporation SA1111 [USB Controller]",
},
.skpcr_mask = SKPCR_UCLKEN,
.devid = SA1111_DEVID_USB,
.irq = {
......@@ -71,9 +68,6 @@ static struct sa1111_dev usb_dev = {
};
static struct sa1111_dev sac_dev = {
.dev = {
.name = "Intel Corporation SA1111 [Audio Controller]",
},
.skpcr_mask = SKPCR_I2SCLKEN | SKPCR_L3CLKEN,
.devid = SA1111_DEVID_SAC,
.irq = {
......@@ -85,17 +79,11 @@ static struct sa1111_dev sac_dev = {
};
static struct sa1111_dev ssp_dev = {
.dev = {
.name = "Intel Corporation SA1111 [SSP Controller]",
},
.skpcr_mask = SKPCR_SCLKEN,
.devid = SA1111_DEVID_SSP,
};
static struct sa1111_dev kbd_dev = {
.dev = {
.name = "Intel Corporation SA1111 [PS2]",
},
.skpcr_mask = SKPCR_PTCLKEN,
.devid = SA1111_DEVID_PS2,
.irq = {
......@@ -105,9 +93,6 @@ static struct sa1111_dev kbd_dev = {
};
static struct sa1111_dev mse_dev = {
.dev = {
.name = "Intel Corporation SA1111 [PS2]",
},
.skpcr_mask = SKPCR_PMCLKEN,
.devid = SA1111_DEVID_PS2,
.irq = {
......@@ -117,17 +102,11 @@ static struct sa1111_dev mse_dev = {
};
static struct sa1111_dev int_dev = {
.dev = {
.name = "Intel Corporation SA1111 [Interrupt Controller]",
},
.skpcr_mask = 0,
.devid = SA1111_DEVID_INT,
};
static struct sa1111_dev pcmcia_dev = {
.dev = {
.name = "Intel Corporation SA1111 [PCMCIA Controller]",
},
.skpcr_mask = 0,
.devid = SA1111_DEVID_PCMCIA,
.irq = {
......@@ -570,7 +549,7 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
sadev->dev.bus = &sa1111_bus_type;
sadev->res.start = sachip->phys + offset;
sadev->res.end = sadev->res.start + 511;
sadev->res.name = sadev->dev.name;
sadev->res.name = sadev->dev.bus_id;
sadev->res.flags = IORESOURCE_MEM;
sadev->mapbase = sachip->base + offset;
......
......@@ -811,7 +811,7 @@ static void ecard_proc_init(void)
#define ec_set_resource(ec,nr,st,sz,flg) \
do { \
(ec)->resource[nr].name = ec->dev.name; \
(ec)->resource[nr].name = ec->dev.bus_id; \
(ec)->resource[nr].start = st; \
(ec)->resource[nr].end = (st) + (sz) - 1; \
(ec)->resource[nr].flags = flg; \
......@@ -893,6 +893,22 @@ static ssize_t ecard_show_resources(struct device *dev, char *buf)
static DEVICE_ATTR(resource, S_IRUGO, ecard_show_resources, NULL);
static ssize_t ecard_show_vendor(struct device *dev, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->manufacturer);
}
static DEVICE_ATTR(vendor, S_IRUGO, ecard_show_vendor, NULL);
static ssize_t ecard_show_device(struct device *dev, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->product);
}
static DEVICE_ATTR(device, S_IRUGO, ecard_show_device, NULL);
/*
* Probe for an expansion card.
*
......@@ -962,8 +978,6 @@ ecard_probe(int slot, card_type_t type)
}
snprintf(ec->dev.bus_id, sizeof(ec->dev.bus_id), "ecard%d", slot);
snprintf(ec->dev.name, sizeof(ec->dev.name), "ecard %04x:%04x",
ec->cid.manufacturer, ec->cid.product);
ec->dev.parent = NULL;
ec->dev.bus = &ecard_bus_type;
ec->dev.dma_mask = &ec->dma_mask;
......@@ -1000,6 +1014,8 @@ ecard_probe(int slot, card_type_t type)
device_create_file(&ec->dev, &dev_attr_dma);
device_create_file(&ec->dev, &dev_attr_irq);
device_create_file(&ec->dev, &dev_attr_resource);
device_create_file(&ec->dev, &dev_attr_vendor);
device_create_file(&ec->dev, &dev_attr_device);
return 0;
......
......@@ -150,11 +150,6 @@ static void dump_instr(struct pt_regs *regs)
set_fs(fs);
}
static void __dump_stack(struct task_struct *tsk, unsigned long sp)
{
dump_mem("Stack: ", sp, 8192+(unsigned long)tsk->thread_info);
}
static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
{
unsigned int fp;
......@@ -183,14 +178,12 @@ void dump_stack(void)
#endif
}
/*
* This is called from SysRq-T (show_task) to display the current call
* trace for each process. This version will also display the running
* threads call trace (ie, us.)
*/
void show_trace_task(struct task_struct *tsk)
void show_stack(struct task_struct *tsk, unsigned long *sp)
{
unsigned int fp;
unsigned long fp;
if (!tsk)
tsk = current;
if (tsk != current)
fp = thread_saved_fp(tsk);
......@@ -222,7 +215,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
current->comm, current->pid, tsk->thread_info + 1);
if (!user_mode(regs) || in_interrupt()) {
__dump_stack(tsk, (unsigned long)(regs + 1));
dump_mem("Stack: ", (unsigned long)(regs + 1), 8192+(unsigned long)tsk->thread_info);
dump_backtrace(regs, tsk);
dump_instr(regs);
}
......
menu "Integrator Options"
depends on ARCH_INTEGRATOR
config INTEGRATOR_IMPD1
tristate "Include support for Integrator/IM-PD1"
help
The IM-PD1 is an add-on logic module for the Integrator which
allows ARM(R) Ltd PrimeCells to be developed and evaluated.
The IM-PD1 can be found on the Integrator/PP2 platform.
If you want to compile this as a module (=code which can be
inserted into and removed from the running kernel), say M
here and read <file:Documentation/modules.txt>. The module
will be called impd1.
endmenu
......@@ -9,3 +9,4 @@ obj-y := core.o time.o
obj-$(CONFIG_LEDS) += leds.o
obj-$(CONFIG_PCI) += pci_v3.o pci.o
obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o
obj-$(CONFIG_INTEGRATOR_IMPD1) += impd1.o
/*
* linux/arch/arm/mach-integrator/impd1.c
*
* Copyright (C) 2003 Deep Blue Solutions 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.
*
* This file provides the core support for the IM-PD1 module.
*
* Module / boot parameters.
* id=n impd1.id=n - set the logic module position in stack to 'n'
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <asm/io.h>
#include <asm/hardware/icst525.h>
#include <asm/hardware/amba.h>
#include <asm/arch/impd1.h>
#include <asm/sizes.h>
static int module_id;
module_param_named(lmid, module_id, int, 0);
MODULE_PARM_DESC(lmid, "logic module stack position");
#define ROM_OFFSET 0x0fffff00
#define ROM_SIZE 256
struct impd1_module {
void *base;
};
static const struct icst525_params impd1_vco_params = {
.ref = 24000, /* 24 MHz */
.vco_max = 200000, /* 200 MHz */
.vd_min = 12,
.vd_max = 519,
.rd_min = 3,
.rd_max = 120,
};
void impd1_set_vco(struct device *dev, int vconr, unsigned long period)
{
struct impd1_module *impd1 = dev_get_drvdata(dev);
struct icst525_vco vco;
u32 val;
vco = icst525_ps_to_vco(&impd1_vco_params, period);
pr_debug("Guessed VCO reg params: S=%d R=%d V=%d\n",
vco.s, vco.r, vco.v);
val = vco.v | (vco.r << 9) | (vco.s << 16);
writel(0xa05f, impd1->base + IMPD1_LOCK);
switch (vconr) {
case 1:
writel(val, impd1->base + IMPD1_OSC1);
break;
case 2:
writel(val, impd1->base + IMPD1_OSC2);
break;
}
writel(0, impd1->base + IMPD1_LOCK);
#if DEBUG
vco.v = val & 0x1ff;
vco.r = (val >> 9) & 0x7f;
vco.s = (val >> 16) & 7;
pr_debug("IM-PD1: VCO%d clock is %ld kHz\n",
vconr, icst525_khz(&impd1_vco_params, vco));
#endif
}
EXPORT_SYMBOL(impd1_set_vco);
void impd1_tweak_control(struct device *dev, u32 mask, u32 val)
{
struct impd1_module *impd1 = dev_get_drvdata(dev);
u32 cur;
val &= mask;
cur = readl(impd1->base + IMPD1_CTRL) & ~mask;
writel(cur | val, impd1->base + IMPD1_CTRL);
}
EXPORT_SYMBOL(impd1_tweak_control);
struct impd1_device {
unsigned long offset;
unsigned int irq[2];
unsigned int id;
};
static struct impd1_device impd1_devs[] = {
{
.offset = 0x03000000,
.id = 0x00041190,
}, {
.offset = 0x00100000,
.irq = { 1 },
.id = 0x00141011,
}, {
.offset = 0x00200000,
.irq = { 2 },
.id = 0x00141011,
}, {
.offset = 0x00300000,
.irq = { 3 },
.id = 0x00041022,
}, {
.offset = 0x00400000,
.irq = { 4 },
.id = 0x00041061,
}, {
.offset = 0x00500000,
.irq = { 5 },
.id = 0x00041061,
}, {
.offset = 0x00600000,
.irq = { 6 },
.id = 0x00041130,
}, {
.offset = 0x00700000,
.irq = { 7, 8 },
.id = 0x00041181,
}, {
.offset = 0x00800000,
.irq = { 9 },
.id = 0x00041041,
}, {
.offset = 0x01000000,
.irq = { 11 },
.id = 0x00041110,
}
};
static int impd1_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct resource *res = &pdev->resource[0];
struct impd1_module *impd1;
int i, ret;
if (pdev->id != module_id)
return -EINVAL;
if (!request_mem_region(res->start, SZ_4K, "LM registers"))
return -EBUSY;
impd1 = kmalloc(sizeof(struct impd1_module), GFP_KERNEL);
if (!impd1) {
ret = -ENOMEM;
goto release_lm;
}
memset(impd1, 0, sizeof(struct impd1_module));
impd1->base = ioremap(res->start, SZ_4K);
if (!impd1->base) {
ret = -ENOMEM;
goto free_impd1;
}
dev_set_drvdata(dev, impd1);
printk("IM-PD1 found at 0x%08lx\n", res->start);
for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) {
struct impd1_device *idev = impd1_devs + i;
struct amba_device *d;
unsigned long pc_base;
pc_base = res->start + idev->offset;
d = kmalloc(sizeof(struct amba_device), GFP_KERNEL);
if (!d)
continue;
memset(d, 0, sizeof(struct amba_device));
snprintf(d->dev.bus_id, sizeof(d->dev.bus_id),
"lm%x:%5.5x", pdev->id, idev->offset >> 12);
d->dev.parent = &pdev->dev;
d->res.start = res->start + idev->offset;
d->res.end = d->res.start + SZ_4K - 1;
d->res.flags = IORESOURCE_MEM;
d->irq = pdev->resource[1].start;
d->periphid = idev->id;
ret = amba_device_register(d, res);
if (ret) {
printk("unable to register device %s: %d\n",
d->dev.bus_id, ret);
kfree(d);
}
}
return 0;
free_impd1:
if (impd1 && impd1->base)
iounmap(impd1->base);
if (impd1)
kfree(impd1);
release_lm:
release_mem_region(res->start, SZ_4K);
return ret;
}
static int impd1_remove(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct resource *res = &pdev->resource[0];
struct impd1_module *impd1 = dev_get_drvdata(dev);
struct list_head *l, *n;
list_for_each_safe(l, n, &dev->children) {
struct device *d = list_to_dev(l);
device_unregister(d);
}
dev_set_drvdata(dev, NULL);
iounmap(impd1->base);
kfree(impd1);
release_mem_region(res->start, SZ_4K);
return 0;
}
static struct device_driver impd1_driver = {
.name = "lm",
.bus = &platform_bus_type,
.probe = impd1_probe,
.remove = impd1_remove,
};
static int __init impd1_init(void)
{
return driver_register(&impd1_driver);
}
static void __exit impd1_exit(void)
{
driver_unregister(&impd1_driver);
}
module_init(impd1_init);
module_exit(impd1_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Integrator/IM-PD1 logic module core driver");
MODULE_AUTHOR("Deep Blue Solutions Ltd");
......@@ -104,9 +104,6 @@ static struct resource sa1111_resources[] = {
static struct platform_device sa1111_device = {
.name = "sa1111",
.id = 0,
.dev = {
.name = "Intel Corporation SA1111",
},
.num_resources = ARRAY_SIZE(sa1111_resources),
.resource = sa1111_resources,
};
......
......@@ -46,7 +46,6 @@ static struct platform_device sa1111_device = {
.name = "sa1111",
.id = 0,
.dev = {
.name = "Intel Corporation SA1111",
.dma_mask = &sa1111_dmamask,
},
.num_resources = ARRAY_SIZE(sa1111_resources),
......
......@@ -54,7 +54,6 @@ static struct platform_device sa1111_device = {
.name = "sa1111",
.id = 0,
.dev = {
.name = "Intel Corporation SA1111",
.dma_mask = &sa1111_dmamask;
},
.num_resources = ARRAY_SIZE(sa1111_resources),
......
......@@ -282,19 +282,19 @@ static int sa1110_target(struct cpufreq_policy *policy,
local_irq_save(flags);
asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
udelay(10);
__asm__ __volatile__("
b 2f
.align 5
1: str %3, [%1, #0] @ MDCNFG
str %4, [%1, #28] @ MDREFR
str %5, [%1, #4] @ MDCAS0
str %6, [%1, #8] @ MDCAS1
str %7, [%1, #12] @ MDCAS2
str %8, [%2, #0] @ PPCR
ldr %0, [%1, #0]
b 3f
2: b 1b
3: nop
__asm__ __volatile__(" \n\
b 2f \n\
.align 5 \n\
1: str %3, [%1, #0] @ MDCNFG \n\
str %4, [%1, #28] @ MDREFR \n\
str %5, [%1, #4] @ MDCAS0 \n\
str %6, [%1, #8] @ MDCAS1 \n\
str %7, [%1, #12] @ MDCAS2 \n\
str %8, [%2, #0] @ PPCR \n\
ldr %0, [%1, #0] \n\
b 3f \n\
2: b 1b \n\
3: nop \n\
nop"
: "=&r" (unused)
: "r" (&MDCNFG), "r" (&PPCR), "0" (sd.mdcnfg),
......
......@@ -144,7 +144,6 @@ static struct platform_device sa11x0udc_device = {
.name = "sa11x0-udc",
.id = 0,
.dev = {
.name = "Intel Corporation SA11x0 [UDC]",
.dma_mask = &sa11x0udc_dma_mask,
},
.num_resources = ARRAY_SIZE(sa11x0udc_resources),
......@@ -162,9 +161,6 @@ static struct resource sa11x0mcp_resources[] = {
static struct platform_device sa11x0mcp_device = {
.name = "sa11x0-mcp",
.id = 0,
.dev = {
.name = "Intel Corporation SA11x0 [MCP]",
},
.num_resources = ARRAY_SIZE(sa11x0mcp_resources),
.resource = sa11x0mcp_resources,
};
......@@ -183,7 +179,6 @@ static struct platform_device sa11x0ssp_device = {
.name = "sa11x0-ssp",
.id = 0,
.dev = {
.name = "Intel Corporation SA11x0 [SSP]",
.dma_mask = &sa11x0ssp_dma_mask,
},
.num_resources = ARRAY_SIZE(sa11x0ssp_resources),
......@@ -206,9 +201,6 @@ static struct resource sa11x0fb_resources[] = {
static struct platform_device sa11x0fb_device = {
.name = "sa11x0-fb",
.id = 0,
.dev = {
.name = "Intel Corporation SA11x0 [LCD]",
},
.num_resources = ARRAY_SIZE(sa11x0fb_resources),
.resource = sa11x0fb_resources,
};
......@@ -216,9 +208,6 @@ static struct platform_device sa11x0fb_device = {
static struct platform_device sa11x0pcmcia_device = {
.name = "sa11x0-pcmcia",
.id = 0,
.dev = {
.name = "Intel Corporation SA11x0 [PCMCIA]",
},
};
static struct platform_device *sa11x0_devices[] __initdata = {
......
......@@ -43,7 +43,6 @@ static struct platform_device sa1111_device = {
.name = "sa1111",
.id = 0,
.dev = {
.name = "Intel Corporation SA1111",
.dma_mask = &sa1111_dmamask,
},
.num_resources = ARRAY_SIZE(sa1111_resources),
......
......@@ -43,7 +43,6 @@ static struct platform_device sa1111_device = {
.name = "sa1111",
.id = 0,
.dev = {
.name = "Intel Corporation SA1111",
.dma_mask = &sa1111_dmamask,
},
.num_resources = ARRAY_SIZE(sa1111_resources),
......
......@@ -227,9 +227,6 @@ static struct resource neponset_resources[] = {
static struct platform_device neponset_device = {
.name = "neponset",
.id = 0,
.dev = {
.name = "Neponset",
},
.num_resources = ARRAY_SIZE(neponset_resources),
.resource = neponset_resources,
};
......@@ -253,7 +250,6 @@ static struct platform_device sa1111_device = {
.name = "sa1111",
.id = 0,
.dev = {
.name = "Intel Corporation SA1111",
.dma_mask = &sa1111_dmamask,
},
.num_resources = ARRAY_SIZE(sa1111_resources),
......
......@@ -38,7 +38,6 @@ static struct platform_device sa1111_device = {
.name = "sa1111",
.id = 0,
.dev = {
.name = "Intel Corporation SA1111",
.dma_mask = &sa1111_dmamask,
},
.num_resources = ARRAY_SIZE(sa1111_resources),
......
......@@ -392,7 +392,6 @@ static struct platform_device sa1111_device = {
.name = "sa1111",
.id = 0,
.dev = {
.name = "Intel Corporation SA1111",
.dma_mask = &sa1111_dmamask,
},
.num_resources = ARRAY_SIZE(sa1111_resources),
......
......@@ -44,7 +44,6 @@ static struct platform_device sa1111_device = {
.name = "sa1111",
.id = 0,
.dev = {
.name = "Intel Corporation SA1111",
.dma_mask = &sa1111_dmamask,
},
.num_resources = ARRAY_SIZE(sa1111_resources),
......
......@@ -305,9 +305,35 @@ static struct mem_types mem_types[] __initdata = {
*/
static void __init build_mem_type_table(void)
{
unsigned int cr = get_cr();
int cpu_arch = cpu_architecture();
const char *policy;
/*
* ARMv6 and above have extended page tables.
*/
if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
/*
* bit 4 becomes XN which we must clear for the
* kernel memory mapping.
*/
mem_types[MT_MEMORY].prot_sect &= ~PMD_BIT4;
/*
* Mark cache clean areas read only from SVC mode
* and no access from userspace.
*/
mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
}
/*
* ARMv6 can map the vectors as write-through.
*/
if (cpu_arch >= CPU_ARCH_ARMv6)
mem_types[MT_VECTORS].prot_pte |= PTE_CACHEABLE;
else
mem_types[MT_VECTORS].prot_pte |= PTE_BUFFERABLE|PTE_CACHEABLE;
/*
* ARMv5 and higher can use ECC memory.
*/
......
/*
* linux/arch/arm/mm/mmu.c
*
* Copyright (C) 2002-2003 Deep Blue Solutions 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/sched.h>
#include <linux/mm.h>
#include <asm/mmu_context.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
unsigned int cpu_last_asid = { 1 << ASID_BITS };
/*
* We fork()ed a process, and we need a new context for the child
* to run in. We reserve version 0 for initial tasks so we will
* always allocate an ASID.
*/
void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
{
mm->context.id = 0;
}
void __new_context(struct mm_struct *mm)
{
unsigned int asid;
asid = ++cpu_last_asid;
if (asid == 0)
asid = cpu_last_asid = 1 << ASID_BITS;
/*
* If we've used up all our ASIDs, we need
* to start a new version and flush the TLB.
*/
if ((asid & ~ASID_MASK) == 0)
flush_tlb_all();
mm->context.id = asid;
}
#define IMPD1_OSC1 0x00
#define IMPD1_OSC2 0x04
#define IMPD1_LOCK 0x08
#define IMPD1_LEDS 0x0c
#define IMPD1_INT 0x10
#define IMPD1_SW 0x14
#define IMPD1_CTRL 0x18
#define IMPD1_CTRL_DISP_LCD (0 << 0)
#define IMPD1_CTRL_DISP_VGA (1 << 0)
#define IMPD1_CTRL_DISP_LCD1 (2 << 0)
#define IMPD1_CTRL_DISP_ENABLE (1 << 2)
#define IMPD1_CTRL_DISP_MASK (7 << 0)
struct device;
void impd1_set_vco(struct device *dev, int vconr, unsigned long period);
void impd1_tweak_control(struct device *dev, u32 mask, u32 val);
#ifndef __ARM_MMU_H
#define __ARM_MMU_H
/*
* The ARM doesn't have a mmu context
*/
typedef struct { } mm_context_t;
#include <linux/config.h>
typedef struct {
#if __LINUX_ARM_ARCH__ >= 6
unsigned int id;
#endif
} mm_context_t;
#if __LINUX_ARM_ARCH__ >= 6
#define ASID(mm) ((mm)->context.id & 255)
#else
#define ASID(mm) (0)
#endif
#endif
......@@ -15,7 +15,45 @@
#include <asm/proc-fns.h>
#if __LINUX_ARM_ARCH__ >= 6
/*
* On ARMv6, we have the following structure in the Context ID:
*
* 31 7 0
* +-------------------------+-----------+
* | process ID | ASID |
* +-------------------------+-----------+
* | context ID |
* +-------------------------------------+
*
* The ASID is used to tag entries in the CPU caches and TLBs.
* The context ID is used by debuggers and trace logic, and
* should be unique within all running processes.
*/
#define ASID_BITS 8
#define ASID_MASK ((~0) << ASID_BITS)
extern unsigned int cpu_last_asid;
void __init_new_context(struct task_struct *tsk, struct mm_struct *mm);
void __new_context(struct mm_struct *mm);
static inline void check_context(struct mm_struct *mm)
{
if (unlikely((mm->context.id ^ cpu_last_asid) >> ASID_BITS))
__new_context(mm);
}
#define init_new_context(tsk,mm) (__init_new_context(tsk,mm),0)
#else
#define check_context(mm) do { } while (0)
#define init_new_context(tsk,mm) 0
#endif
#define destroy_context(mm) do { } while(0)
/*
......@@ -43,6 +81,7 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk)
{
if (prev != next) {
check_context(next);
cpu_switch_mm(next->pgd, next);
}
}
......@@ -51,6 +90,7 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
{
check_context(next);
cpu_switch_mm(next->pgd, next);
}
......
......@@ -49,6 +49,9 @@
#define PMD_SECT_AP_WRITE (1 << 10)
#define PMD_SECT_AP_READ (1 << 11)
#define PMD_SECT_TEX(x) ((x) << 12) /* v5 */
#define PMD_SECT_APX (1 << 15) /* v6 */
#define PMD_SECT_S (1 << 16) /* v6 */
#define PMD_SECT_nG (1 << 17) /* v6 */
#define PMD_SECT_UNCACHED (0)
#define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE)
......
......@@ -41,6 +41,14 @@
#define CR_I (1 << 12) /* Icache enable */
#define CR_V (1 << 13) /* Vectors relocated to 0xffff0000 */
#define CR_RR (1 << 14) /* Round Robin cache replacement */
#define CR_L4 (1 << 15) /* LDR pc can set T bit */
#define CR_DT (1 << 16)
#define CR_IT (1 << 18)
#define CR_ST (1 << 19)
#define CR_FI (1 << 21)
#define CR_U (1 << 22) /* Unaligned access operation */
#define CR_XP (1 << 23) /* Extended page tables */
#define CR_VE (1 << 24) /* Vectored interrupts */
extern unsigned long cr_no_alignment; /* defined in entry-armv.S */
extern unsigned long cr_alignment; /* defined in entry-armv.S */
......
......@@ -14,11 +14,21 @@
#define TLB_V4_U_PAGE (1 << 1)
#define TLB_V4_D_PAGE (1 << 2)
#define TLB_V4_I_PAGE (1 << 3)
#define TLB_V6_U_PAGE (1 << 4)
#define TLB_V6_D_PAGE (1 << 5)
#define TLB_V6_I_PAGE (1 << 6)
#define TLB_V3_FULL (1 << 8)
#define TLB_V4_U_FULL (1 << 9)
#define TLB_V4_D_FULL (1 << 10)
#define TLB_V4_I_FULL (1 << 11)
#define TLB_V6_U_FULL (1 << 12)
#define TLB_V6_D_FULL (1 << 13)
#define TLB_V6_I_FULL (1 << 14)
#define TLB_V6_U_ASID (1 << 16)
#define TLB_V6_D_ASID (1 << 17)
#define TLB_V6_I_ASID (1 << 18)
#define TLB_DCLEAN (1 << 30)
#define TLB_WB (1 << 31)
......@@ -32,6 +42,7 @@
* v4 - ARMv4 without write buffer
* v4wb - ARMv4 with write buffer without I TLB flush entry instruction
* v4wbi - ARMv4 with write buffer with I TLB flush entry instruction
* v6wbi - ARMv6 with write buffer with I TLB flush entry instruction
*/
#undef _TLB
#undef MULTI_TLB
......@@ -102,6 +113,24 @@
# define v4wb_always_flags (-1UL)
#endif
#define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | \
TLB_V6_I_FULL | TLB_V6_D_FULL | \
TLB_V6_I_PAGE | TLB_V6_D_PAGE | \
TLB_V6_I_ASID | TLB_V6_D_ASID)
#if defined(CONFIG_CPU_V6)
# define v6wbi_possible_flags v6wbi_tlb_flags
# define v6wbi_always_flags v6wbi_tlb_flags
# ifdef _TLB
# define MULTI_TLB 1
# else
# define _TLB v6wbi
# endif
#else
# define v6wbi_possible_flags 0
# define v6wbi_always_flags (-1UL)
#endif
#ifndef _TLB
#error Unknown TLB model
#endif
......@@ -194,12 +223,14 @@ extern struct cpu_tlb_fns cpu_tlb;
#define possible_tlb_flags (v3_possible_flags | \
v4_possible_flags | \
v4wbi_possible_flags | \
v4wb_possible_flags)
v4wb_possible_flags | \
v6wbi_possible_flags)
#define always_tlb_flags (v3_always_flags & \
v4_always_flags & \
v4wbi_always_flags & \
v4wb_always_flags)
v4wb_always_flags & \
v6wbi_always_flags)
#define tlb_flag(f) ((always_tlb_flags & (f)) || (__tlb_flag & possible_tlb_flags & (f)))
......@@ -213,17 +244,18 @@ static inline void flush_tlb_all(void)
if (tlb_flag(TLB_V3_FULL))
asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (zero));
if (tlb_flag(TLB_V4_U_FULL))
if (tlb_flag(TLB_V4_U_FULL | TLB_V6_U_FULL))
asm("mcr%? p15, 0, %0, c8, c7, 0" : : "r" (zero));
if (tlb_flag(TLB_V4_D_FULL))
if (tlb_flag(TLB_V4_D_FULL | TLB_V6_D_FULL))
asm("mcr%? p15, 0, %0, c8, c6, 0" : : "r" (zero));
if (tlb_flag(TLB_V4_I_FULL))
if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL))
asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
}
static inline void flush_tlb_mm(struct mm_struct *mm)
{
const int zero = 0;
const int asid = ASID(mm);
const unsigned int __tlb_flag = __cpu_tlb_flags;
if (tlb_flag(TLB_WB))
......@@ -239,6 +271,13 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
if (tlb_flag(TLB_V4_I_FULL))
asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
}
if (tlb_flag(TLB_V6_U_ASID))
asm("mcr%? p15, 0, %0, c8, c7, 2" : : "r" (asid));
if (tlb_flag(TLB_V6_D_ASID))
asm("mcr%? p15, 0, %0, c8, c6, 2" : : "r" (asid));
if (tlb_flag(TLB_V6_I_ASID))
asm("mcr%? p15, 0, %0, c8, c5, 2" : : "r" (asid));
}
static inline void
......@@ -247,7 +286,7 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
const int zero = 0;
const unsigned int __tlb_flag = __cpu_tlb_flags;
uaddr &= PAGE_MASK;
uaddr = (uaddr & PAGE_MASK) | ASID(vma->vm_mm);
if (tlb_flag(TLB_WB))
asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
......@@ -264,6 +303,13 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL))
asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
}
if (tlb_flag(TLB_V6_U_PAGE))
asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (uaddr));
if (tlb_flag(TLB_V6_D_PAGE))
asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (uaddr));
if (tlb_flag(TLB_V6_I_PAGE))
asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (uaddr));
}
static inline void flush_tlb_kernel_page(unsigned long kaddr)
......@@ -286,6 +332,13 @@ static inline void flush_tlb_kernel_page(unsigned long kaddr)
asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (kaddr));
if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL))
asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
if (tlb_flag(TLB_V6_U_PAGE))
asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (kaddr));
if (tlb_flag(TLB_V6_D_PAGE))
asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (kaddr));
if (tlb_flag(TLB_V6_I_PAGE))
asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (kaddr));
}
/*
......
......@@ -41,6 +41,7 @@ extern asmlinkage void __backtrace(void);
#define CPU_ARCH_ARMv5 4
#define CPU_ARCH_ARMv5T 5
#define CPU_ARCH_ARMv5TE 6
#define CPU_ARCH_ARMv6 7
extern int cpu_architecture(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment