Commit 8144c157 authored by David S. Miller's avatar David S. Miller

Merge davem@nuts.ninka.net:/home/davem/src/BK/net-2.5

into kernel.bkbits.net:/home/davem/net-2.5
parents adc71682 28ea8844
......@@ -483,6 +483,16 @@ config PCI_HOST_VIA82C505
depends on PCI && ARCH_SHARK
default y
config ICST525
bool
depends on ARCH_INTEGRATOR
default y
config ARM_AMBA
bool
depends on ARCH_INTEGRATOR
default y
config ISA
bool
depends on FOOTBRIDGE_HOST || ARCH_SHARK || ARCH_CLPS7500 || ARCH_EBSA110 || ARCH_CDB89712 || ARCH_EDB7211 || ARCH_SA1100
......@@ -582,7 +592,7 @@ endif
config CPU_FREQ_INTEGRATOR
tristate "CPUfreq driver for ARM Integrator CPUs"
depends on ARCH_INTEGRATOR && CPU_FREQ
depends on ARCH_INTEGRATOR && ICST525 && CPU_FREQ
default y
help
This enables the CPUfreq driver for ARM Integrator CPUs.
......
......@@ -3,6 +3,8 @@
#
obj-y += platform.o
obj-$(CONFIG_ARM_AMBA) += amba.o
obj-$(CONFIG_ICST525) += icst525.o
obj-$(CONFIG_SA1111) += sa1111.o sa1111-pcibuf.o sa1111-pcipool.o
obj-$(CONFIG_PCI_HOST_PLX90X0) += plx90x0.o
obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o
/*
* linux/arch/arm/common/amba.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.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <asm/io.h>
#include <asm/hardware/amba.h>
#include <asm/sizes.h>
#define to_amba_device(d) container_of(d, struct amba_device, dev)
#define to_amba_driver(d) container_of(d, struct amba_driver, drv)
static struct amba_id *
amba_lookup(struct amba_id *table, struct amba_device *dev)
{
int ret = 0;
while (table->mask) {
ret = (dev->periphid & table->mask) == table->id;
if (ret)
break;
table++;
}
return ret ? table : NULL;
}
static int amba_match(struct device *dev, struct device_driver *drv)
{
struct amba_device *pcdev = to_amba_device(dev);
struct amba_driver *pcdrv = to_amba_driver(drv);
return amba_lookup(pcdrv->id_table, pcdev) != NULL;
}
/*
* Primecells are part of the Advanced Microcontroller Bus Architecture,
* so we call the bus "amba".
*/
struct bus_type amba_bustype = {
.name = "amba",
.match = amba_match,
};
static int __init amba_init(void)
{
return bus_register(&amba_bustype);
}
postcore_initcall(amba_init);
/*
* These are the device model conversion veneers; they convert the
* device model structures to our more specific structures.
*/
static int amba_probe(struct device *dev)
{
struct amba_device *pcdev = to_amba_device(dev);
struct amba_driver *pcdrv = to_amba_driver(dev->driver);
struct amba_id *id;
id = amba_lookup(pcdrv->id_table, pcdev);
return pcdrv->probe(pcdev, id);
}
static int amba_remove(struct device *dev)
{
struct amba_driver *drv = to_amba_driver(dev->driver);
return drv->remove(to_amba_device(dev));
}
static void amba_shutdown(struct device *dev)
{
struct amba_driver *drv = to_amba_driver(dev->driver);
drv->shutdown(to_amba_device(dev));
}
static int amba_suspend(struct device *dev, u32 state, u32 level)
{
struct amba_driver *drv = to_amba_driver(dev->driver);
return drv->suspend(to_amba_device(dev), state, level);
}
static int amba_resume(struct device *dev, u32 level)
{
struct amba_driver *drv = to_amba_driver(dev->driver);
return drv->resume(to_amba_device(dev), level);
}
/**
* amba_driver_register - register an AMBA device driver
* @drv: amba device driver structure
*
* Register an AMBA device driver with the Linux device model
* core. If devices pre-exist, the drivers probe function will
* be called.
*/
int amba_driver_register(struct amba_driver *drv)
{
drv->drv.bus = &amba_bustype;
#define SETFN(fn) if (drv->fn) drv->drv.fn = amba_##fn
SETFN(probe);
SETFN(remove);
SETFN(shutdown);
SETFN(suspend);
SETFN(resume);
return driver_register(&drv->drv);
}
/**
* amba_driver_unregister - remove an AMBA device driver
* @drv: AMBA device driver structure to remove
*
* Unregister an AMBA device driver from the Linux device
* model. The device model will call the drivers remove function
* for each device the device driver is currently handling.
*/
void amba_driver_unregister(struct amba_driver *drv)
{
driver_unregister(&drv->drv);
}
static void amba_device_release(struct device *dev)
{
struct amba_device *d = to_amba_device(dev);
if (d->res.parent)
release_resource(&d->res);
kfree(d);
}
static ssize_t show_id(struct device *_dev, char *buf)
{
struct amba_device *dev = to_amba_device(_dev);
return sprintf(buf, "%08x\n", dev->periphid);
}
static DEVICE_ATTR(id, S_IRUGO, show_id, NULL);
static ssize_t show_irq(struct device *_dev, char *buf)
{
struct amba_device *dev = to_amba_device(_dev);
return sprintf(buf, "%u\n", dev->irq);
}
static DEVICE_ATTR(irq, S_IRUGO, show_irq, NULL);
static ssize_t show_res(struct device *_dev, char *buf)
{
struct amba_device *dev = to_amba_device(_dev);
return sprintf(buf, "\t%08lx\t%08lx\t%08lx\n",
dev->res.start, dev->res.end, dev->res.flags);
}
static DEVICE_ATTR(resource, S_IRUGO, show_res, NULL);
/**
* amba_device_register - register an AMBA device
* @dev: AMBA device to register
* @parent: parent memory resource
*
* Setup the AMBA device, reading the cell ID if present.
* Claim the resource, and register the AMBA device with
* the Linux device manager.
*/
int amba_device_register(struct amba_device *dev, struct resource *parent)
{
u32 pid, cid;
void *tmp;
int i, ret;
dev->dev.release = amba_device_release;
dev->dev.bus = &amba_bustype;
dev->res.name = dev->dev.name;
ret = request_resource(parent, &dev->res);
if (ret == 0) {
tmp = ioremap(dev->res.start, SZ_4K);
if (!tmp) {
ret = -ENOMEM;
goto out;
}
for (pid = 0, i = 0; i < 4; i++)
pid |= (readl(tmp + 0xfe0 + 4 * i) & 255) << (i * 8);
for (cid = 0, i = 0; i < 4; i++)
cid |= (readl(tmp + 0xff0 + 4 * i) & 255) << (i * 8);
iounmap(tmp);
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);
device_create_file(&dev->dev, &dev_attr_irq);
device_create_file(&dev->dev, &dev_attr_resource);
} else {
out:
release_resource(&dev->res);
}
}
return ret;
}
/**
* amba_device_unregister - unregister an AMBA device
* @dev: AMBA device to remove
*
* Remove the specified AMBA device from the Linux device
* manager. All files associated with this object will be
* destroyed, and device drivers notified that the device has
* been removed. The AMBA device's resources including
* the amba_device structure will be freed once all
* references to it have been dropped.
*/
void amba_device_unregister(struct amba_device *dev)
{
device_unregister(&dev->dev);
}
EXPORT_SYMBOL(amba_driver_register);
EXPORT_SYMBOL(amba_driver_unregister);
EXPORT_SYMBOL(amba_device_register);
EXPORT_SYMBOL(amba_device_unregister);
/*
* linux/arch/arm/common/icst525.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.
*
* Support functions for calculating clocks/divisors for the ICST525
* clock generators. See http://www.icst.com/ for more information
* on these devices.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/hardware/icst525.h>
/*
* Divisors for each OD setting.
*/
static unsigned char s2div[8] = { 10, 2, 8, 4, 5, 7, 9, 6 };
unsigned long icst525_khz(const struct icst525_params *p, struct icst525_vco vco)
{
return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * s2div[vco.s]);
}
EXPORT_SYMBOL(icst525_khz);
/*
* Ascending divisor S values.
*/
static unsigned char idx2s[] = { 1, 3, 4, 7, 5, 2, 6, 0 };
struct icst525_vco
icst525_khz_to_vco(const struct icst525_params *p, unsigned long freq)
{
struct icst525_vco vco = { .s = 1, .v = p->vd_max, .r = p->rd_max };
unsigned long f;
unsigned int i = 0, rd, best = (unsigned int)-1;
/*
* First, find the PLL output divisor such
* that the PLL output is within spec.
*/
do {
f = freq * s2div[idx2s[i]];
/*
* f must be between 10MHz and
* 320MHz (5V) or 200MHz (3V)
*/
if (f > 10000 && f <= p->vco_max)
break;
} while (i < ARRAY_SIZE(idx2s));
if (i > ARRAY_SIZE(idx2s))
return vco;
vco.s = idx2s[i];
/*
* Now find the closest divisor combination
* which gives a PLL output of 'f'.
*/
for (rd = p->rd_min; rd <= p->rd_max; rd++) {
unsigned long fref_div, f_pll;
unsigned int vd;
int f_diff;
fref_div = (2 * p->ref) / rd;
vd = (f + fref_div / 2) / fref_div;
if (vd < p->vd_min || vd > p->vd_max)
continue;
f_pll = fref_div * vd;
f_diff = f_pll - f;
if (f_diff < 0)
f_diff = -f_diff;
if ((unsigned)f_diff < best) {
vco.v = vd - 8;
vco.r = rd - 2;
if (f_diff == 0)
break;
best = f_diff;
}
}
return vco;
}
EXPORT_SYMBOL(icst525_khz_to_vco);
struct icst525_vco
icst525_ps_to_vco(const struct icst525_params *p, unsigned long period)
{
struct icst525_vco vco = { .s = 1, .v = p->vd_max, .r = p->rd_max };
unsigned long f, ps;
unsigned int i = 0, rd, best = (unsigned int)-1;
ps = 1000000000UL / p->vco_max;
/*
* First, find the PLL output divisor such
* that the PLL output is within spec.
*/
do {
f = period / s2div[idx2s[i]];
/*
* f must be between 10MHz and
* 320MHz (5V) or 200MHz (3V)
*/
if (f >= ps && f < 100000)
break;
} while (i < ARRAY_SIZE(idx2s));
if (i > ARRAY_SIZE(idx2s))
return vco;
vco.s = idx2s[i];
ps = 500000000UL / p->ref;
/*
* Now find the closest divisor combination
* which gives a PLL output of 'f'.
*/
for (rd = p->rd_min; rd <= p->rd_max; rd++) {
unsigned long f_in_div, f_pll;
unsigned int vd;
int f_diff;
f_in_div = ps * rd;
vd = (f_in_div + f / 2) / f;
if (vd < p->vd_min || vd > p->vd_max)
continue;
f_pll = (f_in_div + vd / 2) / vd;
f_diff = f_pll - f;
if (f_diff < 0)
f_diff = -f_diff;
if ((unsigned)f_diff < best) {
vco.v = vd - 8;
vco.r = rd - 2;
if (f_diff == 0)
break;
best = f_diff;
}
}
return vco;
}
EXPORT_SYMBOL(icst525_ps_to_vco);
......@@ -31,6 +31,8 @@
#include <asm/irq.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/hardware/amba.h>
#include <asm/hardware/amba_kmi.h>
#include <asm/mach/arch.h>
#include <asm/mach/irq.h>
......@@ -104,7 +106,7 @@ static struct irqchip sc_chip = {
.mask = sc_mask_irq,
.unmask = sc_unmask_irq,
};
static void __init integrator_init_irq(void)
{
unsigned int i;
......@@ -126,6 +128,52 @@ static void __init integrator_init_irq(void)
}
}
static struct amba_device kmi0_device = {
.dev = {
.bus_id = "mb:18",
},
.res = {
.start = KMI0_BASE,
.end = KMI0_BASE + KMI_SIZE - 1,
.flags = IORESOURCE_MEM,
},
.irq = IRQ_KMIINT0,
.periphid = 0x00041050,
};
static struct amba_device kmi1_device = {
.dev = {
.bus_id = "mb:19",
},
.res = {
.start = KMI1_BASE,
.end = KMI1_BASE + KMI_SIZE - 1,
.flags = IORESOURCE_MEM,
},
.irq = IRQ_KMIINT1,
.periphid = 0x00041050,
};
static struct amba_device *amba_devs[] __initdata = {
&kmi0_device,
&kmi1_device,
};
static int __init register_devices(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
struct amba_device *d = amba_devs[i];
amba_device_register(d, &iomem_resource);
}
return 0;
}
arch_initcall(register_devices);
MACHINE_START(INTEGRATOR, "ARM-Integrator")
MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd")
BOOT_MEM(0x00000000, 0x16000000, 0xf1600000)
......
......@@ -23,6 +23,7 @@
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/hardware/icst525.h>
static struct cpufreq_driver integrator_driver;
......@@ -31,75 +32,40 @@ static struct cpufreq_driver integrator_driver;
#define CM_STAT (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_STAT_OFFSET)
#define CM_LOCK (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET)
struct vco {
unsigned char vdw;
unsigned char od;
static const struct icst525_params lclk_params = {
.ref = 24000,
.vco_max = 320000,
.vd_min = 8,
.vd_max = 132,
.rd_min = 24,
.rd_max = 24,
};
/*
* Divisors for each OD setting.
*/
static unsigned char cc_divisor[8] = { 10, 2, 8, 4, 5, 7, 9, 6 };
static unsigned int vco_to_freq(struct vco vco, int factor)
{
return 2000 * (vco.vdw + 8) / cc_divisor[vco.od] / factor;
}
/*
* Divisor indexes in ascending divisor order
*/
static unsigned char s2od[] = { 1, 3, 4, 7, 5, 2, 6, 0 };
static struct vco freq_to_vco(unsigned int freq_khz, int factor)
{
struct vco vco = {0, 0};
unsigned int i, f;
freq_khz *= factor;
for (i = 0; i < 8; i++) {
f = freq_khz * cc_divisor[s2od[i]];
/* f must be between 10MHz and 320MHz */
if (f > 10000 && f <= 320000)
break;
}
vco.od = s2od[i];
vco.vdw = f / 2000 - 8;
return vco;
}
static const struct icst525_params cclk_params = {
.ref = 24000,
.vco_max = 320000,
.vd_min = 12,
.vd_max = 160,
.rd_min = 24,
.rd_max = 24,
};
/*
* Validate the speed policy.
*/
static int integrator_verify_policy(struct cpufreq_policy *policy)
{
struct vco vco;
struct icst525_vco vco;
cpufreq_verify_within_limits(policy,
policy->cpuinfo.min_freq,
policy->cpuinfo.max_freq);
vco = freq_to_vco(policy->max, 1);
if (vco.vdw < 4)
vco.vdw = 4;
if (vco.vdw > 152)
vco.vdw = 152;
policy->max = vco_to_freq(vco, 1);
vco = freq_to_vco(policy->min, 1);
if (vco.vdw < 4)
vco.vdw = 4;
if (vco.vdw > 152)
vco.vdw = 152;
vco = icst525_khz_to_vco(&cclk_params, policy->max);
policy->max = icst525_khz(&cclk_params, vco);
policy->min = vco_to_freq(vco, 1);
vco = icst525_khz_to_vco(&cclk_params, policy->min);
policy->min = icst525_khz(&cclk_params, vco);
cpufreq_verify_within_limits(policy,
policy->cpuinfo.min_freq,
......@@ -115,7 +81,7 @@ static int integrator_set_target(struct cpufreq_policy *policy,
{
unsigned long cpus_allowed;
int cpu = policy->cpu;
struct vco vco;
struct icst525_vco vco;
struct cpufreq_freqs freqs;
u_int cm_osc;
......@@ -133,19 +99,20 @@ static int integrator_set_target(struct cpufreq_policy *policy,
/* get current setting */
cm_osc = __raw_readl(CM_OSC);
vco.od = (cm_osc >> 8) & 7;
vco.vdw = cm_osc & 255;
freqs.old = vco_to_freq(vco, 1);
vco.s = (cm_osc >> 8) & 7;
vco.v = cm_osc & 255;
vco.r = 22;
freqs.old = icst525_khz(&cclk_params, vco);
/* freq_to_vco rounds down -- so we need the next larger freq in
* case of CPUFREQ_RELATION_L.
/* icst525_khz_to_vco rounds down -- so we need the next
* larger freq in case of CPUFREQ_RELATION_L.
*/
if (relation == CPUFREQ_RELATION_L)
target_freq += 1999;
if (target_freq > policy->max)
target_freq = policy->max;
vco = freq_to_vco(target_freq, 1);
freqs.new = vco_to_freq(vco, 1);
vco = icst525_khz_to_vco(&cclk_params, target_freq);
freqs.new = icst525_khz(&cclk_params, vco);
freqs.cpu = policy->cpu;
......@@ -158,7 +125,7 @@ static int integrator_set_target(struct cpufreq_policy *policy,
cm_osc = __raw_readl(CM_OSC);
cm_osc &= 0xfffff800;
cm_osc |= vco.vdw | vco.od << 8;
cm_osc |= vco.v | vco.s << 8;
__raw_writel(0xa05f, CM_LOCK);
__raw_writel(cm_osc, CM_OSC);
......@@ -179,7 +146,7 @@ static int integrator_cpufreq_init(struct cpufreq_policy *policy)
unsigned long cpus_allowed;
unsigned int cpu = policy->cpu;
u_int cm_osc, cm_stat, mem_freq_khz;
struct vco vco;
struct icst525_vco vco;
cpus_allowed = current->cpus_allowed;
......@@ -189,23 +156,26 @@ static int integrator_cpufreq_init(struct cpufreq_policy *policy)
/* detect memory etc. */
cm_stat = __raw_readl(CM_STAT);
cm_osc = __raw_readl(CM_OSC);
vco.od = (cm_osc >> 20) & 7;
vco.vdw = (cm_osc >> 12) & 255;
mem_freq_khz = vco_to_freq(vco, 2);
vco.s = (cm_osc >> 20) & 7;
vco.v = (cm_osc >> 12) & 255;
vco.r = 22;
mem_freq_khz = icst525_khz(&lclk_params, vco) / 2;
printk(KERN_INFO "CPU%d: Module id: %d\n", cpu, cm_stat & 255);
printk(KERN_INFO "CPU%d: Memory clock = %d.%03d MHz\n",
cpu, mem_freq_khz / 1000, mem_freq_khz % 1000);
vco.od = (cm_osc >> 8) & 7;
vco.vdw = cm_osc & 255;
vco.s = (cm_osc >> 8) & 7;
vco.v = cm_osc & 255;
vco.r = 22;
/* set default policy and cpuinfo */
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
policy->cpuinfo.max_freq = 160000;
policy->cpuinfo.min_freq = 12000;
policy->cpuinfo.transition_latency = 1000; /* 1 ms, assumed */
policy->cur = policy->min = policy->max = vco_to_freq(vco, 1); /* current freq */
policy->cur = policy->min = policy->max =
icst525_khz(&cclk_params, vco); /* current freq */
set_cpus_allowed(current, cpus_allowed);
......
......@@ -211,14 +211,14 @@ static struct resource irq_resource = {
.end = 0x9005ffff,
};
static struct {
static struct sa1100irq_state {
unsigned int saved;
unsigned int icmr;
unsigned int iclr;
unsigned int iccr;
} sa1100irq_state;
static int sa1100irq_suspend(struct device *dev, u32 state, u32 level)
static int sa1100irq_suspend(struct sys_device *dev, u32 state)
{
struct sa1100irq_state *st = &sa1100irq_state;
......
......@@ -213,7 +213,7 @@ void __flush_dcache_page(struct page *page)
if (off >= (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT)
continue;
flush_cache_page(mpnt, off);
flush_cache_page(mpnt, mpnt->vm_start + (off << PAGE_SHIFT));
}
}
......
......@@ -309,9 +309,9 @@ static void __init build_mem_type_table(void)
const char *policy;
/*
* ARMv5 can use ECC memory.
* ARMv5 and higher can use ECC memory.
*/
if (cpu_arch == CPU_ARCH_ARMv5) {
if (cpu_arch >= CPU_ARCH_ARMv5) {
mem_types[MT_VECTORS].prot_l1 |= ecc_mask;
mem_types[MT_MEMORY].prot_sect |= ecc_mask;
} else {
......
......@@ -53,7 +53,9 @@ SECTIONS
__con_initcall_start = .;
*(.con_initcall.init)
__con_initcall_end = .;
SECURITY_INIT
__security_initcall_start = .;
*(.security_initcall.init)
__security_initcall_end = .;
. = ALIGN(32);
__initramfs_start = .;
usr/built-in.o(.init.ramfs)
......
/*
* linux/drivers/input/serio/amba_kmi.c
* linux/drivers/input/serio/ambakmi.c
*
* Copyright (C) 2000 Deep Blue Solutions Ltd.
* Copyright (C) 2000-2003 Deep Blue Solutions Ltd.
* Copyright (C) 2002 Russell King.
*
* This program is free software; you can redistribute it and/or modify
......@@ -21,6 +21,7 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/hardware/amba.h>
#include <asm/hardware/amba_kmi.h>
#define KMI_BASE (kmi->base)
......@@ -28,11 +29,10 @@
struct amba_kmi_port {
struct serio io;
struct amba_kmi_port *next;
void *base;
unsigned char *base;
unsigned int irq;
unsigned int divisor;
char name[32];
char phys[16];
unsigned int open;
struct resource *res;
};
......@@ -73,7 +73,7 @@ static int amba_kmi_open(struct serio *io)
writeb(kmi->divisor, KMICLKDIV);
writeb(KMICR_EN, KMICR);
ret = request_irq(kmi->irq, amba_kmi_int, 0, kmi->phys, kmi);
ret = request_irq(kmi->irq, amba_kmi_int, 0, kmi->io.phys, kmi);
if (ret) {
printk(KERN_ERR "kmi: failed to claim IRQ%d\n", kmi->irq);
writeb(0, KMICR);
......@@ -94,9 +94,7 @@ static void amba_kmi_close(struct serio *io)
free_irq(kmi->irq, kmi);
}
static struct amba_kmi_port *list;
static int __init amba_kmi_init_one(char *type, unsigned long base, int irq, int nr)
static int amba_kmi_probe(struct amba_device *dev, void *id)
{
struct amba_kmi_port *kmi;
......@@ -110,58 +108,83 @@ static int __init amba_kmi_init_one(char *type, unsigned long base, int irq, int
kmi->io.write = amba_kmi_write;
kmi->io.open = amba_kmi_open;
kmi->io.close = amba_kmi_close;
kmi->io.name = kmi->name;
kmi->io.phys = kmi->phys;
kmi->io.name = dev->dev.name;
kmi->io.phys = dev->dev.bus_id;
kmi->io.driver = kmi;
snprintf(kmi->name, sizeof(kmi->name), "AMBA KMI PS/2 %s port", type);
snprintf(kmi->phys, sizeof(kmi->phys), "amba/serio%d", nr);
kmi->res = request_mem_region(base, KMI_SIZE, kmi->phys);
kmi->res = request_mem_region(dev->res.start, KMI_SIZE, kmi->io.phys);
if (!kmi->res) {
kfree(kmi);
return -EBUSY;
}
kmi->base = ioremap(base, KMI_SIZE);
kmi->base = ioremap(dev->res.start, KMI_SIZE);
if (!kmi->base) {
release_resource(kmi->res);
kfree(kmi);
return -ENOMEM;
}
kmi->irq = irq;
kmi->irq = dev->irq;
kmi->divisor = 24 / 8 - 1;
kmi->next = list;
list = kmi;
amba_set_drvdata(dev, kmi);
serio_register_port(&kmi->io);
return 0;
}
static int __init amba_kmi_init(void)
static int amba_kmi_remove(struct amba_device *dev)
{
amba_kmi_init_one("keyboard", KMI0_BASE, IRQ_KMIINT0, 0);
amba_kmi_init_one("mouse", KMI1_BASE, IRQ_KMIINT1, 1);
struct amba_kmi_port *kmi = amba_get_drvdata(dev);
amba_set_drvdata(dev, NULL);
serio_unregister_port(&kmi->io);
iounmap(kmi->base);
release_resource(kmi->res);
kfree(kmi);
return 0;
}
static void __exit amba_kmi_exit(void)
static int amba_kmi_resume(struct amba_device *dev, u32 level)
{
struct amba_kmi_port *kmi, *next;
struct amba_kmi_port *kmi = amba_get_drvdata(dev);
kmi = list;
while (kmi) {
next = kmi->next;
if (level == RESUME_ENABLE) {
/* kick the serio layer to rescan this port */
serio_rescan(&kmi->io);
}
serio_unregister_port(&kmi->io);
iounmap(kmi->base);
release_resource(kmi->res);
kfree(kmi);
return 0;
}
kmi = next;
}
static struct amba_id amba_kmi_idtable[] = {
{
.id = 0x00041050,
.mask = 0x000fffff,
},
{ 0, 0 }
};
static struct amba_driver ambakmi_driver = {
.drv = {
.name = "kmi-pl050",
},
.id_table = amba_kmi_idtable,
.probe = amba_kmi_probe,
.remove = amba_kmi_remove,
.resume = amba_kmi_resume,
};
static int __init amba_kmi_init(void)
{
return amba_driver_register(&ambakmi_driver);
}
static void __exit amba_kmi_exit(void)
{
return amba_driver_unregister(&ambakmi_driver);
}
module_init(amba_kmi_init);
......
/*
* linux/include/asm-arm/hardware/amba.h
*
* 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.
*/
#ifndef ASMARM_AMBA_H
#define ASMARM_AMBA_H
struct amba_device {
struct device dev;
struct resource res;
unsigned int irq;
unsigned int periphid;
};
struct amba_id {
unsigned int id;
unsigned int mask;
void *data;
};
struct amba_driver {
struct device_driver drv;
int (*probe)(struct amba_device *, void *);
int (*remove)(struct amba_device *);
void (*shutdown)(struct amba_device *);
int (*suspend)(struct amba_device *, u32, u32);
int (*resume)(struct amba_device *, u32);
struct amba_id *id_table;
};
#define amba_get_drvdata(d) dev_get_drvdata(&d->dev)
#define amba_set_drvdata(d,p) dev_set_drvdata(&d->dev, p)
int amba_driver_register(struct amba_driver *);
void amba_driver_unregister(struct amba_driver *);
int amba_device_register(struct amba_device *, struct resource *);
void amba_device_unregister(struct amba_device *);
#endif
/*
* linux/include/asm-arm/hardware/icst525.h
*
* 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.
*
* Support functions for calculating clocks/divisors for the ICST525
* clock generators. See http://www.icst.com/ for more information
* on these devices.
*/
#ifndef ASMARM_HARDWARE_ICST525_H
#define ASMARM_HARDWARE_ICST525_H
struct icst525_params {
unsigned long ref;
unsigned long vco_max; /* inclusive */
unsigned short vd_min; /* inclusive */
unsigned short vd_max; /* inclusive */
unsigned char rd_min; /* inclusive */
unsigned char rd_max; /* inclusive */
};
struct icst525_vco {
unsigned short v;
unsigned char r;
unsigned char s;
};
unsigned long icst525_khz(const struct icst525_params *p, struct icst525_vco vco);
struct icst525_vco icst525_khz_to_vco(const struct icst525_params *p, unsigned long freq);
struct icst525_vco icst525_ps_to_vco(const struct icst525_params *p, unsigned long period);
#endif
......@@ -27,6 +27,9 @@
/*
* These are *only* valid on the kernel direct mapped RAM memory.
* Note: Drivers should NOT use these. They are the wrong
* translation for translating DMA addresses. Use the driver
* DMA support - see dma-mapping.h.
*/
static inline unsigned long virt_to_phys(void *x)
{
......@@ -38,6 +41,9 @@ static inline void *phys_to_virt(unsigned long x)
return (void *)(__phys_to_virt((unsigned long)(x)));
}
/*
* Drivers should NOT use these either.
*/
#define __pa(x) __virt_to_phys((unsigned long)(x))
#define __va(x) ((void *)__phys_to_virt((unsigned long)(x)))
......@@ -72,7 +78,7 @@ static inline void *phys_to_virt(unsigned long x)
#define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
#define virt_to_page(kaddr) (pfn_to_page(__pa(kaddr) >> PAGE_SHIFT))
#define virt_addr_valid(kaddr) ((kaddr) >= PAGE_OFFSET && (kaddr) < (unsigned long)high_memory)
#define virt_addr_valid(kaddr) ((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
#define PHYS_TO_NID(addr) (0)
......
......@@ -87,10 +87,18 @@ static inline void set_fs (mm_segment_t fs)
: "r" (x), "r" (__pu_addr), "i" (-EFAULT) \
: "cc")
#ifndef __ARMEB__
#define __reg_oper0 "%R2"
#define __reg_oper1 "%Q2"
#else
#define __reg_oper0 "%Q2"
#define __reg_oper1 "%R2"
#endif
#define __put_user_asm_dword(x,__pu_addr,err) \
__asm__ __volatile__( \
"1: strt %Q2, [%1], #4\n" \
"2: strt %R2, [%1], #0\n" \
"1: strt " __reg_oper1 ", [%1], #4\n" \
"2: strt " __reg_oper0 ", [%1], #0\n" \
"3:\n" \
" .section .fixup,\"ax\"\n" \
" .align 2\n" \
......
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