Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
fbb46a67
Commit
fbb46a67
authored
Sep 13, 2004
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://bk.arm.linux.org.uk/linux-2.6-rmk
into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents
5c422c68
38dd6915
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
423 additions
and
182 deletions
+423
-182
arch/arm/kernel/apm.c
arch/arm/kernel/apm.c
+198
-154
arch/arm/mach-s3c2410/devs.c
arch/arm/mach-s3c2410/devs.c
+1
-7
arch/arm/mach-s3c2410/gpio.c
arch/arm/mach-s3c2410/gpio.c
+28
-1
include/asm-arm/apm.h
include/asm-arm/apm.h
+29
-20
include/asm-arm/arch-s3c2410/hardware.h
include/asm-arm/arch-s3c2410/hardware.h
+5
-0
include/asm-arm/arch-s3c2410/regs-udc.h
include/asm-arm/arch-s3c2410/regs-udc.h
+162
-0
No files found.
arch/arm/kernel/apm.c
View file @
fbb46a67
...
@@ -46,7 +46,13 @@
...
@@ -46,7 +46,13 @@
/*
/*
* Maximum number of events stored
* Maximum number of events stored
*/
*/
#define APM_MAX_EVENTS 20
#define APM_MAX_EVENTS 16
struct
apm_queue
{
unsigned
int
event_head
;
unsigned
int
event_tail
;
apm_event_t
events
[
APM_MAX_EVENTS
];
};
/*
/*
* The per-file APM data
* The per-file APM data
...
@@ -54,27 +60,25 @@
...
@@ -54,27 +60,25 @@
struct
apm_user
{
struct
apm_user
{
struct
list_head
list
;
struct
list_head
list
;
int
suser
:
1
;
unsigned
int
suser
:
1
;
int
writer
:
1
;
unsigned
int
writer
:
1
;
int
reader
:
1
;
unsigned
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
suspend_result
;
int
event_tail
;
unsigned
int
suspend_state
;
apm_event_t
events
[
APM_MAX_EVENTS
];
#define SUSPEND_NONE 0
/* no suspend pending */
#define SUSPEND_PENDING 1
/* suspend pending read */
#define SUSPEND_READ 2
/* suspend read, pending ack */
#define SUSPEND_ACKED 3
/* suspend acked */
#define SUSPEND_DONE 4
/* suspend completed */
struct
apm_queue
queue
;
};
};
/*
/*
* Local variables
* Local variables
*/
*/
static
int
suspends_pending
;
static
int
suspends_pending
;
static
int
standbys_pending
;
static
int
apm_disabled
;
static
int
apm_disabled
;
static
DECLARE_WAIT_QUEUE_HEAD
(
apm_waitqueue
);
static
DECLARE_WAIT_QUEUE_HEAD
(
apm_waitqueue
);
...
@@ -83,14 +87,19 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
...
@@ -83,14 +87,19 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
/*
/*
* This is a list of everyone who has opened /dev/apm_bios
* This is a list of everyone who has opened /dev/apm_bios
*/
*/
static
spinlock_t
user_list_lock
=
SPIN_LOCK_UNLOCKED
;
static
DECLARE_RWSEM
(
user_list_lock
)
;
static
LIST_HEAD
(
apm_user_list
);
static
LIST_HEAD
(
apm_user_list
);
/*
/*
* The kapmd info.
* kapmd info. kapmd provides us a process context to handle
* "APM" events within - specifically necessary if we're going
* to be suspending the system.
*/
*/
static
struct
task_struct
*
kapmd
;
static
DECLARE_WAIT_QUEUE_HEAD
(
kapmd_wait
)
;
static
DECLARE_COMPLETION
(
kapmd_exit
);
static
DECLARE_COMPLETION
(
kapmd_exit
);
static
spinlock_t
kapmd_queue_lock
=
SPIN_LOCK_UNLOCKED
;
static
struct
apm_queue
kapmd_queue
;
static
const
char
driver_version
[]
=
"1.13"
;
/* no spaces */
static
const
char
driver_version
[]
=
"1.13"
;
/* no spaces */
...
@@ -102,19 +111,6 @@ static const char driver_version[] = "1.13"; /* no spaces */
...
@@ -102,19 +111,6 @@ static const char driver_version[] = "1.13"; /* no spaces */
*/
*/
static
void
__apm_get_power_status
(
struct
apm_power_info
*
info
)
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
}
}
/*
/*
...
@@ -123,65 +119,71 @@ static void __apm_get_power_status(struct apm_power_info *info)
...
@@ -123,65 +119,71 @@ static void __apm_get_power_status(struct apm_power_info *info)
void
(
*
apm_get_power_status
)(
struct
apm_power_info
*
)
=
__apm_get_power_status
;
void
(
*
apm_get_power_status
)(
struct
apm_power_info
*
)
=
__apm_get_power_status
;
EXPORT_SYMBOL
(
apm_get_power_status
);
EXPORT_SYMBOL
(
apm_get_power_status
);
static
int
queue_empty
(
struct
apm_user
*
as
)
/*
* APM event queue management.
*/
static
inline
int
queue_empty
(
struct
apm_queue
*
q
)
{
{
return
as
->
event_head
==
as
->
event_tail
;
return
q
->
event_head
==
q
->
event_tail
;
}
}
static
apm_event_t
get_queued_event
(
struct
apm_user
*
as
)
static
inline
apm_event_t
queue_get_event
(
struct
apm_queue
*
q
)
{
{
as
->
event_tail
=
(
as
->
event_tail
+
1
)
%
APM_MAX_EVENTS
;
q
->
event_tail
=
(
q
->
event_tail
+
1
)
%
APM_MAX_EVENTS
;
return
as
->
events
[
as
->
event_tail
];
return
q
->
events
[
q
->
event_tail
];
}
}
static
void
queue_
event_one_user
(
struct
apm_user
*
as
,
apm_event_t
event
)
static
void
queue_
add_event
(
struct
apm_queue
*
q
,
apm_event_t
event
)
{
{
as
->
event_head
=
(
as
->
event_head
+
1
)
%
APM_MAX_EVENTS
;
q
->
event_head
=
(
q
->
event_head
+
1
)
%
APM_MAX_EVENTS
;
if
(
as
->
event_head
==
as
->
event_tail
)
{
if
(
q
->
event_head
==
q
->
event_tail
)
{
static
int
notified
;
static
int
notified
;
if
(
notified
++
==
0
)
if
(
notified
++
==
0
)
printk
(
KERN_ERR
"apm: an event queue overflowed
\n
"
);
printk
(
KERN_ERR
"apm: an event queue overflowed
\n
"
);
as
->
event_tail
=
(
as
->
event_tail
+
1
)
%
APM_MAX_EVENTS
;
q
->
event_tail
=
(
q
->
event_tail
+
1
)
%
APM_MAX_EVENTS
;
}
}
as
->
events
[
as
->
event_head
]
=
event
;
q
->
events
[
q
->
event_head
]
=
event
;
}
if
(
!
as
->
suser
||
!
as
->
writer
)
return
;
static
void
queue_event_one_user
(
struct
apm_user
*
as
,
apm_event_t
event
)
{
if
(
as
->
suser
&&
as
->
writer
)
{
switch
(
event
)
{
switch
(
event
)
{
case
APM_SYS_SUSPEND
:
case
APM_SYS_SUSPEND
:
case
APM_USER_SUSPEND
:
case
APM_USER_SUSPEND
:
as
->
suspends_pending
++
;
/*
suspends_pending
++
;
* If this user already has a suspend pending,
break
;
* don't queue another one.
*/
if
(
as
->
suspend_state
!=
SUSPEND_NONE
)
return
;
case
APM_SYS_STANDBY
:
as
->
suspend_state
=
SUSPEND_PENDING
;
case
APM_USER_STANDBY
:
suspends_pending
++
;
as
->
standbys_pending
++
;
standbys_pending
++
;
break
;
break
;
}
}
}
queue_add_event
(
&
as
->
queue
,
event
);
}
}
static
void
queue_event
(
apm_event_t
event
,
struct
apm_user
*
sender
)
static
void
queue_event
(
apm_event_t
event
,
struct
apm_user
*
sender
)
{
{
struct
list_head
*
l
;
struct
apm_user
*
as
;
spin_lock
(
&
user_list_lock
);
list_for_each
(
l
,
&
apm_user_list
)
{
struct
apm_user
*
as
=
list_entry
(
l
,
struct
apm_user
,
list
);
down_read
(
&
user_list_lock
);
list_for_each_entry
(
as
,
&
apm_user_list
,
list
)
{
if
(
as
!=
sender
&&
as
->
reader
)
if
(
as
!=
sender
&&
as
->
reader
)
queue_event_one_user
(
as
,
event
);
queue_event_one_user
(
as
,
event
);
}
}
spin_unlock
(
&
user_list_lock
);
up_read
(
&
user_list_lock
);
wake_up_interruptible
(
&
apm_waitqueue
);
wake_up_interruptible
(
&
apm_waitqueue
);
}
}
static
int
apm_suspend
(
void
)
static
void
apm_suspend
(
void
)
{
{
struct
list_head
*
l
;
struct
apm_user
*
as
;
int
err
=
pm_suspend
(
PM_SUSPEND_MEM
);
int
err
=
pm_suspend
(
PM_SUSPEND_MEM
);
/*
/*
...
@@ -193,52 +195,39 @@ static int apm_suspend(void)
...
@@ -193,52 +195,39 @@ static int apm_suspend(void)
/*
/*
* Finally, wake up anyone who is sleeping on the suspend.
* Finally, wake up anyone who is sleeping on the suspend.
*/
*/
spin_lock
(
&
user_list_lock
);
down_read
(
&
user_list_lock
);
list_for_each
(
l
,
&
apm_user_list
)
{
list_for_each_entry
(
as
,
&
apm_user_list
,
list
)
{
struct
apm_user
*
as
=
list_entry
(
l
,
struct
apm_user
,
list
);
as
->
suspend_result
=
err
;
as
->
suspend_result
=
err
;
as
->
suspend_
wait
=
0
;
as
->
suspend_
state
=
SUSPEND_DONE
;
}
}
spin_unlock
(
&
user_list_lock
);
up_read
(
&
user_list_lock
);
wake_up_interruptible
(
&
apm_suspend_waitqueue
);
wake_up_interruptible
(
&
apm_suspend_waitqueue
);
return
err
;
}
}
static
ssize_t
apm_read
(
struct
file
*
fp
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
static
ssize_t
apm_read
(
struct
file
*
fp
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
{
struct
apm_user
*
as
=
fp
->
private_data
;
struct
apm_user
*
as
=
fp
->
private_data
;
apm_event_t
event
;
apm_event_t
event
;
int
i
=
count
,
ret
=
0
,
nonblock
=
fp
->
f_flags
&
O_NONBLOCK
;
int
i
=
count
,
ret
=
0
;
if
(
count
<
sizeof
(
apm_event_t
))
if
(
count
<
sizeof
(
apm_event_t
))
return
-
EINVAL
;
return
-
EINVAL
;
if
(
queue_empty
(
as
)
&&
nonblock
)
if
(
queue_empty
(
&
as
->
queue
)
&&
fp
->
f_flags
&
O_NONBLOCK
)
return
-
EAGAIN
;
return
-
EAGAIN
;
wait_event_interruptible
(
apm_waitqueue
,
!
queue_empty
(
as
));
wait_event_interruptible
(
apm_waitqueue
,
!
queue_empty
(
&
as
->
queue
));
while
((
i
>=
sizeof
(
event
))
&&
!
queue_empty
(
as
))
{
while
((
i
>=
sizeof
(
event
))
&&
!
queue_empty
(
&
as
->
queue
))
{
event
=
get_queued_event
(
as
);
event
=
queue_get_event
(
&
as
->
queue
);
printk
(
" apm_read: event=%d
\n
"
,
event
);
ret
=
-
EFAULT
;
ret
=
-
EFAULT
;
if
(
copy_to_user
(
buf
,
&
event
,
sizeof
(
event
)))
if
(
copy_to_user
(
buf
,
&
event
,
sizeof
(
event
)))
break
;
break
;
switch
(
event
)
{
if
(
event
==
APM_SYS_SUSPEND
||
event
==
APM_USER_SUSPEND
)
case
APM_SYS_SUSPEND
:
as
->
suspend_state
=
SUSPEND_READ
;
case
APM_USER_SUSPEND
:
as
->
suspends_read
++
;
break
;
case
APM_SYS_STANDBY
:
case
APM_USER_STANDBY
:
as
->
standbys_read
++
;
break
;
}
buf
+=
sizeof
(
event
);
buf
+=
sizeof
(
event
);
i
-=
sizeof
(
event
);
i
-=
sizeof
(
event
);
...
@@ -252,10 +241,10 @@ static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t
...
@@ -252,10 +241,10 @@ static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t
static
unsigned
int
apm_poll
(
struct
file
*
fp
,
poll_table
*
wait
)
static
unsigned
int
apm_poll
(
struct
file
*
fp
,
poll_table
*
wait
)
{
{
struct
apm_user
*
as
=
fp
->
private_data
;
struct
apm_user
*
as
=
fp
->
private_data
;
poll_wait
(
fp
,
&
apm_waitqueue
,
wait
);
poll_wait
(
fp
,
&
apm_waitqueue
,
wait
);
return
queue_empty
(
as
)
?
0
:
POLLIN
|
POLLRDNORM
;
return
queue_empty
(
&
as
->
queue
)
?
0
:
POLLIN
|
POLLRDNORM
;
}
}
/*
/*
...
@@ -272,43 +261,57 @@ static int
...
@@ -272,43 +261,57 @@ static int
apm_ioctl
(
struct
inode
*
inode
,
struct
file
*
filp
,
u_int
cmd
,
u_long
arg
)
apm_ioctl
(
struct
inode
*
inode
,
struct
file
*
filp
,
u_int
cmd
,
u_long
arg
)
{
{
struct
apm_user
*
as
=
filp
->
private_data
;
struct
apm_user
*
as
=
filp
->
private_data
;
unsigned
long
flags
;
int
err
=
-
EINVAL
;
int
err
=
-
EINVAL
;
if
(
!
as
->
suser
||
!
as
->
writer
)
if
(
!
as
->
suser
||
!
as
->
writer
)
return
-
EPERM
;
return
-
EPERM
;
switch
(
cmd
)
{
switch
(
cmd
)
{
case
APM_IOC_STANDBY
:
break
;
case
APM_IOC_SUSPEND
:
case
APM_IOC_SUSPEND
:
as
->
suspend_result
=
-
EINTR
;
if
(
as
->
suspend_state
==
SUSPEND_READ
)
{
/*
/*
* If we read a suspend command from /dev/apm_bios,
* If we read a suspend command from /dev/apm_bios,
* then the corresponding APM_IOC_SUSPEND ioctl is
* then the corresponding APM_IOC_SUSPEND ioctl is
* interpreted as an acknowledge.
* interpreted as an acknowledge.
*/
*/
if
(
as
->
suspends_read
>
0
)
{
as
->
suspend_state
=
SUSPEND_ACKED
;
as
->
suspends_read
--
;
as
->
suspends_pending
--
;
suspends_pending
--
;
suspends_pending
--
;
}
else
{
}
else
{
/*
* Otherwise it is a request to suspend the system.
* Queue an event for all readers, and expect an
* acknowledge from all writers who haven't already
* acknowledged.
*/
queue_event
(
APM_USER_SUSPEND
,
as
);
queue_event
(
APM_USER_SUSPEND
,
as
);
}
}
/*
/*
* If there are outstanding suspend requests for other
* If there are no further acknowledges required, suspend
* people on /dev/apm_bios, we must sleep for them.
* the system.
* Last one to bed turns the lights out.
*/
*/
if
(
suspends_pending
>
0
)
{
if
(
suspends_pending
==
0
)
as
->
suspend_wait
=
1
;
apm_suspend
();
err
=
wait_event_interruptible
(
apm_suspend_waitqueue
,
as
->
suspend_wait
==
0
);
/*
if
(
err
==
0
)
* Wait for the suspend/resume to complete. If there are
* pending acknowledges, we wait here for them.
*
* Note that we need to ensure that the PM subsystem does
* not kick us out of the wait when it suspends the threads.
*/
flags
=
current
->
flags
;
current
->
flags
|=
PF_NOFREEZE
;
wait_event_interruptible
(
apm_suspend_waitqueue
,
as
->
suspend_state
==
SUSPEND_DONE
);
current
->
flags
=
flags
;
err
=
as
->
suspend_result
;
err
=
as
->
suspend_result
;
}
else
{
as
->
suspend_state
=
SUSPEND_NONE
;
err
=
apm_suspend
();
}
break
;
break
;
}
}
...
@@ -320,24 +323,19 @@ static int apm_release(struct inode * inode, struct file * filp)
...
@@ -320,24 +323,19 @@ static int apm_release(struct inode * inode, struct file * filp)
struct
apm_user
*
as
=
filp
->
private_data
;
struct
apm_user
*
as
=
filp
->
private_data
;
filp
->
private_data
=
NULL
;
filp
->
private_data
=
NULL
;
spin_lock
(
&
user_list_lock
);
down_write
(
&
user_list_lock
);
list_del
(
&
as
->
list
);
list_del
(
&
as
->
list
);
spin_unlock
(
&
user_list_lock
);
up_write
(
&
user_list_lock
);
/*
/*
* We are now unhooked from the chain. As far as new
* We are now unhooked from the chain. As far as new
* events are concerned, we no longer exist. However, we
* events are concerned, we no longer exist. However, we
* need to balance s
tandbys_pending and suspends_pending,
* need to balance s
uspends_pending, which means the
*
which means the
possibility of sleeping.
* possibility of sleeping.
*/
*/
if
(
as
->
standbys_pending
>
0
)
{
if
(
as
->
suspend_state
!=
SUSPEND_NONE
)
{
standbys_pending
-=
as
->
standbys_pending
;
suspends_pending
-=
1
;
// if (standbys_pending <= 0)
if
(
suspends_pending
==
0
)
// standby();
}
if
(
as
->
suspends_pending
>
0
)
{
suspends_pending
-=
as
->
suspends_pending
;
if
(
suspends_pending
<=
0
)
apm_suspend
();
apm_suspend
();
}
}
...
@@ -364,9 +362,9 @@ static int apm_open(struct inode * inode, struct file * filp)
...
@@ -364,9 +362,9 @@ static int apm_open(struct inode * inode, struct file * filp)
as
->
writer
=
(
filp
->
f_mode
&
FMODE_WRITE
)
==
FMODE_WRITE
;
as
->
writer
=
(
filp
->
f_mode
&
FMODE_WRITE
)
==
FMODE_WRITE
;
as
->
reader
=
(
filp
->
f_mode
&
FMODE_READ
)
==
FMODE_READ
;
as
->
reader
=
(
filp
->
f_mode
&
FMODE_READ
)
==
FMODE_READ
;
spin_lock
(
&
user_list_lock
);
down_write
(
&
user_list_lock
);
list_add
(
&
as
->
list
,
&
apm_user_list
);
list_add
(
&
as
->
list
,
&
apm_user_list
);
spin_unlock
(
&
user_list_lock
);
up_write
(
&
user_list_lock
);
filp
->
private_data
=
as
;
filp
->
private_data
=
as
;
}
}
...
@@ -438,7 +436,7 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
...
@@ -438,7 +436,7 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
info
.
ac_line_status
=
0xff
;
info
.
ac_line_status
=
0xff
;
info
.
battery_status
=
0xff
;
info
.
battery_status
=
0xff
;
info
.
battery_flag
=
0xff
;
info
.
battery_flag
=
0xff
;
info
.
battery_life
=
255
;
info
.
battery_life
=
-
1
;
info
.
time
=
-
1
;
info
.
time
=
-
1
;
info
.
units
=
-
1
;
info
.
units
=
-
1
;
...
@@ -461,34 +459,53 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
...
@@ -461,34 +459,53 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
}
}
#endif
#endif
#if 0
static
int
kapmd
(
void
*
arg
)
static int kapmd(void *startup)
{
{
struct task_struct *tsk = current;
daemonize
(
"kapmd"
);
current
->
flags
|=
PF_NOFREEZE
;
daemonize();
do
{
strcpy(tsk->comm, "kapmd");
apm_event_t
event
;
kapmd = tsk;
spin_lock_irq(&tsk->sigmask_lock);
wait_event_interruptible
(
kapmd_wait
,
siginitsetinv(&tsk->blocked, sigmask(SIGQUIT));
!
queue_empty
(
&
kapmd_queue
)
||
!
pm_active
);
recalc_sigpending(tsk);
spin_unlock_irq(&tsk->sigmask_lock);
complete((struct completion *)startup);
if
(
!
pm_active
)
break
;
do {
spin_lock_irq
(
&
kapmd_queue_lock
);
set_task_state(tsk, TASK_INTERRUPTIBLE);
event
=
0
;
schedule();
if
(
!
queue_empty
(
&
kapmd_queue
))
} while (!signal_pending(tsk));
event
=
queue_get_event
(
&
kapmd_queue
);
spin_unlock_irq
(
&
kapmd_queue_lock
);
switch
(
event
)
{
case
0
:
break
;
case
APM_LOW_BATTERY
:
case
APM_POWER_STATUS_CHANGE
:
queue_event
(
event
,
NULL
);
break
;
case
APM_USER_SUSPEND
:
case
APM_SYS_SUSPEND
:
queue_event
(
event
,
NULL
);
if
(
suspends_pending
==
0
)
apm_suspend
();
break
;
case
APM_CRITICAL_SUSPEND
:
apm_suspend
();
break
;
}
}
while
(
1
);
complete_and_exit
(
&
kapmd_exit
,
0
);
complete_and_exit
(
&
kapmd_exit
,
0
);
}
}
#endif
static
int
__init
apm_init
(
void
)
static
int
__init
apm_init
(
void
)
{
{
// struct completion startup = COMPLETION_INITIALIZER(startup);
int
ret
;
int
ret
;
if
(
apm_disabled
)
{
if
(
apm_disabled
)
{
...
@@ -501,22 +518,24 @@ static int __init apm_init(void)
...
@@ -501,22 +518,24 @@ static int __init apm_init(void)
return
-
EINVAL
;
return
-
EINVAL
;
}
}
// ret = kernel_thread(kapmd, &startup, CLONE_FS | CLONE_FILES);
// if (ret)
// return ret;
// wait_for_completion(&startup);
pm_active
=
1
;
pm_active
=
1
;
ret
=
kernel_thread
(
kapmd
,
NULL
,
CLONE_KERNEL
);
if
(
ret
<
0
)
{
pm_active
=
0
;
return
ret
;
}
#ifdef CONFIG_PROC_FS
#ifdef CONFIG_PROC_FS
create_proc_info_entry
(
"apm"
,
0
,
NULL
,
apm_get_info
);
create_proc_info_entry
(
"apm"
,
0
,
NULL
,
apm_get_info
);
#endif
#endif
ret
=
misc_register
(
&
apm_device
);
ret
=
misc_register
(
&
apm_device
);
if
(
ret
!=
0
)
{
if
(
ret
!=
0
)
{
pm_active
=
0
;
remove_proc_entry
(
"apm"
,
NULL
);
remove_proc_entry
(
"apm"
,
NULL
);
send_sig
(
SIGQUIT
,
kapmd
,
1
);
pm_active
=
0
;
wake_up
(
&
kapmd_wait
);
wait_for_completion
(
&
kapmd_exit
);
wait_for_completion
(
&
kapmd_exit
);
}
}
...
@@ -527,9 +546,10 @@ static void __exit apm_exit(void)
...
@@ -527,9 +546,10 @@ static void __exit apm_exit(void)
{
{
misc_deregister
(
&
apm_device
);
misc_deregister
(
&
apm_device
);
remove_proc_entry
(
"apm"
,
NULL
);
remove_proc_entry
(
"apm"
,
NULL
);
pm_active
=
0
;
pm_active
=
0
;
// send_sig(SIGQUIT, kapmd, 1
);
wake_up
(
&
kapmd_wait
);
//
wait_for_completion(&kapmd_exit);
wait_for_completion
(
&
kapmd_exit
);
}
}
module_init
(
apm_init
);
module_init
(
apm_init
);
...
@@ -556,3 +576,27 @@ static int __init apm_setup(char *str)
...
@@ -556,3 +576,27 @@ static int __init apm_setup(char *str)
__setup
(
"apm="
,
apm_setup
);
__setup
(
"apm="
,
apm_setup
);
#endif
#endif
/**
* apm_queue_event - queue an APM event for kapmd
* @event: APM event
*
* Queue an APM event for kapmd to process and ultimately take the
* appropriate action. Only a subset of events are handled:
* %APM_LOW_BATTERY
* %APM_POWER_STATUS_CHANGE
* %APM_USER_SUSPEND
* %APM_SYS_SUSPEND
* %APM_CRITICAL_SUSPEND
*/
void
apm_queue_event
(
apm_event_t
event
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
kapmd_queue_lock
,
flags
);
queue_add_event
(
&
kapmd_queue
,
event
);
spin_unlock_irqrestore
(
&
kapmd_queue_lock
,
flags
);
wake_up_interruptible
(
&
kapmd_wait
);
}
EXPORT_SYMBOL
(
apm_queue_event
);
arch/arm/mach-s3c2410/devs.c
View file @
fbb46a67
...
@@ -53,7 +53,7 @@ static u64 s3c_device_usb_dmamask = 0xffffffffUL;
...
@@ -53,7 +53,7 @@ static u64 s3c_device_usb_dmamask = 0xffffffffUL;
struct
platform_device
s3c_device_usb
=
{
struct
platform_device
s3c_device_usb
=
{
.
name
=
"s3c2410-ohci"
,
.
name
=
"s3c2410-ohci"
,
.
id
=
0
,
.
id
=
-
1
,
.
num_resources
=
ARRAY_SIZE
(
s3c_usb_resource
),
.
num_resources
=
ARRAY_SIZE
(
s3c_usb_resource
),
.
resource
=
s3c_usb_resource
,
.
resource
=
s3c_usb_resource
,
.
dev
=
{
.
dev
=
{
...
@@ -102,13 +102,7 @@ static struct resource s3c_nand_resource[] = {
...
@@ -102,13 +102,7 @@ static struct resource s3c_nand_resource[] = {
.
start
=
S3C2410_PA_NAND
,
.
start
=
S3C2410_PA_NAND
,
.
end
=
S3C2410_PA_NAND
+
S3C2410_SZ_NAND
,
.
end
=
S3C2410_PA_NAND
+
S3C2410_SZ_NAND
,
.
flags
=
IORESOURCE_MEM
,
.
flags
=
IORESOURCE_MEM
,
},
[
1
]
=
{
.
start
=
IRQ_S3CUART_RX0
,
.
end
=
IRQ_S3CUART_ERR0
,
.
flags
=
IORESOURCE_IRQ
,
}
}
};
};
struct
platform_device
s3c_device_nand
=
{
struct
platform_device
s3c_device_nand
=
{
...
...
arch/arm/mach-s3c2410/gpio.c
View file @
fbb46a67
...
@@ -19,6 +19,10 @@
...
@@ -19,6 +19,10 @@
* along with this program; if not, write to the Free Software
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* Changelog
* 13-Sep-2004 BJD Implemented change of MISCCR
* 14-Sep-2004 BJD Added getpin call
* 14-Sep-2004 BJD Fixed bug in setpin() call
*/
*/
...
@@ -90,9 +94,32 @@ void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
...
@@ -90,9 +94,32 @@ void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
local_irq_save
(
flags
);
local_irq_save
(
flags
);
dat
=
__raw_readl
(
base
+
0x04
);
dat
=
__raw_readl
(
base
+
0x04
);
dat
&=
1
<<
offs
;
dat
&=
~
(
1
<<
offs
)
;
dat
|=
to
<<
offs
;
dat
|=
to
<<
offs
;
__raw_writel
(
dat
,
base
+
0x04
);
__raw_writel
(
dat
,
base
+
0x04
);
local_irq_restore
(
flags
);
local_irq_restore
(
flags
);
}
}
unsigned
int
s3c2410_gpio_getpin
(
unsigned
int
pin
)
{
unsigned
long
base
=
S3C2410_GPIO_BASE
(
pin
);
unsigned
long
offs
=
S3C2410_GPIO_OFFSET
(
pin
);
return
__raw_readl
(
base
+
0x04
)
&
(
1
<<
offs
);
}
unsigned
int
s3c2410_modify_misccr
(
unsigned
int
clear
,
unsigned
int
change
)
{
unsigned
long
flags
;
unsigned
long
misccr
;
local_irq_save
(
flags
);
misccr
=
__raw_readl
(
S3C2410_MISCCR
);
misccr
&=
~
clear
;
misccr
^=
change
;
__raw_writel
(
misccr
,
S3C2410_MISCCR
);
local_irq_restore
(
flags
);
return
misccr
;
}
include/asm-arm/apm.h
View file @
fbb46a67
...
@@ -14,43 +14,52 @@
...
@@ -14,43 +14,52 @@
#define ARM_ASM_SA1100_APM_H
#define ARM_ASM_SA1100_APM_H
#include <linux/config.h>
#include <linux/config.h>
#include <linux/apm_bios.h>
#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
/*
* 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
;
#define APM_AC_OFFLINE 0
#define APM_AC_OFFLINE 0
#define APM_AC_ONLINE 1
#define APM_AC_ONLINE 1
#define APM_AC_BACKUP 2
#define APM_AC_BACKUP 2
#define APM_AC_UNKNOWN
0xFF
#define APM_AC_UNKNOWN
0xff
unsigned
char
battery_status
;
#define APM_BATTERY_STATUS_HIGH 0
#define APM_BATTERY_STATUS_HIGH 0
#define APM_BATTERY_STATUS_LOW 1
#define APM_BATTERY_STATUS_LOW 1
#define APM_BATTERY_STATUS_CRITICAL 2
#define APM_BATTERY_STATUS_CRITICAL 2
#define APM_BATTERY_STATUS_CHARGING 3
#define APM_BATTERY_STATUS_CHARGING 3
#define APM_BATTERY_STATUS_UNKNOWN 0xFF
#define APM_BATTERY_STATUS_NOT_PRESENT 4
#define APM_BATTERY_STATUS_UNKNOWN 0xff
#define APM_BATTERY_LIFE_UNKNOWN 0xFFFF
#define APM_BATTERY_LIFE_MINUTES 0x8000
#define APM_BATTERY_LIFE_VALUE_MASK 0x7FFF
/*
* 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_flag
;
unsigned
char
battery_life
;
#define APM_BATTERY_FLAG_HIGH (1 << 0)
#define APM_BATTERY_FLAG_LOW (1 << 1)
#define APM_BATTERY_FLAG_CRITICAL (1 << 2)
#define APM_BATTERY_FLAG_CHARGING (1 << 3)
#define APM_BATTERY_FLAG_NOT_PRESENT (1 << 7)
#define APM_BATTERY_FLAG_UNKNOWN 0xff
int
battery_life
;
int
time
;
int
time
;
int
units
;
int
units
;
#define APM_UNITS_MINS 0
#define APM_UNITS_SECS 1
#define APM_UNITS_UNKNOWN -1
};
};
/*
/*
* This allows machines to provide their own "apm get power status" function.
* This allows machines to provide their own "apm get power status" function.
*/
*/
extern
void
(
*
apm_get_power_status
)(
struct
apm_power_info
*
);
extern
void
(
*
apm_get_power_status
)(
struct
apm_power_info
*
);
#endif
/*
* Queue an event (APM_SYS_SUSPEND or APM_CRITICAL_SUSPEND)
*/
void
apm_queue_event
(
apm_event_t
event
);
#endif
#endif
include/asm-arm/arch-s3c2410/hardware.h
View file @
fbb46a67
...
@@ -14,6 +14,7 @@
...
@@ -14,6 +14,7 @@
* 06-Jun-2003 BJD Added CPU frequency settings
* 06-Jun-2003 BJD Added CPU frequency settings
* 03-Sep-2003 BJD Linux v2.6 support
* 03-Sep-2003 BJD Linux v2.6 support
* 12-Mar-2004 BJD Fixed include protection, fixed type of clock vars
* 12-Mar-2004 BJD Fixed include protection, fixed type of clock vars
* 14-Sep-2004 BJD Added misccr and getpin to gpio
*/
*/
#ifndef __ASM_ARCH_HARDWARE_H
#ifndef __ASM_ARCH_HARDWARE_H
...
@@ -61,6 +62,10 @@ extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
...
@@ -61,6 +62,10 @@ extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
extern
void
s3c2410_gpio_setpin
(
unsigned
int
pin
,
unsigned
int
to
);
extern
void
s3c2410_gpio_setpin
(
unsigned
int
pin
,
unsigned
int
to
);
extern
unsigned
int
s3c2410_gpio_getpin
(
unsigned
int
pin
);
extern
unsigned
int
s3c2410_modify_misccr
(
unsigned
int
clr
,
unsigned
int
chg
);
#endif
/* __ASSEMBLY__ */
#endif
/* __ASSEMBLY__ */
#include <asm/sizes.h>
#include <asm/sizes.h>
...
...
include/asm-arm/arch-s3c2410/regs-udc.h
0 → 100644
View file @
fbb46a67
/* linux/include/asm/arch-s3c2410/regs-udc.h
*
* Copyright (C) 2004 Herbert Poetzl <herbert@13thfloor.at>
*
* This include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* Changelog:
* 01-08-2004 initial creation
* 12-09-2004 cleanup for submission
*/
#ifndef __ASM_ARCH_REGS_UDC_H
#define __ASM_ARCH_REGS_UDC_H
#define S3C2410_USBDREG(x) ((x) + S3C2410_VA_USBDEV)
#define S3C2410_UDC_FUNC_ADDR_REG S3C2410_USBDREG(0x0140)
#define S3C2410_UDC_PWR_REG S3C2410_USBDREG(0x0144)
#define S3C2410_UDC_EP_INT_REG S3C2410_USBDREG(0x0148)
#define S3C2410_UDC_USB_INT_REG S3C2410_USBDREG(0x0158)
#define S3C2410_UDC_EP_INT_EN_REG S3C2410_USBDREG(0x015c)
#define S3C2410_UDC_USB_INT_EN_REG S3C2410_USBDREG(0x016c)
#define S3C2410_UDC_FRAME_NUM1_REG S3C2410_USBDREG(0x0170)
#define S3C2410_UDC_FRAME_NUM2_REG S3C2410_USBDREG(0x0174)
#define S3C2410_UDC_EP0_FIFO_REG S3C2410_USBDREG(0x01c0)
#define S3C2410_UDC_EP1_FIFO_REG S3C2410_USBDREG(0x01c4)
#define S3C2410_UDC_EP2_FIFO_REG S3C2410_USBDREG(0x01c8)
#define S3C2410_UDC_EP3_FIFO_REG S3C2410_USBDREG(0x01cc)
#define S3C2410_UDC_EP4_FIFO_REG S3C2410_USBDREG(0x01d0)
#define S3C2410_UDC_EP1_DMA_CON S3C2410_USBDREG(0x0200)
#define S3C2410_UDC_EP1_DMA_UNIT S3C2410_USBDREG(0x0204)
#define S3C2410_UDC_EP1_DMA_FIFO S3C2410_USBDREG(0x0208)
#define S3C2410_UDC_EP1_DMA_TTC_L S3C2410_USBDREG(0x020c)
#define S3C2410_UDC_EP1_DMA_TTC_M S3C2410_USBDREG(0x0210)
#define S3C2410_UDC_EP1_DMA_TTC_H S3C2410_USBDREG(0x0214)
#define S3C2410_UDC_EP2_DMA_CON S3C2410_USBDREG(0x0218)
#define S3C2410_UDC_EP2_DMA_UNIT S3C2410_USBDREG(0x021c)
#define S3C2410_UDC_EP2_DMA_FIFO S3C2410_USBDREG(0x0220)
#define S3C2410_UDC_EP2_DMA_TTC_L S3C2410_USBDREG(0x0224)
#define S3C2410_UDC_EP2_DMA_TTC_M S3C2410_USBDREG(0x0228)
#define S3C2410_UDC_EP2_DMA_TTC_H S3C2410_USBDREG(0x022c)
#define S3C2410_UDC_EP3_DMA_CON S3C2410_USBDREG(0x0240)
#define S3C2410_UDC_EP3_DMA_UNIT S3C2410_USBDREG(0x0244)
#define S3C2410_UDC_EP3_DMA_FIFO S3C2410_USBDREG(0x0248)
#define S3C2410_UDC_EP3_DMA_TTC_L S3C2410_USBDREG(0x024c)
#define S3C2410_UDC_EP3_DMA_TTC_M S3C2410_USBDREG(0x0250)
#define S3C2410_UDC_EP3_DMA_TTC_H S3C2410_USBDREG(0x0254)
#define S3C2410_UDC_EP4_DMA_CON S3C2410_USBDREG(0x0258)
#define S3C2410_UDC_EP4_DMA_UNIT S3C2410_USBDREG(0x025c)
#define S3C2410_UDC_EP4_DMA_FIFO S3C2410_USBDREG(0x0260)
#define S3C2410_UDC_EP4_DMA_TTC_L S3C2410_USBDREG(0x0264)
#define S3C2410_UDC_EP4_DMA_TTC_M S3C2410_USBDREG(0x0268)
#define S3C2410_UDC_EP4_DMA_TTC_H S3C2410_USBDREG(0x026c)
#define S3C2410_UDC_INDEX_REG S3C2410_USBDREG(0x0178)
/* indexed registers */
#define S3C2410_UDC_MAXP_REG S3C2410_USBDREG(0x018c)
#define S3C2410_UDC_EP0_CSR_REG S3C2410_USBDREG(0x0184)
#define S3C2410_UDC_IN_CSR1_REG S3C2410_USBDREG(0x0184)
#define S3C2410_UDC_IN_CSR2_REG S3C2410_USBDREG(0x0188)
#define S3C2410_UDC_OUT_CSR1_REG S3C2410_USBDREG(0x0190)
#define S3C2410_UDC_OUT_CSR2_REG S3C2410_USBDREG(0x0194)
#define S3C2410_UDC_OUT_FIFO_CNT1_REG S3C2410_USBDREG(0x0198)
#define S3C2410_UDC_OUT_FIFO_CNT2_REG S3C2410_USBDREG(0x019c)
#define S3C2410_UDC_PWR_ISOUP (1<<7) // R/W
#define S3C2410_UDC_PWR_RESET (1<<3) // R
#define S3C2410_UDC_PWR_RESUME (1<<2) // R/W
#define S3C2410_UDC_PWR_SUSPEND (1<<1) // R
#define S3C2410_UDC_PWR_ENSUSPEND (1<<0) // R/W
#define S3C2410_UDC_PWR_DEFAULT 0x00
#define S3C2410_UDC_INT_EP4 (1<<4) // R/W (clear only)
#define S3C2410_UDC_INT_EP3 (1<<3) // R/W (clear only)
#define S3C2410_UDC_INT_EP2 (1<<2) // R/W (clear only)
#define S3C2410_UDC_INT_EP1 (1<<1) // R/W (clear only)
#define S3C2410_UDC_INT_EP0 (1<<0) // R/W (clear only)
#define S3C2410_UDC_USBINT_RESET (1<<2) // R/W (clear only)
#define S3C2410_UDC_USBINT_RESUME (1<<1) // R/W (clear only)
#define S3C2410_UDC_USBINT_SUSPEND (1<<0) // R/W (clear only)
#define S3C2410_UDC_INTE_EP4 (1<<4) // R/W
#define S3C2410_UDC_INTE_EP3 (1<<3) // R/W
#define S3C2410_UDC_INTE_EP2 (1<<2) // R/W
#define S3C2410_UDC_INTE_EP1 (1<<1) // R/W
#define S3C2410_UDC_INTE_EP0 (1<<0) // R/W
#define S3C2410_UDC_USBINTE_RESET (1<<2) // R/W
#define S3C2410_UDC_USBINTE_SUSPEND (1<<0) // R/W
#define S3C2410_UDC_INDEX_EP0 (0x00)
#define S3C2410_UDC_INDEX_EP1 (0x01) // ??
#define S3C2410_UDC_INDEX_EP2 (0x02) // ??
#define S3C2410_UDC_INDEX_EP3 (0x03) // ??
#define S3C2410_UDC_INDEX_EP4 (0x04) // ??
#define S3C2410_UDC_ICSR1_CLRDT (1<<6) // R/W
#define S3C2410_UDC_ICSR1_SENTSTL (1<<5) // R/W (clear only)
#define S3C2410_UDC_ICSR1_SENDSTL (1<<4) // R/W
#define S3C2410_UDC_ICSR1_FFLUSH (1<<3) // W (set only)
#define S3C2410_UDC_ICSR1_UNDRUN (1<<2) // R/W (clear only)
#define S3C2410_UDC_ICSR1_PKTRDY (1<<0) // R/W (set only)
#define S3C2410_UDC_ICSR2_AUTOSET (1<<7) // R/W
#define S3C2410_UDC_ICSR2_ISO (1<<6) // R/W
#define S3C2410_UDC_ICSR2_MODEIN (1<<5) // R/W
#define S3C2410_UDC_ICSR2_DMAIEN (1<<4) // R/W
#define S3C2410_UDC_OCSR1_CLRDT (1<<7) // R/W
#define S3C2410_UDC_OCSR1_SENTSTL (1<<6) // R/W (clear only)
#define S3C2410_UDC_OCSR1_SENDSTL (1<<5) // R/W
#define S3C2410_UDC_OCSR1_FFLUSH (1<<4) // R/W
#define S3C2410_UDC_OCSR1_DERROR (1<<3) // R
#define S3C2410_UDC_OCSR1_OVRRUN (1<<2) // R/W (clear only)
#define S3C2410_UDC_OCSR1_PKTRDY (1<<0) // R/W (clear only)
#define S3C2410_UDC_OCSR2_AUTOCLR (1<<7) // R/W
#define S3C2410_UDC_OCSR2_ISO (1<<6) // R/W
#define S3C2410_UDC_OCSR2_DMAIEN (1<<5) // R/W
#define S3C2410_UDC_SETIX(x) \
__raw_writel(S3C2410_UDC_INDEX_ ## x, S3C2410_UDC_INDEX_REG);
#define S3C2410_UDC_EP0_CSR_OPKRDY (1<<0)
#define S3C2410_UDC_EP0_CSR_IPKRDY (1<<1)
#define S3C2410_UDC_EP0_CSR_SENTSTL (1<<2)
#define S3C2410_UDC_EP0_CSR_DE (1<<3)
#define S3C2410_UDC_EP0_CSR_SE (1<<4)
#define S3C2410_UDC_EP0_CSR_SENDSTL (1<<5)
#define S3C2410_UDC_EP0_CSR_SOPKTRDY (1<<6)
#define S3C2410_UDC_EP0_CSR_SSE (1<<7)
#define S3C2410_UDC_MAXP_8 (1<<0)
#define S3C2410_UDC_MAXP_16 (1<<1)
#define S3C2410_UDC_MAXP_32 (1<<2)
#define S3C2410_UDC_MAXP_64 (1<<3)
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment