* [PATCH] 1/3 Add pselect/ppoll() system calls
From: David Woodhouse @ 2005-11-29 0:57 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, linuxppc-dev, drepper
In-Reply-To: <1133225007.31573.86.camel@baythorne.infradead.org>
This patch adds the pselect() and ppoll() system calls. Most of this
implementation is as it was in the -mm kernel for a period of time
already before the difficulties with signal delivery became apparent.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
diff --git a/fs/select.c b/fs/select.c
index f10a103..4e0da96 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -179,12 +179,11 @@ get_max:
#define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)
#define POLLEX_SET (POLLPRI)
-int do_select(int n, fd_set_bits *fds, long *timeout)
+int do_select(int n, fd_set_bits *fds, int64_t *timeout)
{
struct poll_wqueues table;
poll_table *wait;
int retval, i;
- long __timeout = *timeout;
rcu_read_lock();
retval = max_select_fd(n, fds);
@@ -196,11 +195,12 @@ int do_select(int n, fd_set_bits *fds, l
poll_initwait(&table);
wait = &table.pt;
- if (!__timeout)
+ if (!*timeout)
wait = NULL;
retval = 0;
for (;;) {
unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp;
+ long __timeout;
set_current_state(TASK_INTERRUPTIBLE);
@@ -255,22 +255,32 @@ int do_select(int n, fd_set_bits *fds, l
*rexp = res_ex;
}
wait = NULL;
- if (retval || !__timeout || signal_pending(current))
+ if (retval || !*timeout || signal_pending(current))
break;
if(table.error) {
retval = table.error;
break;
}
+
+ if (*timeout < 0) {
+ /* Wait indefinitely */
+ __timeout = MAX_SCHEDULE_TIMEOUT;
+ } else if (unlikely(*timeout >= (int64_t)MAX_SCHEDULE_TIMEOUT - 1)) {
+ /* Wait for longer than MAX_SCHEDULE_TIMEOUT. Do it in a loop */
+ __timeout = MAX_SCHEDULE_TIMEOUT - 1;
+ *timeout -= __timeout;
+ } else {
+ __timeout = *timeout;
+ *timeout = 0;
+ }
__timeout = schedule_timeout(__timeout);
+ if (*timeout >= 0)
+ *timeout += __timeout;
}
__set_current_state(TASK_RUNNING);
poll_freewait(&table);
- /*
- * Up-to-date the caller timeout.
- */
- *timeout = __timeout;
return retval;
}
@@ -295,36 +305,14 @@ static void select_bits_free(void *bits,
#define MAX_SELECT_SECONDS \
((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
-asmlinkage long
-sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp)
+static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
+ fd_set __user *exp, int64_t *timeout)
{
fd_set_bits fds;
char *bits;
- long timeout;
int ret, size, max_fdset;
struct fdtable *fdt;
- timeout = MAX_SCHEDULE_TIMEOUT;
- if (tvp) {
- time_t sec, usec;
-
- if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp))
- || __get_user(sec, &tvp->tv_sec)
- || __get_user(usec, &tvp->tv_usec)) {
- ret = -EFAULT;
- goto out_nofds;
- }
-
- ret = -EINVAL;
- if (sec < 0 || usec < 0)
- goto out_nofds;
-
- if ((unsigned long) sec < MAX_SELECT_SECONDS) {
- timeout = ROUND_UP(usec, 1000000/HZ);
- timeout += sec * (unsigned long) HZ;
- }
- }
-
ret = -EINVAL;
if (n < 0)
goto out_nofds;
@@ -362,18 +350,7 @@ sys_select(int n, fd_set __user *inp, fd
zero_fd_set(n, fds.res_out);
zero_fd_set(n, fds.res_ex);
- ret = do_select(n, &fds, &timeout);
-
- if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
- time_t sec = 0, usec = 0;
- if (timeout) {
- sec = timeout / HZ;
- usec = timeout % HZ;
- usec *= (1000000/HZ);
- }
- put_user(sec, &tvp->tv_sec);
- put_user(usec, &tvp->tv_usec);
- }
+ ret = do_select(n, &fds, timeout);
if (ret < 0)
goto out;
@@ -395,6 +372,150 @@ out_nofds:
return ret;
}
+asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
+ fd_set __user *exp, struct timeval __user *tvp)
+{
+ int64_t timeout = -1;
+ struct timeval tv;
+ int ret;
+
+ if (tvp) {
+ if (copy_from_user(&tv, tvp, sizeof(tv)))
+ return -EFAULT;
+
+ if (tv.tv_sec < 0 || tv.tv_usec < 0)
+ return -EINVAL;
+
+ /* Cast to uint64_t to make GCC stop complaining */
+ if ((uint64_t)tv.tv_sec >= (uint64_t)MAX_INT64_SECONDS)
+ timeout = -1; /* infinite */
+ else {
+ timeout = ROUND_UP(tv.tv_sec, 1000000/HZ);
+ timeout += tv.tv_sec * HZ;
+ }
+ }
+
+ ret = core_sys_select(n, inp, outp, exp, &timeout);
+
+ if (tvp) {
+ if (current->personality & STICKY_TIMEOUTS)
+ goto sticky;
+ tv.tv_usec = jiffies_to_usecs(do_div((*(uint64_t*)&timeout), HZ));
+ tv.tv_sec = timeout;
+ if (copy_to_user(tvp, &tv, sizeof(tv))) {
+ sticky:
+ /*
+ * If an application puts its timeval in read-only
+ * memory, we don't want the Linux-specific update to
+ * the timeval to cause a fault after the select has
+ * completed successfully. However, because we're not
+ * updating the timeval, we can't restart the system
+ * call.
+ */
+ if (ret == -ERESTARTNOHAND)
+ ret = -EINTR;
+ }
+ }
+
+ return ret;
+}
+
+#ifdef TIF_RESTORE_SIGMASK
+asmlinkage long sys_pselect7(int n, fd_set __user *inp, fd_set __user *outp,
+ fd_set __user *exp, struct timespec __user *tsp,
+ const sigset_t __user *sigmask, size_t sigsetsize)
+{
+ int64_t timeout = MAX_SCHEDULE_TIMEOUT;
+ sigset_t ksigmask, sigsaved;
+ struct timespec ts;
+ int ret;
+
+ if (tsp) {
+ if (copy_from_user(&ts, tsp, sizeof(ts)))
+ return -EFAULT;
+
+ if (ts.tv_sec < 0 || ts.tv_nsec < 0)
+ return -EINVAL;
+
+ /* Cast to uint64_t to make GCC stop complaining */
+ if ((uint64_t)ts.tv_sec >= (uint64_t)MAX_INT64_SECONDS)
+ timeout = -1; /* infinite */
+ else {
+ timeout = ROUND_UP(ts.tv_sec, 1000000000/HZ);
+ timeout += ts.tv_sec * HZ;
+ }
+ }
+
+ if (sigmask) {
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+ if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
+ return -EFAULT;
+
+ sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+ sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+ }
+
+ ret = core_sys_select(n, inp, outp, exp, &timeout);
+
+ if (tsp) {
+ if (current->personality & STICKY_TIMEOUTS)
+ goto sticky;
+ ts.tv_nsec = jiffies_to_usecs(do_div((*(uint64_t*)&timeout), HZ)) * 1000;
+ ts.tv_sec = timeout;
+ if (copy_to_user(tsp, &ts, sizeof(ts))) {
+ sticky:
+ /*
+ * If an application puts its timeval in read-only
+ * memory, we don't want the Linux-specific update to
+ * the timeval to cause a fault after the select has
+ * completed successfully. However, because we're not
+ * updating the timeval, we can't restart the system
+ * call.
+ */
+ if (ret == -ERESTARTNOHAND)
+ ret = -EINTR;
+ }
+ }
+
+ if (ret == -ERESTARTNOHAND) {
+ /* Don't restore the signal mask yet. Let do_signal() deliver the signal
+ on the way back to userspace, before the signal mask is restored. */
+ if (sigmask) {
+ memcpy(¤t->saved_sigmask, &sigsaved, sizeof(sigsaved));
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+ } else if (sigmask)
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+ return ret;
+}
+
+/*
+ * Most architectures can't handle 7-argument syscalls. So we provide a
+ * 6-argument version where the sixth argument is a pointer to a structure
+ * which has a pointer to the sigset_t itself followed by a size_t containing
+ * the sigset size.
+ */
+asmlinkage long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp,
+ fd_set __user *exp, struct timespec __user *tsp, void __user *sig)
+{
+ size_t sigsetsize = 0;
+ sigset_t __user *up = NULL;
+
+ if (sig) {
+ if (!access_ok(VERIFY_READ, sig, sizeof(void *)+sizeof(size_t))
+ || __get_user(up, (sigset_t * __user *)sig)
+ || __get_user(sigsetsize,
+ (size_t * __user)(sig+sizeof(void *))))
+ return -EFAULT;
+ }
+
+ return sys_pselect7(n, inp, outp, exp, tsp, up, sigsetsize);
+}
+#endif /* TIF_RESTORE_SIGMASK */
+
struct poll_list {
struct poll_list *next;
int len;
@@ -436,16 +557,19 @@ static void do_pollfd(unsigned int num,
}
static int do_poll(unsigned int nfds, struct poll_list *list,
- struct poll_wqueues *wait, long timeout)
+ struct poll_wqueues *wait, int64_t *timeout)
{
int count = 0;
poll_table* pt = &wait->pt;
- if (!timeout)
+ /* Optimise the no-wait case */
+ if (!(*timeout))
pt = NULL;
for (;;) {
struct poll_list *walk;
+ long __timeout;
+
set_current_state(TASK_INTERRUPTIBLE);
walk = list;
while(walk != NULL) {
@@ -453,18 +577,33 @@ static int do_poll(unsigned int nfds, s
walk = walk->next;
}
pt = NULL;
- if (count || !timeout || signal_pending(current))
+ if (count || !*timeout || signal_pending(current))
break;
count = wait->error;
if (count)
break;
- timeout = schedule_timeout(timeout);
+
+ if (*timeout < 0) {
+ /* Wait indefinitely */
+ __timeout = MAX_SCHEDULE_TIMEOUT;
+ } else if (unlikely(*timeout >= (int64_t)MAX_SCHEDULE_TIMEOUT - 1)) {
+ /* Wait for longer than MAX_SCHEDULE_TIMEOUT. Do it in a loop */
+ __timeout = MAX_SCHEDULE_TIMEOUT - 1;
+ *timeout -= __timeout;
+ } else {
+ __timeout = *timeout;
+ *timeout = 0;
+ }
+
+ __timeout = schedule_timeout(__timeout);
+ if (*timeout >= 0)
+ *timeout += __timeout;
}
__set_current_state(TASK_RUNNING);
return count;
}
-asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long timeout)
+int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, int64_t *timeout)
{
struct poll_wqueues table;
int fdcount, err;
@@ -482,14 +621,6 @@ asmlinkage long sys_poll(struct pollfd _
if (nfds > max_fdset && nfds > OPEN_MAX)
return -EINVAL;
- if (timeout) {
- /* Careful about overflow in the intermediate values */
- if ((unsigned long) timeout < MAX_SCHEDULE_TIMEOUT / HZ)
- timeout = (unsigned long)(timeout*HZ+999)/1000+1;
- else /* Negative or overflow */
- timeout = MAX_SCHEDULE_TIMEOUT;
- }
-
poll_initwait(&table);
head = NULL;
@@ -519,6 +650,7 @@ asmlinkage long sys_poll(struct pollfd _
}
i -= pp->len;
}
+
fdcount = do_poll(nfds, head, &table, timeout);
/* OK, now copy the revents fields back to user space. */
@@ -547,3 +679,94 @@ out_fds:
poll_freewait(&table);
return err;
}
+
+asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,
+ long timeout_msecs)
+{
+ int64_t timeout_jiffies = 0;
+
+ if (timeout_msecs) {
+#if HZ > 1000
+ /* We can only overflow if HZ > 1000 */
+ if (timeout_msecs / 1000 > (int64_t)0x7fffffffffffffffULL / (int64_t)HZ)
+ timeout_jiffies = -1;
+ else
+#endif
+ timeout_jiffies = msecs_to_jiffies(timeout_msecs);
+ }
+
+ return do_sys_poll(ufds, nfds, &timeout_jiffies);
+}
+
+#ifdef TIF_RESTORE_SIGMASK
+asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
+ struct timespec __user *tsp, const sigset_t __user *sigmask,
+ size_t sigsetsize)
+{
+ sigset_t ksigmask, sigsaved;
+ struct timespec ts;
+ int64_t timeout = -1;
+ int ret;
+
+ if (tsp) {
+ if (copy_from_user(&ts, tsp, sizeof(ts)))
+ return -EFAULT;
+
+ /* Cast to uint64_t to make GCC stop complaining */
+ if ((uint64_t)ts.tv_sec >= (uint64_t)MAX_INT64_SECONDS)
+ timeout = -1; /* infinite */
+ else {
+ timeout = ROUND_UP(ts.tv_sec, 1000000000/HZ);
+ timeout += ts.tv_sec * HZ;
+ }
+ }
+
+ if (sigmask) {
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+ if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
+ return -EFAULT;
+
+ sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+ sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+ }
+
+ ret = do_sys_poll(ufds, nfds, &timeout);
+
+ /* We can restart this syscall, usually */
+ if (ret == -EINTR) {
+ /* Don't restore the signal mask yet. Let do_signal() deliver the signal
+ on the way back to userspace, before the signal mask is restored. */
+ if (sigmask) {
+ memcpy(¤t->saved_sigmask, &sigsaved, sizeof(sigsaved));
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+ ret = -ERESTARTNOHAND;
+ } else if (sigmask)
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+ if (tsp && timeout >= 0) {
+ if (current->personality & STICKY_TIMEOUTS)
+ goto sticky;
+ /* Yes, we know it's actually an int64_t, but it's also positive. */
+ ts.tv_nsec = jiffies_to_usecs(do_div((*(uint64_t*)&timeout), HZ)) * 1000;
+ ts.tv_sec = timeout;
+ if (copy_to_user(tsp, &ts, sizeof(ts))) {
+ sticky:
+ /*
+ * If an application puts its timeval in read-only
+ * memory, we don't want the Linux-specific update to
+ * the timeval to cause a fault after the select has
+ * completed successfully. However, because we're not
+ * updating the timeval, we can't restart the system
+ * call.
+ */
+ if (ret == -ERESTARTNOHAND && timeout >= 0)
+ ret = -EINTR;
+ }
+ }
+
+ return ret;
+}
+#endif /* TIF_RESTORE_SIGMASK */
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -53,6 +53,8 @@
#include <asm/mmu_context.h>
#include <asm/ioctls.h>
+extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);
+
/*
* Not all architectures have sys_utime, so implement this in terms
* of sys_utimes.
@@ -1607,36 +1609,14 @@ static void select_bits_free(void *bits,
#define MAX_SELECT_SECONDS \
((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
-asmlinkage long
-compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp,
- compat_ulong_t __user *exp, struct compat_timeval __user *tvp)
+int compat_core_sys_select(int n, compat_ulong_t __user *inp,
+ compat_ulong_t __user *outp, compat_ulong_t __user *exp, int64_t *timeout)
{
fd_set_bits fds;
char *bits;
- long timeout;
int size, max_fdset, ret = -EINVAL;
struct fdtable *fdt;
- timeout = MAX_SCHEDULE_TIMEOUT;
- if (tvp) {
- time_t sec, usec;
-
- if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp))
- || __get_user(sec, &tvp->tv_sec)
- || __get_user(usec, &tvp->tv_usec)) {
- ret = -EFAULT;
- goto out_nofds;
- }
-
- if (sec < 0 || usec < 0)
- goto out_nofds;
-
- if ((unsigned long) sec < MAX_SELECT_SECONDS) {
- timeout = ROUND_UP(usec, 1000000/HZ);
- timeout += sec * (unsigned long) HZ;
- }
- }
-
if (n < 0)
goto out_nofds;
@@ -1673,19 +1653,7 @@ compat_sys_select(int n, compat_ulong_t
zero_fd_set(n, fds.res_out);
zero_fd_set(n, fds.res_ex);
- ret = do_select(n, &fds, &timeout);
-
- if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
- time_t sec = 0, usec = 0;
- if (timeout) {
- sec = timeout / HZ;
- usec = timeout % HZ;
- usec *= (1000000/HZ);
- }
- if (put_user(sec, &tvp->tv_sec) ||
- put_user(usec, &tvp->tv_usec))
- ret = -EFAULT;
- }
+ ret = do_select(n, &fds, timeout);
if (ret < 0)
goto out;
@@ -1706,6 +1674,216 @@ out_nofds:
return ret;
}
+asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
+ compat_ulong_t __user *outp, compat_ulong_t __user *exp,
+ struct compat_timeval __user *tvp)
+{
+ int64_t timeout = -1;
+ struct compat_timeval tv;
+ int ret;
+
+ if (tvp) {
+ if (copy_from_user(&tv, tvp, sizeof(tv)))
+ return -EFAULT;
+
+ if (tv.tv_sec < 0 || tv.tv_usec < 0)
+ return -EINVAL;
+
+ /* Cast to uint64_t to make GCC stop complaining */
+ if ((uint64_t)tv.tv_sec >= (uint64_t)MAX_INT64_SECONDS)
+ timeout = -1; /* infinite */
+ else {
+ timeout = ROUND_UP(tv.tv_sec, 1000000/HZ);
+ timeout += tv.tv_sec * HZ;
+ }
+ }
+
+ ret = compat_core_sys_select(n, inp, outp, exp, &timeout);
+
+ if (tvp) {
+ if (current->personality & STICKY_TIMEOUTS)
+ goto sticky;
+ tv.tv_usec = jiffies_to_usecs(do_div((*(uint64_t*)&timeout), HZ));
+ tv.tv_sec = timeout;
+ if (copy_to_user(tvp, &tv, sizeof(tv))) {
+ sticky:
+ /*
+ * If an application puts its timeval in read-only
+ * memory, we don't want the Linux-specific update to
+ * the timeval to cause a fault after the select has
+ * completed successfully. However, because we're not
+ * updating the timeval, we can't restart the system
+ * call.
+ */
+ if (ret == -ERESTARTNOHAND)
+ ret = -EINTR;
+ }
+ }
+
+ return ret;
+}
+
+#ifdef TIF_RESTORE_SIGMASK
+asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
+ compat_ulong_t __user *outp, compat_ulong_t __user *exp,
+ struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,
+ compat_size_t sigsetsize)
+{
+ compat_sigset_t s32;
+ sigset_t ksigmask, sigsaved;
+ long timeout = MAX_SCHEDULE_TIMEOUT;
+ struct compat_timespec ts;
+ int ret;
+
+ if (tsp) {
+ if (copy_from_user(&ts, tsp, sizeof(ts)))
+ return -EFAULT;
+
+ if (ts.tv_sec < 0 || ts.tv_nsec < 0)
+ return -EINVAL;
+ }
+
+ if (sigmask) {
+ if (sigsetsize != sizeof(compat_sigset_t))
+ return -EINVAL;
+ if (copy_from_user(&s32, sigmask, sizeof(s32)))
+ return -EFAULT;
+ sigset_from_compat(&ksigmask, &s32);
+
+ sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+ sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+ }
+
+ do {
+ if (tsp) {
+ if ((unsigned long)ts.tv_sec < MAX_SELECT_SECONDS) {
+ timeout = ROUND_UP(ts.tv_nsec, 1000000000/HZ);
+ timeout += ts.tv_sec * (unsigned long)HZ;
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
+ } else {
+ ts.tv_sec -= MAX_SELECT_SECONDS;
+ timeout = MAX_SELECT_SECONDS * HZ;
+ }
+ }
+
+ ret = compat_core_sys_select(n, inp, outp, exp, &timeout);
+
+ } while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec));
+
+ if (tsp && !(current->personality & STICKY_TIMEOUTS)) {
+ ts.tv_sec += timeout / HZ;
+ ts.tv_nsec += (timeout % HZ) * (1000000000/HZ);
+ if (ts.tv_nsec >= 1000000000) {
+ ts.tv_sec++;
+ ts.tv_nsec -= 1000000000;
+ }
+ (void)copy_to_user(tsp, &ts, sizeof(ts));
+ }
+
+ if (ret == -ERESTARTNOHAND) {
+ /* Don't restore the signal mask yet. Let do_signal() deliver the signal
+ on the way back to userspace, before the signal mask is restored. */
+ if (sigmask) {
+ memcpy(¤t->saved_sigmask, &sigsaved, sizeof(sigsaved));
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+ } else if (sigmask)
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+ return ret;
+}
+
+asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp,
+ compat_ulong_t __user *outp, compat_ulong_t __user *exp,
+ struct compat_timespec __user *tsp, void __user *sig)
+{
+ compat_size_t sigsetsize = 0;
+ compat_uptr_t up = 0;
+
+ if (sig) {
+ if (!access_ok(VERIFY_READ, sig,
+ sizeof(compat_uptr_t)+sizeof(compat_size_t)) ||
+ __get_user(up, (compat_uptr_t __user *)sig) ||
+ __get_user(sigsetsize,
+ (compat_size_t __user *)(sig+sizeof(up))))
+ return -EFAULT;
+ }
+ return compat_sys_pselect7(n, inp, outp, exp, tsp, compat_ptr(up),
+ sigsetsize);
+}
+
+asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
+ unsigned int nfds, struct compat_timespec __user *tsp,
+ const compat_sigset_t __user *sigmask, compat_size_t sigsetsize)
+{
+ compat_sigset_t s32;
+ sigset_t ksigmask, sigsaved;
+ struct compat_timespec ts;
+ int64_t timeout = -1;
+ int ret;
+
+ if (tsp) {
+ if (copy_from_user(&ts, tsp, sizeof(ts)))
+ return -EFAULT;
+
+ /* We assume that ts.tv_sec is always lower than
+ the number of seconds that can be expressed in
+ an int64_t. Otherwise the compiler bitches at us */
+ timeout = ROUND_UP(ts.tv_sec, 1000000000/HZ);
+ timeout += ts.tv_sec * HZ;
+ }
+
+ if (sigmask) {
+ if (sigsetsize |= sizeof(compat_sigset_t))
+ return -EINVAL;
+ if (copy_from_user(&s32, sigmask, sizeof(s32)))
+ return -EFAULT;
+ sigset_from_compat(&ksigmask, &s32);
+
+ sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+ sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+ }
+
+ ret = do_sys_poll(ufds, nfds, &timeout);
+
+ /* We can restart this syscall, usually */
+ if (ret == -EINTR) {
+ /* Don't restore the signal mask yet. Let do_signal() deliver the signal
+ on the way back to userspace, before the signal mask is restored. */
+ if (sigmask) {
+ memcpy(¤t->saved_sigmask, &sigsaved, sizeof(sigsaved));
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+ ret = -ERESTARTNOHAND;
+ } else if (sigmask)
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+ if (tsp && timeout >= 0) {
+ if (current->personality & STICKY_TIMEOUTS)
+ goto sticky;
+ /* Yes, we know it's actually an int64_t, but it's also positive. */
+ ts.tv_nsec = jiffies_to_usecs(do_div((*(uint64_t*)&timeout), HZ)) * 1000;
+ ts.tv_sec = timeout;
+ if (copy_to_user(tsp, &ts, sizeof(ts))) {
+ sticky:
+ /*
+ * If an application puts its timeval in read-only
+ * memory, we don't want the Linux-specific update to
+ * the timeval to cause a fault after the select has
+ * completed successfully. However, because we're not
+ * updating the timeval, we can't restart the system
+ * call.
+ */
+ if (ret == -ERESTARTNOHAND && timeout >= 0)
+ ret = -EINTR;
+ }
+ }
+
+ return ret;
+}
+#endif /* TIF_RESTORE_SIGMASK */
+
#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
/* Stuff for NFS server syscalls... */
struct compat_nfsctl_svc {
diff --git a/include/linux/poll.h b/include/linux/poll.h
index f6da702..5b9c85c 100644
--- a/include/linux/poll.h
+++ b/include/linux/poll.h
@@ -92,7 +92,11 @@ void zero_fd_set(unsigned long nr, unsig
memset(fdset, 0, FDS_BYTES(nr));
}
-extern int do_select(int n, fd_set_bits *fds, long *timeout);
+#define MAX_INT64_SECONDS (((int64_t)(~((uint64_t)0)>>1)/HZ)-1)
+
+extern int do_select(int n, fd_set_bits *fds, int64_t *timeout);
+extern int do_sys_poll(struct pollfd __user * ufds, unsigned int nfds,
+ int64_t *timeout);
#endif /* KERNEL */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2038bd2..bf7db28 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -800,6 +800,7 @@ struct task_struct {
struct sighand_struct *sighand;
sigset_t blocked, real_blocked;
+ sigset_t saved_sigmask; /* To be restored with TIF_RESTORE_SIGMASK */
struct sigpending pending;
unsigned long sas_ss_sp;
--
dwmw2
^ permalink raw reply related
* [PATCH] 0/3 Add pselect/ppoll()
From: David Woodhouse @ 2005-11-29 0:57 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, linuxppc-dev, drepper
The following implementation of ppoll() and pselect() system calls
depends on the architecture providing a TIF_RESTORE_SIGMASK flag in the
thread_info.
These system calls have to change the signal mask during their
operation, and signal handlers must be invoked using the new, temporary
signal mask. The old signal mask must be restored either upon successful
exit from the system call, or upon returning from the invoked signal
handler if the system call is interrupted. We can't simply restore the
original signal mask and return to userspace, since the restored signal
mask may actually block the signal which interrupted the system call.
The TIF_RESTORE_SIGMASK flag deals with this by causing the syscall exit
path to trap into do_signal() just as TIF_SIGPENDING does, and by
causing do_signal() to use the saved signal mask instead of the current
signal mask when setting up the stack frame for the signal handler -- or
by causing do_signal() to simply restore the saved signal mask in the
case where there is no handler to be invoked.
The first patch implements the sys_pselect() and sys_ppoll() system
calls, which are present only if TIF_RESTORE_SIGMASK is defined. That
#ifdef should go away in time when all architectures have implemented
it. The second patch implements TIF_RESTORE_SIGMASK for the PowerPC
kernel (in the -mm tree), and the third patch then removes the
arch-specific implementations of sys_rt_sigsuspend() and replaces them
with generic versions using the same trick.
--
dwmw2
^ permalink raw reply
* Problem running kernel 2.6.14 (DENX) on MPC866
From: Gil Madar @ 2005-11-28 23:47 UTC (permalink / raw)
To: linuxppc-embedded
Hi All,
I load linux from u-boot, and manage to go all the way until the call to cpu_idle() from rest_init().
The system claims mounts a root file system over NFS. Sniffer logs and host logs support this claim.
If I do a while ( 1 ) printk( whatever ), just before cpu_idle(), the system continues to run.
If I let it call cpu_idle(), the system hangs.
If I powercycle the board, I see many occurences of exceptions in the log_buf. They all claim there has
been an access to an invalid address as in "<4>Oops: kernel access of bad area, sig: 11".
The exceptions are never printed and the 'bad address' is offset 0x1C from the IMMR. The access
is from m8xx_get_irq().
Has anybody else faced similar problems?
Note: I had to workaround the
ppc_md.set_rtc_time = m8xx_set_rtc_time;
ppc_md.get_rtc_time = m8xx_get_rtc_time;
initialisations in m8xx_setup.c.
What additional modifications are needed for the MPC866?
Is there something broken in my setup?
Is there a need for additional information?
As I'm doing this without an emulator, I appreciate any ideas.
Thanks for your time. I appreciate any response,
Gil
Here is a log of the run.
U-Boot 1.1.3 (Nov 22 2005 - 00:26:43)
CPU: unknown MPC86x (0x08010004) at 133 MHz: 16 kB I-Cache 8 kB D-Cache FEC present
*** Warning: CPU Core has Silicon Bugs -- Check the Errata ***
Board: IDU()
DRAM: 16 MB
Using default environment
In: serial
Out: serial
Err: serial
Net: FEC ETHERNET
Monitor Command Prompt:>setenv gatewayip 10.0.0.138;setenv ethaddr 00:01:02:03:04:05; setenv console ttyCPM0,38400n8; setenv
ipaddr 10.0.0.4;setenv serverip 10.0.0.2;setenv hostname idu;setenv netmask 255.0.0.0; setenv rootpath /mnt/iso1
Monitor Command Prompt:>setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) console=$(console) ethaddr=$(ethad
dr) ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off
Monitor Command Prompt:>tftpboot 600000 uImage
Using FEC ETHERNET device
TFTP from server 10.0.0.2; our IP address is 10.0.0.4
Filename 'uImage'.
Load address: 0x600000
Loading: #################################################################
#################################################################
#################################################################
#################################################################
####
done
Bytes transferred = 1350694 (149c26 hex)
Monitor Command Prompt:>bootm 600000
## Booting image at 00600000 ...
Image Name: Linux-2.6.14
Image Type: PowerPC Linux Kernel Image (gzip compressed)
Data Size: 1350630 Bytes = 1.3 MB
Load Address: 00000000
Entry Point: 00000000
Verifying Checksum ... OK
Uncompressing Kernel Image ... OK
## Current stack ends at 0x00F9DBB0 => set upper limit to 0x00800000
## cmdline at 0x007FFF00 ... 0x007FFF90
memstart = 0x00000000
memsize = 0x01000000
flashstart = 0x00000000
flashsize = 0x00000000
flashoffset = 0x00000000
sramstart = 0x00000000
sramsize = 0x00000000
immr_base = 0x0F000000
bootflags = 0x00000001
intfreq = 133 MHz
busfreq = 66.500 MHz
ethaddr = 00:01:02:03:04:05
IP addr = 10.0.0.4
baudrate = 38400 bps
No initrd
## Transferring control to Linux (at address 00000000) ...
Linux version 2.6.14 (xxxx@yyyy) (gcc version 3.3.3 (DENX ELDK 3.1.1 3.3.3-10)) #44 Tue Nov 29 00:41:34 IST 2005
Built 1 zonelists
Kernel command line: root=/dev/nfs rw nfsroot=10.0.0.2:/mnt/iso1 console=ttyCPM0,38400n8 ethaddr=00:01:02:03:04:05 ip=10.0.0
.4:10.0.0.2:10.0.0.138:255.0.0.0:idu::off
PID hash table entries: 128 (order: 7, 2048 bytes)
Decrementer Frequency = 498750000/60
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
Memory: 13084k available (2364k kernel code, 656k data, 84k init, 0k highmem)
Mount-cache hash table entries: 512
NET: Registered protocol family 16
NTFS driver 2.1.24 [Flags: R/W].
JFS: nTxBlock = 102, nTxLock = 819
Initializing Cryptographic API
Serial: CPM driver $Revision: 0.01 $
ttyCPM0 at MMIO 0xf000a80 (irq = 20) is a CPM UART
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered
loop: loaded (max 8 devices)
eth0: FEC ENET Version 0.2, FEC irq 3, addr 00:01:02:03:04:05
NET: Registered protocol family 2
IP route cache hash table entries: 256 (order: -2, 1024 bytes)
TCP established hash table entries: 1024 (order: 0, 4096 bytes)
TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
TCP: Hash tables configured (established 1024 bind 1024)
TCP reno registered
TCP bic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
IP-Config: Complete:
device=eth0, addr=10.0.0.4, mask=255.0.0.0, gw=10.0.0.138,
host=idu, domain=, nis-domain=(none),
bootserver=10.0.0.2, rootserver=10.0.0.2, rootpath=
Looking up port of RPC 100003/2 on 10.0.0.2
Looking up port of RPC 100005/1 on 10.0.0.2
VFS: Mounted root (nfs filesystem).
Freeing unused kernel memory: 84k init
---------here the system hangs -----------------
^ permalink raw reply
* [PATCH] powerpc: More serial probe fixes (#2)
From: Benjamin Herrenschmidt @ 2005-11-29 0:21 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc64-dev, linuxppc-dev list
This fixes the new serial probe code with some PCI MMIO UARTs, and fixes
CHRP build with ARCH=powerpc.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Index: linux-work/arch/powerpc/kernel/legacy_serial.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/legacy_serial.c 2005-11-29 11:02:28.000000000 +1100
+++ linux-work/arch/powerpc/kernel/legacy_serial.c 2005-11-29 11:21:52.000000000 +1100
@@ -38,15 +38,13 @@ static int __init add_legacy_port(struct
int iotype, phys_addr_t base,
phys_addr_t taddr, unsigned long irq)
{
- u32 *clk, *spd, clock;
+ u32 *clk, *spd, clock = BASE_BAUD * 16;
int index;
/* get clock freq. if present */
clk = (u32 *)get_property(np, "clock-frequency", NULL);
if (clk && *clk)
clock = *clk;
- else
- clock = BASE_BAUD * 16;
/* get default speed if present */
spd = (u32 *)get_property(np, "current-speed", NULL);
@@ -88,7 +86,7 @@ static int __init add_legacy_port(struct
if (iotype == UPIO_PORT)
legacy_serial_ports[index].iobase = base;
else
- legacy_serial_ports[index].membase = (void __iomem *)base;
+ legacy_serial_ports[index].mapbase = base;
legacy_serial_ports[index].iotype = iotype;
legacy_serial_ports[index].uartclk = clock;
legacy_serial_ports[index].irq = irq;
@@ -148,17 +146,17 @@ static int __init add_legacy_pci_port(st
{
phys_addr_t addr, base;
u32 *addrp;
- int iotype, index = -1;
+ int iotype, index = -1, lindex = 0;
-#if 0
/* We only support ports that have a clock frequency properly
* encoded in the device-tree (that is have an fcode). Anything
* else can't be used that early and will be normally probed by
- * the generic 8250_pci driver later on.
+ * the generic 8250_pci driver later on. The reason is that 8250
+ * compatible UARTs on PCI need all sort of quirks (port offsets
+ * etc...) that this code doesn't know about
*/
if (get_property(np, "clock-frequency", NULL) == NULL)
return -1;
-#endif
/* Get the PCI address. Assume BAR 0 */
addrp = of_get_pci_address(pci_dev, 0, NULL);
@@ -183,7 +181,23 @@ static int __init add_legacy_pci_port(st
if (np != pci_dev) {
u32 *reg = (u32 *)get_property(np, "reg", NULL);
if (reg && (*reg < 4))
- index = legacy_serial_count + *reg;
+ index = lindex = *reg;
+ }
+
+ /* Local index means it's the Nth port in the PCI chip. Unfortunately
+ * the offset to add here is device specific. We know about those
+ * EXAR ports and we default to the most common case. If your UART
+ * doesn't work for these settings, you'll have to add your own special
+ * cases here
+ */
+ if (device_is_compatible(pci_dev, "pci13a8,152") ||
+ device_is_compatible(pci_dev, "pci13a8,154") ||
+ device_is_compatible(pci_dev, "pci13a8,158")) {
+ addr += 0x200 * lindex;
+ base += 0x200 * lindex;
+ } else {
+ addr += 8 * lindex;
+ base += 8 * lindex;
}
/* Add port, irq will be dealt with later. We passed a translated
@@ -264,7 +278,6 @@ void __init find_legacy_serial_ports(voi
DBG("legacy_serial_console = %d\n", legacy_serial_console);
/* udbg is 64 bits only for now, that will change soon though ... */
-#ifdef CONFIG_PPC64
while (legacy_serial_console >= 0) {
struct legacy_serial_info *info =
&legacy_serial_infos[legacy_serial_console];
@@ -281,7 +294,6 @@ void __init find_legacy_serial_ports(voi
udbg_init_uart(addr, info->speed, info->clock);
break;
}
-#endif /* CONFIG_PPC64 */
DBG(" <- find_legacy_serial_port()\n");
}
@@ -343,6 +355,15 @@ static void __init fixup_port_pio(int in
}
}
+static void __init fixup_port_mmio(int index,
+ struct device_node *np,
+ struct plat_serial8250_port *port)
+{
+ DBG("fixup_port_mmio(%d)\n", index);
+
+ port->membase = ioremap(port->mapbase, 0x100);
+}
+
/*
* This is called as an arch initcall, hopefully before the PCI bus is
* probed and/or the 8250 driver loaded since we need to register our
@@ -377,6 +398,8 @@ static int __init serial_dev_init(void)
fixup_port_irq(i, np, port);
if (port->iotype == UPIO_PORT)
fixup_port_pio(i, np, port);
+ if (port->iotype == UPIO_MEM)
+ fixup_port_mmio(i, np, port);
}
DBG("Registering platform serial ports\n");
Index: linux-work/arch/powerpc/platforms/chrp/setup.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/chrp/setup.c 2005-11-24 17:18:42.000000000 +1100
+++ linux-work/arch/powerpc/platforms/chrp/setup.c 2005-11-29 11:26:01.000000000 +1100
@@ -49,7 +49,6 @@
#include <asm/hydra.h>
#include <asm/sections.h>
#include <asm/time.h>
-#include <asm/btext.h>
#include <asm/i8259.h>
#include <asm/mpic.h>
#include <asm/rtas.h>
@@ -58,7 +57,6 @@
#include "chrp.h"
void rtas_indicator_progress(char *, unsigned short);
-void btext_progress(char *, unsigned short);
int _chrp_type;
EXPORT_SYMBOL(_chrp_type);
@@ -264,11 +262,6 @@ void __init chrp_setup_arch(void)
ppc_md.set_rtc_time = rtas_set_rtc_time;
}
-#ifdef CONFIG_BOOTX_TEXT
- if (ppc_md.progress == NULL && boot_text_mapped)
- ppc_md.progress = btext_progress;
-#endif
-
#ifdef CONFIG_BLK_DEV_INITRD
/* this is fine for chrp */
initrd_below_start_ok = 1;
@@ -522,12 +515,3 @@ void __init chrp_init(void)
smp_ops = &chrp_smp_ops;
#endif /* CONFIG_SMP */
}
-
-#ifdef CONFIG_BOOTX_TEXT
-void
-btext_progress(char *s, unsigned short hex)
-{
- btext_drawstring(s);
- btext_drawstring("\n");
-}
-#endif /* CONFIG_BOOTX_TEXT */
^ permalink raw reply
* Re: PowerBook5,8 - TrackPad update
From: Michael Hanselmann @ 2005-11-29 0:06 UTC (permalink / raw)
To: Parag Warudkar; +Cc: linuxppc-dev, debian-powerpc, linux-kernel
In-Reply-To: <70210ED5-37CA-40BC-8293-FF1DAA3E8BD5@comcast.net>
[-- Attachment #1.1: Type: text/plain, Size: 988 bytes --]
Hello Parag
> Attached is the code which takes care of above 3 - tested but it
> should be considered half baked for obvious reasons and
I hacked your code some more to make it work on my October 2005
PowerBook 1.67 GHz. The product ID I have, 0x0215, was in none of the
available drivers and the data format is somewhat different.
You find my hacked version attached -- be aware that in its current form
it will not work with any touchpad except 0x0215.
> in addition I added some relayfs write calls [...]
I wrapped them into #if's, so one is not required to have relayfs in the
kernel to use the driver.
> The code might break the existing (old) trackpads as the detection
> might not be correct.
My changes do that definitively, but it's only a hack.
As far as I see it, all methods can be built into one driver. Is there
already someone working on combining them?
Greets,
Michael
--
Gentoo Linux Developer using m0n0wall | http://hansmi.ch/
[-- Attachment #1.2: appletouch.c --]
[-- Type: text/x-csrc, Size: 16927 bytes --]
/*
* Apple USB Touchpad (for post-February 2005 PowerBooks) driver
*
* Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net)
* Copyright (C) 2005 Stelian Pop (stelian@popies.net)
* Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
* Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
* Copyright (C) 2005 Parag Warudkar (parag.warudkar@gmail.com)
*
* Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
* Nov 2005 - Parag Warudkar
* o Add preliminary support for Oct 2005 Powerbooks
* (Doesn't work fully yet)
* o Converted to use input_device_allocate()
* o Added ability to export data via relayfs
*
* This program 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/input.h>
#include <linux/usb_input.h>
#include <linux/debugfs.h>
#include <asm/prom.h>
#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
#include <linux/relayfs_fs.h>
#endif
#if !defined(PPC) && !defined(POWERPC)
#error "Module intended for PowerPC based PowerBooks!"
#endif
/* Apple has powerbooks which have the keyboard with different Product IDs */
#define APPLE_VENDOR_ID 0x05AC
#define ATP_DEVICE(prod) \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
USB_DEVICE_ID_MATCH_INT_CLASS | \
USB_DEVICE_ID_MATCH_INT_PROTOCOL, \
.idVendor = APPLE_VENDOR_ID, \
.idProduct = (prod), \
.bInterfaceClass = 0x03, \
.bInterfaceProtocol = 0x02
/* table of devices that work with this driver */
static struct usb_device_id atp_table [] = {
/* Earlier PowerBooks */
{ ATP_DEVICE(0x020E) },
{ ATP_DEVICE(0x020F) },
{ ATP_DEVICE(0x030A) },
{ ATP_DEVICE(0x030B) },
/* PowerBooks Late Oct 2005 */
{ ATP_DEVICE(0x0214) },
{ ATP_DEVICE(0x0215) },
/* Terminating entry */
{ }
};
MODULE_DEVICE_TABLE (usb, atp_table);
#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
struct rchan* rch = NULL;
struct rchan_callbacks* rcb = NULL;
#endif
/*
* number of sensors. Note that only 16 instead of 26 X (horizontal)
* sensors exist on 12" and 15" PowerBooks. All models have 16 Y
* (vertical) sensors.
*/
#define ATP_MAX_XSENSORS 15
#define ATP_MAX_YSENSORS 7
/* amount of fuzz this touchpad generates */
#define ATP_FUZZ 16
/* maximum pressure this driver will report */
#define ATP_PRESSURE 300
/*
* multiplication factor for the X and Y coordinates.
* We try to keep the touchpad aspect ratio while still doing only simple
* arithmetics.
* The factors below give coordinates like:
* 0 <= x < 960 on 12" and 15" Powerbooks
* 0 <= x < 1600 on 17" Powerbooks
* 0 <= y < 646
*/
#define ATP_XFACT 64
#define ATP_YFACT 43
/*
* Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is
* ignored.
*/
#define ATP_THRESHOLD 5
typedef enum PB_MAC_TYPE {
PowerBook54,
PowerBook56,
PowerBook58,
PowerBook59,
Unknown
} PB_MAC_TYPE;
/* Structure to hold all of our device specific stuff */
struct atp {
struct usb_device * udev; /* usb device */
struct urb * urb; /* usb request block */
signed char * data; /* transferred data */
int open; /* non-zero if opened */
struct input_dev *input; /* input dev */
int valid; /* are the sensors valid ? */
int x_old; /* last reported x/y, */
int y_old; /* used for smoothing */
/* current value of the sensors */
signed char xy_cur[ATP_MAX_XSENSORS + ATP_MAX_YSENSORS];
/* last value of the sensors */
signed char xy_old[ATP_MAX_XSENSORS + ATP_MAX_YSENSORS];
/* accumulated sensors */
int xy_acc[ATP_MAX_XSENSORS + ATP_MAX_YSENSORS];
PB_MAC_TYPE mtype;
};
#define dbg_dump(msg, tab) \
if (debug > 1) { \
int i; \
printk("appletouch: %s %lld", msg, (long long)jiffies); \
for (i = 0; i < ATP_MAX_XSENSORS + ATP_MAX_YSENSORS; i++) \
printk(" %02x", tab[i]); \
printk("\n"); \
}
#define dprintk(format, a...) \
do { \
if (debug) printk(format, ##a); \
} while (0)
MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Parag Warudkar");
MODULE_DESCRIPTION("Apple Al PowerBook USB touchpad driver");
MODULE_LICENSE("GPL");
static int debug = 1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Activate debugging output");
/* USB URB buffer length - 81 works on Feb 05 models.
* Oct 05 models fail with EOVERFLOW, detected and corrected
* separately.
*/
//static int data_len = 81;
static int data_len = 80;
module_param(data_len, int, 0644);
MODULE_PARM_DESC(data_len, "Specify USB URB buffer length (auto-detected normally)");
PB_MAC_TYPE atp_machine_detect(void)
{
if(machine_is_compatible("PowerBook5,9"))
return PowerBook59;
if(machine_is_compatible("PowerBook5,8"))
return PowerBook58;
if(machine_is_compatible("PowerBook5,6"))
return PowerBook56;
if (machine_is_compatible("PowerBook5,4"))
return PowerBook54;
return Unknown;
}
static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
int *z, int *fingers)
{
int i;
/* values to calculate mean */
int pcum = 0, psum = 0;
*fingers = 0;
for (i = 0; i < nb_sensors; i++) {
if (xy_sensors[i] < ATP_THRESHOLD)
continue;
if ((i - 1 < 0) || (xy_sensors[i - 1] < ATP_THRESHOLD))
(*fingers)++;
pcum += xy_sensors[i] * i;
psum += xy_sensors[i];
}
if (psum > 0) {
*z = psum;
return pcum * fact / psum;
}
return 0;
}
static inline void atp_report_fingers(struct input_dev *input, int fingers)
{
input_report_key(input, BTN_TOOL_FINGER, fingers == 1);
input_report_key(input, BTN_TOOL_DOUBLETAP, fingers == 2);
input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2);
}
static void atp_complete(struct urb* urb, struct pt_regs* regs)
{
int x, y, x_z, y_z, x_f, y_f;
int retval, i;
struct atp *dev = urb->context;
static int ctr = 1;
switch (urb->status) {
case 0:
/* success */
break;
case -EOVERFLOW:
if(ctr){
printk("appletouch: OVERFLOW with data length %d\n", data_len);
ctr = 0;
}
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
/* This urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d",
__FUNCTION__, urb->status);
return;
default:
goto exit;
}
/* drop incomplete datasets */
if (dev->urb->actual_length != data_len) {
printk(KERN_WARNING "appletouch: incomplete data package length %d\n", dev->urb->actual_length);
goto exit;
}
#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
if ( dev->data ) {
relay_write(rch, dev->data, dev->urb->actual_length);
}
#endif
dev->xy_cur[0] = dev->data[19];
dev->xy_cur[1] = dev->data[20];
dev->xy_cur[2] = dev->data[22];
dev->xy_cur[3] = dev->data[23];
dev->xy_cur[4] = dev->data[25];
dev->xy_cur[5] = dev->data[26];
dev->xy_cur[6] = dev->data[28];
dev->xy_cur[7] = dev->data[29];
dev->xy_cur[8] = dev->data[31];
dev->xy_cur[9] = dev->data[32];
dev->xy_cur[10] = dev->data[34];
dev->xy_cur[11] = dev->data[35];
dev->xy_cur[12] = dev->data[37];
dev->xy_cur[13] = dev->data[38];
dev->xy_cur[14] = dev->data[40];
dev->xy_cur[15] = dev->data[1];
dev->xy_cur[16] = dev->data[2];
dev->xy_cur[17] = dev->data[4];
dev->xy_cur[18] = dev->data[5];
dev->xy_cur[19] = dev->data[7];
dev->xy_cur[20] = dev->data[8];
dev->xy_cur[21] = dev->data[10];
/*
for(i = 0; i < ATP_MAX_XSENSORS + ATP_MAX_YSENSORS; i++) {
printk("%2x ", dev->xy_cur[i]);
}
printk("\n");
*/
/* reorder the sensors values */
//for (i = 0; i < 8; i++) {
/* X values */
/*dev->xy_cur[i ] = dev->data[5 * i + 2];
dev->xy_cur[i + 8] = dev->data[5 * i + 4];
dev->xy_cur[i + 16] = dev->data[5 * i + 42];
if (i < 2)
dev->xy_cur[i + 24] = dev->data[5 * i + 44];*/
/* Y values */
/*dev->xy_cur[i + 26] = dev->data[5 * i + 1];
dev->xy_cur[i + 34] = dev->data[5 * i + 3];
}*/
//dbg_dump("sample", dev->xy_cur);
if (!dev->valid) {
/* first sample */
dev->valid = 1;
dev->x_old = dev->y_old = -1;
memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
/* 17" Powerbooks have 10 extra X sensors */
/*for (i = 16; i < ATP_MAX_XSENSORS; i++)
if (dev->xy_cur[i]) {
printk("appletouch: 17\" model detected.\n");
input_set_abs_params(dev->input, ABS_X, 0,
((ATP_MAX_XSENSORS - 1) * ATP_XFACT) - 1,
ATP_FUZZ, 0);
break;
}*/
goto exit;
}
for (i = 0; i < ATP_MAX_XSENSORS + ATP_MAX_YSENSORS; i++) {
/* accumulate the change */
signed char change = dev->xy_old[i] - dev->xy_cur[i];
dev->xy_acc[i] -= change;
/* prevent down drifting */
if (dev->xy_acc[i] < 0)
dev->xy_acc[i] = 0;
}
memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
//dbg_dump("accumulator", dev->xy_acc);
x = atp_calculate_abs(dev->xy_acc, ATP_MAX_XSENSORS,
ATP_XFACT, &x_z, &x_f);
y = atp_calculate_abs(dev->xy_acc + ATP_MAX_XSENSORS, ATP_MAX_YSENSORS,
ATP_YFACT, &y_z, &y_f);
if (x && y) {
if (dev->x_old != -1) {
x = (dev->x_old * 3 + x) >> 2;
y = (dev->y_old * 3 + y) >> 2;
dev->x_old = x;
dev->y_old = y;
if (debug > 1)
printk("appletouch: X: %3d Y: %3d "
"Xz: %3d Yz: %3d\n",
x, y, x_z, y_z);
input_report_key(dev->input, BTN_TOUCH, 1);
input_report_abs(dev->input, ABS_X, x);
input_report_abs(dev->input, ABS_Y, y);
input_report_abs(dev->input, ABS_PRESSURE,
min(ATP_PRESSURE, x_z + y_z));
atp_report_fingers(dev->input, max(x_f, y_f));
}
dev->x_old = x;
dev->y_old = y;
}
else if (!x && !y) {
dev->x_old = dev->y_old = -1;
input_report_key(dev->input, BTN_TOUCH, 0);
input_report_abs(dev->input, ABS_PRESSURE, 0);
atp_report_fingers(dev->input, 0);
/* reset the accumulator on release */
memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
}
input_report_key(dev->input, BTN_LEFT, !!dev->data[data_len-1]);
input_sync(dev->input);
exit:
retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
if (retval) {
err("%s - usb_submit_urb failed with result %d",
__FUNCTION__, retval);
}
}
static int atp_open(struct input_dev *input)
{
struct atp *dev = input->private;
if (usb_submit_urb(dev->urb, GFP_ATOMIC)) {
printk("atp: usb_submit_urb Error\n");
return -EIO;
}
dev->open = 1;
return 0;
}
static void atp_close(struct input_dev *input)
{
struct atp *dev = input->private;
usb_kill_urb(dev->urb);
dev->open = 0;
}
static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id)
{
struct atp *dev = NULL;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
int int_in_endpointAddr = 0;
int i, retval = -ENOMEM;
int regret=0;
printk(KERN_INFO "AppleTouch: Inside atp_probe\n");
/* allocate memory for our device state and initialize it */
dev = kmalloc(sizeof(struct atp), GFP_KERNEL);
if (dev == NULL) {
err("Out of memory");
goto err_kmalloc;
}
memset(dev, 0, sizeof(struct atp));
dev->mtype = atp_machine_detect();
if(dev->mtype == Unknown)
{
printk(KERN_INFO "appletouch: Unknown machine type!\n");
return -ENODEV;
}
if(dev->mtype > 1)
{
if(data_len < 256)
{
printk(KERN_INFO "appletouch: Setting URB buffer length to 256\n");
data_len = 256;
}
}
printk("appletouch: Machine type is: %d\n", dev->mtype);
dev->udev = interface_to_usbdev(iface);
/* set up the endpoint information */
/* use only the first interrupt-in endpoint */
iface_desc = iface->cur_altsetting;
for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
endpoint = &iface_desc->endpoint[i].desc;
if (!int_in_endpointAddr &&
(endpoint->bEndpointAddress & USB_DIR_IN) &&
((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
== USB_ENDPOINT_XFER_INT)) {
/* we found an interrupt in endpoint */
int_in_endpointAddr = endpoint->bEndpointAddress;
printk(KERN_INFO "AppleTouch: atp_probe found interrupt in endpoint: %d\n", int_in_endpointAddr);
break;
}
}
if (!int_in_endpointAddr) {
retval = -EIO;
err("Could not find int-in endpoint");
goto err_endpoint;
}
/* save our data pointer in this interface device */
usb_set_intfdata(iface, dev);
dev->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->urb) {
retval = -ENOMEM;
goto err_usballoc;
}
dev->data = usb_buffer_alloc(dev->udev, data_len, GFP_KERNEL,
&dev->urb->transfer_dma);
if (!dev->data) {
retval = -ENOMEM;
goto err_usbbufalloc;
}
usb_fill_int_urb(dev->urb, dev->udev,
usb_rcvintpipe(dev->udev, int_in_endpointAddr),
dev->data, data_len, atp_complete, dev, 1);
dev->input = input_allocate_device();
dev->input->name = "appletouch";
dev->input->dev = &iface->dev;
dev->input->private = dev;
dev->input->open = atp_open;
dev->input->close = atp_close;
usb_to_input_id(dev->udev, &dev->input->id);
set_bit(EV_ABS, dev->input->evbit);
/*
* 12" and 15" Powerbooks only have 16 x sensors,
* 17" models are detected later.
*/
input_set_abs_params(dev->input, ABS_X, 0,
(16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
input_set_abs_params(dev->input, ABS_Y, 0,
(ATP_MAX_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
input_set_abs_params(dev->input, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
set_bit(EV_KEY, dev->input->evbit);
set_bit(BTN_TOUCH, dev->input->keybit);
set_bit(BTN_TOOL_FINGER, dev->input->keybit);
set_bit(BTN_TOOL_DOUBLETAP, dev->input->keybit);
set_bit(BTN_TOOL_TRIPLETAP, dev->input->keybit);
set_bit(BTN_LEFT, dev->input->keybit);
regret = input_register_device(dev->input);
printk(KERN_INFO "input: appletouch connected, Reg code: %d\n", regret);
return 0;
err_usbbufalloc:
usb_free_urb(dev->urb);
err_usballoc:
usb_set_intfdata(iface, NULL);
err_endpoint:
kfree(dev);
err_kmalloc:
return retval;
}
static void atp_disconnect(struct usb_interface *iface)
{
struct atp *dev = usb_get_intfdata(iface);
usb_set_intfdata(iface, NULL);
if (dev) {
usb_kill_urb(dev->urb);
input_unregister_device(dev->input);
usb_free_urb(dev->urb);
usb_buffer_free(dev->udev, data_len,
dev->data, dev->urb->transfer_dma);
kfree(dev);
}
printk(KERN_INFO "input: appletouch disconnected\n");
}
static int atp_suspend(struct usb_interface *iface, pm_message_t message)
{
struct atp *dev = usb_get_intfdata(iface);
usb_kill_urb(dev->urb);
dev->valid = 0;
return 0;
}
static int atp_resume(struct usb_interface *iface)
{
struct atp *dev = usb_get_intfdata(iface);
if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC))
return -EIO;
return 0;
}
static struct usb_driver atp_driver = {
.owner = THIS_MODULE,
.name = "appletouch",
.probe = atp_probe,
.disconnect = atp_disconnect,
.suspend = atp_suspend,
.resume = atp_resume,
.id_table = atp_table,
};
static int __init atp_init(void)
{
#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
rcb = kmalloc(sizeof(struct rchan_callbacks), GFP_KERNEL);
rcb->subbuf_start = NULL;
rcb->buf_mapped = NULL;
rcb->buf_unmapped = NULL;
rch = relay_open("atpdata", NULL, 256, 256, NULL);
if (!rch) return -ENOMEM;
printk("appletouch: Relayfs enabled.\n");
#endif
return usb_register(&atp_driver);
}
static void __exit atp_exit(void)
{
#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
relay_close(rch);
kfree(rcb);
#endif
usb_deregister(&atp_driver);
}
module_init(atp_init);
module_exit(atp_exit);
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: INTERACTIVE_CONSOLE for misc-embedded.c and watchdog issue
From: Tom Rini @ 2005-11-28 23:27 UTC (permalink / raw)
To: Marcelo Tosatti; +Cc: linux-ppc-embedded
In-Reply-To: <20051117151730.GA10180@logos.cnet>
On Thu, Nov 17, 2005 at 01:17:30PM -0200, Marcelo Tosatti wrote:
> The following patch against misc-embedded.c adds an INTERACTIVE_CONSOLE
> #define to guard reading from console (causes unecessary delay in some
> situations).
>
> Its an adaptation of misc.c's define, a difference being that platform
> headers define "NO_INTERACTIVE_CONSOLE" if required.
>
> What do you think?
Please put a comment above the #ifndef stating where the define should
be. But I have a feeling that's going to be somewhere under
arch/ppc/platforms/ or include/asm-ppc/ and I don't know if that's a
good idea...
I've got a vauge idea on how we can handle this a little bit more
cleanly, in the merge tree.
--
Tom Rini
http://gate.crashing.org/~trini/
^ permalink raw reply
* Re: [PATCH] ppc32: fix treeboot image entrypoint
From: Tom Rini @ 2005-11-28 22:34 UTC (permalink / raw)
To: Andrew Morton, Matt Porter, linuxppc-embedded
In-Reply-To: <20051124213821.GA21929@gate.ebshome.net>
On Thu, Nov 24, 2005 at 01:38:21PM -0800, Eugene Surovegin wrote:
> Correctly specify treeboot based image entrypoint. Currently makefile
> uses $(ENTRYPOINT) which isn't defined anywhere. Each board port sets
> entrypoint-$(CONFIG_BOARD_NAME) instead.
>
> Without this patch I cannot boot Ocotea (PPC440GX eval board) anymore.
> I was getting random "OS panic" errors from OpenBIOS for a while, but
> with current kernel I get them all the time (probably because image
> became bigger).
>
> Signed-off-by: Eugene Surovegin <ebs@ebshome.net>
I wonder how that got lost when I think ENTRYPOINT was changed to
entrypoint-$(board_name). Maybe we should also think about changing the
default entry point in mktreeboot.c, what do you think Eugene? or Matt?
Acked-by: Tom Rini <trini@kernel.crashing.org>
--
Tom Rini
http://gate.crashing.org/~trini/
^ permalink raw reply
* Re: [RFC] add PHY support to AM79C874
From: Pantelis Antoniou @ 2005-11-28 21:00 UTC (permalink / raw)
To: Aristeu Sergio Rozanski Filho; +Cc: linuxppc-embedded
In-Reply-To: <20051128141042.GR7163@cathedrallabs.org>
On Monday 28 November 2005 16:10, Aristeu Sergio Rozanski Filho wrote:
> This is a simple port from old fec driver to PHY layer to support AMD
> AM79C874 PHY.
> As I don't have the hardware to test this, all kinds of feedback are
> most welcome.
> Thanks,
>
> --
> Aristeu
>
>
Looks fine to me...
Regards
Pantelis
^ permalink raw reply
* Re: [PATCH] ppc32: Adds MPC885ADS, MPC866ADS and MPC8272ADS-specific platform stuff for fs_enet
From: Marcelo Tosatti @ 2005-11-28 14:48 UTC (permalink / raw)
To: Vitaly Bordug; +Cc: BLandau, linuxppc-embedded list
In-Reply-To: <438B379B.6090904@ru.mvista.com>
On Mon, Nov 28, 2005 at 08:00:11PM +0300, Vitaly Bordug wrote:
> Added proper ppc_sys identification and fs_platform_info's for MPC 885ADS,
> 866ADS and 8272ADS. Assuming setbitsXX/clrbitsXX patch is applied.
>
>
> Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
Looks great now for the parts I can comment on...
^ permalink raw reply
* PPC32 memory models
From: Andy Whitcroft @ 2005-11-28 19:06 UTC (permalink / raw)
To: Anton Blanchard, Paul Mackerras; +Cc: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 566 bytes --]
It seems that there is some confusion over what we should be supporting
memory model wise for PPC32 under powerpc architecture. The current
Kconfig limits you to only SPARSEMEM which isn't parameterised for PPC32
at all. Are we expecting to be able to support PPC32 as yet in this
architecture? If so it seems we have a couple of issues with the Kconfig.
Attached is a patch to enable FLATMEM and disable SPARSEMEM for PPC32
which seems to be the working combinations. It may well not be what is
intended. But I offer it to start discussions.
Comments.
-apw
[-- Attachment #2: sparsemem-powerpc-allow-flatmem-on-32bit --]
[-- Type: text/plain, Size: 796 bytes --]
powerpc: ppc32 clean up available memory models
Clean up the currently available memory models for ppc32. It seems
that we do need FLATMEM for ppc32 on non-NUMA. It also seems that
SPARSEMEM is not parameterised yet so disable that.
Signed-off-by: Andy Whitcroft <apw@shadwen.org>
---
diff -upN reference/arch/powerpc/Kconfig current/arch/powerpc/Kconfig
--- reference/arch/powerpc/Kconfig
+++ current/arch/powerpc/Kconfig
@@ -584,14 +584,15 @@ config ARCH_SELECT_MEMORY_MODEL
config ARCH_FLATMEM_ENABLE
def_bool y
- depends on PPC64 && !NUMA
+ depends on !NUMA
config ARCH_SPARSEMEM_ENABLE
def_bool y
+ depends on PPC64
config ARCH_SPARSEMEM_DEFAULT
def_bool y
- depends on SMP && PPC_PSERIES
+ depends on SMP && PPC_PSERIES && NUMA
source "mm/Kconfig"
^ permalink raw reply
* [PATCH] ppc32 8xx: Added setbitsXX/clrbitsXX macro for read-modify-write operations (resend)
From: Vitaly Bordug @ 2005-11-28 18:01 UTC (permalink / raw)
To: Marcelo Tosatti; +Cc: linuxppc-devel list, linuxppc-embedded list
This adds setbitsXX/clrbitsXX macro for read-modify-write operations
and converts the 8xx core and drivers to use them.
Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
---
arch/ppc/8xx_io/commproc.c | 6 +++---
arch/ppc/syslib/m8xx_setup.c | 12 +++++-------
arch/ppc/syslib/m8xx_wdt.c | 3 +--
include/asm-ppc/io.h | 7 +++++++
4 files changed, 16 insertions(+), 12 deletions(-)
applies-to: 1e8504d2a91579756c89ef2d65ebd526f973cde8
d9135d1517154ad693ac15ee88a2408add6cd88b
diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c
index 579cd40..5cecb6e 100644
--- a/arch/ppc/8xx_io/commproc.c
+++ b/arch/ppc/8xx_io/commproc.c
@@ -73,7 +73,7 @@ cpm_mask_irq(unsigned int irq)
{
int cpm_vec = irq - CPM_IRQ_OFFSET;
- out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr, in_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr) & ~(1 << cpm_vec));
+ clrbits32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr,(1 << cpm_vec));
}
static void
@@ -81,7 +81,7 @@ cpm_unmask_irq(unsigned int irq)
{
int cpm_vec = irq - CPM_IRQ_OFFSET;
- out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr, in_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr) | (1 << cpm_vec));
+ setbits32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr,(1 << cpm_vec));
}
static void
@@ -198,7 +198,7 @@ cpm_interrupt_init(void)
if (setup_irq(CPM_IRQ_OFFSET + CPMVEC_ERROR, &cpm_error_irqaction))
panic("Could not allocate CPM error IRQ!");
- out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr, in_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr) | CICR_IEN);
+ setbits32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr, CICR_IEN);
}
/*
diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c
index 1cc3abe..ad7db45 100644
--- a/arch/ppc/syslib/m8xx_setup.c
+++ b/arch/ppc/syslib/m8xx_setup.c
@@ -149,8 +149,7 @@ void __init m8xx_calibrate_decr(void)
out_be32(&((immap_t *)IMAP_ADDR)->im_clkrstk.cark_sccrk, KAPWR_KEY);
/* Force all 8xx processors to use divide by 16 processor clock. */
- out_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr,
- in_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr)|0x02000000);
+ setbits32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr, 0x02000000);
/* Processor frequency is MHz.
* The value 'fp' is the number of decrementer ticks per second.
*/
@@ -184,10 +183,9 @@ void __init m8xx_calibrate_decr(void)
out_be32(&((immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk, KAPWR_KEY);
/* Disable the RTC one second and alarm interrupts. */
- out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, in_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc) & ~(RTCSC_SIE | RTCSC_ALE));
+ clrbits16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, (RTCSC_SIE | RTCSC_ALE));
/* Enable the RTC */
- out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, in_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc) | (RTCSC_RTF | RTCSC_RTE));
-
+ setbits16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, (RTCSC_RTF | RTCSC_RTE));
/* Enabling the decrementer also enables the timebase interrupts
* (or from the other point of view, to get decrementer interrupts
* we have to enable the timebase). The decrementer interrupt
@@ -232,8 +230,8 @@ m8xx_restart(char *cmd)
__volatile__ unsigned char dummy;
local_irq_disable();
- out_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr, in_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr) | 0x00000080);
+ setbits32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr, 0x00000080);
/* Clear the ME bit in MSR to cause checkstop on machine check
*/
mtmsr(mfmsr() & ~0x1000);
@@ -303,8 +301,8 @@ m8xx_init_IRQ(void)
i8259_init(0);
/* The i8259 cascade interrupt must be level sensitive. */
- out_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel, in_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel & ~(0x80000000 >> ISA_BRIDGE_INT)));
+ clrbits32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel, (0x80000000 >> ISA_BRIDGE_INT));
if (setup_irq(ISA_BRIDGE_INT, &mbx_i8259_irqaction))
enable_irq(ISA_BRIDGE_INT);
#endif /* CONFIG_PCI */
diff --git a/arch/ppc/syslib/m8xx_wdt.c b/arch/ppc/syslib/m8xx_wdt.c
index a21632d..57f8b9f 100644
--- a/arch/ppc/syslib/m8xx_wdt.c
+++ b/arch/ppc/syslib/m8xx_wdt.c
@@ -40,8 +40,7 @@ static irqreturn_t m8xx_wdt_interrupt(in
m8xx_wdt_reset();
- out_be16(&imap->im_sit.sit_piscr, in_be16(&imap->im_sit.sit_piscr) | PISCR_PS); /* clear irq */
-
+ setbits16(&imap->im_sit.sit_piscr, PISCR_PS);
return IRQ_HANDLED;
}
diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h
index 84ac6e2..9c2e3db 100644
--- a/include/asm-ppc/io.h
+++ b/include/asm-ppc/io.h
@@ -573,4 +573,11 @@ extern void pci_iounmap(struct pci_dev *
*/
#define xlate_dev_kmem_ptr(p) p
+/* access ports */
+#define setbits32(_addr, _v) out_be32((_addr), in_be32(_addr) | (_v))
+#define clrbits32(_addr, _v) out_be32((_addr), in_be32(_addr) & ~(_v))
+
+#define setbits16(_addr, _v) out_be16((_addr), in_be16(_addr) | (_v))
+#define clrbits16(_addr, _v) out_be16((_addr), in_be16(_addr) & ~(_v))
+
#endif /* __KERNEL__ */
---
Sincerely,
Vitaly
^ permalink raw reply related
* [PATCH] ppc32: Adds MPC885ADS, MPC866ADS and MPC8272ADS-specific platform stuff for fs_enet
From: Vitaly Bordug @ 2005-11-28 17:00 UTC (permalink / raw)
To: BLandau; +Cc: linuxppc-embedded list
[-- Attachment #1: Type: text/plain, Size: 223 bytes --]
Added proper ppc_sys identification and fs_platform_info's for MPC 885ADS, 866ADS and
8272ADS. Assuming setbitsXX/clrbitsXX patch is applied.
Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
---
Sincerely,
Vitaly
[-- Attachment #2: pre2.patch --]
[-- Type: text/x-patch, Size: 32010 bytes --]
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 8fa51b0..8e6fcb2 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -506,6 +506,53 @@ config WINCEPT
endchoice
+menu "Freescale Ethernet driver platform-specific options"
+ depends on FS_ENET
+
+ config MPC8xx_SECOND_ETH
+ bool "Second Ethernet channel"
+ depends on (MPC885ADS || MPC86XADS)
+ default y
+ help
+ This enables support for second Ethernet on MPC885ADS and MPC86xADS boards.
+ The latter will use SCC1, for 885ADS you can select it below.
+
+ choice
+ prompt "Second Ethernet channel"
+ depends on MPC8xx_SECOND_ETH
+ default MPC8xx_SECOND_ETH_FEC2
+
+ config MPC8xx_SECOND_ETH_FEC2
+ bool "FEC2"
+ depends on MPC885ADS
+ help
+ Enable FEC2 to serve as 2-nd Ethernet channel. Note that SMC2
+ (often 2-nd UART) will not work if this is enabled.
+
+ config MPC8xx_SECOND_ETH_SCC1
+ bool "SCC1"
+ depends on MPC86XADS
+ select MPC8xx_SCC_ENET_FIXED
+ help
+ Enable SCC1 to serve as 2-nd Ethernet channel. Note that SMC1
+ (often 1-nd UART) will not work if this is enabled.
+
+ config MPC8xx_SECOND_ETH_SCC3
+ bool "SCC3"
+ depends on MPC885ADS
+ help
+ Enable SCC3 to serve as 2-nd Ethernet channel. Note that SMC1
+ (often 1-nd UART) will not work if this is enabled.
+
+ endchoice
+
+ config MPC8xx_SCC_ENET_FIXED
+ depends on MPC8xx_SECOND_ETH_SCC
+ default n
+ bool "Use fixed MII-less mode for SCC Ethernet"
+
+endmenu
+
choice
prompt "Machine Type"
depends on 6xx || POWER3 || POWER4
diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
index 7c5cdab..ee50b0d 100644
--- a/arch/ppc/platforms/Makefile
+++ b/arch/ppc/platforms/Makefile
@@ -22,6 +22,8 @@ ifeq ($(CONFIG_PPC_PMAC),y)
obj-$(CONFIG_NVRAM) += pmac_nvram.o
obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o
endif
+
+obj-$(CONFIG_ADS8272) += mpc8272ads_setup.o
obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o
obj-$(CONFIG_PREP_RESIDUAL) += residual.o
obj-$(CONFIG_PQ2ADS) += pq2ads.o
@@ -45,6 +47,8 @@ obj-$(CONFIG_SBC82xx) += sbc82xx.o
obj-$(CONFIG_SPRUCE) += spruce.o
obj-$(CONFIG_LITE5200) += lite5200.o
obj-$(CONFIG_EV64360) += ev64360.o
+obj-$(CONFIG_MPC86XADS) += mpc866ads_setup.o
+obj-$(CONFIG_MPC885ADS) += mpc885ads_setup.o
ifeq ($(CONFIG_SMP),y)
obj-$(CONFIG_PPC_PMAC) += pmac_smp.o
diff --git a/arch/ppc/platforms/fads.h b/arch/ppc/platforms/fads.h
index a48fb8d..e1c0b1b 100644
--- a/arch/ppc/platforms/fads.h
+++ b/arch/ppc/platforms/fads.h
@@ -112,7 +112,7 @@
/* CPM Ethernet through SCC1 or SCC2 */
-#ifdef CONFIG_SCC1_ENET /* Probably 860 variant */
+#if defined(CONFIG_SCC1_ENET) || defined(CONFIG_MPC8xx_SECOND_ETH_SCC1) /* Probably 860 variant */
/* Bits in parallel I/O port registers that have to be set/cleared
* to configure the pins for SCC1 use.
* TCLK - CLK1, RCLK - CLK2.
diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/platforms/mpc8272ads_setup.c
new file mode 100644
index 0000000..4f76b1b
--- /dev/null
+++ b/arch/ppc/platforms/mpc8272ads_setup.c
@@ -0,0 +1,253 @@
+/*
+ * arch/ppc/platforms/82xx/pq2ads_pd.c
+ *
+ * MPC82xx Board-specific PlatformDevice descriptions
+ *
+ * 2005 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <linux/fs_enet_pd.h>
+
+#include <asm/io.h>
+#include <asm/mpc8260.h>
+#include <asm/cpm2.h>
+#include <asm/immap_cpm2.h>
+#include <asm/irq.h>
+#include <asm/ppc_sys.h>
+#include <asm/ppcboot.h>
+
+#include "pq2ads_pd.h"
+
+static void init_fcc1_ioports(void);
+static void init_fcc2_ioports(void);
+
+static struct fs_mii_bus_info mii_bus_info = {
+ .method = fsmii_bitbang,
+ .id = 0,
+ .i.bitbang = {
+ .mdio_port = fsiop_portc,
+ .mdio_bit = 18,
+ .mdc_port = fsiop_portc,
+ .mdc_bit = 19,
+ .delay = 1,
+ },
+};
+
+static struct fs_platform_info mpc82xx_fcc1_pdata = {
+ .fs_no = fsid_fcc1,
+ .cp_page = CPM_CR_FCC1_PAGE,
+ .cp_block = CPM_CR_FCC1_SBLOCK,
+ .clk_trx = (PC_F1RXCLK | PC_F1TXCLK),
+ .clk_route = CMX1_CLK_ROUTE,
+ .clk_mask = CMX1_CLK_MASK,
+ .init_ioports = init_fcc1_ioports,
+
+ .phy_addr = 0,
+#ifdef PHY_INTERRUPT
+ .phy_irq = PHY_INTERRUPT,
+#else
+ .phy_irq = -1;
+#endif
+ .mem_offset = FCC1_MEM_OFFSET,
+ .bus_info = &mii_bus_info,
+ .rx_ring = 32,
+ .tx_ring = 32,
+ .rx_copybreak = 240,
+ .use_napi = 0,
+ .napi_weight = 17,
+};
+
+static struct fs_platform_info mpc82xx_fcc2_pdata = {
+ .fs_no = fsid_fcc2,
+ .cp_page = CPM_CR_FCC2_PAGE,
+ .cp_block = CPM_CR_FCC2_SBLOCK,
+ .clk_trx = (PC_F2RXCLK | PC_F2TXCLK),
+ .clk_route = CMX2_CLK_ROUTE,
+ .clk_mask = CMX2_CLK_MASK,
+ .init_ioports = init_fcc2_ioports,
+
+ .phy_addr = 3,
+#ifdef PHY_INTERRUPT
+ .phy_irq = PHY_INTERRUPT,
+#else
+ .phy_irq = -1;
+#endif
+ .mem_offset = FCC2_MEM_OFFSET,
+ .bus_info = &mii_bus_info,
+ .rx_ring = 32,
+ .tx_ring = 32,
+ .rx_copybreak = 240,
+ .use_napi = 0,
+ .napi_weight = 17,
+};
+
+static void init_fcc1_ioports(void)
+{
+ struct io_port *io;
+ u32 tempval;
+ int i=0;
+ cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+ u32 *bcsr = ioremap(BCSR_ADDR+4, sizeof(u32));
+
+ io = &immap->im_ioport;
+
+ /* Enable the PHY */
+ clrbits32(bcsr, BCSR1_FETHIEN);
+ setbits32(bcsr, BCSR1_FETH_RST);
+
+ /* FCC1 pins are on port A/C. */
+ /* Configure port A and C pins for FCC1 Ethernet. */
+
+ tempval = in_be32(&io->iop_pdira);
+ tempval &= ~PA1_DIRA0;
+ tempval |= PA1_DIRA1;
+ out_be32(&io->iop_pdira, tempval);
+
+ tempval = in_be32(&io->iop_psora);
+ tempval &= ~PA1_PSORA0;
+ tempval |= PA1_PSORA1;
+ out_be32(&io->iop_psora, tempval);
+
+ setbits32(&io->iop_ppara,PA1_DIRA0 | PA1_DIRA1);
+
+ /* Alter clocks */
+ tempval = PC_F1TXCLK|PC_F1RXCLK;
+
+ clrbits32(&io->iop_psorc, tempval);
+ clrbits32(&io->iop_pdirc, tempval);
+ setbits32(&io->iop_pparc, tempval);
+
+ clrbits32(&immap->im_cpmux.cmx_fcr, CMX1_CLK_MASK);
+ setbits32(&immap->im_cpmux.cmx_fcr, CMX1_CLK_ROUTE);
+ iounmap(bcsr);
+ iounmap(immap);
+}
+
+static void init_fcc2_ioports(void)
+{
+ cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+ u32 *bcsr = ioremap(BCSR_ADDR+12, sizeof(u32));
+
+ struct io_port *io;
+ u32 tempval;
+
+ immap = cpm2_immr;
+
+ io = &immap->im_ioport;
+
+ /* Enable the PHY */
+ clrbits32(bcsr, BCSR3_FETHIEN2);
+ setbits32(bcsr, BCSR3_FETH2_RST);
+
+ /* FCC2 are port B/C. */
+ /* Configure port A and C pins for FCC2 Ethernet. */
+
+ tempval = in_be32(&io->iop_pdirb);
+ tempval &= ~PB2_DIRB0;
+ tempval |= PB2_DIRB1;
+ out_be32(&io->iop_pdirb, tempval);
+
+ tempval = in_be32(&io->iop_psorb);
+ tempval &= ~PB2_PSORB0;
+ tempval |= PB2_PSORB1;
+ out_be32(&io->iop_psorb, tempval);
+
+ setbits32(&io->iop_pparb,PB2_DIRB0 | PB2_DIRB1);
+
+ tempval = PC_F2RXCLK|PC_F2TXCLK;
+
+ /* Alter clocks */
+ clrbits32(&io->iop_psorc,tempval);
+ clrbits32(&io->iop_pdirc,tempval);
+ setbits32(&io->iop_pparc,tempval);
+
+ clrbits32(&immap->im_cpmux.cmx_fcr, CMX2_CLK_MASK);
+ setbits32(&immap->im_cpmux.cmx_fcr, CMX2_CLK_ROUTE);
+
+ iounmap(bcsr);
+ iounmap(immap);
+}
+
+
+static void __init mpc8272ads_fixup_enet_pdata(struct platform_device *pdev,
+ int idx)
+{
+ bd_t* bi = (void*)__res;
+ int fs_no = fsid_fcc1+pdev->id-1;
+
+ mpc82xx_fcc1_pdata.dpram_offset = mpc82xx_fcc2_pdata.dpram_offset = (u32)cpm2_immr->im_dprambase;
+ mpc82xx_fcc1_pdata.fcc_regs_c = mpc82xx_fcc2_pdata.fcc_regs_c = (u32)cpm2_immr->im_fcc_c;
+
+ switch(fs_no) {
+ case fsid_fcc1:
+ memcpy(&mpc82xx_fcc1_pdata.macaddr,bi->bi_enetaddr,6);
+ pdev->dev.platform_data = &mpc82xx_fcc1_pdata;
+ break;
+ case fsid_fcc2:
+ memcpy(&mpc82xx_fcc2_pdata.macaddr,bi->bi_enetaddr,6);
+ mpc82xx_fcc2_pdata.macaddr[5] ^= 1;
+ pdev->dev.platform_data = &mpc82xx_fcc2_pdata;
+ break;
+ }
+}
+
+static int __init mpc8272ads_platform_notify(struct device *dev)
+{
+ static struct {
+ const char *bus_id;
+ void (*rtn) (struct platform_device * pdev, int idx);
+ } dev_map[] = {
+ {"fsl-cpm-fcc", mpc8272ads_fixup_enet_pdata},
+ };
+ struct platform_device *pdev;
+ int i, j, idx;
+ const char *s;
+ if (dev && dev->bus_id)
+ for (i = 0; i < ARRAY_SIZE(dev_map); i++) {
+ idx = -1;
+
+ if ((s = strrchr(dev->bus_id, '.')) != NULL)
+ idx = (int)simple_strtol(s + 1, NULL, 10);
+ else
+ s = dev->bus_id;
+ j = s - dev->bus_id;
+ if (!strncmp(dev->bus_id, dev_map[i].bus_id, j)) {
+ pdev =
+ container_of(dev, struct platform_device,
+ dev);
+ dev_map[i].rtn(pdev, idx);
+ }
+ }
+ return 0;
+}
+
+int __init mpc8272ads_init(void)
+{
+ printk(KERN_NOTICE "mpc8272ads: Init\n");
+
+ platform_notify = mpc8272ads_platform_notify;
+
+ identify_ppc_sys_by_name_and_id(BOARD_CHIP_NAME, cpm2_immr->im_memctl.memc_immr);
+
+ /*Remove stuff does not utilized platform way*/
+ ppc_sys_device_remove(MPC82xx_CPM_SCC1);
+ ppc_sys_device_remove(MPC82xx_CPM_SCC2);
+ ppc_sys_device_remove(MPC82xx_CPM_SCC3);
+ ppc_sys_device_remove(MPC82xx_CPM_SCC4);
+ ppc_sys_device_remove(MPC82xx_CPM_SMC1);
+ ppc_sys_device_remove(MPC82xx_CPM_SMC2);
+
+ return 0;
+}
+
+arch_initcall(mpc8272ads_init);
diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/platforms/mpc866ads_setup.c
new file mode 100644
index 0000000..0809cf3
--- /dev/null
+++ b/arch/ppc/platforms/mpc866ads_setup.c
@@ -0,0 +1,283 @@
+/*arch/ppc/platforms/mpc885ads-setup.c
+ *
+ * Platform setup for the Freescale mpc885ads board
+ *
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * Copyright 2005 MontaVista Software Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+
+#include <linux/fs_enet_pd.h>
+#include <linux/mii.h>
+
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/ppcboot.h>
+#include <asm/8xx_immap.h>
+#include <asm/commproc.h>
+#include <asm/ppc_sys.h>
+#include <asm/mpc8xx.h>
+
+extern unsigned char __res[];
+
+static struct fs_mii_bus_info fec_mii_bus_info = {
+ .method = fsmii_fec,
+ .id = 0,
+};
+
+static struct fs_mii_bus_info scc_mii_bus_info = {
+ .method = fsmii_fixed,
+ .id = 0,
+ .i.fixed.speed = 10,
+ .i.fixed.duplex = 0,
+};
+
+static struct fs_platform_info mpc8xx_fec_pdata[] = {
+ {
+ .rx_ring = 128,
+ .tx_ring = 16,
+ .rx_copybreak = 240,
+
+ .use_napi = 1,
+ .napi_weight = 17,
+
+ .phy_addr = 15,
+ .phy_irq = -1,
+
+ .use_rmii = 0,
+
+ .bus_info = &fec_mii_bus_info,
+ }
+};
+
+static struct fs_platform_info mpc8xx_scc_pdata = {
+ .rx_ring = 64,
+ .tx_ring = 8,
+ .rx_copybreak = 240,
+
+ .use_napi = 1,
+ .napi_weight = 17,
+
+ .phy_addr = -1,
+ .phy_irq = -1,
+
+ .bus_info = &scc_mii_bus_info,
+};
+
+void __init board_init(void)
+{
+ volatile cpm8xx_t *cp = cpmp;
+ unsigned *bcsr_io;
+
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+ if (bcsr_io == NULL) {
+ printk(KERN_CRIT "Could not remap BCSR1\n");
+ return;
+ }
+#ifdef CONFIG_SERIAL_CPM_SMC1
+ cp->cp_simode &= ~(0xe0000000 >> 17); /* brg1 */
+ clrbits32(bcsr_io,(0x80000000 >> 7));
+#else
+ setbits32(bcsr_io,(0x80000000 >> 7));
+
+ cp->cp_pbpar &= ~(0x000000c0);
+ cp->cp_pbdir |= 0x000000c0;
+ cp->cp_smc[0].smc_smcmr = 0;
+ cp->cp_smc[0].smc_smce = 0;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SMC2
+ cp->cp_simode &= ~(0xe0000000 >> 1);
+ cp->cp_simode |= (0x20000000 >> 1); /* brg2 */
+ clrbits32(bcsr_io,(0x80000000 >> 13));
+#else
+ clrbits32(bcsr_io,(0x80000000 >> 13));
+ cp->cp_pbpar &= ~(0x00000c00);
+ cp->cp_pbdir |= 0x00000c00;
+ cp->cp_smc[1].smc_smcmr = 0;
+ cp->cp_smc[1].smc_smce = 0;
+#endif
+ iounmap(bcsr_io);
+}
+
+static void setup_fec1_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+
+ setbits16(&immap->im_ioport.iop_pdpar, 0x1fff);
+ setbits16(&immap->im_ioport.iop_pddir, 0x1fff);
+}
+
+static void setup_scc1_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+ unsigned *bcsr_io;
+
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+ if (bcsr_io == NULL) {
+ printk(KERN_CRIT "Could not remap BCSR1\n");
+ return;
+ }
+
+ /* Enable the PHY.
+ */
+ clrbits32(bcsr_io,BCSR1_ETHEN);
+
+ /* Configure port A pins for Txd and Rxd.
+ */
+ /* Disable receive and transmit in case EPPC-Bug started it.
+ */
+ setbits16(&immap->im_ioport.iop_papar, PA_ENET_RXD | PA_ENET_TXD);
+ clrbits16(&immap->im_ioport.iop_padir, PA_ENET_RXD | PA_ENET_TXD);
+ clrbits16(&immap->im_ioport.iop_paodr, PA_ENET_TXD);
+
+ /* Configure port C pins to enable CLSN and RENA.
+ */
+ clrbits16(&immap->im_ioport.iop_pcpar, PC_ENET_CLSN | PC_ENET_RENA);
+ clrbits16(&immap->im_ioport.iop_pcdir, PC_ENET_CLSN | PC_ENET_RENA);
+ setbits16(&immap->im_ioport.iop_pcso, PC_ENET_CLSN | PC_ENET_RENA);
+ /* Configure port A for TCLK and RCLK.
+ */
+ setbits16(&immap->im_ioport.iop_papar, PA_ENET_TCLK | PA_ENET_RCLK);
+ clrbits16(&immap->im_ioport.iop_padir, PA_ENET_TCLK | PA_ENET_RCLK);
+ clrbits32(&immap->im_cpm.cp_pbpar, PB_ENET_TENA);
+ clrbits32(&immap->im_cpm.cp_pbdir, PB_ENET_TENA);
+
+ /* Configure Serial Interface clock routing.
+ * First, clear all SCC bits to zero, then set the ones we want.
+ */
+ clrbits32(&immap->im_cpm.cp_sicr, SICR_ENET_MASK);
+ setbits32(&immap->im_cpm.cp_sicr, SICR_ENET_CLKRT);
+
+ /* In the original SCC enet driver the following code is placed at
+ the end of the initialization */
+ setbits32(&immap->im_cpm.cp_pbpar, PB_ENET_TENA);
+ setbits32(&immap->im_cpm.cp_pbdir, PB_ENET_TENA);
+
+}
+
+static void mpc866ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
+{
+ struct fs_platform_info *fpi = pdev->dev.platform_data;
+
+ volatile cpm8xx_t *cp;
+ bd_t *bd = (bd_t *) __res;
+ char *e;
+ int i;
+
+ /* Get pointer to Communication Processor */
+ cp = cpmp;
+ switch (fs_no) {
+ case fsid_fec1:
+ fpi = &mpc8xx_fec_pdata[0];
+ fpi->init_ioports = &setup_fec1_ioports;
+
+ break;
+ case fsid_scc1:
+ fpi = &mpc8xx_scc_pdata;
+ fpi->init_ioports = &setup_scc1_ioports;
+
+ break;
+ default:
+ break;
+ }
+
+ pdev->dev.platform_data = fpi;
+ fpi->fs_no = fs_no;
+
+ e = (unsigned char *)&bd->bi_enetaddr;
+ for (i = 0; i < 6; i++)
+ fpi->macaddr[i] = *e++;
+
+ fpi->macaddr[5 - pdev->id]++;
+
+}
+
+static void mpc866ads_fixup_fec_enet_pdata(struct platform_device *pdev,
+ int idx)
+{
+ /* This is for FEC devices only */
+ if (strcmp(pdev->name, "fsl-cpm-fec"))
+ return;
+ mpc866ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
+}
+
+static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
+ int idx)
+{
+ /* This is for SCC devices only */
+ if (strcmp(pdev->name, "fsl-cpm-scc"))
+ return;
+
+ mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
+}
+
+static int mpc866ads_platform_notify(struct device *dev)
+{
+ static struct {
+ const char *bus_id;
+ void (*rtn) (struct platform_device * pdev, int idx);
+ } dev_map[] = {
+ {
+ "fsl-cpm-fec", mpc866ads_fixup_fec_enet_pdata}, {
+ "fsl-cpm-scc", mpc866ads_fixup_scc_enet_pdata},};
+ struct platform_device *pdev;
+ int i, j, idx;
+ const char *s;
+ if (dev && dev->bus_id)
+ for (i = 0; i < ARRAY_SIZE(dev_map); i++) {
+ idx = -1;
+
+ if ((s = strrchr(dev->bus_id, '.')) != NULL)
+ idx = (int)simple_strtol(s + 1, NULL, 10);
+ else
+ s = dev->bus_id;
+ j = s - dev->bus_id;
+ if (!strncmp(dev->bus_id, dev_map[i].bus_id, j)) {
+ pdev =
+ container_of(dev, struct platform_device,
+ dev);
+ dev_map[i].rtn(pdev, idx);
+ }
+ }
+ return 0;
+}
+
+int __init mpc866ads_init(void)
+{
+ printk(KERN_NOTICE "mpc866ads: Init\n");
+
+ platform_notify = mpc866ads_platform_notify;
+
+ identify_ppc_sys_by_name(BOARD_CHIP_NAME);
+
+ ppc_sys_device_remove(MPC8xx_CPM_FEC2);
+ ppc_sys_device_remove(MPC8xx_CPM_SCC3);
+ ppc_sys_device_remove(MPC8xx_CPM_SCC2);
+ ppc_sys_device_remove(MPC8xx_CPM_SCC4);
+ ppc_sys_device_remove(MPC8xx_CPM_SMC1);
+ ppc_sys_device_remove(MPC8xx_CPM_SMC2);
+
+ return 0;
+}
+
+arch_initcall(mpc866ads_init);
diff --git a/arch/ppc/platforms/mpc885ads_setup.c b/arch/ppc/platforms/mpc885ads_setup.c
new file mode 100644
index 0000000..5e72f64
--- /dev/null
+++ b/arch/ppc/platforms/mpc885ads_setup.c
@@ -0,0 +1,400 @@
+/*arch/ppc/platforms/mpc885ads-setup.c
+ *
+ * Platform setup for the Freescale mpc885ads board
+ *
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * Copyright 2005 MontaVista Software Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+
+#include <linux/fs_enet_pd.h>
+#include <linux/mii.h>
+
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/ppcboot.h>
+#include <asm/8xx_immap.h>
+#include <asm/commproc.h>
+#include <asm/ppc_sys.h>
+
+extern unsigned char __res[];
+
+static void __init mpc885ads_scc_phy_init(char);
+
+static struct fs_mii_bus_info fec_mii_bus_info = {
+ .method = fsmii_fec,
+ .id = 0,
+};
+
+static struct fs_mii_bus_info scc_mii_bus_info = {
+#ifdef CONFIG_SCC_ENET_8xx_FIXED
+ .method = fsmii_fixed,
+#else
+ .method = fsmii_fec,
+#endif
+
+ .id = 0,
+};
+
+static struct fs_platform_info mpc8xx_fec_pdata[] = {
+ {
+ .rx_ring = 128,
+ .tx_ring = 16,
+ .rx_copybreak = 240,
+
+ .use_napi = 1,
+ .napi_weight = 17,
+
+ .phy_addr = 0,
+ .phy_irq = SIU_IRQ7,
+
+ .bus_info = &fec_mii_bus_info,
+ }, {
+ .rx_ring = 128,
+ .tx_ring = 16,
+ .rx_copybreak = 240,
+
+ .use_napi = 1,
+ .napi_weight = 17,
+
+ .phy_addr = 1,
+ .phy_irq = SIU_IRQ7,
+
+ .bus_info = &fec_mii_bus_info,
+ }
+};
+
+static struct fs_platform_info mpc8xx_scc_pdata = {
+ .rx_ring = 64,
+ .tx_ring = 8,
+ .rx_copybreak = 240,
+
+ .use_napi = 1,
+ .napi_weight = 17,
+
+ .phy_addr = 2,
+#ifdef CONFIG_MPC8xx_SCC_ENET_FIXED
+ .phy_irq = -1,
+#else
+ .phy_irq = SIU_IRQ7,
+#endif
+
+ .bus_info = &scc_mii_bus_info,
+};
+
+void __init board_init(void)
+{
+ volatile cpm8xx_t *cp = cpmp;
+ unsigned int *bcsr_io;
+
+#ifdef CONFIG_FS_ENET
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+#endif
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+ if (bcsr_io == NULL) {
+ printk(KERN_CRIT "Could not remap BCSR\n");
+ return;
+ }
+#ifdef CONFIG_SERIAL_CPM_SMC1
+ cp->cp_simode &= ~(0xe0000000 >> 17); /* brg1 */
+ clrbits32(bcsr_io, BCSR1_RS232EN_1);
+#else
+ setbits32(bcsr_io,BCSR1_RS232EN_1);
+ cp->cp_smc[0].smc_smcmr = 0;
+ cp->cp_smc[0].smc_smce = 0;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SMC2
+ cp->cp_simode &= ~(0xe0000000 >> 1);
+ cp->cp_simode |= (0x20000000 >> 1); /* brg2 */
+ clrbits32(bcsr_io,BCSR1_RS232EN_2);
+#else
+ setbits32(bcsr_io,BCSR1_RS232EN_2);
+ cp->cp_smc[1].smc_smcmr = 0;
+ cp->cp_smc[1].smc_smce = 0;
+#endif
+ iounmap(bcsr_io);
+
+#ifdef CONFIG_FS_ENET
+ /* use MDC for MII (common) */
+ setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
+ clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
+#endif
+}
+
+static void setup_fec1_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+
+ /* configure FEC1 pins */
+ setbits16(&immap->im_ioport.iop_papar, 0xf830);
+ setbits16(&immap->im_ioport.iop_padir, 0x0830);
+ clrbits16(&immap->im_ioport.iop_padir, 0xf000);
+ setbits32(&immap->im_cpm.cp_pbpar, 0x00001001);
+
+ clrbits32(&immap->im_cpm.cp_pbdir, 0x00001001);
+ setbits16(&immap->im_ioport.iop_pcpar, 0x000c);
+ clrbits16(&immap->im_ioport.iop_pcdir, 0x000c);
+ setbits32(&immap->im_cpm.cp_pepar, 0x00000003);
+
+ setbits32(&immap->im_cpm.cp_pedir, 0x00000003);
+ clrbits32(&immap->im_cpm.cp_peso, 0x00000003);
+ clrbits32(&immap->im_cpm.cp_cptr, 0x00000100);
+}
+
+static void setup_fec2_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+
+ /* configure FEC2 pins */
+ setbits32(&immap->im_cpm.cp_pepar, 0x0003fffc);
+ setbits32(&immap->im_cpm.cp_pedir, 0x0003fffc);
+ setbits32(&immap->im_cpm.cp_peso, 0x00037800);
+ clrbits32(&immap->im_cpm.cp_peso, 0x000087fc);
+ clrbits32(&immap->im_cpm.cp_cptr, 0x00000080);
+}
+
+static void setup_scc3_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+ unsigned *bcsr_io;
+
+ bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE);
+
+ if (bcsr_io == NULL) {
+ printk(KERN_CRIT "Could not remap BCSR\n");
+ return;
+ }
+
+ /* Enable the PHY.
+ */
+ setbits32(bcsr_io+4, BCSR4_ETH10_RST);
+ /* Configure port A pins for Txd and Rxd.
+ */
+ setbits16(&immap->im_ioport.iop_papar, PA_ENET_RXD | PA_ENET_TXD);
+ clrbits16(&immap->im_ioport.iop_padir, PA_ENET_RXD | PA_ENET_TXD);
+
+ /* Configure port C pins to enable CLSN and RENA.
+ */
+ clrbits16(&immap->im_ioport.iop_pcpar, PC_ENET_CLSN | PC_ENET_RENA);
+ clrbits16(&immap->im_ioport.iop_pcdir, PC_ENET_CLSN | PC_ENET_RENA);
+ setbits16(&immap->im_ioport.iop_pcso, PC_ENET_CLSN | PC_ENET_RENA);
+
+ /* Configure port E for TCLK and RCLK.
+ */
+ setbits32(&immap->im_cpm.cp_pepar, PE_ENET_TCLK | PE_ENET_RCLK);
+ clrbits32(&immap->im_cpm.cp_pepar, PE_ENET_TENA);
+ clrbits32(&immap->im_cpm.cp_pedir,
+ PE_ENET_TCLK | PE_ENET_RCLK | PE_ENET_TENA);
+ clrbits32(&immap->im_cpm.cp_peso, PE_ENET_TCLK | PE_ENET_RCLK);
+ setbits32(&immap->im_cpm.cp_peso, PE_ENET_TENA);
+
+ /* Configure Serial Interface clock routing.
+ * First, clear all SCC bits to zero, then set the ones we want.
+ */
+ clrbits32(&immap->im_cpm.cp_sicr, SICR_ENET_MASK);
+ setbits32(&immap->im_cpm.cp_sicr, SICR_ENET_CLKRT);
+
+ /* Disable Rx and Tx. SMC1 sshould be stopped if SCC3 eternet are used.
+ */
+ immap->im_cpm.cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+ /* On the MPC885ADS SCC ethernet PHY is initialized in the full duplex mode
+ * by H/W setting after reset. SCC ethernet controller support only half duplex.
+ * This discrepancy of modes causes a lot of carrier lost errors.
+ */
+
+ /* In the original SCC enet driver the following code is placed at
+ the end of the initialization */
+ setbits32(&immap->im_cpm.cp_pepar, PE_ENET_TENA);
+ clrbits32(&immap->im_cpm.cp_pedir, PE_ENET_TENA);
+ setbits32(&immap->im_cpm.cp_peso, PE_ENET_TENA);
+
+ setbits32(bcsr_io+1, BCSR1_ETHEN);
+ iounmap(bcsr_io);
+}
+
+static void mpc885ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
+{
+ struct fs_platform_info *fpi = pdev->dev.platform_data;
+
+ volatile cpm8xx_t *cp;
+ bd_t *bd = (bd_t *) __res;
+ char *e;
+ int i;
+
+ /* Get pointer to Communication Processor */
+ cp = cpmp;
+ switch (fs_no) {
+ case fsid_fec1:
+ fpi = &mpc8xx_fec_pdata[0];
+ fpi->init_ioports = &setup_fec1_ioports;
+ break;
+ case fsid_fec2:
+ fpi = &mpc8xx_fec_pdata[1];
+ fpi->init_ioports = &setup_fec2_ioports;
+ break;
+ case fsid_scc3:
+ fpi = &mpc8xx_scc_pdata;
+ fpi->init_ioports = &setup_scc3_ioports;
+ mpc885ads_scc_phy_init(fpi->phy_addr);
+ break;
+ default:
+ break;
+ }
+
+ pdev->dev.platform_data = fpi;
+ fpi->fs_no = fs_no;
+
+ e = (unsigned char *)&bd->bi_enetaddr;
+ for (i = 0; i < 6; i++)
+ fpi->macaddr[i] = *e++;
+
+ fpi->macaddr[5 - pdev->id]++;
+
+}
+
+static void mpc885ads_fixup_fec_enet_pdata(struct platform_device *pdev,
+ int idx)
+{
+ /* This is for FEC devices only */
+ if (!strstr(pdev->name, "fsl-cpm-fec"))
+ return;
+ mpc885ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
+}
+
+static void __init mpc885ads_fixup_scc_enet_pdata(struct platform_device *pdev,
+ int idx)
+{
+ /* This is for SCC devices only */
+ if (!strstr(pdev->name, "fsl-cpm-scc"))
+ return;
+
+ mpc885ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
+}
+
+/* SCC ethernet controller does not have MII management channel. FEC1 MII
+ * channel is used to communicate with the 10Mbit PHY.
+ */
+
+#define MII_ECNTRL_PINMUX 0x4
+#define FEC_ECNTRL_PINMUX 0x00000004
+#define FEC_RCNTRL_MII_MODE 0x00000004
+
+/* Make MII read/write commands.
+ */
+#define mk_mii_write(REG, VAL, PHY_ADDR) (0x50020000 | (((REG) & 0x1f) << 18) | \
+ ((VAL) & 0xffff) | ((PHY_ADDR) << 23))
+
+static void mpc885ads_scc_phy_init(char phy_addr)
+{
+ volatile immap_t *immap;
+ volatile fec_t *fecp;
+ bd_t *bd;
+
+ bd = (bd_t *) __res;
+ immap = (immap_t *) IMAP_ADDR; /* pointer to internal registers */
+ fecp = &(immap->im_cpm.cp_fec);
+
+ /* Enable MII pins of the FEC1
+ */
+ setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
+ clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
+ /* Set MII speed to 2.5 MHz
+ */
+ out_be32(&fecp->fec_mii_speed,
+ ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1);
+
+ /* Enable FEC pin MUX
+ */
+ setbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX);
+ setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
+
+ out_be32(&fecp->fec_mii_data,
+ mk_mii_write(MII_BMCR, BMCR_ISOLATE, phy_addr));
+ udelay(100);
+ out_be32(&fecp->fec_mii_data,
+ mk_mii_write(MII_ADVERTISE,
+ ADVERTISE_10HALF | ADVERTISE_CSMA, phy_addr));
+ udelay(100);
+
+ /* Disable FEC MII settings
+ */
+ clrbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX);
+ clrbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
+ out_be32(&fecp->fec_mii_speed, 0);
+}
+
+static int mpc885ads_platform_notify(struct device *dev)
+{
+ static struct {
+ const char *bus_id;
+ void (*rtn) (struct platform_device * pdev, int idx);
+ } dev_map[] = {
+ {
+ "fsl-cpm-fec", mpc885ads_fixup_fec_enet_pdata}, {
+ "fsl-cpm-scc", mpc885ads_fixup_scc_enet_pdata},};
+ struct platform_device *pdev;
+ int i, j, idx;
+ const char *s;
+ if (dev && dev->bus_id)
+ for (i = 0; i < ARRAY_SIZE(dev_map); i++) {
+ idx = -1;
+
+ if ((s = strrchr(dev->bus_id, '.')) != NULL)
+ idx = (int)simple_strtol(s + 1, NULL, 10);
+ else
+ s = dev->bus_id;
+ j = s - dev->bus_id;
+ if (!strncmp(dev->bus_id, dev_map[i].bus_id, j)) {
+ pdev =
+ container_of(dev, struct platform_device,
+ dev);
+ dev_map[i].rtn(pdev, idx);
+ }
+ }
+ return 0;
+}
+
+int __init mpc885ads_init(void)
+{
+ printk(KERN_NOTICE "mpc885ads: Init\n");
+
+ platform_notify = mpc885ads_platform_notify;
+
+ identify_ppc_sys_by_name(BOARD_CHIP_NAME);
+
+#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3
+ ppc_sys_device_remove(MPC8xx_CPM_FEC2);
+#endif
+#ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
+ ppc_sys_device_remove(MPC8xx_CPM_SCC3);
+#endif
+
+ ppc_sys_device_remove(MPC8xx_CPM_SCC1);
+ ppc_sys_device_remove(MPC8xx_CPM_SCC2);
+ ppc_sys_device_remove(MPC8xx_CPM_SCC4);
+ ppc_sys_device_remove(MPC8xx_CPM_SMC1);
+ ppc_sys_device_remove(MPC8xx_CPM_SMC2);
+
+ return 0;
+}
+
+arch_initcall(mpc885ads_init);
diff --git a/arch/ppc/platforms/pq2ads.h b/arch/ppc/platforms/pq2ads.h
index 067d9a5..6b26dd3 100644
--- a/arch/ppc/platforms/pq2ads.h
+++ b/arch/ppc/platforms/pq2ads.h
@@ -13,6 +13,10 @@
#include <asm/ppcboot.h>
+#if defined(CONFIG_ADS8272)
+#define BOARD_CHIP_NAME "8272"
+#endif
+
/* Memory map is configured by the PROM startup.
* We just map a few things we need. The CSR is actually 4 byte-wide
* registers that can be accessed as 8-, 16-, or 32-bit values.
diff --git a/arch/ppc/platforms/pq2ads_pd.h b/arch/ppc/platforms/pq2ads_pd.h
new file mode 100644
index 0000000..5b5e92d
--- /dev/null
+++ b/arch/ppc/platforms/pq2ads_pd.h
@@ -0,0 +1,114 @@
+#ifndef __PQ2ADS_PD_H
+#define __PQ2ADS_PD_H
+/*
+ * arch/ppc/platforms/82xx/pq2ads_pd.h
+ *
+ * Some defines for MPC82xx board-specific PlatformDevice descriptions
+ *
+ * 2005 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/* FCC1 Clock Source Configuration. These can be redefined in the board specific file.
+ Can only choose from CLK9-12 */
+
+#define F1_RXCLK 11
+#define F1_TXCLK 10
+
+/* FCC2 Clock Source Configuration. These can be redefined in the board specific file.
+ Can only choose from CLK13-16 */
+#define F2_RXCLK 15
+#define F2_TXCLK 16
+
+/* FCC3 Clock Source Configuration. These can be redefined in the board specific file.
+ Can only choose from CLK13-16 */
+#define F3_RXCLK 13
+#define F3_TXCLK 14
+
+/* Automatically generates register configurations */
+#define PC_CLK(x) ((uint)(1<<(x-1))) /* FCC CLK I/O ports */
+
+#define CMXFCR_RF1CS(x) ((uint)((x-5)<<27)) /* FCC1 Receive Clock Source */
+#define CMXFCR_TF1CS(x) ((uint)((x-5)<<24)) /* FCC1 Transmit Clock Source */
+#define CMXFCR_RF2CS(x) ((uint)((x-9)<<19)) /* FCC2 Receive Clock Source */
+#define CMXFCR_TF2CS(x) ((uint)((x-9)<<16)) /* FCC2 Transmit Clock Source */
+#define CMXFCR_RF3CS(x) ((uint)((x-9)<<11)) /* FCC3 Receive Clock Source */
+#define CMXFCR_TF3CS(x) ((uint)((x-9)<<8)) /* FCC3 Transmit Clock Source */
+
+#define PC_F1RXCLK PC_CLK(F1_RXCLK)
+#define PC_F1TXCLK PC_CLK(F1_TXCLK)
+#define CMX1_CLK_ROUTE (CMXFCR_RF1CS(F1_RXCLK) | CMXFCR_TF1CS(F1_TXCLK))
+#define CMX1_CLK_MASK ((uint)0xff000000)
+
+#define PC_F2RXCLK PC_CLK(F2_RXCLK)
+#define PC_F2TXCLK PC_CLK(F2_TXCLK)
+#define CMX2_CLK_ROUTE (CMXFCR_RF2CS(F2_RXCLK) | CMXFCR_TF2CS(F2_TXCLK))
+#define CMX2_CLK_MASK ((uint)0x00ff0000)
+
+#define PC_F3RXCLK PC_CLK(F3_RXCLK)
+#define PC_F3TXCLK PC_CLK(F3_TXCLK)
+#define CMX3_CLK_ROUTE (CMXFCR_RF3CS(F3_RXCLK) | CMXFCR_TF3CS(F3_TXCLK))
+#define CMX3_CLK_MASK ((uint)0x0000ff00)
+
+/* I/O Pin assignment for FCC1. I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PA1_COL 0x00000001U
+#define PA1_CRS 0x00000002U
+#define PA1_TXER 0x00000004U
+#define PA1_TXEN 0x00000008U
+#define PA1_RXDV 0x00000010U
+#define PA1_RXER 0x00000020U
+#define PA1_TXDAT 0x00003c00U
+#define PA1_RXDAT 0x0003c000U
+#define PA1_PSORA0 (PA1_RXDAT | PA1_TXDAT)
+#define PA1_PSORA1 (PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
+ PA1_RXDV | PA1_RXER)
+#define PA1_DIRA0 (PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
+#define PA1_DIRA1 (PA1_TXDAT | PA1_TXEN | PA1_TXER)
+
+
+/* I/O Pin assignment for FCC2. I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PB2_TXER 0x00000001U
+#define PB2_RXDV 0x00000002U
+#define PB2_TXEN 0x00000004U
+#define PB2_RXER 0x00000008U
+#define PB2_COL 0x00000010U
+#define PB2_CRS 0x00000020U
+#define PB2_TXDAT 0x000003c0U
+#define PB2_RXDAT 0x00003c00U
+#define PB2_PSORB0 (PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
+ PB2_RXER | PB2_RXDV | PB2_TXER)
+#define PB2_PSORB1 (PB2_TXEN)
+#define PB2_DIRB0 (PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
+#define PB2_DIRB1 (PB2_TXDAT | PB2_TXEN | PB2_TXER)
+
+
+/* I/O Pin assignment for FCC3. I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PB3_RXDV 0x00004000U
+#define PB3_RXER 0x00008000U
+#define PB3_TXER 0x00010000U
+#define PB3_TXEN 0x00020000U
+#define PB3_COL 0x00040000U
+#define PB3_CRS 0x00080000U
+#define PB3_TXDAT 0x0f000000U
+#define PB3_RXDAT 0x00f00000U
+#define PB3_PSORB0 (PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
+ PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
+#define PB3_PSORB1 0
+#define PB3_DIRB0 (PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
+#define PB3_DIRB1 (PB3_TXDAT | PB3_TXEN | PB3_TXER)
+
+#define FCC_MEM_OFFSET(x) (CPM_FCC_SPECIAL_BASE + (x*128))
+#define FCC1_MEM_OFFSET FCC_MEM_OFFSET(0)
+#define FCC2_MEM_OFFSET FCC_MEM_OFFSET(1)
+
+#endif
^ permalink raw reply related
* [PATCH] ppc32 8xx: Added setbitsXX/clrbitsXX macro for read-modify-write operations
From: Vitaly Bordug @ 2005-11-28 15:34 UTC (permalink / raw)
To: Marcelo Tosatti; +Cc: linuxppc-devel list, linuxppc-embedded list
This adds setbitsXX/clrbitsXX macro for read-modify-write operations
and converts the 8xx core and drivers to use it.
Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
---
arch/ppc/8xx_io/commproc.c | 6 +++---
arch/ppc/syslib/m8xx_setup.c | 12 +++++-------
arch/ppc/syslib/m8xx_wdt.c | 3 +--
include/asm-ppc/io.h | 7 +++++++
4 files changed, 16 insertions(+), 12 deletions(-)
applies-to: d2cd86c706af9e6ad47e2dda6b24df0d93f6f98f
055cb7782e10f214243c31522229173660cb24bc
diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c
index 579cd40..5cecb6e 100644
--- a/arch/ppc/8xx_io/commproc.c
+++ b/arch/ppc/8xx_io/commproc.c
@@ -73,7 +73,7 @@ cpm_mask_irq(unsigned int irq)
{
int cpm_vec = irq - CPM_IRQ_OFFSET;
- out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr, in_be32(&((immap_t
*)IMAP_ADDR)->im_cpic.cpic_cimr) & ~(1 << cpm_vec));
+ clrbits32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr,(1 << cpm_vec));
}
static void
@@ -81,7 +81,7 @@ cpm_unmask_irq(unsigned int irq)
{
int cpm_vec = irq - CPM_IRQ_OFFSET;
- out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr, in_be32(&((immap_t
*)IMAP_ADDR)->im_cpic.cpic_cimr) | (1 << cpm_vec));
+ setbits32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr,(1 << cpm_vec));
}
static void
@@ -198,7 +198,7 @@ cpm_interrupt_init(void)
if (setup_irq(CPM_IRQ_OFFSET + CPMVEC_ERROR, &cpm_error_irqaction))
panic("Could not allocate CPM error IRQ!");
- out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr, in_be32(&((immap_t
*)IMAP_ADDR)->im_cpic.cpic_cicr) | CICR_IEN);
+ setbits32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr, CICR_IEN);
}
/*
diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c
index 1cc3abe..ad7db45 100644
--- a/arch/ppc/syslib/m8xx_setup.c
+++ b/arch/ppc/syslib/m8xx_setup.c
@@ -149,8 +149,7 @@ void __init m8xx_calibrate_decr(void)
out_be32(&((immap_t *)IMAP_ADDR)->im_clkrstk.cark_sccrk, KAPWR_KEY);
/* Force all 8xx processors to use divide by 16 processor clock. */
- out_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr,
- in_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr)|0x02000000);
+ setbits32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr, 0x02000000);
/* Processor frequency is MHz.
* The value 'fp' is the number of decrementer ticks per second.
*/
@@ -184,10 +183,9 @@ void __init m8xx_calibrate_decr(void)
out_be32(&((immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk, KAPWR_KEY);
/* Disable the RTC one second and alarm interrupts. */
- out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, in_be16(&((immap_t
*)IMAP_ADDR)->im_sit.sit_rtcsc) & ~(RTCSC_SIE | RTCSC_ALE));
+ clrbits16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, (RTCSC_SIE | RTCSC_ALE));
/* Enable the RTC */
- out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, in_be16(&((immap_t
*)IMAP_ADDR)->im_sit.sit_rtcsc) | (RTCSC_RTF | RTCSC_RTE));
-
+ setbits16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, (RTCSC_RTF | RTCSC_RTE));
/* Enabling the decrementer also enables the timebase interrupts
* (or from the other point of view, to get decrementer interrupts
* we have to enable the timebase). The decrementer interrupt
@@ -232,8 +230,8 @@ m8xx_restart(char *cmd)
__volatile__ unsigned char dummy;
local_irq_disable();
- out_be32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr, in_be32(&((immap_t
*)IMAP_ADDR)->im_clkrst.car_plprcr) | 0x00000080);
+ setbits32(&((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr, 0x00000080);
/* Clear the ME bit in MSR to cause checkstop on machine check
*/
mtmsr(mfmsr() & ~0x1000);
@@ -303,8 +301,8 @@ m8xx_init_IRQ(void)
i8259_init(0);
/* The i8259 cascade interrupt must be level sensitive. */
- out_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel, in_be32(&((immap_t
*)IMAP_ADDR)->im_siu_conf.sc_siel & ~(0x80000000 >> ISA_BRIDGE_INT)));
+ clrbits32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel, (0x80000000 >> ISA_BRIDGE_INT));
if (setup_irq(ISA_BRIDGE_INT, &mbx_i8259_irqaction))
enable_irq(ISA_BRIDGE_INT);
#endif /* CONFIG_PCI */
diff --git a/arch/ppc/syslib/m8xx_wdt.c b/arch/ppc/syslib/m8xx_wdt.c
index a21632d..57f8b9f 100644
--- a/arch/ppc/syslib/m8xx_wdt.c
+++ b/arch/ppc/syslib/m8xx_wdt.c
@@ -40,8 +40,7 @@ static irqreturn_t m8xx_wdt_interrupt(in
m8xx_wdt_reset();
- out_be16(&imap->im_sit.sit_piscr, in_be16(&imap->im_sit.sit_piscr) | PISCR_PS); /* clear
irq */
-
+ setbits16(&imap->im_sit.sit_piscr, PISCR_PS);
return IRQ_HANDLED;
}
diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h
index 2bfdf9c..0ff4395 100644
--- a/include/asm-ppc/io.h
+++ b/include/asm-ppc/io.h
@@ -556,4 +556,11 @@ extern void pci_iounmap(struct pci_dev *
*/
#define xlate_dev_kmem_ptr(p) p
+/* access ports */
+#define setbits32(_addr, _v) out_be32((_addr), in_be32(_addr) | (_v))
+#define clrbits32(_addr, _v) out_be32((_addr), in_be32(_addr) & ~(_v))
+
+#define setbits16(_addr, _v) out_be16((_addr), in_be16(_addr) | (_v))
+#define clrbits16(_addr, _v) out_be16((_addr), in_be16(_addr) & ~(_v))
+
#endif /* __KERNEL__ */
---
Sincerely,
Vitaly
^ permalink raw reply related
* Joystick and Lite5200
From: Alan Carvalho @ 2005-11-28 15:27 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 6533 bytes --]
Hi all,
I am trying use Logitech WingMan Strike Force 3D on Lite5200 board. I am
using linux-2.6.14 Denx's tree, just selecting this options:
CONFIG_INPUT=y
CONFIG_INPUT_JOYDEV=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=y
and
CONFIG_USB_HID=y
CONFIG_USB_HIDINPUT=y
CONFIG_HID_FF=y
CONFIG_LOGITECH_FF=y
As my device ID is not listed in hid-ff.c and hid-lgff.c, then I mapped it:
drivers/usb/input/hid-ff.c :
{0x46d, 0xc285, hid_lgff_init}, // Logitech Wingman Strike Force 3d
drivers/usb/input/hid-lgff.c
{0x046d, 0xc285, ff_joystick},
(I need do it in the PC to force feedback work fine too)
But the problem is the driver is not working correctly, if I try open
/dev/input/event0 it return "No such device", but as you can see below
evbug.c show correctly all joystick events.
Suggestions?
Best regard,
Alan
/ # dmesg
...
usbmon: debugfs is not available
2005 April 22 USB 1.1 'Open' Host Controller (OHCI) Driver (PPC SOC)
block sizes: ed 64 td 64
initializing PPC-SOC USB Controller
ppc-soc-ohci ppc-soc-ohci: USB Host Controller
ppc-soc-ohci ppc-soc-ohci: new USB bus registered, assigned bus number 1
ppc-soc-ohci ppc-soc-ohci: irq 44, io mem 0xf0001000
ppc-soc-ohci ppc-soc-ohci: resetting from state 'reset', control = 0x0
ppc-soc-ohci ppc-soc-ohci: OHCI controller state
ppc-soc-ohci ppc-soc-ohci: OHCI 1.0, NO legacy support registers
ppc-soc-ohci ppc-soc-ohci: control 0x083 HCFS=operational CBSR=3
ppc-soc-ohci ppc-soc-ohci: cmdstatus 0x00000 SOC=0
ppc-soc-ohci ppc-soc-ohci: intrstatus 0x00000044 RHSC SF
ppc-soc-ohci ppc-soc-ohci: intrenable 0x8000001a MIE UE RD WDH
ppc-soc-ohci ppc-soc-ohci: hcca frame #0005
ppc-soc-ohci ppc-soc-ohci: roothub.a 02001202 POTPGT=2 NOCP NPS NDP=2(2)
ppc-soc-ohci ppc-soc-ohci: roothub.b 00000000 PPCM=0000 DR=0000
ppc-soc-ohci ppc-soc-ohci: roothub.status 00008000 DRWE
ppc-soc-ohci ppc-soc-ohci: roothub.portstatus [0] 0x00000100 PPS
ppc-soc-ohci ppc-soc-ohci: roothub.portstatus [1] 0x00000100 PPS
ppc-soc-ohci ppc-soc-ohci: created debug files
usb usb1: default language 0x0409
usb usb1: new device strings: Mfr=3, Product=2, SerialNumber=1
usb usb1: Product: USB Host Controller
usb usb1: Manufacturer: Linux 2.6.14 ohci_hcd
usb usb1: SerialNumber: PPC-SOC USB
usb usb1: adding 1-0:1.0 (config #1, interface 0)
hub 1-0:1.0: usb_probe_interface
hub 1-0:1.0: usb_probe_interface - got id
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected
hub 1-0:1.0: standalone hub
hub 1-0:1.0: ganged power switching
hub 1-0:1.0: global over-current protection
hub 1-0:1.0: power on to power good time: 4ms
hub 1-0:1.0: local power source is good
hub 1-0:1.0: no over-current condition exists
hub 1-0:1.0: enabling power on all ports
ohci_hcd: 2005 April 22 USB 1.1 'Open' Host Controller (OHCI) Driver (PCI)
ohci_hcd: block sizes: ed 64 td 64
usbcore: registered new driver usbhid
drivers/usb/input/hid-core.c: v2.6:USB HID core driver
hub 1-0:1.0: state 5 ports 2 chg 0000 evt 0000
Serial: MPC52xx PSC driver
ttyS0 at MMIO 0xf0002000 (irq = 39) is a MPC52xx PSC
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered
RAMDISK driver initialized: 64 RAM disks of 4096K size 1024 blocksize
eth0: Phy @ 0x0, type LXT971 (0x001378e2)
Generic platform RAM MTD, (c) 2004 Simtec Electronics
mice: PS/2 mouse device common for all mice
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 4096 (order: 2, 16384 bytes)
TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
TCP: Hash tables configured (established 4096 bind 4096)
TCP reno registered
TCP bic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
RAMDISK: Compressed image found at block 0
VFS: Mounted root (romfs filesystem) readonly.
Freeing unused kernel memory: 108k init
hub 1-0:1.0: state 5 ports 2 chg 0000 evt 0002
ppc-soc-ohci ppc-soc-ohci: GetStatus roothub.portstatus [0] = 0x00010301 CSC
LSDA PPS CCS
hub 1-0:1.0: port 1, status 0301, change 0001, 1.5 Mb/s
hub 1-0:1.0: debounce: port 1: total 100ms stable 100ms status 0x301
ppc-soc-ohci ppc-soc-ohci: GetStatus roothub.portstatus [0] = 0x00100303
PRSC LSDA PPS PES CCS
usb 1-1: new low speed USB device using ppc-soc-ohci and address 2
ppc-soc-ohci ppc-soc-ohci: GetStatus roothub.portstatus [0] = 0x00100303
PRSC LSDA PPS PES CCS
usb 1-1: skipped 1 descriptor after interface
usb 1-1: default language 0x0409
usb 1-1: new device strings: Mfr=4, Product=32, SerialNumber=0
usb 1-1: Product: WingMan Strike Force 3D
usb 1-1: Manufacturer: Logitech Inc.
usb 1-1: adding 1-1:1.0 (config #1, interface 0)
usbhid 1-1:1.0: usb_probe_interface
usbhid 1-1:1.0: usb_probe_interface - got id
drivers/usb/input/hid-core.c: timeout initializing reports
Force feedback for Logitech force feedback devices by Johann Deneux <
johann.deneux@it.uu.se>
input: Logitech Inc. WingMan Strike Force 3D//class/input as input0
evbug.c: Connected device: "Logitech Inc. WingMan Strike Force 3D",
usb-PPC-SOC USB-1/input0
input<7>evbug.c: Event. Dev: usb-PPC-SOC USB-1/input0, Type: 3, Code: 0,
Value: 620
evbug.c: Event. Dev: usb-PPC-SOC USB-1/input0, Type: 3, Code: 1, Value: 536
evbug.c: Event. Dev: usb-PPC-SOC USB-1/input0, Type: 3, Code: 5, Value: 140
evbug.c: Event. Dev: usb-PPC-SOC USB-1/input0, Type: 3, Code: 6, Value: 126
evbug.c: Event. Dev: usb-PPC-SOC USB-1/input0, Type: 0, Code: 0, Value: 0
: USB HID v1.00 Joystick [Logitech Inc. WingMan Strike Force 3D] on
usb-PPC-SOC USB-1
hub 1-0:1.0: state 5 ports 2 chg 0000 evt 0002
evbug.c: Event. Dev: usb-PPC-SOC USB-1/input0, Type: 3, Code: 0, Value: 619
evbug.c: Event. Dev: usb-PPC-SOC USB-1/input0, Type: 0, Code: 0, Value: 0
evbug.c: Event. Dev: usb-PPC-SOC USB-1/input0, Type: 3, Code: 5, Value: 141
evbug.c: Event. Dev: usb-PPC-SOC USB-1/input0, Type: 0, Code: 0, Value: 0
evbug.c: Event. Dev: usb-PPC-SOC USB-1/input0, Type: 3, Code: 0, Value: 618
evbug.c: Event. Dev: usb-PPC-SOC USB-1/input0, Type: 0, Code: 0, Value: 0
evbug.c: Event. Dev: usb-PPC-SOC USB-1/input0, Type: 3, Code: 0, Value: 624
evbug.c: Event. Dev: usb-PPC-SOC USB-1/input0, Type: 0, Code: 0, Value: 0
evbug.c: Event. Dev: usb-PPC-SOC USB-1/input0, Type: 3, Code: 0, Value: 618
evbug.c: Event. Dev: usb-PPC-SOC USB-1/input0, Type: 0, Code: 0, Value: 0
/ # cat /dev/input/event2
cat: /dev/input/event2: No such device
[-- Attachment #2: Type: text/html, Size: 7170 bytes --]
^ permalink raw reply
* Re: yosemite flash confusion
From: Wolfgang Denk @ 2005-11-28 14:54 UTC (permalink / raw)
To: Peter Fercher; +Cc: 'linux-ppc-embedded'
In-Reply-To: <006101c5f402$613ac2c0$dbe5fed4@scsad.scs.ch>
Dear Peter,
in message <006101c5f402$613ac2c0$dbe5fed4@scsad.scs.ch> you wrote:
>
> the yosemite (revision 1.1) i got has a 512 MBit Flash chip on it (S29GL512).
> u-boot 1.1.3 that came with it was configured to use only 32 Mbytes ???
Seems they installed an old version of U-Boot.
> when i try to use the u-boot.bin (newest from the denx homepage:
> ftp://ftp.denx.de/pub/u-boot/images/amcc/yosemite/) then i get:
> (reprogrammed using the yosemite.cfg that was mailed to this list some days ago)
> U-Boot 1.1.4 (Oct 24 2005 - 09:23:33)
...
> FLASH: 64 MB
> *** Warning - bad CRC, using default environment
This means you did not set up your environment and used "saveenv" to
store it. This also means that your MAC address is undefined.
...
> Net: No ethernet found.
...
> it sees the 64MB flash but somehow can't find the ethernet anymore..
> does anybody know what the problem is there ?
You forgot to set the MAC address...
Please set the "ethaddr" environment variable to define a valid MAC
address, then use "saveenv" to save it to flash, and then reset the
board...
BTW: this is off topic here. You should have posted on the
U-Boot-Users mailing list instead.
Best regards,
Wolfgang Denk
--
Software Engineering: Embedded and Realtime Systems, Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
Never put off until tomorrow what you can put off indefinitely.
^ permalink raw reply
* Re: [PATCH] ppc32 8xx: Added setbitsXX/clrbitsXX macro for read-modify-write operations (resend)
From: Marcelo Tosatti @ 2005-11-28 14:39 UTC (permalink / raw)
To: Vitaly Bordug; +Cc: linuxppc-devel list, linuxppc-embedded list
In-Reply-To: <438B45FE.5060003@ru.mvista.com>
On Mon, Nov 28, 2005 at 09:01:34PM +0300, Vitaly Bordug wrote:
> This adds setbitsXX/clrbitsXX macro for read-modify-write operations
> and converts the 8xx core and drivers to use them.
>
> Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
Looks good, thanks Vitaly.
^ permalink raw reply
* [RFC] add PHY support to AM79C874
From: Aristeu Sergio Rozanski Filho @ 2005-11-28 14:10 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 189 bytes --]
This is a simple port from old fec driver to PHY layer to support AMD
AM79C874 PHY.
As I don't have the hardware to test this, all kinds of feedback are
most welcome.
Thanks,
--
Aristeu
[-- Attachment #2: phy-add_am79c874_phy.patch --]
[-- Type: text/plain, Size: 2901 bytes --]
Index: testing/drivers/net/phy/Kconfig
===================================================================
--- testing.orig/drivers/net/phy/Kconfig 2005-11-25 15:26:38.000000000 -0200
+++ testing/drivers/net/phy/Kconfig 2005-11-25 15:28:55.000000000 -0200
@@ -53,5 +53,11 @@
---help---
Currently supports the cis8204
+config AMD_PHY
+ tristate "Drivers for the AMD PHYs"
+ depends on PHYLIB
+ ---help---
+ Currenty supports AM79C874
+
endmenu
Index: testing/drivers/net/phy/Makefile
===================================================================
--- testing.orig/drivers/net/phy/Makefile 2005-11-25 15:26:38.000000000 -0200
+++ testing/drivers/net/phy/Makefile 2005-11-25 15:26:56.000000000 -0200
@@ -8,3 +8,5 @@
obj-$(CONFIG_CICADA_PHY) += cicada.o
obj-$(CONFIG_LXT_PHY) += lxt.o
obj-$(CONFIG_QSEMI_PHY) += qsemi.o
+obj-$(CONFIG_AMD_PHY) += amd.o
+
Index: testing/drivers/net/phy/amd.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ testing/drivers/net/phy/amd.c 2005-11-28 11:39:34.000000000 -0200
@@ -0,0 +1,71 @@
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#define MII_AM79C874_MFR 16 /* Miscellaneous Features Register */
+#define MII_AM79C874_ICSR 17 /* Interrupt Control/Status Register */
+#define MII_AM79C874_DR 18 /* Diagnostic Register */
+#define MII_AM79C874_PMLR 19 /* Power Management & Loopback Register */
+#define MII_AM79C874_MCR 21 /* Mode Control Register */
+#define MII_AM79C874_DC 23 /* Disconnect Counter */
+#define MII_AM79C874_REC 24 /* Receiver Error Counter */
+
+static int am79c874_ack_interrupt(struct phy_device *phy)
+{
+ int err;
+
+ err = phy_read(phy, MII_AM79C874_ICSR);
+
+ if (err < 0)
+ return err;
+ return 0;
+}
+
+static int am79c874_config_intr(struct phy_device *phy)
+{
+ int err;
+
+ if (phy->interrupts == PHY_INTERRUPT_ENABLED)
+ err = phy_write(phy, MII_AM79C874_ICSR, 0xff00);
+ else
+ err = phy_write(phy, MII_AM79C874_ICSR, 0);
+
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static struct phy_driver am79c874 = {
+ .phy_id = 0x00022561,
+ .name = "AM79C874",
+ .phy_id_mask = 0x0fffffff,
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = am79c874_ack_interrupt,
+ .config_intr = am79c874_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static __init int am79c874_init(void)
+{
+ return phy_driver_register(&am79c874);
+}
+
+static __exit void am79c874_exit(void)
+{
+ phy_driver_unregister(&am79c874);
+}
+module_init(am79c874_init);
+module_exit(am79c874_exit);
+
^ permalink raw reply
* Re: kernel 2.6.14 on MPC8272ADS
From: Vitaly Bordug @ 2005-11-28 13:09 UTC (permalink / raw)
To: ihornberger; +Cc: linuxppc-embedded
In-Reply-To: <1133175485.30984.1.camel@iho.sysgo.com>
Ingo Hornberger wrote:
> Hi Bracha,
>
> I assume that you're using an 8xx!?
>
> This code isn't completely updated yet, but here is a small patch which
> should be more or less working...
>
There is a patch, that did what you are attempting to do below correct way.
mfspr(SPRN_IMMR) does not correctly identify the board, you need to define BOARD_CHIP_NAME
somewhere in board-specific code to get it defined. The <>_device.c and <>_sys.c pair is
in the linus git tree currently, and error message below will not appear even if
BOARD_CHIP_NAME is undefined.
You might want to try more recent kernel.
> regards,
> Ingo
>
> On Sun, 2005-11-27 at 12:22 +0200, Landau, Bracha wrote:
>> I'm trying to move to the latest kernel release from linux 2.6.13.4 on the MPC8272ADS board.
>> 2.6.13.4 works, but from 2.6.14 and up (I don't know where from 2.6.13.4 to 2.6.14 the problem starts) the kernel crashes on bootup with the message
>> "Kernel BUG in ppc_sys_init at arch/ppc/syslib/ppc_sys_init.c:131"
>> Anyone know how to fix this problem?
>>
>> _______________________________________________
>> Linuxppc-embedded mailing list
>> Linuxppc-embedded@ozlabs.org
>> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>>
>>
>> ------------------------------------------------------------------------
>>
>> diff -Nurb a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c
>> --- a/arch/ppc/syslib/m8xx_setup.c 2005-10-28 02:02:08.000000000 +0200
>> +++ b/arch/ppc/syslib/m8xx_setup.c 2005-11-25 11:11:03.000000000 +0100
>> @@ -82,7 +82,7 @@
>> ROOT_DEV = Root_HDA1; /* hda1 */
>> #endif
>>
>> -#ifdef CONFIG_BLK_DEV_INITRD
>> +#if defined(CONFIG_BLK_DEV_INITRD) || defined(CONFIG_EXTRACT_ROOTFS)
>> #if 0
>> ROOT_DEV = Root_FD0; /* floppy */
>> rd_prompt = 1;
>> @@ -389,7 +389,7 @@
>> m8xx_setup_pci_ptrs();
>> #endif
>>
>> -#ifdef CONFIG_BLK_DEV_INITRD
>> +#if defined(CONFIG_BLK_DEV_INITRD) || defined(CONFIG_EXTRACT_ROOTFS)
>> /* take care of initrd if we have one */
>> if ( r4 )
>> {
>> @@ -404,6 +404,15 @@
>> strcpy(cmd_line, (char *)(r6+KERNELBASE));
>> }
>>
>> + /*
>> + * Check if we are really on a Power QUICC CPU.
>> + * Note, that we do not halt the Kernel at this point,
>> + * because we won't get any output here otherwise.
>> + */
>> + if( (mfspr(SPRN_PVR) >> 16) != 0x0050 )
>> + printk( KERN_ERR "ERROR: %s: %d: Wrong CPU Type! (We assumed a Power QUICC CPU)\n" );
>> + identify_ppc_sys_by_id(mfspr(SPRN_IMMR));
>> +
>> ppc_md.setup_arch = m8xx_setup_arch;
>> ppc_md.show_percpuinfo = m8xx_show_percpuinfo;
>> ppc_md.irq_canonicalize = NULL;
>> diff -Nurb a/arch/ppc/syslib/mpc8xx_sys.c b/arch/ppc/syslib/mpc8xx_sys.c
>> --- a/arch/ppc/syslib/mpc8xx_sys.c 2005-10-28 02:02:08.000000000 +0200
>> +++ b/arch/ppc/syslib/mpc8xx_sys.c 2005-11-25 11:11:03.000000000 +0100
>> @@ -20,9 +20,16 @@
>>
>> struct ppc_sys_spec *cur_ppc_sys_spec;
>> struct ppc_sys_spec ppc_sys_specs[] = {
>> + /* The mpc85x and 86x, all have the system ID 0x00.
>> + * And as it seems that even the 885 has the ID 0x00,
>> + * I assume 0x00 for all MPC8XX systems.
>> + * For other cases, you should add a new entry above the
>> + * MPC8XX. You could use the first 8 bits to make
>> + * a more specific match for your system.
>> + */
>> {
>> - .ppc_sys_name = "MPC86X",
>> - .mask = 0xFFFFFFFF,
>> + .ppc_sys_name = "MPC8XX",
>> + .mask = 0x00FF0000,
>> .value = 0x00000000,
>> .num_devices = 2,
>> .device_list = (enum ppc_sys_devices[])
>>
>> ------------------------------------------------------------------------
>>
>> _______________________________________________
>> Linuxppc-embedded mailing list
>> Linuxppc-embedded@ozlabs.org
>> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
--
Sincerely,
Vitaly
^ permalink raw reply
* Re: kernel 2.6.14 on MPC8272ADS
From: Vitaly Bordug @ 2005-11-28 13:04 UTC (permalink / raw)
To: Landau, Bracha; +Cc: linuxppc-embedded list
In-Reply-To: <02AA386EB831044F8537A696BA785C7807645A@ILEX5.IL.NDS.COM>
Landau, Bracha wrote:
> I'm trying to move to the latest kernel release from linux 2.6.13.4 on the MPC8272ADS board.
> 2.6.13.4 works, but from 2.6.14 and up (I don't know where from 2.6.13.4 to 2.6.14 the problem starts) the kernel crashes on bootup with the message
> "Kernel BUG in ppc_sys_init at arch/ppc/syslib/ppc_sys_init.c:131"
> Anyone know how to fix this problem?
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
>
The patch that 'fix' it is currently ready, I am about to submit it today, after I'll
assure that nothing missed there.
--
Sincerely,
Vitaly
^ permalink raw reply
* RE: Badness in 2.6.15-rc1 on 8xx
From: Chris Down @ 2005-11-28 11:33 UTC (permalink / raw)
To: 'Joakim Tjernlund', linuxppc-embedded
In-Reply-To: <F6AD7E21CDF4E145A44F61F43EE6D9393FE1C7@tmnt04.transmode.se>
-----Original Message-----
From: Joakim Tjernlund [mailto:joakim.tjernlund@transmode.se]
Sent: 28 November 2005 10:53
To: Chris Down; linuxppc-embedded@ozlabs.org
Subject: RE: Badness in 2.6.15-rc1 on 8xx
> Anyone seen this when booting 2.6.15-rc1 on 8xx?
> Mount-cache hash table entries: 512
> Badness in dma_alloc_init at arch/ppc/kernel/dma-mapping.c:346
> Call trace:
> [c00039e8] check_bug_trap+0x80/0xa8
> [c0003c1c] program_check_exception+0x20c/0x480
> [c00031e0] ret_from_except_full+0x0/0x4c
> [c01b86b8] dma_alloc_init+0x40/0xcc
> [c000225c] init+0x8c/0x288
> [c00050ac] kernel_thread+0x44/0x60
> NET: Registered protocol family 16
> The kernel boots just fine into user space so it seems harmless, but I
> suspect it will bite me later.
>
>
> I am currently working with 2.6.15-rc1 on MPC852 and I am
> seeing a similar
> problem.
>
> Badness in dma_alloc_init at arch/ppc/kernel/dma-mapping.c:346
> Call trace:
> [c00036f8] check_bug_trap+0xa4/0xb8
> [c0003f9c] program_check_exception+0x2f0/0x4c4
> [c0003320] ret_from_except_full+0x0/0x4c
> [c024c530] dma_alloc_init+0x3c/0xbc
> [c0002280] init+0xbc/0x25c
> [c000538c] kernel_thread+0x44/0x60
>
> Have not had time to look at it yet, however I was not getting this on
> 2.6.11.
>
> Chris
Let me guess you have IMAP_ADDR set to 0xff000000? Then you need to
change
CONSISTENT_START to something else(like 0xffa00000). Its somwhere in the
Advanced setup.
Jocke
You are correct I do have IMAP_ADDR set to 0xff000000 and setting
CONSISTENT_START to 0xffa00000 solves the problem.
Chris
^ permalink raw reply
* Re: [PATCH] Make ARCH=ppc build again with new syscall path
From: David Woodhouse @ 2005-11-28 11:28 UTC (permalink / raw)
To: Wolfgang Denk; +Cc: linuxppc-dev
In-Reply-To: <20051128110146.ACD2E353F54@atlas.denx.de>
On Mon, 2005-11-28 at 12:01 +0100, Wolfgang Denk wrote:
> In message <1133172766.31573.14.camel@baythorne.infradead.org> you wrote:
> >
> > There's also a third option, which _encourages_ people to port their
> > platform without necessarily making it easier: just let arch/ppc break.
>
> Please don't. This is supposed to be a "stable" kernel tree.
I wouldn't advocate doing it just yet, but I don't think anyone really
expects to see arch/ppc continue until Linus announces 2.7.0. Setting a
cut-off of 2.6.17 or so, or perhaps a point in time when we officially
stop caring about it, would seem a sensible approach.
Neither did I suggest actively breaking it or removing it -- if you feel
strongly about keeping it then I'm sure Paul would accept your patches
to make it keep working, even after others have stopped bothering.
But I think the time and effort required to maintain arch/ppc in
perpetuity should be weighed up against that of just porting the
embedded platforms to arch/powerpc.
It's your choice, of course, but I personally don't think I'll be
submitting many more patches which take arch/ppc into account -- this
one was an exception because it was me who broke it, and it is still a
_little_ too early to be letting it break, IMO.
--
dwmw2
^ permalink raw reply
* Re: kernel 2.6.14 on MPC8272ADS
From: Ingo Hornberger @ 2005-11-28 10:58 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <02AA386EB831044F8537A696BA785C7807645A@ILEX5.IL.NDS.COM>
[-- Attachment #1: Type: text/plain, Size: 760 bytes --]
Hi Bracha,
I assume that you're using an 8xx!?
This code isn't completely updated yet, but here is a small patch which
should be more or less working...
regards,
Ingo
On Sun, 2005-11-27 at 12:22 +0200, Landau, Bracha wrote:
> I'm trying to move to the latest kernel release from linux 2.6.13.4 on the MPC8272ADS board.
> 2.6.13.4 works, but from 2.6.14 and up (I don't know where from 2.6.13.4 to 2.6.14 the problem starts) the kernel crashes on bootup with the message
> "Kernel BUG in ppc_sys_init at arch/ppc/syslib/ppc_sys_init.c:131"
> Anyone know how to fix this problem?
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
[-- Attachment #2: ppc_8xx_2.6.14_syslib.patch --]
[-- Type: text/x-patch, Size: 2326 bytes --]
diff -Nurb a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c
--- a/arch/ppc/syslib/m8xx_setup.c 2005-10-28 02:02:08.000000000 +0200
+++ b/arch/ppc/syslib/m8xx_setup.c 2005-11-25 11:11:03.000000000 +0100
@@ -82,7 +82,7 @@
ROOT_DEV = Root_HDA1; /* hda1 */
#endif
-#ifdef CONFIG_BLK_DEV_INITRD
+#if defined(CONFIG_BLK_DEV_INITRD) || defined(CONFIG_EXTRACT_ROOTFS)
#if 0
ROOT_DEV = Root_FD0; /* floppy */
rd_prompt = 1;
@@ -389,7 +389,7 @@
m8xx_setup_pci_ptrs();
#endif
-#ifdef CONFIG_BLK_DEV_INITRD
+#if defined(CONFIG_BLK_DEV_INITRD) || defined(CONFIG_EXTRACT_ROOTFS)
/* take care of initrd if we have one */
if ( r4 )
{
@@ -404,6 +404,15 @@
strcpy(cmd_line, (char *)(r6+KERNELBASE));
}
+ /*
+ * Check if we are really on a Power QUICC CPU.
+ * Note, that we do not halt the Kernel at this point,
+ * because we won't get any output here otherwise.
+ */
+ if( (mfspr(SPRN_PVR) >> 16) != 0x0050 )
+ printk( KERN_ERR "ERROR: %s: %d: Wrong CPU Type! (We assumed a Power QUICC CPU)\n" );
+ identify_ppc_sys_by_id(mfspr(SPRN_IMMR));
+
ppc_md.setup_arch = m8xx_setup_arch;
ppc_md.show_percpuinfo = m8xx_show_percpuinfo;
ppc_md.irq_canonicalize = NULL;
diff -Nurb a/arch/ppc/syslib/mpc8xx_sys.c b/arch/ppc/syslib/mpc8xx_sys.c
--- a/arch/ppc/syslib/mpc8xx_sys.c 2005-10-28 02:02:08.000000000 +0200
+++ b/arch/ppc/syslib/mpc8xx_sys.c 2005-11-25 11:11:03.000000000 +0100
@@ -20,9 +20,16 @@
struct ppc_sys_spec *cur_ppc_sys_spec;
struct ppc_sys_spec ppc_sys_specs[] = {
+ /* The mpc85x and 86x, all have the system ID 0x00.
+ * And as it seems that even the 885 has the ID 0x00,
+ * I assume 0x00 for all MPC8XX systems.
+ * For other cases, you should add a new entry above the
+ * MPC8XX. You could use the first 8 bits to make
+ * a more specific match for your system.
+ */
{
- .ppc_sys_name = "MPC86X",
- .mask = 0xFFFFFFFF,
+ .ppc_sys_name = "MPC8XX",
+ .mask = 0x00FF0000,
.value = 0x00000000,
.num_devices = 2,
.device_list = (enum ppc_sys_devices[])
^ permalink raw reply
* RE: Badness in 2.6.15-rc1 on 8xx
From: Ingo Hornberger @ 2005-11-28 10:57 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <TMNT04vAauNjVuMhvqg000000ab@tmnt04.transmode.se>
Hi Joakim,
I was recently faced with the same problem. It's right that it boots
fine into user land. But the bad 'consistent' start address would cause
trouble as soon as you try to initiate some dma transfer.
It is configurable under [Advanced setup].
I now use a value, seen on another 8xx board (it was some siemens board)
which was 0xf0000000. It works just fine.
As far as I understood the exact address isn't important, only that it
is unused in the kernel.
regards,
Ingo
On Fri, 2005-11-25 at 22:41 +0100, Joakim Tjernlund wrote:
> >
> > > -----Original Message-----
> > > From: linuxppc-embedded-bounces@ozlabs.org
> > > [mailto:linuxppc-embedded-bounces@ozlabs.org] On Behalf Of
> > > Joakim Tjernlund
> > > Sent: Freitag, 25. November 2005 14:28
> > > To: linuxppc-embedded@ozlabs.org
> > > Subject: Badness in 2.6.15-rc1 on 8xx
> > >
> > > Anyone seen this when booting 2.6.15-rc1 on 8xx?
> > > Mount-cache hash table entries: 512
> > > Badness in dma_alloc_init at arch/ppc/kernel/dma-mapping.c:346
> > > Call trace:
> > > [c00039e8] check_bug_trap+0x80/0xa8
> > > [c0003c1c] program_check_exception+0x20c/0x480
> > > [c00031e0] ret_from_except_full+0x0/0x4c
> > > [c01b86b8] dma_alloc_init+0x40/0xcc
> > > [c000225c] init+0x8c/0x288
> > > [c00050ac] kernel_thread+0x44/0x60
> > > NET: Registered protocol family 16
> > > The kernel boots just fine into user space so it seems
> > > harmless, but I suspect it will bite me later.
> > >
> > > Something anoying:
> > > Why did the new cpm_uart driver change major and minor number
> > > for the tty?
> > > As it is now I can't boot my 2.4 rootfs as init think it
> > > should find the console on ttyS0.
> > > Would be great if major and minor could be configurable.
> > Because it's a new driver...with a new name (ttyCPM0) and a new
> > device number. It shared the device number and name in 2.4
> > with the "standard" device driver (8250/16550), and that made
> > it very difficult to use both in 2.4.
>
> To me it makes more sense to let a major number represent a function, not a driver.
> Shouldn't be that hard to make these drivers cooperate wrt. minor number.
>
> To allow for easy customization one could instead do:
> #ifndef SERIAL_CPM_MAJOR
> #define SERIAL_CPM_MAJOR 204
> #endif
> #ifndef SERIAL_CPM_MINOR
> #define SERIAL_CPM_MINOR 46
> #endif
>
> Each platform could then define major and minor as they like.
>
> Jocke
>
> > Maybe you should use console=ttyCPM0 in your boot parameters for 2.6.
> >
> > Regards,
> > Torsten
> > >
> > > Jocke
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
^ permalink raw reply
* Re: [PATCH] Make ARCH=ppc build again with new syscall path
From: Wolfgang Denk @ 2005-11-28 11:01 UTC (permalink / raw)
To: David Woodhouse; +Cc: linuxppc-dev
In-Reply-To: <1133172766.31573.14.camel@baythorne.infradead.org>
In message <1133172766.31573.14.camel@baythorne.infradead.org> you wrote:
>
> There's also a third option, which _encourages_ people to port their
> platform without necessarily making it easier: just let arch/ppc break.
Please don't. This is supposed to be a "stable" kernel tree.
Best regards,
Wolfgang Denk
--
Software Engineering: Embedded and Realtime Systems, Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
Monday is an awful way to spend one seventh of your life.
^ permalink raw reply
* RE: Badness in 2.6.15-rc1 on 8xx
From: Joakim Tjernlund @ 2005-11-28 10:52 UTC (permalink / raw)
To: Chris Down, linuxppc-embedded
=20
> -----Original Message-----
> From: Chris Down [mailto:chris@alcor.co.uk]=20
> Sent: 28 November 2005 11:01
> To: Joakim Tjernlund; linuxppc-embedded@ozlabs.org
> Subject: RE: Badness in 2.6.15-rc1 on 8xx
>=20
> From: linuxppc-embedded-bounces@ozlabs.org
> [mailto:linuxppc-embedded-bounces@ozlabs.org] On Behalf Of=20
> Joakim Tjernlund
> Sent: 25 November 2005 13:28
> To: linuxppc-embedded@ozlabs.org
> Subject: Badness in 2.6.15-rc1 on 8xx
>=20
> Anyone seen this when booting 2.6.15-rc1 on 8xx?
> Mount-cache hash table entries: 512
> Badness in dma_alloc_init at arch/ppc/kernel/dma-mapping.c:346
> Call trace:
> [c00039e8] check_bug_trap+0x80/0xa8
> [c0003c1c] program_check_exception+0x20c/0x480
> [c00031e0] ret_from_except_full+0x0/0x4c
> [c01b86b8] dma_alloc_init+0x40/0xcc
> [c000225c] init+0x8c/0x288
> [c00050ac] kernel_thread+0x44/0x60
> NET: Registered protocol family 16
> The kernel boots just fine into user space so it seems harmless, but I
> suspect it will bite me later.
>=20
>=20
> I am currently working with 2.6.15-rc1 on MPC852 and I am=20
> seeing a similar
> problem.
>=20
> Badness in dma_alloc_init at arch/ppc/kernel/dma-mapping.c:346
> Call trace:
> [c00036f8] check_bug_trap+0xa4/0xb8
> [c0003f9c] program_check_exception+0x2f0/0x4c4
> [c0003320] ret_from_except_full+0x0/0x4c
> [c024c530] dma_alloc_init+0x3c/0xbc
> [c0002280] init+0xbc/0x25c
> [c000538c] kernel_thread+0x44/0x60
>=20
> Have not had time to look at it yet, however I was not getting this on
> 2.6.11.
>=20
> Chris
Let me guess you have IMAP_ADDR set to 0xff000000? Then you need to
change
CONSISTENT_START to something else(like 0xffa00000). Its somwhere in the
Advanced setup.
Jocke
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox