Commit d26d2b94 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 c3136961 574e0aa5
...@@ -534,15 +534,63 @@ config CPU_FREQ ...@@ -534,15 +534,63 @@ config CPU_FREQ
written) to implement the policy. If you don't understand what this written) to implement the policy. If you don't understand what this
is all about, it's safe to say 'N'. is all about, it's safe to say 'N'.
# CPUfreq on SA11x0 is special -- it _needs_ the userspace governor
config CPU_FREQ_SA1100
bool
depends on CPU_FREQ && SA1100_LART
default y
config CPU_FREQ_SA1110
bool
depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3)
default y
if (CPU_FREQ_SA1100 || CPU_FREQ_SA1110)
config CPU_FREQ_GOV_USERSPACE
bool
depends on CPU_FREQ
default y
config CPU_FREQ_24_API config CPU_FREQ_24_API
bool bool
depends on CPU_FREQ depends on CPU_FREQ_GOV_USERSPACE && SYSCTL
default y default y
config CPU_FREQ_PROC_INTF config CPU_FREQ_PROC_INTF
tristate tristate "/proc/cpufreq interface (deprecated)"
depends on CPU_FREQ depends on CPU_FREQ && PROC_FS
help
This enables the /proc/cpufreq interface for controlling
CPUFreq. Please note that it is recommended to use the sysfs
interface instead (which is built automatically).
For details, take a look at linux/Documentation/cpufreq.
If in doubt, say N.
endif
# CPUfreq on Integrator can use the generic cpufreq core
config CPU_FREQ_INTEGRATOR
tristate "CPUfreq driver for ARM Integrator CPUs"
depends on ARCH_INTEGRATOR && CPU_FREQ
default y default y
help
This enables the CPUfreq driver for ARM Integrator CPUs.
For details, take a look at linux/Documentation/cpufreq.
If in doubt, say Y.
if (CPU_FREQ_INTEGRATOR)
source "drivers/cpufreq/Kconfig"
endif
source "drivers/pci/Kconfig" source "drivers/pci/Kconfig"
......
...@@ -743,25 +743,23 @@ struct sa1111_save_data { ...@@ -743,25 +743,23 @@ struct sa1111_save_data {
static int sa1111_suspend(struct device *dev, u32 state, u32 level) static int sa1111_suspend(struct device *dev, u32 state, u32 level)
{ {
struct sa1111 *sachip = dev_get_drvdata(dev); struct sa1111 *sachip = dev_get_drvdata(dev);
struct sa1111_save_data *save;
unsigned long flags; unsigned long flags;
char *base; char *base;
/* if (!dev->saved_state && level == SUSPEND_NOTIFY)
* Save state. dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
*/ if (!dev->saved_state)
if (level == SUSPEND_SAVE_STATE || return -ENOMEM;
level == SUSPEND_DISABLE ||
level == SUSPEND_POWER_DOWN) {
struct sa1111_save_data *save;
if (!dev->saved_state) save = (struct sa1111_save_data *)dev->saved_state;
dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
if (!dev->saved_state)
return -ENOMEM;
save = (struct sa1111_save_data *)dev->saved_state; spin_lock_irqsave(&sachip->lock, flags);
spin_lock_irqsave(&sachip->lock, flags); /*
* Save state.
*/
if (level == SUSPEND_SAVE_STATE) {
base = sachip->base; base = sachip->base;
save->skcr = sa1111_readl(base + SA1111_SKCR); save->skcr = sa1111_readl(base + SA1111_SKCR);
save->skpcr = sa1111_readl(base + SA1111_SKPCR); save->skpcr = sa1111_readl(base + SA1111_SKPCR);
...@@ -779,26 +777,21 @@ static int sa1111_suspend(struct device *dev, u32 state, u32 level) ...@@ -779,26 +777,21 @@ static int sa1111_suspend(struct device *dev, u32 state, u32 level)
save->wakepol1 = sa1111_readl(base + SA1111_WAKEPOL1); save->wakepol1 = sa1111_readl(base + SA1111_WAKEPOL1);
save->wakeen0 = sa1111_readl(base + SA1111_WAKEEN0); save->wakeen0 = sa1111_readl(base + SA1111_WAKEEN0);
save->wakeen1 = sa1111_readl(base + SA1111_WAKEEN1); save->wakeen1 = sa1111_readl(base + SA1111_WAKEEN1);
spin_unlock_irqrestore(&sachip->lock, flags);
} }
/* /*
* Disable. * Disable.
*/ */
if (level == SUSPEND_DISABLE && state == 4) { if (level == SUSPEND_POWER_DOWN && state == 4) {
unsigned int val; unsigned int val = sa1111_readl(sachip->base + SA1111_SKCR);
spin_lock_irqsave(&sachip->lock, flags);
base = sachip->base;
sa1111_writel(0, base + SA1111_SKPWM0); sa1111_writel(val | SKCR_SLEEP, sachip->base + SA1111_SKCR);
sa1111_writel(0, base + SA1111_SKPWM1); sa1111_writel(0, sachip->base + SA1111_SKPWM0);
val = sa1111_readl(base + SA1111_SKCR); sa1111_writel(0, sachip->base + SA1111_SKPWM1);
sa1111_writel(val | SKCR_SLEEP, base + SA1111_SKCR);
spin_unlock_irqrestore(&sachip->lock, flags);
} }
spin_unlock_irqrestore(&sachip->lock, flags);
return 0; return 0;
} }
...@@ -819,17 +812,15 @@ static int sa1111_resume(struct device *dev, u32 level) ...@@ -819,17 +812,15 @@ static int sa1111_resume(struct device *dev, u32 level)
unsigned long flags, id; unsigned long flags, id;
char *base; char *base;
if (level != RESUME_RESTORE_STATE && level != RESUME_ENABLE)
return 0;
save = (struct sa1111_save_data *)dev->saved_state; save = (struct sa1111_save_data *)dev->saved_state;
if (!save) if (!save)
return 0; return 0;
dev->saved_state = NULL; spin_lock_irqsave(&sachip->lock, flags);
/* /*
* Ensure that the SA1111 is still here. * Ensure that the SA1111 is still here.
* FIXME: shouldn't do this here.
*/ */
id = sa1111_readl(sachip->base + SA1111_SKID); id = sa1111_readl(sachip->base + SA1111_SKID);
if ((id & SKID_ID_MASK) != SKID_SA1111_ID) { if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
...@@ -839,29 +830,42 @@ static int sa1111_resume(struct device *dev, u32 level) ...@@ -839,29 +830,42 @@ static int sa1111_resume(struct device *dev, u32 level)
return 0; return 0;
} }
spin_lock_irqsave(&sachip->lock, flags); /*
sa1111_wake(sachip); * First of all, wake up the chip.
*/
if (level == RESUME_POWER_ON) {
sa1111_wake(sachip);
sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN0);
sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN1);
}
if (level == RESUME_RESTORE_STATE) {
base = sachip->base;
sa1111_writel(save->skcr, base + SA1111_SKCR);
sa1111_writel(save->skpcr, base + SA1111_SKPCR);
sa1111_writel(save->skcdr, base + SA1111_SKCDR);
sa1111_writel(save->skaud, base + SA1111_SKAUD);
sa1111_writel(save->skpwm0, base + SA1111_SKPWM0);
sa1111_writel(save->skpwm1, base + SA1111_SKPWM1);
base = sachip->base + SA1111_INTC;
sa1111_writel(save->intpol0, base + SA1111_INTPOL0);
sa1111_writel(save->intpol1, base + SA1111_INTPOL1);
sa1111_writel(save->inten0, base + SA1111_INTEN0);
sa1111_writel(save->inten1, base + SA1111_INTEN1);
sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0);
sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1);
sa1111_writel(save->wakeen0, base + SA1111_WAKEEN0);
sa1111_writel(save->wakeen1, base + SA1111_WAKEEN1);
}
base = sachip->base;
sa1111_writel(save->skcr, base + SA1111_SKCR);
sa1111_writel(save->skpcr, base + SA1111_SKPCR);
sa1111_writel(save->skcdr, base + SA1111_SKCDR);
sa1111_writel(save->skaud, base + SA1111_SKAUD);
sa1111_writel(save->skpwm0, base + SA1111_SKPWM0);
sa1111_writel(save->skpwm1, base + SA1111_SKPWM1);
base = sachip->base + SA1111_INTC;
sa1111_writel(save->intpol0, base + SA1111_INTPOL0);
sa1111_writel(save->intpol1, base + SA1111_INTPOL1);
sa1111_writel(save->inten0, base + SA1111_INTEN0);
sa1111_writel(save->inten1, base + SA1111_INTEN1);
sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0);
sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1);
sa1111_writel(save->wakeen0, base + SA1111_WAKEEN0);
sa1111_writel(save->wakeen1, base + SA1111_WAKEEN1);
spin_unlock_irqrestore(&sachip->lock, flags); spin_unlock_irqrestore(&sachip->lock, flags);
kfree(save); if (level == RESUME_ENABLE) {
dev->saved_state = NULL;
kfree(save);
}
return 0; return 0;
} }
......
...@@ -16,6 +16,7 @@ obj-n := ...@@ -16,6 +16,7 @@ obj-n :=
obj- := obj- :=
obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_APM) += apm.o
obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_ARCH_ACORN) += ecard.o time-acorn.o obj-$(CONFIG_ARCH_ACORN) += ecard.o time-acorn.o
obj-$(CONFIG_ARCH_CLPS7500) += time-acorn.o obj-$(CONFIG_ARCH_CLPS7500) += time-acorn.o
obj-$(CONFIG_FOOTBRIDGE) += isa.o obj-$(CONFIG_FOOTBRIDGE) += isa.o
......
/*
* bios-less APM driver for ARM Linux
* Jamey Hicks <jamey@crl.dec.com>
* adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com)
*
* APM 1.2 Reference:
* Intel Corporation, Microsoft Corporation. Advanced Power Management
* (APM) BIOS Interface Specification, Revision 1.2, February 1996.
*
* [This document is available from Microsoft at:
* http://www.microsoft.com/hwdev/busbios/amp_12.htm]
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/timer.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/miscdevice.h>
#include <linux/apm_bios.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/init.h>
#include <linux/completion.h>
#include <asm/system.h>
/*
* The apm_bios device is one of the misc char devices.
* This is its minor number.
*/
#define APM_MINOR_DEV 134
/*
* See Documentation/Config.help for the configuration options.
*
* Various options can be changed at boot time as follows:
* (We allow underscores for compatibility with the modules code)
* apm=on/off enable/disable APM
*/
/*
* Maximum number of events stored
*/
#define APM_MAX_EVENTS 20
/*
* The per-file APM data
*/
struct apm_user {
struct list_head list;
int suser: 1;
int writer: 1;
int reader: 1;
int suspend_wait: 1;
int suspend_result;
int suspends_pending;
int standbys_pending;
unsigned int suspends_read;
unsigned int standbys_read;
int event_head;
int event_tail;
apm_event_t events[APM_MAX_EVENTS];
};
/*
* Local variables
*/
static int suspends_pending;
static int standbys_pending;
static int apm_disabled;
static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
/*
* This is a list of everyone who has opened /dev/apm_bios
*/
static spinlock_t user_list_lock = SPIN_LOCK_UNLOCKED;
static LIST_HEAD(apm_user_list);
/*
* The kapmd info.
*/
static struct task_struct *kapmd;
static DECLARE_COMPLETION(kapmd_exit);
static const char driver_version[] = "1.13"; /* no spaces */
/*
* This structure gets filled in by the machine specific 'get_power_status'
* implementation. Any fields which are not set default to a safe value.
*/
struct apm_power_info {
unsigned char ac_line_status;
unsigned char battery_status;
unsigned char battery_flag;
unsigned char battery_life;
int time;
int units;
};
/*
* Compatibility cruft until the IPAQ people move over to the new
* interface.
*/
static void __apm_get_power_status(struct apm_power_info *info)
{
#if 0 && defined(CONFIG_SA1100_H3600) && defined(CONFIG_TOUCHSCREEN_H3600)
extern int h3600_apm_get_power_status(u_char *, u_char *, u_char *,
u_char *, u_short *);
if (machine_is_h3600()) {
int dx;
h3600_apm_get_power_status(&info->ac_line_status,
&info->battery_status, &info->battery_flag,
&info->battery_life, &dx);
info->time = dx & 0x7fff;
info->units = dx & 0x8000 ? 0 : 1;
}
#endif
}
/*
* This allows machines to provide their own "apm get power status" function.
*/
void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status;
EXPORT_SYMBOL(apm_get_power_status);
static int queue_empty(struct apm_user *as)
{
return as->event_head == as->event_tail;
}
static apm_event_t get_queued_event(struct apm_user *as)
{
as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
return as->events[as->event_tail];
}
static void queue_event_one_user(struct apm_user *as, apm_event_t event)
{
as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
if (as->event_head == as->event_tail) {
static int notified;
if (notified++ == 0)
printk(KERN_ERR "apm: an event queue overflowed\n");
as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
}
as->events[as->event_head] = event;
if (!as->suser || !as->writer)
return;
switch (event) {
case APM_SYS_SUSPEND:
case APM_USER_SUSPEND:
as->suspends_pending++;
suspends_pending++;
break;
case APM_SYS_STANDBY:
case APM_USER_STANDBY:
as->standbys_pending++;
standbys_pending++;
break;
}
}
static void queue_event(apm_event_t event, struct apm_user *sender)
{
struct list_head *l;
spin_lock(&user_list_lock);
list_for_each(l, &apm_user_list) {
struct apm_user *as = list_entry(l, struct apm_user, list);
if (as != sender && as->reader)
queue_event_one_user(as, event);
}
spin_unlock(&user_list_lock);
wake_up_interruptible(&apm_waitqueue);
}
/* defined in pm.c */
extern int suspend(void);
static int apm_suspend(void)
{
struct list_head *l;
int err = suspend();
/*
* Anyone on the APM queues will think we're still suspended.
* Send a message so everyone knows we're now awake again.
*/
queue_event(APM_NORMAL_RESUME, NULL);
/*
* Finally, wake up anyone who is sleeping on the suspend.
*/
spin_lock(&user_list_lock);
list_for_each(l, &apm_user_list) {
struct apm_user *as = list_entry(l, struct apm_user, list);
as->suspend_result = err;
as->suspend_wait = 0;
}
spin_unlock(&user_list_lock);
wake_up_interruptible(&apm_suspend_waitqueue);
return err;
}
static ssize_t apm_read(struct file *fp, char *buf, size_t count, loff_t *ppos)
{
struct apm_user *as = fp->private_data;
apm_event_t event;
int i = count, ret = 0, nonblock = fp->f_flags & O_NONBLOCK;
if (count < sizeof(apm_event_t))
return -EINVAL;
if (queue_empty(as) && nonblock)
return -EAGAIN;
wait_event_interruptible(apm_waitqueue, !queue_empty(as));
while ((i >= sizeof(event)) && !queue_empty(as)) {
event = get_queued_event(as);
printk(" apm_read: event=%d\n", event);
ret = -EFAULT;
if (copy_to_user(buf, &event, sizeof(event)))
break;
switch (event) {
case APM_SYS_SUSPEND:
case APM_USER_SUSPEND:
as->suspends_read++;
break;
case APM_SYS_STANDBY:
case APM_USER_STANDBY:
as->standbys_read++;
break;
}
buf += sizeof(event);
i -= sizeof(event);
}
if (i < count)
ret = count - i;
return ret;
}
static unsigned int apm_poll(struct file *fp, poll_table * wait)
{
struct apm_user * as = fp->private_data;
poll_wait(fp, &apm_waitqueue, wait);
return queue_empty(as) ? 0 : POLLIN | POLLRDNORM;
}
/*
* apm_ioctl - handle APM ioctl
*
* APM_IOC_SUSPEND
* This IOCTL is overloaded, and performs two functions. It is used to:
* - initiate a suspend
* - acknowledge a suspend read from /dev/apm_bios.
* Only when everyone who has opened /dev/apm_bios with write permission
* has acknowledge does the actual suspend happen.
*/
static int
apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
{
struct apm_user *as = filp->private_data;
int err = -EINVAL;
if (!as->suser || !as->writer)
return -EPERM;
switch (cmd) {
case APM_IOC_STANDBY:
break;
case APM_IOC_SUSPEND:
/*
* If we read a suspend command from /dev/apm_bios,
* then the corresponding APM_IOC_SUSPEND ioctl is
* interpreted as an acknowledge.
*/
if (as->suspends_read > 0) {
as->suspends_read--;
as->suspends_pending--;
suspends_pending--;
} else {
queue_event(APM_USER_SUSPEND, as);
}
/*
* If there are outstanding suspend requests for other
* people on /dev/apm_bios, we must sleep for them.
* Last one to bed turns the lights out.
*/
if (suspends_pending > 0) {
as->suspend_wait = 1;
err = wait_event_interruptible(apm_suspend_waitqueue,
as->suspend_wait == 0);
if (err == 0)
err = as->suspend_result;
} else {
err = apm_suspend();
}
break;
}
return err;
}
static int apm_release(struct inode * inode, struct file * filp)
{
struct apm_user *as = filp->private_data;
filp->private_data = NULL;
spin_lock(&user_list_lock);
list_del(&as->list);
spin_unlock(&user_list_lock);
/*
* We are now unhooked from the chain. As far as new
* events are concerned, we no longer exist. However, we
* need to balance standbys_pending and suspends_pending,
* which means the possibility of sleeping.
*/
if (as->standbys_pending > 0) {
standbys_pending -= as->standbys_pending;
// if (standbys_pending <= 0)
// standby();
}
if (as->suspends_pending > 0) {
suspends_pending -= as->suspends_pending;
if (suspends_pending <= 0)
apm_suspend();
}
kfree(as);
return 0;
}
static int apm_open(struct inode * inode, struct file * filp)
{
struct apm_user *as;
as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
if (as) {
memset(as, 0, sizeof(*as));
/*
* XXX - this is a tiny bit broken, when we consider BSD
* process accounting. If the device is opened by root, we
* instantly flag that we used superuser privs. Who knows,
* we might close the device immediately without doing a
* privileged operation -- cevans
*/
as->suser = capable(CAP_SYS_ADMIN);
as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
spin_lock(&user_list_lock);
list_add(&as->list, &apm_user_list);
spin_unlock(&user_list_lock);
filp->private_data = as;
}
return as ? 0 : -ENOMEM;
}
static struct file_operations apm_bios_fops = {
owner: THIS_MODULE,
read: apm_read,
poll: apm_poll,
ioctl: apm_ioctl,
open: apm_open,
release: apm_release,
};
static struct miscdevice apm_device = {
minor: APM_MINOR_DEV,
name: "apm_bios",
fops: &apm_bios_fops
};
#ifdef CONFIG_PROC_FS
/*
* Arguments, with symbols from linux/apm_bios.h.
*
* 0) Linux driver version (this will change if format changes)
* 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2.
* 2) APM flags from APM Installation Check (0x00):
* bit 0: APM_16_BIT_SUPPORT
* bit 1: APM_32_BIT_SUPPORT
* bit 2: APM_IDLE_SLOWS_CLOCK
* bit 3: APM_BIOS_DISABLED
* bit 4: APM_BIOS_DISENGAGED
* 3) AC line status
* 0x00: Off-line
* 0x01: On-line
* 0x02: On backup power (BIOS >= 1.1 only)
* 0xff: Unknown
* 4) Battery status
* 0x00: High
* 0x01: Low
* 0x02: Critical
* 0x03: Charging
* 0x04: Selected battery not present (BIOS >= 1.2 only)
* 0xff: Unknown
* 5) Battery flag
* bit 0: High
* bit 1: Low
* bit 2: Critical
* bit 3: Charging
* bit 7: No system battery
* 0xff: Unknown
* 6) Remaining battery life (percentage of charge):
* 0-100: valid
* -1: Unknown
* 7) Remaining battery life (time units):
* Number of remaining minutes or seconds
* -1: Unknown
* 8) min = minutes; sec = seconds
*/
static int apm_get_info(char *buf, char **start, off_t fpos, int length)
{
struct apm_power_info info;
char *units;
int ret;
info.ac_line_status = 0xff;
info.battery_status = 0xff;
info.battery_flag = 0xff;
info.battery_life = 255;
info.time = -1;
info.units = -1;
if (apm_get_power_status)
apm_get_power_status(&info);
switch (info.units) {
default: units = "?"; break;
case 0: units = "min"; break;
case 1: units = "sec"; break;
}
ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
driver_version, APM_32_BIT_SUPPORT,
info.ac_line_status, info.battery_status,
info.battery_flag, info.battery_life,
info.time, units);
return ret;
}
#endif
#if 0
static int kapmd(void *startup)
{
struct task_struct *tsk = current;
daemonize();
strcpy(tsk->comm, "kapmd");
kapmd = tsk;
spin_lock_irq(&tsk->sigmask_lock);
siginitsetinv(&tsk->blocked, sigmask(SIGQUIT));
recalc_sigpending(tsk);
spin_unlock_irq(&tsk->sigmask_lock);
complete((struct completion *)startup);
do {
set_task_state(tsk, TASK_INTERRUPTIBLE);
schedule();
} while (!signal_pending(tsk));
complete_and_exit(&kapmd_exit, 0);
}
#endif
static int __init apm_init(void)
{
// struct completion startup = COMPLETION_INITIALIZER(startup);
int ret;
if (apm_disabled) {
printk(KERN_NOTICE "apm: disabled on user request.\n");
return -ENODEV;
}
if (PM_IS_ACTIVE()) {
printk(KERN_NOTICE "apm: overridden by ACPI.\n");
return -EINVAL;
}
// ret = kernel_thread(kapmd, &startup, CLONE_FS | CLONE_FILES);
// if (ret)
// return ret;
// wait_for_completion(&startup);
pm_active = 1;
#ifdef CONFIG_PROC_FS
create_proc_info_entry("apm", 0, NULL, apm_get_info);
#endif
ret = misc_register(&apm_device);
if (ret != 0) {
pm_active = 0;
remove_proc_entry("apm", NULL);
send_sig(SIGQUIT, kapmd, 1);
wait_for_completion(&kapmd_exit);
}
return ret;
}
static void __exit apm_exit(void)
{
misc_deregister(&apm_device);
remove_proc_entry("apm", NULL);
pm_active = 0;
// send_sig(SIGQUIT, kapmd, 1);
// wait_for_completion(&kapmd_exit);
}
module_init(apm_init);
module_exit(apm_exit);
MODULE_AUTHOR("Stephen Rothwell");
MODULE_DESCRIPTION("Advanced Power Management");
MODULE_LICENSE("GPL");
EXPORT_NO_SYMBOLS;
#ifndef MODULE
static int __init apm_setup(char *str)
{
while ((str != NULL) && (*str != '\0')) {
if (strncmp(str, "off", 3) == 0)
apm_disabled = 1;
if (strncmp(str, "on", 2) == 0)
apm_disabled = 0;
str = strchr(str, ',');
if (str != NULL)
str += strspn(str, ", \t");
}
return 1;
}
__setup("apm=", apm_setup);
#endif
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <asm/mach/pci.h> #include <asm/mach/pci.h>
static int debug_pci; static int debug_pci;
int have_isa_bridge;
void pcibios_report_status(u_int status_mask, int warn) void pcibios_report_status(u_int status_mask, int warn)
{ {
...@@ -363,9 +362,8 @@ pbus_assign_bus_resources(struct pci_bus *bus, struct pci_sys_data *root) ...@@ -363,9 +362,8 @@ pbus_assign_bus_resources(struct pci_bus *bus, struct pci_sys_data *root)
void __devinit pcibios_fixup_bus(struct pci_bus *bus) void __devinit pcibios_fixup_bus(struct pci_bus *bus)
{ {
struct pci_sys_data *root = bus->sysdata; struct pci_sys_data *root = bus->sysdata;
struct list_head *walk; struct pci_dev *dev;
u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY; u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_FAST_BACK;
u16 all_status = -1;
pbus_assign_bus_resources(bus, root); pbus_assign_bus_resources(bus, root);
...@@ -373,42 +371,43 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) ...@@ -373,42 +371,43 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
* Walk the devices on this bus, working out what we can * Walk the devices on this bus, working out what we can
* and can't support. * and can't support.
*/ */
for (walk = bus->devices.next; walk != &bus->devices; walk = walk->next) { list_for_each_entry(dev, &bus->devices, bus_list) {
struct pci_dev *dev = pci_dev_b(walk);
u16 status; u16 status;
pdev_fixup_device_resources(root, dev); pdev_fixup_device_resources(root, dev);
pci_read_config_word(dev, PCI_STATUS, &status); pci_read_config_word(dev, PCI_STATUS, &status);
all_status &= status;
/*
* If any device on this bus does not support fast back
* to back transfers, then the bus as a whole is not able
* to support them. Having fast back to back transfers
* on saves us one PCI cycle per transaction.
*/
if (!(status & PCI_STATUS_FAST_BACK))
features &= ~PCI_COMMAND_FAST_BACK;
if (pdev_bad_for_parity(dev)) if (pdev_bad_for_parity(dev))
features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY); features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
/* switch (dev->class >> 8) {
* If this device is an ISA bridge, set the have_isa_bridge #if defined(CONFIG_ISA) || defined(CONFIG_EISA)
* flag. We will then go looking for things like keyboard, case PCI_CLASS_BRIDGE_ISA:
* etc case PCI_CLASS_BRIDGE_EISA:
*/ /*
if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA || * If this device is an ISA bridge, set isa_bridge
dev->class >> 8 == PCI_CLASS_BRIDGE_EISA) * to point at this device. We will then go looking
have_isa_bridge = !0; * for things like keyboard, etc.
*/
isa_bridge = dev;
break;
#endif
} }
/*
* If any device on this bus does not support fast back to back
* transfers, then the bus as a whole is not able to support them.
* Having fast back to back transfers on saves us one PCI cycle
* per transaction.
*/
if (all_status & PCI_STATUS_FAST_BACK)
features |= PCI_COMMAND_FAST_BACK;
/* /*
* Now walk the devices again, this time setting them up. * Now walk the devices again, this time setting them up.
*/ */
for (walk = bus->devices.next; walk != &bus->devices; walk = walk->next) { list_for_each_entry(dev, &bus->devices, bus_list) {
struct pci_dev *dev = pci_dev_b(walk);
u16 cmd; u16 cmd;
pci_read_config_word(dev, PCI_COMMAND, &cmd); pci_read_config_word(dev, PCI_COMMAND, &cmd);
...@@ -416,7 +415,17 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) ...@@ -416,7 +415,17 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
pci_write_config_word(dev, PCI_COMMAND, cmd); pci_write_config_word(dev, PCI_COMMAND, cmd);
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
SMP_CACHE_BYTES >> 2); L1_CACHE_BYTES >> 2);
}
/*
* Propagate the flags to the PCI bridge.
*/
if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
if (features & PCI_COMMAND_FAST_BACK)
bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
if (features & PCI_COMMAND_PARITY)
bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
} }
/* /*
...@@ -454,20 +463,17 @@ pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *rang ...@@ -454,20 +463,17 @@ pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *rang
*/ */
u8 __devinit pci_std_swizzle(struct pci_dev *dev, u8 *pinp) u8 __devinit pci_std_swizzle(struct pci_dev *dev, u8 *pinp)
{ {
int pin = *pinp; int pin = *pinp - 1;
if (pin != 0) { while (dev->bus->self) {
pin -= 1; pin = (pin + PCI_SLOT(dev->devfn)) & 3;
while (dev->bus->self) { /*
pin = (pin + PCI_SLOT(dev->devfn)) & 3; * move up the chain of bridges,
/* * swizzling as we go.
* move up the chain of bridges, */
* swizzling as we go. dev = dev->bus->self;
*/
dev = dev->bus->self;
}
*pinp = pin + 1;
} }
*pinp = pin + 1;
return PCI_SLOT(dev->devfn); return PCI_SLOT(dev->devfn);
} }
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/notifier.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -57,7 +56,7 @@ ...@@ -57,7 +56,7 @@
enum req { enum req {
req_readbytes, req_readbytes,
req_reset_all req_reset
}; };
struct ecard_request { struct ecard_request {
...@@ -131,14 +130,11 @@ slot_to_ecard(unsigned int slot) ...@@ -131,14 +130,11 @@ slot_to_ecard(unsigned int slot)
#define POD_INT_ADDR(x) ((volatile unsigned char *)\ #define POD_INT_ADDR(x) ((volatile unsigned char *)\
((BUS_ADDR((x)) - IO_BASE) + IO_START)) ((BUS_ADDR((x)) - IO_BASE) + IO_START))
static inline void ecard_task_reset(void) static inline void ecard_task_reset(struct ecard_request *req)
{ {
ecard_t *ec; struct expansion_card *ec = req->ec;
if (ec->loader)
for (ec = cards; ec; ec = ec->next) ecard_loader_reset(POD_INT_ADDR(ec->podaddr), ec->loader);
if (ec->loader)
ecard_loader_reset(POD_INT_ADDR(ec->podaddr),
ec->loader);
} }
static void static void
...@@ -218,8 +214,8 @@ static void ecard_do_request(struct ecard_request *req) ...@@ -218,8 +214,8 @@ static void ecard_do_request(struct ecard_request *req)
ecard_task_readbytes(req); ecard_task_readbytes(req);
break; break;
case req_reset_all: case req_reset:
ecard_task_reset(); ecard_task_reset(req);
break; break;
} }
} }
...@@ -355,60 +351,6 @@ ecard_call(struct ecard_request *req) ...@@ -355,60 +351,6 @@ ecard_call(struct ecard_request *req)
/* ======================= Mid-level card control ===================== */ /* ======================= Mid-level card control ===================== */
/*
* This function is responsible for resetting the expansion cards to a
* sensible state immediately prior to rebooting the system. This function
* has process state (keventd), so we can sleep.
*
* Possible "val" values here:
* SYS_RESTART - restarting system
* SYS_HALT - halting system
* SYS_POWER_OFF - powering down system
*
* We ignore all calls, unless it is a SYS_RESTART call - power down/halts
* will be followed by a SYS_RESTART if ctrl-alt-del is pressed again.
*/
static int ecard_reboot(struct notifier_block *me, unsigned long val, void *v)
{
struct ecard_request req;
if (val != SYS_RESTART)
return 0;
/*
* Disable the expansion card interrupt
*/
disable_irq(IRQ_EXPANSIONCARD);
/*
* If we have any expansion card loader code which will handle
* the reset for us, call it now.
*/
req.req = req_reset_all;
ecard_call(&req);
/*
* Disable the expansion card interrupt again, just to be sure.
*/
disable_irq(IRQ_EXPANSIONCARD);
/*
* Finally, reset the expansion card interrupt mask to
* all enable (RISC OS doesn't set this)
*/
#ifdef HAS_EXPMASK
have_expmask = ~0;
__raw_writeb(have_expmask, EXPMASK_ENABLE);
#endif
return 0;
}
static struct notifier_block ecard_reboot_notifier = {
.notifier_call = ecard_reboot,
};
static void static void
ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld) ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld)
{ {
...@@ -1083,11 +1025,6 @@ static int __init ecard_init(void) ...@@ -1083,11 +1025,6 @@ static int __init ecard_init(void)
{ {
int slot, irqhw; int slot, irqhw;
/*
* Register our reboot notifier
*/
register_reboot_notifier(&ecard_reboot_notifier);
#ifdef CONFIG_CPU_32 #ifdef CONFIG_CPU_32
init_waitqueue_head(&ecard_wait); init_waitqueue_head(&ecard_wait);
#endif #endif
...@@ -1158,11 +1095,32 @@ static int ecard_drv_remove(struct device *dev) ...@@ -1158,11 +1095,32 @@ static int ecard_drv_remove(struct device *dev)
return 0; return 0;
} }
/*
* Before rebooting, we must make sure that the expansion card is in a
* sensible state, so it can be re-detected. This means that the first
* page of the ROM must be visible. We call the expansion cards reset
* handler, if any.
*/
static void ecard_drv_shutdown(struct device *dev)
{
struct expansion_card *ec = ECARD_DEV(dev);
struct ecard_driver *drv = ECARD_DRV(dev->driver);
struct ecard_request req;
if (drv->shutdown)
drv->shutdown(ec);
ecard_release(ec);
req.req = req_reset;
req.ec = ec;
ecard_call(&req);
}
int ecard_register_driver(struct ecard_driver *drv) int ecard_register_driver(struct ecard_driver *drv)
{ {
drv->drv.bus = &ecard_bus_type; drv->drv.bus = &ecard_bus_type;
drv->drv.probe = ecard_drv_probe; drv->drv.probe = ecard_drv_probe;
drv->drv.remove = ecard_drv_remove; drv->drv.remove = ecard_drv_remove;
drv->drv.shutdown = ecard_drv_shutdown;
return driver_register(&drv->drv); return driver_register(&drv->drv);
} }
......
...@@ -1028,8 +1028,10 @@ vector_IRQ: @ ...@@ -1028,8 +1028,10 @@ vector_IRQ: @
@ @
@ now branch to the relevant MODE handling routine @ now branch to the relevant MODE handling routine
@ @
mov r13, #PSR_I_BIT | MODE_SVC mrs r13, cpsr
msr spsr_c, r13 @ switch to SVC_32 mode bic r13, r13, #MODE_MASK
orr r13, r13, #MODE_SVC
msr spsr, r13 @ switch to SVC_32 mode
and lr, lr, #15 and lr, lr, #15
ldr lr, [pc, lr, lsl #2] ldr lr, [pc, lr, lsl #2]
......
...@@ -75,9 +75,8 @@ no_work_pending: ...@@ -75,9 +75,8 @@ no_work_pending:
* This is how we return from a fork. * This is how we return from a fork.
*/ */
ENTRY(ret_from_fork) ENTRY(ret_from_fork)
#ifdef CONFIG_PREEMPT ldr r0, [r0, #TI_TASK]
bl schedule_tail bl schedule_tail
#endif
get_thread_info tsk get_thread_info tsk
ldr r1, [tsk, #TI_FLAGS] @ check for syscall tracing ldr r1, [tsk, #TI_FLAGS] @ check for syscall tracing
mov why, #1 mov why, #1
......
/*
* linux/arch/arm/kernel/suspend.c
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License.
*
* This is the common support code for suspending an ARM machine.
* pm_do_suspend() is responsible for actually putting the CPU to
* sleep.
*/
#include <linux/config.h>
#include <linux/pm.h>
#include <linux/device.h>
#include <linux/cpufreq.h>
#include <asm/leds.h>
#include <asm/system.h>
int suspend(void)
{
int ret;
/*
* Suspend "legacy" devices.
*/
ret = pm_send_all(PM_SUSPEND, (void *)3);
if (ret != 0)
goto out;
/*
* Tell LDM devices we're going to suspend.
*/
ret = device_suspend(4, SUSPEND_NOTIFY);
if (ret != 0)
goto resume_legacy;
/*
* Disable, devices, and save state.
*/
device_suspend(4, SUSPEND_DISABLE);
device_suspend(4, SUSPEND_SAVE_STATE);
/*
* Tell devices that they're going to be powered off.
*/
device_suspend(4, SUSPEND_POWER_DOWN);
local_irq_disable();
leds_event(led_stop);
ret = pm_do_suspend();
leds_event(led_start);
local_irq_enable();
/*
* Tell devices that they now have power.
*/
device_resume(RESUME_POWER_ON);
/*
* Restore the CPU frequency settings.
*/
#ifdef CONFIG_CPU_FREQ
cpufreq_restore();
#endif
/*
* Resume LDM devices.
*/
device_resume(RESUME_RESTORE_STATE);
device_resume(RESUME_ENABLE);
resume_legacy:
/*
* Resume "legacy" devices.
*/
pm_send_all(PM_RESUME, (void *)0);
out:
return ret;
}
#ifdef CONFIG_SYSCTL
#include <linux/init.h>
#include <linux/sysctl.h>
/*
* This came from arch/arm/mach-sa1100/pm.c:
* Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
* with modifications by Nicolas Pitre and Russell King.
*
* ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than
* linux/sysctl.h.
*
* This means our interface here won't survive long - it needs a new
* interface. Quick hack to get this working - use sysctl id 9999.
*/
#warning ACPI broke the kernel, this interface needs to be fixed up.
#define CTL_ACPI 9999
#define ACPI_S1_SLP_TYP 19
static struct ctl_table pm_table[] =
{
{ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&suspend},
{0}
};
static struct ctl_table pm_dir_table[] =
{
{CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
{0}
};
/*
* Initialize power interface
*/
static int __init pm_init(void)
{
register_sysctl_table(pm_dir_table, 1);
return 0;
}
fs_initcall(pm_init);
#endif
...@@ -200,6 +200,7 @@ void do_settimeofday(struct timeval *tv) ...@@ -200,6 +200,7 @@ void do_settimeofday(struct timeval *tv)
static struct irqaction timer_irq = { static struct irqaction timer_irq = {
.name = "timer", .name = "timer",
.flags = SA_INTERRUPT,
}; };
/* /*
......
...@@ -4,10 +4,11 @@ ...@@ -4,10 +4,11 @@
# Object file lists. # Object file lists.
obj-y := arch.o cpu.o irq.o mm.o time.o obj-y := arch.o irq.o mm.o time.o
obj-m := obj-m :=
obj-n := obj-n :=
obj- := obj- :=
obj-$(CONFIG_LEDS) += leds.o obj-$(CONFIG_LEDS) += leds.o
obj-$(CONFIG_PCI) += pci_v3.o pci.o obj-$(CONFIG_PCI) += pci_v3.o pci.o
obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/io.h> #include <asm/io.h>
static struct cpufreq_driver integrator_driver;
#define CM_ID (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_ID_OFFSET) #define CM_ID (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_ID_OFFSET)
#define CM_OSC (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_OSC_OFFSET) #define CM_OSC (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_OSC_OFFSET)
#define CM_STAT (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_STAT_OFFSET) #define CM_STAT (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_STAT_OFFSET)
...@@ -43,7 +45,6 @@ static unsigned int vco_to_freq(struct vco vco, int factor) ...@@ -43,7 +45,6 @@ static unsigned int vco_to_freq(struct vco vco, int factor)
return 2000 * (vco.vdw + 8) / cc_divisor[vco.od] / factor; return 2000 * (vco.vdw + 8) / cc_divisor[vco.od] / factor;
} }
#ifdef CONFIG_CPU_FREQ
/* /*
* Divisor indexes in ascending divisor order * Divisor indexes in ascending divisor order
*/ */
...@@ -69,21 +70,17 @@ static struct vco freq_to_vco(unsigned int freq_khz, int factor) ...@@ -69,21 +70,17 @@ static struct vco freq_to_vco(unsigned int freq_khz, int factor)
return vco; return vco;
} }
/* /*
* Validate the speed in khz. If it is outside our * Validate the speed policy.
* range, then return the lowest.
*/ */
static int integrator_verify_speed(struct cpufreq_policy *policy) static int integrator_verify_policy(struct cpufreq_policy *policy)
{ {
struct vco vco; struct vco vco;
if (policy->max > policy->cpuinfo.max_freq) cpufreq_verify_within_limits(policy,
policy->max = policy->cpuinfo.max_freq; policy->cpuinfo.min_freq,
policy->cpuinfo.max_freq);
if (policy->max < 12000)
policy->max = 12000;
if (policy->max > 160000)
policy->max = 160000;
vco = freq_to_vco(policy->max, 1); vco = freq_to_vco(policy->max, 1);
...@@ -92,12 +89,28 @@ static int integrator_verify_speed(struct cpufreq_policy *policy) ...@@ -92,12 +89,28 @@ static int integrator_verify_speed(struct cpufreq_policy *policy)
if (vco.vdw > 152) if (vco.vdw > 152)
vco.vdw = 152; vco.vdw = 152;
policy->min = policy->max = vco_to_freq(vco, 1); 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;
policy->min = vco_to_freq(vco, 1);
cpufreq_verify_within_limits(policy,
policy->cpuinfo.min_freq,
policy->cpuinfo.max_freq);
return 0; return 0;
} }
static int integrator_set_policy(struct cpufreq_policy *policy)
static int integrator_set_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{ {
unsigned long cpus_allowed; unsigned long cpus_allowed;
int cpu = policy->cpu; int cpu = policy->cpu;
...@@ -121,9 +134,18 @@ static int integrator_set_policy(struct cpufreq_policy *policy) ...@@ -121,9 +134,18 @@ static int integrator_set_policy(struct cpufreq_policy *policy)
cm_osc = __raw_readl(CM_OSC); cm_osc = __raw_readl(CM_OSC);
vco.od = (cm_osc >> 8) & 7; vco.od = (cm_osc >> 8) & 7;
vco.vdw = cm_osc & 255; vco.vdw = cm_osc & 255;
freqs.old = vco_to_freq(vco, 1); freqs.old = vco_to_freq(vco, 1);
freqs.new = target_freq;
/* freq_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);
freqs.cpu = policy->cpu; freqs.cpu = policy->cpu;
if (freqs.old == freqs.new) { if (freqs.old == freqs.new) {
...@@ -132,7 +154,6 @@ static int integrator_set_policy(struct cpufreq_policy *policy) ...@@ -132,7 +154,6 @@ static int integrator_set_policy(struct cpufreq_policy *policy)
} }
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
vco = freq_to_vco(policy->max, 1);
cm_osc = __raw_readl(CM_OSC); cm_osc = __raw_readl(CM_OSC);
cm_osc &= 0xfffff800; cm_osc &= 0xfffff800;
...@@ -152,80 +173,64 @@ static int integrator_set_policy(struct cpufreq_policy *policy) ...@@ -152,80 +173,64 @@ static int integrator_set_policy(struct cpufreq_policy *policy)
return 0; return 0;
} }
static struct cpufreq_policy integrator_policy = { static int integrator_cpufreq_init(struct cpufreq *policy)
.cpu = 0, {
.policy = CPUFREQ_POLICY_POWERSAVE, unsigned long cus_allowed;
.cpuinfo = { unsigned int cpu = policy->cpu;
.max_freq = 160000, u_int cm_osc, cm_stat, mem_freq_khz;
.min_freq = 12000, struct vco vco;
.transition_latency = CPUFREQ_ETERNAL,
},
};
static struct cpufreq_driver integrator_driver = { cpus_allowed = current->cpus_allowed;
.verify = integrator_verify_speed,
.setpolicy = integrator_set_policy,
.policy = &integrator_policy,
.name = "integrator",
};
#endif
static int __init integrator_cpu_init(void) set_cpus_allowed(current, 1 << cpu);
{ BUG_ON(cpu != smp_processor_id());
struct cpufreq_policy *policies;
unsigned long cpus_allowed;
int cpu;
policies = kmalloc(sizeof(struct cpufreq_policy) * NR_CPUS, /* detect memory etc. */
GFP_KERNEL); cm_stat = __raw_readl(CM_STAT);
if (!policies) { cm_osc = __raw_readl(CM_OSC);
printk(KERN_ERR "CPU: unable to allocate policies structure\n"); vco.od = (cm_osc >> 20) & 7;
return -ENOMEM; vco.vdw = (cm_osc >> 12) & 255;
} mem_freq_khz = vco_to_freq(vco, 2);
cpus_allowed = current->cpus_allowed; printk(KERN_INFO "CPU%d: Module id: %d\n", cpu, cm_stat & 255);
for (cpu = 0; cpu < NR_CPUS; cpu++) { printk(KERN_INFO "CPU%d: Memory clock = %d.%03d MHz\n",
u_int cm_osc, cm_stat, mem_freq_khz; cpu, mem_freq_khz / 1000, mem_freq_khz % 1000);
struct vco vco;
if (!cpu_online(cpu))
continue;
set_cpus_allowed(current, 1 << cpu);
BUG_ON(cpu != smp_processor_id());
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);
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;
policies[cpu].cpu = cpu;
policies[cpu].policy = CPUFREQ_POLICY_POWERSAVE,
policies[cpu].cpuinfo.max_freq = 160000;
policies[cpu].cpuinfo.min_freq = 12000;
policies[cpu].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
policies[cpu].min =
policies[cpu].max = vco_to_freq(vco, 1);
}
set_cpus_allowed(current, cpus_allowed); vco.od = (cm_osc >> 8) & 7;
vco.vdw = cm_osc & 255;
/* 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 */
#ifdef CONFIG_CPU_FREQ set_cpus_allowed(current, cpus_allowed);
integrator_driver.policy = policies;
cpufreq_register(&integrator_driver);
#else
kfree(policies);
#endif
return 0; return 0;
} }
arch_initcall(integrator_cpu_init); static struct cpufreq_driver integrator_driver = {
.verify = integrator_verify_policy,
.target = integrator_set_target,
.init = integrator_cpufreq_init,
.name = "integrator",
};
static int __init integrator_cpu_init(void)
{
return cpufreq_register_driver(&integrator_driver);
}
static void __exit integrator_cpu_exit(void)
{
cpufreq_unregister_driver(&integrator_driver);
}
MODULE_AUTHOR ("Russell M. King");
MODULE_DESCRIPTION ("cpufreq driver for ARM Integrator CPUs");
MODULE_LICENSE ("GPL");
module_init(integrator_cpu_init);
module_exit(integrator_cpu_exit);
...@@ -9,15 +9,8 @@ obj-n := ...@@ -9,15 +9,8 @@ obj-n :=
obj- := obj- :=
led-y := leds.o led-y := leds.o
# This needs to be cleaned up. We probably need to have SA1100 obj-$(CONFIG_CPU_FREQ_SA1100) += cpu-sa1100.o
# and SA1110 config symbols. obj-$(CONFIG_CPU_FREQ_SA1110) += cpu-sa1110.o
ifeq ($(CONFIG_CPU_FREQ),y)
obj-$(CONFIG_SA1100_ASSABET) += cpu-sa1110.o
obj-$(CONFIG_SA1100_CERF) += cpu-sa1110.o
obj-$(CONFIG_SA1100_HACKKIT) += cpu-sa1110.o
obj-$(CONFIG_SA1100_LART) += cpu-sa1100.o
obj-$(CONFIG_SA1100_PT_SYSTEM3) += cpu-sa1110.o
endif
# Specific board support # Specific board support
obj-$(CONFIG_SA1100_ADSBITSY) += adsbitsy.o obj-$(CONFIG_SA1100_ADSBITSY) += adsbitsy.o
......
...@@ -101,7 +101,7 @@ typedef struct { ...@@ -101,7 +101,7 @@ typedef struct {
} sa1100_dram_regs_t; } sa1100_dram_regs_t;
static struct cpufreq_driver sa1100_driver;
static sa1100_dram_regs_t sa1100_dram_settings[] = static sa1100_dram_regs_t sa1100_dram_settings[] =
{ {
...@@ -176,60 +176,73 @@ static void sa1100_update_dram_timings(int current_speed, int new_speed) ...@@ -176,60 +176,73 @@ static void sa1100_update_dram_timings(int current_speed, int new_speed)
} }
} }
static int sa1100_setspeed(struct cpufreq_policy *policy) static int sa1100_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{ {
unsigned int cur = sa11x0_getspeed(); unsigned int cur = sa11x0_getspeed();
unsigned int new_ppcr;
struct cpufreq_freqs freqs; struct cpufreq_freqs freqs;
switch(relation){
case CPUFREQ_RELATION_L:
new_ppcr = sa11x0_freq_to_ppcr(target_freq);
if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max)
new_ppcr--;
break;
case CPUFREQ_RELATION_H:
new_ppcr = sa11x0_freq_to_ppcr(target_freq);
if ((sa11x0_ppcr_to_freq(new_ppcr) > target_freq) &&
(sa11x0_ppcr_to_freq(new_ppcr - 1) >= policy->min))
mew_ppcr--;
break;
}
freqs.old = cur; freqs.old = cur;
freqs.new = policy->max; freqs.new = sa11x0_ppcr_to_freq(new_ppcr);
freqs.cpu = 0; freqs.cpu = 0;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
if (policy->max > cur) if (freqs.new > cur)
sa1100_update_dram_timings(cur, policy->max); sa1100_update_dram_timings(cur, freqs.new);
PPCR = sa11x0_freq_to_ppcr(policy->max); PPCR = new_ppcr;
if (policy->max < cur) if (freqs.new < cur)
sa1100_update_dram_timings(cur, policy->max); sa1100_update_dram_timings(cur, freqs.new);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
return 0; return 0;
} }
static struct cpufreq_policy sa1100_policy = { static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
.cpu = 0, {
.policy = CPUFREQ_POLICY_POWERSAVE, if (policy->cpu != 0)
.cpuinfo = { return -EINVAL;
.max_freq = 287000, policy->cur = policy->min = policy->max = sa11x0_getspeed();
.min_freq = 59000, policy->policy = CPUFREQ_POLICY_POWERSAVE;
.transition_latency = CPUFREQ_ETERNAL, policy->cpuinfo.min_freq = 59000;
}, policy->cpuinfo.max_freq = 287000;
}; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
return 0;
}
static struct cpufreq_driver sa1100_driver = { static struct cpufreq_driver sa1100_driver = {
.verify = sa11x0_verify_speed, .verify = sa11x0_verify_speed,
.setpolicy = sa1100_setspeed, .target = sa1100_target,
.policy = &sa1100_policy, .init = sa1100_cpu_init,
.name = "sa1100", .name = "sa1100",
}; };
static int __init sa1100_dram_init(void) static int __init sa1100_dram_init(void)
{ {
int ret = -ENODEV; cpufreq_gov_userspace_init();
if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID)
if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID) { return cpufreq_register_driver(&sa1100_driver);
sa1100_driver.cpu_cur_freq[0] = else
sa1100_policy.min = return -ENODEV;
sa1100_policy.max = sa11x0_getspeed();
ret = cpufreq_register(&sa1100_driver);
}
return ret;
} }
arch_initcall(sa1100_dram_init); arch_initcall(sa1100_dram_init);
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
#undef DEBUG #undef DEBUG
static struct cpufreq_driver sa1110_driver;
struct sdram_params { struct sdram_params {
u_char rows; /* bits */ u_char rows; /* bits */
u_char cas_latency; /* cycles */ u_char cas_latency; /* cycles */
...@@ -208,11 +210,11 @@ sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram) ...@@ -208,11 +210,11 @@ sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram)
} }
/* /*
* Ok, set the CPU frequency. Since we've done the validation * Ok, set the CPU frequency.
* above, we can match for an exact frequency. If we don't find
* an exact match, we will to set the lowest frequency to be safe.
*/ */
static int sa1110_setspeed(struct cpufreq_policy *policy) static int sa1110_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{ {
struct sdram_params *sdram = &sdram_params; struct sdram_params *sdram = &sdram_params;
struct cpufreq_freqs freqs; struct cpufreq_freqs freqs;
...@@ -220,8 +222,25 @@ static int sa1110_setspeed(struct cpufreq_policy *policy) ...@@ -220,8 +222,25 @@ static int sa1110_setspeed(struct cpufreq_policy *policy)
unsigned long flags; unsigned long flags;
unsigned int ppcr, unused; unsigned int ppcr, unused;
ppcr = sa11x0_freq_to_ppcr(policy->max); switch(relation){
sdram_calculate_timing(&sd, policy->max, sdram); case CPUFREQ_RELATION_L:
ppcr = sa11x0_freq_to_ppcr(target_freq);
if (sa11x0_ppcr_to_freq(ppcr) > policy->max)
ppcr--;
break;
case CPUFREQ_RELATION_H:
ppcr = sa11x0_freq_to_ppcr(target_freq);
if (ppcr && (sa11x0_ppcr_to_freq(ppcr) > target_freq) &&
(sa11x0_ppcr_to_freq(ppcr-1) >= policy->min))
ppcr--;
break;
}
freqs.old = sa11x0_getspeed();
freqs.new = sa11x0_ppcr_to_freq(ppcr);
freqs.cpu = 0;
sdram_calculate_timing(&sd, freqs.new, sdram);
#if 0 #if 0
/* /*
...@@ -240,10 +259,6 @@ static int sa1110_setspeed(struct cpufreq_policy *policy) ...@@ -240,10 +259,6 @@ static int sa1110_setspeed(struct cpufreq_policy *policy)
sd.mdcas[2] = 0xaaaaaaaa; sd.mdcas[2] = 0xaaaaaaaa;
#endif #endif
freqs.old = sa11x0_getspeed();
freqs.new = policy->max;
freqs.cpu = 0;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
/* /*
...@@ -288,27 +303,29 @@ static int sa1110_setspeed(struct cpufreq_policy *policy) ...@@ -288,27 +303,29 @@ static int sa1110_setspeed(struct cpufreq_policy *policy)
/* /*
* Now, return the SDRAM refresh back to normal. * Now, return the SDRAM refresh back to normal.
*/ */
sdram_update_refresh(policy->max, sdram); sdram_update_refresh(freqs.new, sdram);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
return 0; return 0;
} }
static struct cpufreq_policy sa1110_policy = { static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
.cpu = 0, {
.policy = CPUFREQ_POLICY_POWERSAVE, if (policy->cpu != 0)
.cpuinfo = { return -EINVAL;
.max_freq = 287000, policy->cur = policy->min = policy->max = sa11x0_getspeed();
.min_freq = 59000, policy->policy = CPUFREQ_POLICY_POWERSAVE;
.transition_latency = CPUFREQ_ETERNAL, policy->cpuinfo.min_freq = 59000;
}, policy->cpuinfo.max_freq = 287000;
}; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
return 0;
}
static struct cpufreq_driver sa1110_driver = { static struct cpufreq_driver sa1110_driver = {
.verify = sa11x0_verify_speed, .verify = sa11x0_verify_speed,
.setpolicy = sa1110_setspeed, .target = sa1110_target,
.policy = &sa1110_policy, .init = sa1110_cpu_init,
.name = "sa1110", .name = "sa1110",
}; };
...@@ -331,15 +348,11 @@ static int __init sa1110_clk_init(void) ...@@ -331,15 +348,11 @@ static int __init sa1110_clk_init(void)
sdram->tck, sdram->trcd, sdram->trp, sdram->tck, sdram->trcd, sdram->trp,
sdram->twr, sdram->refresh, sdram->cas_latency); sdram->twr, sdram->refresh, sdram->cas_latency);
cpufreq_gov_userspace_init();
memcpy(&sdram_params, sdram, sizeof(sdram_params)); memcpy(&sdram_params, sdram, sizeof(sdram_params));
sa1110_driver.cpu_cur_freq[0] = return cpufreq_register_driver(&sa1110_driver);
sa1110_policy.min =
sa1110_policy.max = sa11x0_getspeed();
sa1110_setspeed(&sa1110_policy);
return cpufreq_register(&sa1110_driver);
} }
return 0; return 0;
......
...@@ -48,33 +48,48 @@ static const unsigned short cclk_frequency_100khz[NR_FREQS] = { ...@@ -48,33 +48,48 @@ static const unsigned short cclk_frequency_100khz[NR_FREQS] = {
2802 /* 280.2 MHz */ 2802 /* 280.2 MHz */
}; };
#ifdef CONFIG_CPU_FREQ #if defined(CONFIG_CPU_FREQ_SA1100) || defined(CONFIG_CPU_FREQ_SA1110)
/* rounds up(!) */
unsigned int sa11x0_freq_to_ppcr(unsigned int khz) unsigned int sa11x0_freq_to_ppcr(unsigned int khz)
{ {
int i; int i;
khz /= 100; khz /= 100;
for (i = NR_FREQS - 1; i > 0; i--) for (i = 0; i < NR_FREQS; i++)
if (cclk_frequency_100khz[i] <= khz) if (cclk_frequency_100khz[i] >= khz)
break; break;
return i; return i;
} }
/* unsigned int sa11x0_ppcr_to_freq(unsigned int idx)
* Validate the policy. We aren't able to do any fancy in-kernel {
* scaling, so we force min=max, and set the policy to "performance". unsigned int freq = 0;
* If we can't generate the precise frequency requested, round it up. if (idx < NR_FREQS)
freq = cclk_frequency_100khz[idx] * 100;
return freq;
}
/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
* this platform, anyway.
*/ */
int sa11x0_verify_speed(struct cpufreq_policy *policy) int sa11x0_verify_speed(struct cpufreq_policy *policy)
{ {
if (policy->max > policy->cpuinfo.max_freq) unsigned int tmp;
policy->max = policy->cpuinfo.max_freq; if (policy->cpu)
return -EINVAL;
cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
/* make sure that at least one frequency is within the policy */
tmp = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->min)] * 100;
if (tmp > policy->max)
policy->max = tmp;
cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
policy->max = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->max)] * 100;
policy->min = policy->max;
policy->policy = CPUFREQ_POLICY_POWERSAVE;
return 0; return 0;
} }
......
...@@ -23,3 +23,4 @@ struct cpufreq_policy; ...@@ -23,3 +23,4 @@ struct cpufreq_policy;
extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz); extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
extern int sa11x0_verify_speed(struct cpufreq_policy *policy); extern int sa11x0_verify_speed(struct cpufreq_policy *policy);
extern unsigned int sa11x0_getspeed(void); extern unsigned int sa11x0_getspeed(void);
extern unsigned int sa11x0_ppcr_to_freq(unsigned int idx);
...@@ -211,6 +211,99 @@ static struct resource irq_resource = { ...@@ -211,6 +211,99 @@ static struct resource irq_resource = {
.end = 0x9005ffff, .end = 0x9005ffff,
}; };
struct sa1100irq_state {
unsigned int saved;
unsigned int icmr;
unsigned int iclr;
unsigned int iccr;
};
static int sa1100irq_suspend(struct device *dev, u32 state, u32 level)
{
struct sa1100irq_state *st;
if (!dev->saved_state && level == SUSPEND_NOTIFY)
dev->saved_state = kmalloc(sizeof(struct sa1100irq_state),
GFP_KERNEL);
if (!dev->saved_state)
return -ENOMEM;
if (level == SUSPEND_POWER_DOWN) {
st = (struct sa1100irq_state *)dev->saved_state;
st->saved = 1;
st->icmr = ICMR;
st->iclr = ICLR;
st->iccr = ICCR;
/*
* Disable all GPIO-based interrupts.
*/
ICMR &= ~(IC_GPIO11_27|IC_GPIO10|IC_GPIO9|IC_GPIO8|IC_GPIO7|
IC_GPIO6|IC_GPIO5|IC_GPIO4|IC_GPIO3|IC_GPIO2|
IC_GPIO1|IC_GPIO0);
/*
* Set the appropriate edges for wakeup.
*/
GRER = PWER & GPIO_IRQ_rising_edge;
GFER = PWER & GPIO_IRQ_falling_edge;
/*
* Clear any pending GPIO interrupts.
*/
GEDR = GEDR;
}
return 0;
}
static int sa1100irq_resume(struct device *dev, u32 level)
{
struct sa1100irq_state *st;
if (level == RESUME_POWER_ON) {
st = (struct sa1100irq_state *)dev->saved_state;
dev->saved_state = NULL;
if (st->saved) {
ICCR = st->iccr;
ICLR = st->iclr;
GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
ICMR = st->icmr;
}
kfree(st);
}
return 0;
}
static struct device_driver sa1100irq_driver = {
.name = "sa11x0-irq",
.bus = &system_bus_type,
.suspend = sa1100irq_suspend,
.resume = sa1100irq_resume,
};
static struct sys_device sa1100irq_device = {
.name = "irq",
.id = 0,
.dev = {
.name = "Intel SA11x0 [Interrupt Controller]",
.driver = &sa1100irq_driver,
},
};
static int __init sa1100irq_init_devicefs(void)
{
driver_register(&sa1100irq_driver);
return sys_device_register(&sa1100irq_device);
}
device_initcall(sa1100irq_init_devicefs);
void __init sa1100_init_irq(void) void __init sa1100_init_irq(void)
{ {
unsigned int irq; unsigned int irq;
......
...@@ -22,25 +22,12 @@ ...@@ -22,25 +22,12 @@
* 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array. * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array.
* Storage is local on the stack now. * Storage is local on the stack now.
*/ */
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/device.h> #include <linux/time.h>
#include <linux/cpufreq.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/memory.h> #include <asm/memory.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/leds.h>
/*
* Debug macros
*/
#undef DEBUG
extern void sa1100_cpu_suspend(void); extern void sa1100_cpu_suspend(void);
extern void sa1100_cpu_resume(void); extern void sa1100_cpu_resume(void);
...@@ -58,10 +45,9 @@ enum { SLEEP_SAVE_SP = 0, ...@@ -58,10 +45,9 @@ enum { SLEEP_SAVE_SP = 0,
SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER, SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER,
SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3, SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3,
SLEEP_SAVE_GPDR, SLEEP_SAVE_GRER, SLEEP_SAVE_GFER, SLEEP_SAVE_GAFR, SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR,
SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR, SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR,
SLEEP_SAVE_ICMR,
SLEEP_SAVE_Ser1SDCR0, SLEEP_SAVE_Ser1SDCR0,
SLEEP_SAVE_SIZE SLEEP_SAVE_SIZE
...@@ -72,10 +58,6 @@ int pm_do_suspend(void) ...@@ -72,10 +58,6 @@ int pm_do_suspend(void)
{ {
unsigned long sleep_save[SLEEP_SAVE_SIZE]; unsigned long sleep_save[SLEEP_SAVE_SIZE];
local_irq_disable();
leds_event(led_stop);
/* preserve current time */ /* preserve current time */
RCNR = xtime.tv_sec; RCNR = xtime.tv_sec;
...@@ -88,8 +70,6 @@ int pm_do_suspend(void) ...@@ -88,8 +70,6 @@ int pm_do_suspend(void)
SAVE(OIER); SAVE(OIER);
SAVE(GPDR); SAVE(GPDR);
SAVE(GRER);
SAVE(GFER);
SAVE(GAFR); SAVE(GAFR);
SAVE(PPDR); SAVE(PPDR);
...@@ -99,13 +79,6 @@ int pm_do_suspend(void) ...@@ -99,13 +79,6 @@ int pm_do_suspend(void)
SAVE(Ser1SDCR0); SAVE(Ser1SDCR0);
SAVE(ICMR);
/* ... maybe a global variable initialized by arch code to set this? */
GRER = PWER;
GFER = 0;
GEDR = GEDR;
/* Clear previous reset status */ /* Clear previous reset status */
RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR; RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR;
...@@ -115,22 +88,23 @@ int pm_do_suspend(void) ...@@ -115,22 +88,23 @@ int pm_do_suspend(void)
/* go zzz */ /* go zzz */
sa1100_cpu_suspend(); sa1100_cpu_suspend();
/* ensure not to come back here if it wasn't intended */ /*
* Ensure not to come back here if it wasn't intended
*/
PSPR = 0; PSPR = 0;
#ifdef DEBUG /*
printk(KERN_DEBUG "*** made it back from resume\n"); * Ensure interrupt sources are disabled; we will re-init
#endif * the interrupt subsystem via the device manager.
*/
ICLR = 0;
ICCR = 1;
ICMR = 0;
/* restore registers */ /* restore registers */
RESTORE(GPDR); RESTORE(GPDR);
RESTORE(GRER);
RESTORE(GFER);
RESTORE(GAFR); RESTORE(GAFR);
/* clear any edge detect bit */
GEDR = GEDR;
RESTORE(PPDR); RESTORE(PPDR);
RESTORE(PPSR); RESTORE(PPSR);
RESTORE(PPAR); RESTORE(PPAR);
...@@ -138,6 +112,9 @@ int pm_do_suspend(void) ...@@ -138,6 +112,9 @@ int pm_do_suspend(void)
RESTORE(Ser1SDCR0); RESTORE(Ser1SDCR0);
/*
* Clear the peripheral sleep-hold bit.
*/
PSSR = PSSR_PH; PSSR = PSSR_PH;
RESTORE(OSMR0); RESTORE(OSMR0);
...@@ -147,24 +124,9 @@ int pm_do_suspend(void) ...@@ -147,24 +124,9 @@ int pm_do_suspend(void)
RESTORE(OSCR); RESTORE(OSCR);
RESTORE(OIER); RESTORE(OIER);
ICLR = 0;
ICCR = 1;
RESTORE(ICMR);
/* restore current time */ /* restore current time */
xtime.tv_sec = RCNR; xtime.tv_sec = RCNR;
leds_event(led_start);
local_irq_enable();
/*
* Restore the CPU frequency settings.
*/
#ifdef CONFIG_CPU_FREQ
cpufreq_restore();
#endif
return 0; return 0;
} }
...@@ -172,78 +134,3 @@ unsigned long sleep_phys_sp(void *sp) ...@@ -172,78 +134,3 @@ unsigned long sleep_phys_sp(void *sp)
{ {
return virt_to_phys(sp); return virt_to_phys(sp);
} }
#ifdef CONFIG_SYSCTL
/*
* ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than
* linux/sysctl.h.
*
* This means our interface here won't survive long - it needs a new
* interface. Quick hack to get this working - use sysctl id 9999.
*/
#warning ACPI broke the kernel, this interface needs to be fixed up.
#define CTL_ACPI 9999
#define ACPI_S1_SLP_TYP 19
/*
* Send us to sleep.
*/
static int sysctl_pm_do_suspend(void)
{
int retval;
/*
* Suspend "legacy" devices.
*/
retval = pm_send_all(PM_SUSPEND, (void *)3);
if (retval == 0) {
/*
* Suspend LDM devices.
*/
device_suspend(4, SUSPEND_NOTIFY);
device_suspend(4, SUSPEND_SAVE_STATE);
device_suspend(4, SUSPEND_DISABLE);
retval = pm_do_suspend();
/*
* Resume LDM devices.
*/
device_resume(RESUME_RESTORE_STATE);
device_resume(RESUME_ENABLE);
/*
* Resume "legacy" devices.
*/
pm_send_all(PM_RESUME, (void *)0);
}
return retval;
}
static struct ctl_table pm_table[] =
{
{ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_do_suspend},
{0}
};
static struct ctl_table pm_dir_table[] =
{
{CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
{0}
};
/*
* Initialize power interface
*/
static int __init pm_init(void)
{
register_sysctl_table(pm_dir_table, 1);
return 0;
}
fs_initcall(pm_init);
#endif
EXPORT_SYMBOL(pm_do_suspend);
...@@ -213,11 +213,17 @@ static void __init system3_init_irq(void) ...@@ -213,11 +213,17 @@ static void __init system3_init_irq(void)
static int sdram_notifier(struct notifier_block *nb, unsigned long event, static int sdram_notifier(struct notifier_block *nb, unsigned long event,
void *data) void *data)
{ {
struct cpufreq_policy *policy = data;
switch (event) { switch (event) {
case CPUFREQ_MINMAX: case CPUFREQ_ADJUST:
cpufreq_updateminmax(data, 147500, 206000); case CPUFREQ_INCOMPATIBLE:
cpufreq_verify_within_limits(policy, 147500, 206000);
break;
case CPUFREQ_NOTIFY:
if ((policy->min < 147500) ||
(policy->max > 206000))
panic("cpufreq failed to limit the speed\n");
break; break;
} }
return 0; return 0;
} }
...@@ -405,7 +411,7 @@ static int __init system3_init(void) ...@@ -405,7 +411,7 @@ static int __init system3_init(void)
goto DONE; goto DONE;
} }
#if defined( CONFIG_CPU_FREQ ) #ifdef CONFIG_CPU_FREQ
ret = cpufreq_register_notifier(&system3_clkchg_block); ret = cpufreq_register_notifier(&system3_clkchg_block);
if ( ret != 0 ) { if ( ret != 0 ) {
printk( KERN_WARNING"PT Digital Board: could not register clock scale callback\n" ); printk( KERN_WARNING"PT Digital Board: could not register clock scale callback\n" );
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
# To add an entry into this database, please see Documentation/arm/README, # To add an entry into this database, please see Documentation/arm/README,
# or contact rmk@arm.linux.org.uk # or contact rmk@arm.linux.org.uk
# #
# Last update: Mon Jan 13 22:55:16 2003 # Last update: Wed Mar 5 22:11:59 2003
# #
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
# #
...@@ -228,7 +228,7 @@ csb226 ARCH_CSB226 CSB226 216 ...@@ -228,7 +228,7 @@ csb226 ARCH_CSB226 CSB226 216
arnold SA1100_ARNOLD ARNOLD 217 arnold SA1100_ARNOLD ARNOLD 217
psiboard SA1100_PSIBOARD PSIBOARD 218 psiboard SA1100_PSIBOARD PSIBOARD 218
jz8028 ARCH_JZ8028 JZ8028 219 jz8028 ARCH_JZ8028 JZ8028 219
ipaq3 ARCH_IPAQ3 IPAQ3 220 h5400 ARCH_IPAQ3 IPAQ3 220
forte SA1100_FORTE FORTE 221 forte SA1100_FORTE FORTE 221
acam SA1100_ACAM ACAM 222 acam SA1100_ACAM ACAM 222
abox SA1100_ABOX ABOX 223 abox SA1100_ABOX ABOX 223
...@@ -259,7 +259,7 @@ stork_nest ARCH_STORK_NEST STORK_NEST 247 ...@@ -259,7 +259,7 @@ stork_nest ARCH_STORK_NEST STORK_NEST 247
stork_egg ARCH_STORK_EGG STORK_EGG 248 stork_egg ARCH_STORK_EGG STORK_EGG 248
wismo SA1100_WISMO WISMO 249 wismo SA1100_WISMO WISMO 249
ezlinx ARCH_EZLINX EZLINX 250 ezlinx ARCH_EZLINX EZLINX 250
at91rm9200 ARCH_AT91 AT91 251 at91 ARCH_AT91 AT91 251
orion ARCH_ORION ORION 252 orion ARCH_ORION ORION 252
neptune ARCH_NEPTUNE NEPTUNE 253 neptune ARCH_NEPTUNE NEPTUNE 253
hackkit SA1100_HACKKIT HACKKIT 254 hackkit SA1100_HACKKIT HACKKIT 254
...@@ -281,3 +281,27 @@ stlc1502 ARCH_STLC1502 STLC1502 269 ...@@ -281,3 +281,27 @@ stlc1502 ARCH_STLC1502 STLC1502 269
siren ARCH_SIREN SIREN 270 siren ARCH_SIREN SIREN 270
greenlake ARCH_GREENLAKE GREENLAKE 271 greenlake ARCH_GREENLAKE GREENLAKE 271
argus ARCH_ARGUS ARGUS 272 argus ARCH_ARGUS ARGUS 272
combadge SA1100_COMBADGE COMBADGE 273
rokepxa ARCH_ROKEPXA ROKEPXA 274
cintegrator ARCH_CINTEGRATOR CINTEGRATOR 275
guidea07 ARCH_GUIDEA07 GUIDEA07 276
tat257 ARCH_TAT257 TAT257 277
igp2425 ARCH_IGP2425 IGP2425 278
bluegrama ARCH_BLUEGRAMMA BLUEGRAMMA 279
ipod ARCH_IPOD IPOD 280
adsbitsyx ARCH_ADSBITSYX ADSBITSYX 281
trizeps2 ARCH_TRIZEPS2 TRIZEPS2 282
viper ARCH_VIPER VIPER 283
adsbitsyplus SA1100_ADSBITSYPLUS ADSBITSYPLUS 284
adsagc SA1100_ADSAGC ADSAGC 285
stp7312 ARCH_STP7312 STP7312 286
nx_phnx ARCH_PXA255 PXA255 287
wep_ep250 ARCH_WEP_EP250 WEP_EP250 288
inhandelf3 ARCH_INHANDELF3 INHANDELF3 289
adi_coyote ARCH_ADI_COYOTE ADI_COYOTE 290
iyonix ARCH_IYONIX IYONIX 291
damicam_sa1110 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292
meg03 ARCH_MEG03 MEG03 293
pxa_whitechapel ARCH_PXA_WHITECHAPEL PXA_WHITECHAPEL 294
nwsc ARCH_NWSC NWSC 295
nwlarm ARCH_NWLARM NWLARM 296
...@@ -973,23 +973,6 @@ ether1_getstats (struct net_device *dev) ...@@ -973,23 +973,6 @@ ether1_getstats (struct net_device *dev)
return &priv->stats; return &priv->stats;
} }
static int
ether1_set_mac_address(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
if (netif_running(dev))
return -EBUSY;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
/*
* We'll set the MAC address on the chip when we open it.
*/
return 0;
}
/* /*
* Set or clear the multicast filter for this adaptor. * Set or clear the multicast filter for this adaptor.
* num_addrs == -1 Promiscuous mode, receive all packets. * num_addrs == -1 Promiscuous mode, receive all packets.
...@@ -1062,7 +1045,6 @@ ether1_probe(struct expansion_card *ec, const struct ecard_id *id) ...@@ -1062,7 +1045,6 @@ ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
dev->hard_start_xmit = ether1_sendpacket; dev->hard_start_xmit = ether1_sendpacket;
dev->get_stats = ether1_getstats; dev->get_stats = ether1_getstats;
dev->set_multicast_list = ether1_setmulticastlist; dev->set_multicast_list = ether1_setmulticastlist;
dev->set_mac_address = ether1_set_mac_address;
dev->tx_timeout = ether1_timeout; dev->tx_timeout = ether1_timeout;
dev->watchdog_timeo = 5 * HZ / 100; dev->watchdog_timeo = 5 * HZ / 100;
......
...@@ -461,23 +461,6 @@ static struct net_device_stats *ether3_getstats(struct net_device *dev) ...@@ -461,23 +461,6 @@ static struct net_device_stats *ether3_getstats(struct net_device *dev)
return &priv->stats; return &priv->stats;
} }
static int
ether3_set_mac_address(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
if (netif_running(dev))
return -EBUSY;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
/*
* We'll set the MAC address on the chip when we open it.
*/
return 0;
}
/* /*
* Set or clear promiscuous/multicast mode filter for this adaptor. * Set or clear promiscuous/multicast mode filter for this adaptor.
* *
...@@ -903,7 +886,6 @@ ether3_probe(struct expansion_card *ec, const struct ecard_id *id) ...@@ -903,7 +886,6 @@ ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
dev->hard_start_xmit = ether3_sendpacket; dev->hard_start_xmit = ether3_sendpacket;
dev->get_stats = ether3_getstats; dev->get_stats = ether3_getstats;
dev->set_multicast_list = ether3_setmulticastlist; dev->set_multicast_list = ether3_setmulticastlist;
dev->set_mac_address = ether3_set_mac_address;
dev->tx_timeout = ether3_timeout; dev->tx_timeout = ether3_timeout;
dev->watchdog_timeo = 5 * HZ / 100; dev->watchdog_timeo = 5 * HZ / 100;
......
...@@ -482,23 +482,6 @@ etherh_close(struct net_device *dev) ...@@ -482,23 +482,6 @@ etherh_close(struct net_device *dev)
return 0; return 0;
} }
static int
etherh_set_mac_address(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
if (netif_running(dev))
return -EBUSY;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
/*
* We'll set the MAC address on the chip when we open it.
*/
return 0;
}
/* /*
* Initialisation * Initialisation
*/ */
...@@ -585,7 +568,6 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id) ...@@ -585,7 +568,6 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
dev->open = etherh_open; dev->open = etherh_open;
dev->stop = etherh_close; dev->stop = etherh_close;
dev->set_mac_address = etherh_set_mac_address;
dev->set_config = etherh_set_config; dev->set_config = etherh_set_config;
dev->irq = ec->irq; dev->irq = ec->irq;
dev->base_addr = ecard_address(ec, ECARD_MEMC, 0); dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);
......
...@@ -47,7 +47,6 @@ ...@@ -47,7 +47,6 @@
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/cpufreq.h>
#include <pcmcia/version.h> #include <pcmcia/version.h>
#include <pcmcia/cs_types.h> #include <pcmcia/cs_types.h>
......
...@@ -1590,11 +1590,21 @@ sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val, ...@@ -1590,11 +1590,21 @@ sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val,
struct sa1100fb_info *fbi = TO_INF(nb, freq_policy); struct sa1100fb_info *fbi = TO_INF(nb, freq_policy);
struct cpufreq_policy *policy = data; struct cpufreq_policy *policy = data;
if (val == CPUFREQ_INCOMPATIBLE) { switch (val) {
case CPUFREQ_ADJUST:
case CPUFREQ_INCOMPATIBLE:
printk(KERN_DEBUG "min dma period: %d ps, " printk(KERN_DEBUG "min dma period: %d ps, "
"new clock %d kHz\n", sa1100fb_min_dma_period(fbi), "new clock %d kHz\n", sa1100fb_min_dma_period(fbi),
policy->max); policy->max);
/* todo: fill in min/max values */ /* todo: fill in min/max values */
break;
case CPUFREQ_NOTIFY:
do {} while(0);
/* todo: panic if min/max values aren't fulfilled
* [can't really happen unless there's a bug in the
* CPU policy verififcation process *
*/
break;
} }
return 0; return 0;
} }
......
...@@ -23,7 +23,6 @@ anakin_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -23,7 +23,6 @@ anakin_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
void __init time_init(void) void __init time_init(void)
{ {
timer_irq.handler = anakin_timer_interrupt; timer_irq.handler = anakin_timer_interrupt;
timer_irq.flags = SA_INTERRUPT;
setup_irq(IRQ_TICK, &timer_irq); setup_irq(IRQ_TICK, &timer_irq);
} }
......
...@@ -75,15 +75,12 @@ static unsigned long sa1100_gettimeoffset (void) ...@@ -75,15 +75,12 @@ static unsigned long sa1100_gettimeoffset (void)
static void sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static void sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
unsigned int next_match; unsigned int next_match;
unsigned long flags;
do { do {
do_leds(); do_leds();
local_irq_save(flags);
do_timer(regs); do_timer(regs);
OSSR = OSSR_M0; /* Clear match on timer 0 */ OSSR = OSSR_M0; /* Clear match on timer 0 */
next_match = (OSMR0 += LATCH); next_match = (OSMR0 += LATCH);
local_irq_restore(flags);
do_set_rtc(); do_set_rtc();
} while ((signed long)(next_match - OSCR) <= 0); } while ((signed long)(next_match - OSCR) <= 0);
......
...@@ -34,6 +34,5 @@ void __init time_init(void) ...@@ -34,6 +34,5 @@ void __init time_init(void)
xtime.tv_sec = 0; xtime.tv_sec = 0;
timer_irq.handler = timer_interrupt; timer_irq.handler = timer_interrupt;
timer_irq.flags = SA_INTERRUPT; /* FIXME: really? */
setup_irq(IRQ_TIMER, &timer_irq); setup_irq(IRQ_TIMER, &timer_irq);
} }
...@@ -267,6 +267,7 @@ extern struct bus_type ecard_bus_type; ...@@ -267,6 +267,7 @@ extern struct bus_type ecard_bus_type;
struct ecard_driver { struct ecard_driver {
int (*probe)(struct expansion_card *, const struct ecard_id *id); int (*probe)(struct expansion_card *, const struct ecard_id *id);
void (*remove)(struct expansion_card *); void (*remove)(struct expansion_card *);
void (*shutdown)(struct expansion_card *);
const struct ecard_id *id_table; const struct ecard_id *id_table;
unsigned int id; unsigned int id;
struct device_driver drv; struct device_driver drv;
......
...@@ -26,16 +26,10 @@ ...@@ -26,16 +26,10 @@
#define ide_default_io_base(i) ((ide_ioreg_t)0) #define ide_default_io_base(i) ((ide_ioreg_t)0)
#define ide_default_irq(b) (0) #define ide_default_irq(b) (0)
#define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id)) #define __ide_mm_insw(port,addr,len) readsw(port,addr,len)
#define ide_free_irq(irq,dev_id) free_irq((irq), (dev_id)) #define __ide_mm_insl(port,addr,len) readsl(port,addr,len)
#define ide_check_region(from,extent) check_region((from), (extent)) #define __ide_mm_outsw(port,addr,len) writesw(port,addr,len)
#define ide_request_region(from,extent,name) request_region((from), (extent), (name)) #define __ide_mm_outsl(port,addr,len) writesl(port,addr,len)
#define ide_release_region(from,extent) release_region((from), (extent))
/*
* The following are not needed for the non-m68k ports
*/
#define ide_ack_intr(hwif) (1)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -131,7 +131,10 @@ static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask) ...@@ -131,7 +131,10 @@ static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask)
/* /*
* Return the index of the PCI controller for device PDEV. * Return the index of the PCI controller for device PDEV.
*/ */
#define pci_controller_num(PDEV) (0) static inline int pci_controller_num(struct pci_dev *dev)
{
return 0;
}
#if defined(CONFIG_SA1111) && !defined(CONFIG_PCI) #if defined(CONFIG_SA1111) && !defined(CONFIG_PCI)
......
...@@ -110,6 +110,7 @@ extern struct page *empty_zero_page; ...@@ -110,6 +110,7 @@ extern struct page *empty_zero_page;
#define pgd_bad(pgd) (0) #define pgd_bad(pgd) (0)
#define pgd_present(pgd) (1) #define pgd_present(pgd) (1)
#define pgd_clear(pgdp) do { } while (0) #define pgd_clear(pgdp) do { } while (0)
#define set_pgd(pgd,pgdp) do { } while (0)
#define page_pte_prot(page,prot) mk_pte(page, prot) #define page_pte_prot(page,prot) mk_pte(page, prot)
#define page_pte(page) mk_pte(page, __pgprot(0)) #define page_pte(page) mk_pte(page, __pgprot(0))
......
...@@ -34,6 +34,8 @@ typedef int __kernel_ptrdiff_t; ...@@ -34,6 +34,8 @@ typedef int __kernel_ptrdiff_t;
typedef long __kernel_time_t; typedef long __kernel_time_t;
typedef long __kernel_suseconds_t; typedef long __kernel_suseconds_t;
typedef long __kernel_clock_t; typedef long __kernel_clock_t;
typedef int __kernel_timer_t;
typedef int __kernel_clockid_t;
typedef int __kernel_daddr_t; typedef int __kernel_daddr_t;
typedef char * __kernel_caddr_t; typedef char * __kernel_caddr_t;
typedef unsigned short __kernel_uid16_t; typedef unsigned short __kernel_uid16_t;
......
/* /*
* linux/include/asm-arm/proc-armv/tlbflush.h * linux/include/asm-arm/proc-armv/tlbflush.h
* *
* Copyright (C) 1999-2002 Russell King * Copyright (C) 1999-2003 Russell King
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -38,21 +38,31 @@ ...@@ -38,21 +38,31 @@
#define v3_tlb_flags (TLB_V3_FULL | TLB_V3_PAGE) #define v3_tlb_flags (TLB_V3_FULL | TLB_V3_PAGE)
#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710) #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
# define v3_possible_flags v3_tlb_flags
# define v3_always_flags v3_tlb_flags
# ifdef _TLB # ifdef _TLB
# define MULTI_TLB 1 # define MULTI_TLB 1
# else # else
# define _TLB v3 # define _TLB v3
# endif # endif
#else
# define v3_possible_flags 0
# define v3_always_flags (-1UL)
#endif #endif
#define v4_tlb_flags (TLB_V4_U_FULL | TLB_V4_U_PAGE) #define v4_tlb_flags (TLB_V4_U_FULL | TLB_V4_U_PAGE)
#if defined(CONFIG_CPU_ARM720T) #if defined(CONFIG_CPU_ARM720T)
# define v4_possible_flags v4_tlb_flags
# define v4_always_flags v4_tlb_flags
# ifdef _TLB # ifdef _TLB
# define MULTI_TLB 1 # define MULTI_TLB 1
# else # else
# define _TLB v4 # define _TLB v4
# endif # endif
#else
# define v4_possible_flags 0
# define v4_always_flags (-1UL)
#endif #endif
#define v4wbi_tlb_flags (TLB_WB | \ #define v4wbi_tlb_flags (TLB_WB | \
...@@ -62,11 +72,16 @@ ...@@ -62,11 +72,16 @@
#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \ #if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \
defined(CONFIG_CPU_ARM926T) || defined(CONFIG_CPU_ARM1020) || \ defined(CONFIG_CPU_ARM926T) || defined(CONFIG_CPU_ARM1020) || \
defined(CONFIG_CPU_XSCALE) defined(CONFIG_CPU_XSCALE)
# define v4wbi_possible_flags v4wbi_tlb_flags
# define v4wbi_always_flags v4wbi_tlb_flags
# ifdef _TLB # ifdef _TLB
# define MULTI_TLB 1 # define MULTI_TLB 1
# else # else
# define _TLB v4wbi # define _TLB v4wbi
# endif # endif
#else
# define v4wbi_possible_flags 0
# define v4wbi_always_flags (-1UL)
#endif #endif
#define v4wb_tlb_flags (TLB_WB | \ #define v4wb_tlb_flags (TLB_WB | \
...@@ -74,11 +89,16 @@ ...@@ -74,11 +89,16 @@
TLB_V4_D_PAGE) TLB_V4_D_PAGE)
#if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100) #if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100)
# define v4wb_possible_flags v4wb_tlb_flags
# define v4wb_always_flags v4wb_tlb_flags
# ifdef _TLB # ifdef _TLB
# define MULTI_TLB 1 # define MULTI_TLB 1
# else # else
# define _TLB v4wb # define _TLB v4wb
# endif # endif
#else
# define v4wb_possible_flags 0
# define v4wb_always_flags (-1UL)
#endif #endif
#ifndef _TLB #ifndef _TLB
...@@ -98,23 +118,23 @@ struct cpu_tlb_fns { ...@@ -98,23 +118,23 @@ struct cpu_tlb_fns {
*/ */
#ifdef MULTI_TLB #ifdef MULTI_TLB
extern struct cpu_tlb_fns cpu_tlb;
#define __cpu_flush_user_tlb_range cpu_tlb.flush_user_range #define __cpu_flush_user_tlb_range cpu_tlb.flush_user_range
#define __cpu_flush_kern_tlb_range cpu_tlb.flush_kern_range #define __cpu_flush_kern_tlb_range cpu_tlb.flush_kern_range
#define __cpu_tlb_flags cpu_tlb.tlb_flags
#else #else
#define __cpu_flush_user_tlb_range __glue(_TLB,_flush_user_tlb_range) #define __cpu_flush_user_tlb_range __glue(_TLB,_flush_user_tlb_range)
#define __cpu_flush_kern_tlb_range __glue(_TLB,_flush_kern_tlb_range) #define __cpu_flush_kern_tlb_range __glue(_TLB,_flush_kern_tlb_range)
#define __cpu_tlb_flags __glue(_TLB,_tlb_flags)
extern void __cpu_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *); extern void __cpu_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *);
extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long); extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long);
#endif #endif
extern struct cpu_tlb_fns cpu_tlb;
#define __cpu_tlb_flags cpu_tlb.tlb_flags
/* /*
* TLB Management * TLB Management
* ============== * ==============
...@@ -158,11 +178,34 @@ extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long); ...@@ -158,11 +178,34 @@ extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long);
* - kaddr - Kernel virtual memory address * - kaddr - Kernel virtual memory address
*/ */
#define tlb_flag(f) (__cpu_tlb_flags & (f)) /*
* We optimise the code below by:
* - building a set of TLB flags that might be set in __cpu_tlb_flags
* - building a set of TLB flags that will always be set in __cpu_tlb_flags
* - if we're going to need __cpu_tlb_flags, access it once and only once
*
* This allows us to build optimal assembly for the single-CPU type case,
* and as close to optimal given the compiler constrants for multi-CPU
* case. We could do better for the multi-CPU case if the compiler
* implemented the "%?" method, but this has been discontinued due to too
* many people getting it wrong.
*/
#define possible_tlb_flags (v3_possible_flags | \
v4_possible_flags | \
v4wbi_possible_flags | \
v4wb_possible_flags)
#define always_tlb_flags (v3_always_flags & \
v4_always_flags & \
v4wbi_always_flags & \
v4wb_always_flags)
#define tlb_flag(f) ((always_tlb_flags & (f)) || (__tlb_flag & possible_tlb_flags & (f)))
static inline void flush_tlb_all(void) static inline void flush_tlb_all(void)
{ {
const int zero = 0; const int zero = 0;
const unsigned int __tlb_flag = __cpu_tlb_flags;
if (tlb_flag(TLB_WB)) if (tlb_flag(TLB_WB))
asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero)); asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
...@@ -180,6 +223,7 @@ static inline void flush_tlb_all(void) ...@@ -180,6 +223,7 @@ static inline void flush_tlb_all(void)
static inline void flush_tlb_mm(struct mm_struct *mm) static inline void flush_tlb_mm(struct mm_struct *mm)
{ {
const int zero = 0; const int zero = 0;
const unsigned int __tlb_flag = __cpu_tlb_flags;
if (tlb_flag(TLB_WB)) if (tlb_flag(TLB_WB))
asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero)); asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
...@@ -200,6 +244,7 @@ static inline void ...@@ -200,6 +244,7 @@ static inline void
flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
{ {
const int zero = 0; const int zero = 0;
const unsigned int __tlb_flag = __cpu_tlb_flags;
uaddr &= PAGE_MASK; uaddr &= PAGE_MASK;
...@@ -223,6 +268,7 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) ...@@ -223,6 +268,7 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
static inline void flush_tlb_kernel_page(unsigned long kaddr) static inline void flush_tlb_kernel_page(unsigned long kaddr)
{ {
const int zero = 0; const int zero = 0;
const unsigned int __tlb_flag = __cpu_tlb_flags;
kaddr &= PAGE_MASK; kaddr &= PAGE_MASK;
...@@ -241,6 +287,10 @@ static inline void flush_tlb_kernel_page(unsigned long kaddr) ...@@ -241,6 +287,10 @@ static inline void flush_tlb_kernel_page(unsigned long kaddr)
asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero)); asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
} }
#undef tlb_flag
#undef always_tlb_flags
#undef possible_tlb_flags
/* /*
* Convert calls to our calling convention. * Convert calls to our calling convention.
*/ */
......
...@@ -122,15 +122,4 @@ ...@@ -122,15 +122,4 @@
#include CPU_INCLUDE_NAME #include CPU_INCLUDE_NAME
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#if 0
* The following is to fool mkdep into generating the correct
* dependencies. Without this, it can't figure out that this
* file does indeed depend on the cpu-*.h files.
#include <asm/cpu-single.h>
#include <asm/cpu-multi26.h>
#include <asm/cpu-multi32.h>
*
#endif
#endif /* __ASM_PROCFNS_H */ #endif /* __ASM_PROCFNS_H */
...@@ -14,16 +14,6 @@ extern unsigned int system_serial_low; ...@@ -14,16 +14,6 @@ extern unsigned int system_serial_low;
extern unsigned int system_serial_high; extern unsigned int system_serial_high;
extern unsigned int mem_fclk_21285; extern unsigned int mem_fclk_21285;
/*
* This tells us if we have an ISA bridge
* present in a PCI system.
*/
#ifdef CONFIG_PCI
extern int have_isa_bridge;
#else
#define have_isa_bridge (0)
#endif
struct pt_regs; struct pt_regs;
void die(const char *msg, struct pt_regs *regs, int err) void die(const char *msg, struct pt_regs *regs, int err)
...@@ -75,7 +65,7 @@ extern int cpu_architecture(void); ...@@ -75,7 +65,7 @@ extern int cpu_architecture(void);
* The `mb' is to tell GCC not to cache `current' across this call. * The `mb' is to tell GCC not to cache `current' across this call.
*/ */
struct thread_info; struct thread_info;
extern struct task_struct *__switch_to(struct thread_info *, struct thread_info *); extern struct thread_info *__switch_to(struct thread_info *, struct thread_info *);
#define switch_to(prev,next,last) \ #define switch_to(prev,next,last) \
do { \ do { \
......
...@@ -354,6 +354,13 @@ static int cpufreq_add_dev (struct device * dev) ...@@ -354,6 +354,13 @@ static int cpufreq_add_dev (struct device * dev)
&cpufreq_driver->policy[cpu], &cpufreq_driver->policy[cpu],
sizeof(struct cpufreq_policy)); sizeof(struct cpufreq_policy));
/* 2.4-API init for this CPU */
#ifdef CONFIG_CPU_FREQ_24_API
cpu_min_freq[cpu] = cpufreq_driver->policy[cpu].cpuinfo.min_freq;
cpu_max_freq[cpu] = cpufreq_driver->policy[cpu].cpuinfo.max_freq;
cpu_cur_freq[cpu] = cpufreq_driver->cpu_cur_freq[cpu];
#endif
if (cpufreq_driver->target) if (cpufreq_driver->target)
cpufreq_governor(cpu, CPUFREQ_GOV_START); cpufreq_governor(cpu, CPUFREQ_GOV_START);
......
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