(2006-08-06) rescue-bootcd
This commit is contained in:
287
extra/linux-2.6.10/drivers/serial/.8250.o.cmd
Normal file
287
extra/linux-2.6.10/drivers/serial/.8250.o.cmd
Normal file
@@ -0,0 +1,287 @@
|
||||
cmd_drivers/serial/8250.o := gcc -Wp,-MD,drivers/serial/.8250.o.d -nostdinc -iwithprefix include -D__KERNEL__ -Iinclude -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -O2 -fomit-frame-pointer -pipe -msoft-float -mpreferred-stack-boundary=2 -fno-unit-at-a-time -march=pentium-mmx -Iinclude/asm-i386/mach-default -Wdeclaration-after-statement -DKBUILD_BASENAME=8250 -DKBUILD_MODNAME=8250 -c -o drivers/serial/8250.o drivers/serial/8250.c
|
||||
|
||||
deps_drivers/serial/8250.o := \
|
||||
drivers/serial/8250.c \
|
||||
$(wildcard include/config/serial/8250/console.h) \
|
||||
$(wildcard include/config/magic/sysrq.h) \
|
||||
$(wildcard include/config/.h) \
|
||||
$(wildcard include/config/serial/many/ports.h) \
|
||||
$(wildcard include/config/serial/detect/irq.h) \
|
||||
$(wildcard include/config/serial/multiport.h) \
|
||||
$(wildcard include/config/hub6.h) \
|
||||
$(wildcard include/config/serial/8250/detect/irq.h) \
|
||||
$(wildcard include/config/serial/8250/multiport.h) \
|
||||
$(wildcard include/config/serial/8250/many/ports.h) \
|
||||
$(wildcard include/config/serial/8250/nr/uarts.h) \
|
||||
$(wildcard include/config/serial/8250/rsa.h) \
|
||||
$(wildcard include/config/ppc.h) \
|
||||
$(wildcard include/config/mca.h) \
|
||||
$(wildcard include/config/type.h) \
|
||||
$(wildcard include/config/irq.h) \
|
||||
include/linux/config.h \
|
||||
$(wildcard include/config/h.h) \
|
||||
include/linux/module.h \
|
||||
$(wildcard include/config/modules.h) \
|
||||
$(wildcard include/config/modversions.h) \
|
||||
$(wildcard include/config/module/unload.h) \
|
||||
$(wildcard include/config/kallsyms.h) \
|
||||
include/linux/sched.h \
|
||||
$(wildcard include/config/keys.h) \
|
||||
$(wildcard include/config/schedstats.h) \
|
||||
$(wildcard include/config/smp.h) \
|
||||
$(wildcard include/config/numa.h) \
|
||||
$(wildcard include/config/security.h) \
|
||||
$(wildcard include/config/preempt.h) \
|
||||
include/asm/param.h \
|
||||
include/linux/capability.h \
|
||||
include/linux/types.h \
|
||||
$(wildcard include/config/uid16.h) \
|
||||
include/linux/posix_types.h \
|
||||
include/linux/stddef.h \
|
||||
include/linux/compiler.h \
|
||||
include/linux/compiler-gcc3.h \
|
||||
include/linux/compiler-gcc.h \
|
||||
include/asm/posix_types.h \
|
||||
include/asm/types.h \
|
||||
$(wildcard include/config/highmem64g.h) \
|
||||
$(wildcard include/config/lbd.h) \
|
||||
include/linux/spinlock.h \
|
||||
$(wildcard include/config/debug/spinlock.h) \
|
||||
$(wildcard include/config/lockmeter.h) \
|
||||
include/linux/preempt.h \
|
||||
include/linux/linkage.h \
|
||||
include/asm/linkage.h \
|
||||
$(wildcard include/config/regparm.h) \
|
||||
$(wildcard include/config/x86/alignment/16.h) \
|
||||
include/linux/thread_info.h \
|
||||
include/linux/bitops.h \
|
||||
include/asm/bitops.h \
|
||||
include/asm/thread_info.h \
|
||||
$(wildcard include/config/4kstacks.h) \
|
||||
$(wildcard include/config/debug/stack/usage.h) \
|
||||
include/asm/page.h \
|
||||
$(wildcard include/config/x86/use/3dnow.h) \
|
||||
$(wildcard include/config/x86/pae.h) \
|
||||
$(wildcard include/config/hugetlb/page.h) \
|
||||
$(wildcard include/config/highmem4g.h) \
|
||||
$(wildcard include/config/discontigmem.h) \
|
||||
include/asm/processor.h \
|
||||
$(wildcard include/config/mk8.h) \
|
||||
$(wildcard include/config/mk7.h) \
|
||||
include/asm/vm86.h \
|
||||
include/asm/math_emu.h \
|
||||
include/asm/sigcontext.h \
|
||||
include/asm/segment.h \
|
||||
include/asm/cpufeature.h \
|
||||
include/asm/msr.h \
|
||||
include/asm/system.h \
|
||||
$(wildcard include/config/x86/cmpxchg.h) \
|
||||
$(wildcard include/config/x86/oostore.h) \
|
||||
include/linux/kernel.h \
|
||||
$(wildcard include/config/debug/spinlock/sleep.h) \
|
||||
/usr/lib/gcc/i686-pc-linux-gnu/3.4.1/include/stdarg.h \
|
||||
include/asm/byteorder.h \
|
||||
$(wildcard include/config/x86/bswap.h) \
|
||||
include/linux/byteorder/little_endian.h \
|
||||
include/linux/byteorder/swab.h \
|
||||
include/linux/byteorder/generic.h \
|
||||
include/asm/bug.h \
|
||||
include/asm-generic/bug.h \
|
||||
include/linux/cache.h \
|
||||
include/asm/cache.h \
|
||||
$(wildcard include/config/x86/l1/cache/shift.h) \
|
||||
include/linux/threads.h \
|
||||
$(wildcard include/config/nr/cpus.h) \
|
||||
include/asm/percpu.h \
|
||||
include/asm-generic/percpu.h \
|
||||
include/linux/stringify.h \
|
||||
include/linux/timex.h \
|
||||
$(wildcard include/config/time/interpolation.h) \
|
||||
include/linux/time.h \
|
||||
include/linux/seqlock.h \
|
||||
include/asm/timex.h \
|
||||
$(wildcard include/config/x86/elan.h) \
|
||||
$(wildcard include/config/x86/tsc.h) \
|
||||
$(wildcard include/config/x86/generic.h) \
|
||||
include/linux/jiffies.h \
|
||||
include/asm/div64.h \
|
||||
include/linux/rbtree.h \
|
||||
include/linux/cpumask.h \
|
||||
$(wildcard include/config/hotplug/cpu.h) \
|
||||
include/linux/bitmap.h \
|
||||
include/linux/string.h \
|
||||
include/asm/string.h \
|
||||
include/asm/semaphore.h \
|
||||
include/asm/atomic.h \
|
||||
$(wildcard include/config/m386.h) \
|
||||
include/linux/wait.h \
|
||||
include/linux/list.h \
|
||||
include/linux/prefetch.h \
|
||||
include/asm/current.h \
|
||||
include/linux/rwsem.h \
|
||||
$(wildcard include/config/rwsem/generic/spinlock.h) \
|
||||
include/asm/rwsem.h \
|
||||
include/asm/ptrace.h \
|
||||
$(wildcard include/config/frame/pointer.h) \
|
||||
include/asm/mmu.h \
|
||||
include/linux/smp.h \
|
||||
include/linux/sem.h \
|
||||
$(wildcard include/config/sysvipc.h) \
|
||||
include/linux/ipc.h \
|
||||
include/asm/ipcbuf.h \
|
||||
include/asm/sembuf.h \
|
||||
include/linux/signal.h \
|
||||
include/asm/signal.h \
|
||||
include/asm/siginfo.h \
|
||||
include/asm-generic/siginfo.h \
|
||||
include/linux/resource.h \
|
||||
include/asm/resource.h \
|
||||
include/linux/securebits.h \
|
||||
include/linux/fs_struct.h \
|
||||
include/linux/completion.h \
|
||||
include/linux/pid.h \
|
||||
include/linux/percpu.h \
|
||||
include/linux/slab.h \
|
||||
include/linux/gfp.h \
|
||||
include/linux/mmzone.h \
|
||||
$(wildcard include/config/force/max/zoneorder.h) \
|
||||
include/linux/numa.h \
|
||||
include/linux/topology.h \
|
||||
$(wildcard include/config/sched/smt.h) \
|
||||
include/asm/topology.h \
|
||||
include/asm-generic/topology.h \
|
||||
include/linux/init.h \
|
||||
$(wildcard include/config/hotplug.h) \
|
||||
include/linux/kmalloc_sizes.h \
|
||||
$(wildcard include/config/mmu.h) \
|
||||
$(wildcard include/config/large/allocs.h) \
|
||||
include/linux/param.h \
|
||||
include/linux/timer.h \
|
||||
include/linux/aio.h \
|
||||
include/linux/workqueue.h \
|
||||
include/linux/aio_abi.h \
|
||||
include/linux/stat.h \
|
||||
include/asm/stat.h \
|
||||
include/linux/kmod.h \
|
||||
$(wildcard include/config/kmod.h) \
|
||||
include/linux/errno.h \
|
||||
include/asm/errno.h \
|
||||
include/asm-generic/errno.h \
|
||||
include/asm-generic/errno-base.h \
|
||||
include/linux/elf.h \
|
||||
include/asm/elf.h \
|
||||
include/asm/user.h \
|
||||
include/linux/utsname.h \
|
||||
include/linux/kobject.h \
|
||||
include/linux/sysfs.h \
|
||||
$(wildcard include/config/sysfs.h) \
|
||||
include/linux/kref.h \
|
||||
include/linux/kobject_uevent.h \
|
||||
$(wildcard include/config/kobject/uevent.h) \
|
||||
include/linux/moduleparam.h \
|
||||
include/asm/local.h \
|
||||
include/asm/module.h \
|
||||
$(wildcard include/config/m486.h) \
|
||||
$(wildcard include/config/m586.h) \
|
||||
$(wildcard include/config/m586tsc.h) \
|
||||
$(wildcard include/config/m586mmx.h) \
|
||||
$(wildcard include/config/m686.h) \
|
||||
$(wildcard include/config/mpentiumii.h) \
|
||||
$(wildcard include/config/mpentiumiii.h) \
|
||||
$(wildcard include/config/mpentiumm.h) \
|
||||
$(wildcard include/config/mpentium4.h) \
|
||||
$(wildcard include/config/mk6.h) \
|
||||
$(wildcard include/config/mcrusoe.h) \
|
||||
$(wildcard include/config/mefficeon.h) \
|
||||
$(wildcard include/config/mwinchipc6.h) \
|
||||
$(wildcard include/config/mwinchip2.h) \
|
||||
$(wildcard include/config/mwinchip3d.h) \
|
||||
$(wildcard include/config/mcyrixiii.h) \
|
||||
$(wildcard include/config/mviac3/2.h) \
|
||||
include/linux/ioport.h \
|
||||
include/linux/console.h \
|
||||
include/linux/sysrq.h \
|
||||
include/linux/delay.h \
|
||||
include/asm/delay.h \
|
||||
include/linux/device.h \
|
||||
include/linux/pm.h \
|
||||
$(wildcard include/config/pm.h) \
|
||||
include/linux/tty.h \
|
||||
$(wildcard include/config/legacy/pty/count.h) \
|
||||
include/linux/fs.h \
|
||||
$(wildcard include/config/dnotify.h) \
|
||||
$(wildcard include/config/quota.h) \
|
||||
$(wildcard include/config/epoll.h) \
|
||||
$(wildcard include/config/auditsyscall.h) \
|
||||
include/linux/limits.h \
|
||||
include/linux/kdev_t.h \
|
||||
include/linux/ioctl.h \
|
||||
include/asm/ioctl.h \
|
||||
include/linux/dcache.h \
|
||||
include/linux/rcupdate.h \
|
||||
include/linux/prio_tree.h \
|
||||
include/linux/radix-tree.h \
|
||||
include/linux/audit.h \
|
||||
$(wildcard include/config/audit.h) \
|
||||
include/linux/quota.h \
|
||||
include/linux/dqblk_xfs.h \
|
||||
include/linux/dqblk_v1.h \
|
||||
include/linux/dqblk_v2.h \
|
||||
include/linux/nfs_fs_i.h \
|
||||
include/linux/nfs.h \
|
||||
include/linux/sunrpc/msg_prot.h \
|
||||
include/linux/fcntl.h \
|
||||
include/asm/fcntl.h \
|
||||
include/linux/err.h \
|
||||
include/linux/major.h \
|
||||
include/linux/termios.h \
|
||||
include/asm/termios.h \
|
||||
include/asm/termbits.h \
|
||||
include/asm/ioctls.h \
|
||||
include/linux/tty_driver.h \
|
||||
include/linux/cdev.h \
|
||||
include/linux/tty_ldisc.h \
|
||||
include/linux/tty_flip.h \
|
||||
include/linux/serial_reg.h \
|
||||
include/linux/serial_core.h \
|
||||
$(wildcard include/config/serial/core/console.h) \
|
||||
$(wildcard include/config/hard/pps.h) \
|
||||
include/linux/interrupt.h \
|
||||
$(wildcard include/config/generic/hardirqs.h) \
|
||||
$(wildcard include/config/generic/irq/probe.h) \
|
||||
include/linux/hardirq.h \
|
||||
include/linux/smp_lock.h \
|
||||
$(wildcard include/config/lock/kernel.h) \
|
||||
include/asm/hardirq.h \
|
||||
include/linux/irq.h \
|
||||
$(wildcard include/config/arch/s390.h) \
|
||||
include/asm/irq.h \
|
||||
$(wildcard include/config/x86/local/apic.h) \
|
||||
$(wildcard include/config/irqbalance.h) \
|
||||
include/asm-i386/mach-default/irq_vectors.h \
|
||||
include/asm-i386/mach-default/irq_vectors_limits.h \
|
||||
$(wildcard include/config/pci/msi.h) \
|
||||
$(wildcard include/config/x86/io/apic.h) \
|
||||
include/asm/hw_irq.h \
|
||||
include/linux/profile.h \
|
||||
$(wildcard include/config/proc/fs.h) \
|
||||
$(wildcard include/config/profiling.h) \
|
||||
include/asm/sections.h \
|
||||
include/asm-generic/sections.h \
|
||||
include/linux/irq_cpustat.h \
|
||||
include/linux/circ_buf.h \
|
||||
include/linux/serial.h \
|
||||
include/linux/serial_8250.h \
|
||||
include/asm/io.h \
|
||||
$(wildcard include/config/x86/ppro/fence.h) \
|
||||
$(wildcard include/config/x86/numaq.h) \
|
||||
include/asm-generic/iomap.h \
|
||||
include/linux/vmalloc.h \
|
||||
drivers/serial/8250.h \
|
||||
$(wildcard include/config/serial/8250/share/irq.h) \
|
||||
$(wildcard include/config/pci.h) \
|
||||
include/asm/serial.h \
|
||||
|
||||
drivers/serial/8250.o: $(deps_drivers/serial/8250.o)
|
||||
|
||||
$(deps_drivers/serial/8250.o):
|
||||
307
extra/linux-2.6.10/drivers/serial/.8250_pci.o.cmd
Normal file
307
extra/linux-2.6.10/drivers/serial/.8250_pci.o.cmd
Normal file
@@ -0,0 +1,307 @@
|
||||
cmd_drivers/serial/8250_pci.o := gcc -Wp,-MD,drivers/serial/.8250_pci.o.d -nostdinc -iwithprefix include -D__KERNEL__ -Iinclude -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -O2 -fomit-frame-pointer -pipe -msoft-float -mpreferred-stack-boundary=2 -fno-unit-at-a-time -march=pentium-mmx -Iinclude/asm-i386/mach-default -Wdeclaration-after-statement -DKBUILD_BASENAME=8250_pci -DKBUILD_MODNAME=8250_pci -c -o drivers/serial/8250_pci.o drivers/serial/8250_pci.c
|
||||
|
||||
deps_drivers/serial/8250_pci.o := \
|
||||
drivers/serial/8250_pci.c \
|
||||
include/linux/module.h \
|
||||
$(wildcard include/config/modules.h) \
|
||||
$(wildcard include/config/modversions.h) \
|
||||
$(wildcard include/config/module/unload.h) \
|
||||
$(wildcard include/config/kallsyms.h) \
|
||||
include/linux/config.h \
|
||||
$(wildcard include/config/h.h) \
|
||||
include/linux/sched.h \
|
||||
$(wildcard include/config/keys.h) \
|
||||
$(wildcard include/config/schedstats.h) \
|
||||
$(wildcard include/config/smp.h) \
|
||||
$(wildcard include/config/numa.h) \
|
||||
$(wildcard include/config/security.h) \
|
||||
$(wildcard include/config/preempt.h) \
|
||||
$(wildcard include/config/magic/sysrq.h) \
|
||||
include/asm/param.h \
|
||||
include/linux/capability.h \
|
||||
include/linux/types.h \
|
||||
$(wildcard include/config/uid16.h) \
|
||||
include/linux/posix_types.h \
|
||||
include/linux/stddef.h \
|
||||
include/linux/compiler.h \
|
||||
include/linux/compiler-gcc3.h \
|
||||
include/linux/compiler-gcc.h \
|
||||
include/asm/posix_types.h \
|
||||
include/asm/types.h \
|
||||
$(wildcard include/config/highmem64g.h) \
|
||||
$(wildcard include/config/lbd.h) \
|
||||
include/linux/spinlock.h \
|
||||
$(wildcard include/config/debug/spinlock.h) \
|
||||
$(wildcard include/config/lockmeter.h) \
|
||||
include/linux/preempt.h \
|
||||
include/linux/linkage.h \
|
||||
include/asm/linkage.h \
|
||||
$(wildcard include/config/regparm.h) \
|
||||
$(wildcard include/config/x86/alignment/16.h) \
|
||||
include/linux/thread_info.h \
|
||||
include/linux/bitops.h \
|
||||
include/asm/bitops.h \
|
||||
include/asm/thread_info.h \
|
||||
$(wildcard include/config/4kstacks.h) \
|
||||
$(wildcard include/config/debug/stack/usage.h) \
|
||||
include/asm/page.h \
|
||||
$(wildcard include/config/x86/use/3dnow.h) \
|
||||
$(wildcard include/config/x86/pae.h) \
|
||||
$(wildcard include/config/hugetlb/page.h) \
|
||||
$(wildcard include/config/highmem4g.h) \
|
||||
$(wildcard include/config/discontigmem.h) \
|
||||
include/asm/processor.h \
|
||||
$(wildcard include/config/mk8.h) \
|
||||
$(wildcard include/config/mk7.h) \
|
||||
include/asm/vm86.h \
|
||||
include/asm/math_emu.h \
|
||||
include/asm/sigcontext.h \
|
||||
include/asm/segment.h \
|
||||
include/asm/cpufeature.h \
|
||||
include/asm/msr.h \
|
||||
include/asm/system.h \
|
||||
$(wildcard include/config/x86/cmpxchg.h) \
|
||||
$(wildcard include/config/x86/oostore.h) \
|
||||
include/linux/kernel.h \
|
||||
$(wildcard include/config/debug/spinlock/sleep.h) \
|
||||
/usr/lib/gcc/i686-pc-linux-gnu/3.4.1/include/stdarg.h \
|
||||
include/asm/byteorder.h \
|
||||
$(wildcard include/config/x86/bswap.h) \
|
||||
include/linux/byteorder/little_endian.h \
|
||||
include/linux/byteorder/swab.h \
|
||||
include/linux/byteorder/generic.h \
|
||||
include/asm/bug.h \
|
||||
include/asm-generic/bug.h \
|
||||
include/linux/cache.h \
|
||||
include/asm/cache.h \
|
||||
$(wildcard include/config/x86/l1/cache/shift.h) \
|
||||
include/linux/threads.h \
|
||||
$(wildcard include/config/nr/cpus.h) \
|
||||
include/asm/percpu.h \
|
||||
include/asm-generic/percpu.h \
|
||||
include/linux/stringify.h \
|
||||
include/linux/timex.h \
|
||||
$(wildcard include/config/time/interpolation.h) \
|
||||
include/linux/time.h \
|
||||
include/linux/seqlock.h \
|
||||
include/asm/timex.h \
|
||||
$(wildcard include/config/x86/elan.h) \
|
||||
$(wildcard include/config/x86/tsc.h) \
|
||||
$(wildcard include/config/x86/generic.h) \
|
||||
include/linux/jiffies.h \
|
||||
include/asm/div64.h \
|
||||
include/linux/rbtree.h \
|
||||
include/linux/cpumask.h \
|
||||
$(wildcard include/config/hotplug/cpu.h) \
|
||||
include/linux/bitmap.h \
|
||||
include/linux/string.h \
|
||||
include/asm/string.h \
|
||||
include/asm/semaphore.h \
|
||||
include/asm/atomic.h \
|
||||
$(wildcard include/config/m386.h) \
|
||||
include/linux/wait.h \
|
||||
include/linux/list.h \
|
||||
include/linux/prefetch.h \
|
||||
include/asm/current.h \
|
||||
include/linux/rwsem.h \
|
||||
$(wildcard include/config/rwsem/generic/spinlock.h) \
|
||||
include/asm/rwsem.h \
|
||||
include/asm/ptrace.h \
|
||||
$(wildcard include/config/frame/pointer.h) \
|
||||
include/asm/mmu.h \
|
||||
include/linux/smp.h \
|
||||
include/linux/sem.h \
|
||||
$(wildcard include/config/sysvipc.h) \
|
||||
include/linux/ipc.h \
|
||||
include/asm/ipcbuf.h \
|
||||
include/asm/sembuf.h \
|
||||
include/linux/signal.h \
|
||||
include/asm/signal.h \
|
||||
include/asm/siginfo.h \
|
||||
include/asm-generic/siginfo.h \
|
||||
include/linux/resource.h \
|
||||
include/asm/resource.h \
|
||||
include/linux/securebits.h \
|
||||
include/linux/fs_struct.h \
|
||||
include/linux/completion.h \
|
||||
include/linux/pid.h \
|
||||
include/linux/percpu.h \
|
||||
include/linux/slab.h \
|
||||
$(wildcard include/config/.h) \
|
||||
include/linux/gfp.h \
|
||||
include/linux/mmzone.h \
|
||||
$(wildcard include/config/force/max/zoneorder.h) \
|
||||
include/linux/numa.h \
|
||||
include/linux/topology.h \
|
||||
$(wildcard include/config/sched/smt.h) \
|
||||
include/asm/topology.h \
|
||||
include/asm-generic/topology.h \
|
||||
include/linux/init.h \
|
||||
$(wildcard include/config/hotplug.h) \
|
||||
include/linux/kmalloc_sizes.h \
|
||||
$(wildcard include/config/mmu.h) \
|
||||
$(wildcard include/config/large/allocs.h) \
|
||||
include/linux/param.h \
|
||||
include/linux/timer.h \
|
||||
include/linux/aio.h \
|
||||
include/linux/workqueue.h \
|
||||
include/linux/aio_abi.h \
|
||||
include/linux/stat.h \
|
||||
include/asm/stat.h \
|
||||
include/linux/kmod.h \
|
||||
$(wildcard include/config/kmod.h) \
|
||||
include/linux/errno.h \
|
||||
include/asm/errno.h \
|
||||
include/asm-generic/errno.h \
|
||||
include/asm-generic/errno-base.h \
|
||||
include/linux/elf.h \
|
||||
include/asm/elf.h \
|
||||
include/asm/user.h \
|
||||
include/linux/utsname.h \
|
||||
include/linux/kobject.h \
|
||||
include/linux/sysfs.h \
|
||||
$(wildcard include/config/sysfs.h) \
|
||||
include/linux/kref.h \
|
||||
include/linux/kobject_uevent.h \
|
||||
$(wildcard include/config/kobject/uevent.h) \
|
||||
include/linux/moduleparam.h \
|
||||
include/asm/local.h \
|
||||
include/asm/module.h \
|
||||
$(wildcard include/config/m486.h) \
|
||||
$(wildcard include/config/m586.h) \
|
||||
$(wildcard include/config/m586tsc.h) \
|
||||
$(wildcard include/config/m586mmx.h) \
|
||||
$(wildcard include/config/m686.h) \
|
||||
$(wildcard include/config/mpentiumii.h) \
|
||||
$(wildcard include/config/mpentiumiii.h) \
|
||||
$(wildcard include/config/mpentiumm.h) \
|
||||
$(wildcard include/config/mpentium4.h) \
|
||||
$(wildcard include/config/mk6.h) \
|
||||
$(wildcard include/config/mcrusoe.h) \
|
||||
$(wildcard include/config/mefficeon.h) \
|
||||
$(wildcard include/config/mwinchipc6.h) \
|
||||
$(wildcard include/config/mwinchip2.h) \
|
||||
$(wildcard include/config/mwinchip3d.h) \
|
||||
$(wildcard include/config/mcyrixiii.h) \
|
||||
$(wildcard include/config/mviac3/2.h) \
|
||||
include/linux/pci.h \
|
||||
$(wildcard include/config/pci/names.h) \
|
||||
$(wildcard include/config/pci.h) \
|
||||
$(wildcard include/config/isa.h) \
|
||||
$(wildcard include/config/eisa.h) \
|
||||
$(wildcard include/config/pci/msi.h) \
|
||||
$(wildcard include/config/pci/domains.h) \
|
||||
include/linux/mod_devicetable.h \
|
||||
include/linux/pci_ids.h \
|
||||
include/linux/ioport.h \
|
||||
include/linux/device.h \
|
||||
include/linux/pm.h \
|
||||
$(wildcard include/config/pm.h) \
|
||||
include/linux/dmapool.h \
|
||||
include/asm/io.h \
|
||||
$(wildcard include/config/x86/ppro/fence.h) \
|
||||
$(wildcard include/config/x86/numaq.h) \
|
||||
include/asm-generic/iomap.h \
|
||||
include/linux/vmalloc.h \
|
||||
include/asm/scatterlist.h \
|
||||
include/asm/pci.h \
|
||||
include/linux/mm.h \
|
||||
$(wildcard include/config/sysctl.h) \
|
||||
$(wildcard include/config/stack/growsup.h) \
|
||||
$(wildcard include/config/highmem.h) \
|
||||
$(wildcard include/config/shmem.h) \
|
||||
$(wildcard include/config/proc/fs.h) \
|
||||
$(wildcard include/config/debug/pagealloc.h) \
|
||||
$(wildcard include/config/arch/gate/area.h) \
|
||||
include/linux/prio_tree.h \
|
||||
include/linux/fs.h \
|
||||
$(wildcard include/config/dnotify.h) \
|
||||
$(wildcard include/config/quota.h) \
|
||||
$(wildcard include/config/epoll.h) \
|
||||
$(wildcard include/config/auditsyscall.h) \
|
||||
include/linux/limits.h \
|
||||
include/linux/kdev_t.h \
|
||||
include/linux/ioctl.h \
|
||||
include/asm/ioctl.h \
|
||||
include/linux/dcache.h \
|
||||
include/linux/rcupdate.h \
|
||||
include/linux/radix-tree.h \
|
||||
include/linux/audit.h \
|
||||
$(wildcard include/config/audit.h) \
|
||||
include/linux/quota.h \
|
||||
include/linux/dqblk_xfs.h \
|
||||
include/linux/dqblk_v1.h \
|
||||
include/linux/dqblk_v2.h \
|
||||
include/linux/nfs_fs_i.h \
|
||||
include/linux/nfs.h \
|
||||
include/linux/sunrpc/msg_prot.h \
|
||||
include/linux/fcntl.h \
|
||||
include/asm/fcntl.h \
|
||||
include/linux/err.h \
|
||||
include/asm/pgtable.h \
|
||||
$(wildcard include/config/highpte.h) \
|
||||
include/asm/fixmap.h \
|
||||
$(wildcard include/config/x86/local/apic.h) \
|
||||
$(wildcard include/config/x86/io/apic.h) \
|
||||
$(wildcard include/config/x86/visws/apic.h) \
|
||||
$(wildcard include/config/x86/f00f/bug.h) \
|
||||
$(wildcard include/config/x86/cyclone/timer.h) \
|
||||
$(wildcard include/config/acpi/boot.h) \
|
||||
$(wildcard include/config/pci/mmconfig.h) \
|
||||
include/asm/acpi.h \
|
||||
$(wildcard include/config/acpi/pci.h) \
|
||||
$(wildcard include/config/acpi/sleep.h) \
|
||||
include/asm/apicdef.h \
|
||||
include/asm/pgtable-2level-defs.h \
|
||||
include/asm/pgtable-2level.h \
|
||||
include/asm-generic/pgtable.h \
|
||||
include/linux/page-flags.h \
|
||||
$(wildcard include/config/swap.h) \
|
||||
include/asm-generic/pci-dma-compat.h \
|
||||
include/linux/dma-mapping.h \
|
||||
include/asm/dma-mapping.h \
|
||||
include/asm-generic/pci.h \
|
||||
include/linux/delay.h \
|
||||
include/asm/delay.h \
|
||||
include/linux/tty.h \
|
||||
$(wildcard include/config/legacy/pty/count.h) \
|
||||
include/linux/major.h \
|
||||
include/linux/termios.h \
|
||||
include/asm/termios.h \
|
||||
include/asm/termbits.h \
|
||||
include/asm/ioctls.h \
|
||||
include/linux/tty_driver.h \
|
||||
include/linux/cdev.h \
|
||||
include/linux/tty_ldisc.h \
|
||||
include/linux/serial_core.h \
|
||||
$(wildcard include/config/type.h) \
|
||||
$(wildcard include/config/irq.h) \
|
||||
$(wildcard include/config/serial/core/console.h) \
|
||||
$(wildcard include/config/hard/pps.h) \
|
||||
include/linux/interrupt.h \
|
||||
$(wildcard include/config/generic/hardirqs.h) \
|
||||
$(wildcard include/config/generic/irq/probe.h) \
|
||||
include/linux/hardirq.h \
|
||||
include/linux/smp_lock.h \
|
||||
$(wildcard include/config/lock/kernel.h) \
|
||||
include/asm/hardirq.h \
|
||||
include/linux/irq.h \
|
||||
$(wildcard include/config/arch/s390.h) \
|
||||
include/asm/irq.h \
|
||||
$(wildcard include/config/irqbalance.h) \
|
||||
include/asm-i386/mach-default/irq_vectors.h \
|
||||
include/asm-i386/mach-default/irq_vectors_limits.h \
|
||||
include/asm/hw_irq.h \
|
||||
include/linux/profile.h \
|
||||
$(wildcard include/config/profiling.h) \
|
||||
include/asm/sections.h \
|
||||
include/asm-generic/sections.h \
|
||||
include/linux/irq_cpustat.h \
|
||||
include/linux/circ_buf.h \
|
||||
include/linux/8250_pci.h \
|
||||
drivers/serial/8250.h \
|
||||
$(wildcard include/config/serial/8250/share/irq.h) \
|
||||
|
||||
drivers/serial/8250_pci.o: $(deps_drivers/serial/8250_pci.o)
|
||||
|
||||
$(deps_drivers/serial/8250_pci.o):
|
||||
310
extra/linux-2.6.10/drivers/serial/.8250_pnp.o.cmd
Normal file
310
extra/linux-2.6.10/drivers/serial/.8250_pnp.o.cmd
Normal file
@@ -0,0 +1,310 @@
|
||||
cmd_drivers/serial/8250_pnp.o := gcc -Wp,-MD,drivers/serial/.8250_pnp.o.d -nostdinc -iwithprefix include -D__KERNEL__ -Iinclude -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -O2 -fomit-frame-pointer -pipe -msoft-float -mpreferred-stack-boundary=2 -fno-unit-at-a-time -march=pentium-mmx -Iinclude/asm-i386/mach-default -Wdeclaration-after-statement -DKBUILD_BASENAME=8250_pnp -DKBUILD_MODNAME=8250_pnp -c -o drivers/serial/8250_pnp.o drivers/serial/8250_pnp.c
|
||||
|
||||
deps_drivers/serial/8250_pnp.o := \
|
||||
drivers/serial/8250_pnp.c \
|
||||
include/linux/module.h \
|
||||
$(wildcard include/config/modules.h) \
|
||||
$(wildcard include/config/modversions.h) \
|
||||
$(wildcard include/config/module/unload.h) \
|
||||
$(wildcard include/config/kallsyms.h) \
|
||||
include/linux/config.h \
|
||||
$(wildcard include/config/h.h) \
|
||||
include/linux/sched.h \
|
||||
$(wildcard include/config/keys.h) \
|
||||
$(wildcard include/config/schedstats.h) \
|
||||
$(wildcard include/config/smp.h) \
|
||||
$(wildcard include/config/numa.h) \
|
||||
$(wildcard include/config/security.h) \
|
||||
$(wildcard include/config/preempt.h) \
|
||||
$(wildcard include/config/magic/sysrq.h) \
|
||||
include/asm/param.h \
|
||||
include/linux/capability.h \
|
||||
include/linux/types.h \
|
||||
$(wildcard include/config/uid16.h) \
|
||||
include/linux/posix_types.h \
|
||||
include/linux/stddef.h \
|
||||
include/linux/compiler.h \
|
||||
include/linux/compiler-gcc3.h \
|
||||
include/linux/compiler-gcc.h \
|
||||
include/asm/posix_types.h \
|
||||
include/asm/types.h \
|
||||
$(wildcard include/config/highmem64g.h) \
|
||||
$(wildcard include/config/lbd.h) \
|
||||
include/linux/spinlock.h \
|
||||
$(wildcard include/config/debug/spinlock.h) \
|
||||
$(wildcard include/config/lockmeter.h) \
|
||||
include/linux/preempt.h \
|
||||
include/linux/linkage.h \
|
||||
include/asm/linkage.h \
|
||||
$(wildcard include/config/regparm.h) \
|
||||
$(wildcard include/config/x86/alignment/16.h) \
|
||||
include/linux/thread_info.h \
|
||||
include/linux/bitops.h \
|
||||
include/asm/bitops.h \
|
||||
include/asm/thread_info.h \
|
||||
$(wildcard include/config/4kstacks.h) \
|
||||
$(wildcard include/config/debug/stack/usage.h) \
|
||||
include/asm/page.h \
|
||||
$(wildcard include/config/x86/use/3dnow.h) \
|
||||
$(wildcard include/config/x86/pae.h) \
|
||||
$(wildcard include/config/hugetlb/page.h) \
|
||||
$(wildcard include/config/highmem4g.h) \
|
||||
$(wildcard include/config/discontigmem.h) \
|
||||
include/asm/processor.h \
|
||||
$(wildcard include/config/mk8.h) \
|
||||
$(wildcard include/config/mk7.h) \
|
||||
include/asm/vm86.h \
|
||||
include/asm/math_emu.h \
|
||||
include/asm/sigcontext.h \
|
||||
include/asm/segment.h \
|
||||
include/asm/cpufeature.h \
|
||||
include/asm/msr.h \
|
||||
include/asm/system.h \
|
||||
$(wildcard include/config/x86/cmpxchg.h) \
|
||||
$(wildcard include/config/x86/oostore.h) \
|
||||
include/linux/kernel.h \
|
||||
$(wildcard include/config/debug/spinlock/sleep.h) \
|
||||
/usr/lib/gcc/i686-pc-linux-gnu/3.4.1/include/stdarg.h \
|
||||
include/asm/byteorder.h \
|
||||
$(wildcard include/config/x86/bswap.h) \
|
||||
include/linux/byteorder/little_endian.h \
|
||||
include/linux/byteorder/swab.h \
|
||||
include/linux/byteorder/generic.h \
|
||||
include/asm/bug.h \
|
||||
include/asm-generic/bug.h \
|
||||
include/linux/cache.h \
|
||||
include/asm/cache.h \
|
||||
$(wildcard include/config/x86/l1/cache/shift.h) \
|
||||
include/linux/threads.h \
|
||||
$(wildcard include/config/nr/cpus.h) \
|
||||
include/asm/percpu.h \
|
||||
include/asm-generic/percpu.h \
|
||||
include/linux/stringify.h \
|
||||
include/linux/timex.h \
|
||||
$(wildcard include/config/time/interpolation.h) \
|
||||
include/linux/time.h \
|
||||
include/linux/seqlock.h \
|
||||
include/asm/timex.h \
|
||||
$(wildcard include/config/x86/elan.h) \
|
||||
$(wildcard include/config/x86/tsc.h) \
|
||||
$(wildcard include/config/x86/generic.h) \
|
||||
include/linux/jiffies.h \
|
||||
include/asm/div64.h \
|
||||
include/linux/rbtree.h \
|
||||
include/linux/cpumask.h \
|
||||
$(wildcard include/config/hotplug/cpu.h) \
|
||||
include/linux/bitmap.h \
|
||||
include/linux/string.h \
|
||||
include/asm/string.h \
|
||||
include/asm/semaphore.h \
|
||||
include/asm/atomic.h \
|
||||
$(wildcard include/config/m386.h) \
|
||||
include/linux/wait.h \
|
||||
include/linux/list.h \
|
||||
include/linux/prefetch.h \
|
||||
include/asm/current.h \
|
||||
include/linux/rwsem.h \
|
||||
$(wildcard include/config/rwsem/generic/spinlock.h) \
|
||||
include/asm/rwsem.h \
|
||||
include/asm/ptrace.h \
|
||||
$(wildcard include/config/frame/pointer.h) \
|
||||
include/asm/mmu.h \
|
||||
include/linux/smp.h \
|
||||
include/linux/sem.h \
|
||||
$(wildcard include/config/sysvipc.h) \
|
||||
include/linux/ipc.h \
|
||||
include/asm/ipcbuf.h \
|
||||
include/asm/sembuf.h \
|
||||
include/linux/signal.h \
|
||||
include/asm/signal.h \
|
||||
include/asm/siginfo.h \
|
||||
include/asm-generic/siginfo.h \
|
||||
include/linux/resource.h \
|
||||
include/asm/resource.h \
|
||||
include/linux/securebits.h \
|
||||
include/linux/fs_struct.h \
|
||||
include/linux/completion.h \
|
||||
include/linux/pid.h \
|
||||
include/linux/percpu.h \
|
||||
include/linux/slab.h \
|
||||
$(wildcard include/config/.h) \
|
||||
include/linux/gfp.h \
|
||||
include/linux/mmzone.h \
|
||||
$(wildcard include/config/force/max/zoneorder.h) \
|
||||
include/linux/numa.h \
|
||||
include/linux/topology.h \
|
||||
$(wildcard include/config/sched/smt.h) \
|
||||
include/asm/topology.h \
|
||||
include/asm-generic/topology.h \
|
||||
include/linux/init.h \
|
||||
$(wildcard include/config/hotplug.h) \
|
||||
include/linux/kmalloc_sizes.h \
|
||||
$(wildcard include/config/mmu.h) \
|
||||
$(wildcard include/config/large/allocs.h) \
|
||||
include/linux/param.h \
|
||||
include/linux/timer.h \
|
||||
include/linux/aio.h \
|
||||
include/linux/workqueue.h \
|
||||
include/linux/aio_abi.h \
|
||||
include/linux/stat.h \
|
||||
include/asm/stat.h \
|
||||
include/linux/kmod.h \
|
||||
$(wildcard include/config/kmod.h) \
|
||||
include/linux/errno.h \
|
||||
include/asm/errno.h \
|
||||
include/asm-generic/errno.h \
|
||||
include/asm-generic/errno-base.h \
|
||||
include/linux/elf.h \
|
||||
include/asm/elf.h \
|
||||
include/asm/user.h \
|
||||
include/linux/utsname.h \
|
||||
include/linux/kobject.h \
|
||||
include/linux/sysfs.h \
|
||||
$(wildcard include/config/sysfs.h) \
|
||||
include/linux/kref.h \
|
||||
include/linux/kobject_uevent.h \
|
||||
$(wildcard include/config/kobject/uevent.h) \
|
||||
include/linux/moduleparam.h \
|
||||
include/asm/local.h \
|
||||
include/asm/module.h \
|
||||
$(wildcard include/config/m486.h) \
|
||||
$(wildcard include/config/m586.h) \
|
||||
$(wildcard include/config/m586tsc.h) \
|
||||
$(wildcard include/config/m586mmx.h) \
|
||||
$(wildcard include/config/m686.h) \
|
||||
$(wildcard include/config/mpentiumii.h) \
|
||||
$(wildcard include/config/mpentiumiii.h) \
|
||||
$(wildcard include/config/mpentiumm.h) \
|
||||
$(wildcard include/config/mpentium4.h) \
|
||||
$(wildcard include/config/mk6.h) \
|
||||
$(wildcard include/config/mcrusoe.h) \
|
||||
$(wildcard include/config/mefficeon.h) \
|
||||
$(wildcard include/config/mwinchipc6.h) \
|
||||
$(wildcard include/config/mwinchip2.h) \
|
||||
$(wildcard include/config/mwinchip3d.h) \
|
||||
$(wildcard include/config/mcyrixiii.h) \
|
||||
$(wildcard include/config/mviac3/2.h) \
|
||||
include/linux/pci.h \
|
||||
$(wildcard include/config/pci/names.h) \
|
||||
$(wildcard include/config/pci.h) \
|
||||
$(wildcard include/config/isa.h) \
|
||||
$(wildcard include/config/eisa.h) \
|
||||
$(wildcard include/config/pci/msi.h) \
|
||||
$(wildcard include/config/pci/domains.h) \
|
||||
include/linux/mod_devicetable.h \
|
||||
include/linux/pci_ids.h \
|
||||
include/linux/ioport.h \
|
||||
include/linux/device.h \
|
||||
include/linux/pm.h \
|
||||
$(wildcard include/config/pm.h) \
|
||||
include/linux/dmapool.h \
|
||||
include/asm/io.h \
|
||||
$(wildcard include/config/x86/ppro/fence.h) \
|
||||
$(wildcard include/config/x86/numaq.h) \
|
||||
include/asm-generic/iomap.h \
|
||||
include/linux/vmalloc.h \
|
||||
include/asm/scatterlist.h \
|
||||
include/asm/pci.h \
|
||||
include/linux/mm.h \
|
||||
$(wildcard include/config/sysctl.h) \
|
||||
$(wildcard include/config/stack/growsup.h) \
|
||||
$(wildcard include/config/highmem.h) \
|
||||
$(wildcard include/config/shmem.h) \
|
||||
$(wildcard include/config/proc/fs.h) \
|
||||
$(wildcard include/config/debug/pagealloc.h) \
|
||||
$(wildcard include/config/arch/gate/area.h) \
|
||||
include/linux/prio_tree.h \
|
||||
include/linux/fs.h \
|
||||
$(wildcard include/config/dnotify.h) \
|
||||
$(wildcard include/config/quota.h) \
|
||||
$(wildcard include/config/epoll.h) \
|
||||
$(wildcard include/config/auditsyscall.h) \
|
||||
include/linux/limits.h \
|
||||
include/linux/kdev_t.h \
|
||||
include/linux/ioctl.h \
|
||||
include/asm/ioctl.h \
|
||||
include/linux/dcache.h \
|
||||
include/linux/rcupdate.h \
|
||||
include/linux/radix-tree.h \
|
||||
include/linux/audit.h \
|
||||
$(wildcard include/config/audit.h) \
|
||||
include/linux/quota.h \
|
||||
include/linux/dqblk_xfs.h \
|
||||
include/linux/dqblk_v1.h \
|
||||
include/linux/dqblk_v2.h \
|
||||
include/linux/nfs_fs_i.h \
|
||||
include/linux/nfs.h \
|
||||
include/linux/sunrpc/msg_prot.h \
|
||||
include/linux/fcntl.h \
|
||||
include/asm/fcntl.h \
|
||||
include/linux/err.h \
|
||||
include/asm/pgtable.h \
|
||||
$(wildcard include/config/highpte.h) \
|
||||
include/asm/fixmap.h \
|
||||
$(wildcard include/config/x86/local/apic.h) \
|
||||
$(wildcard include/config/x86/io/apic.h) \
|
||||
$(wildcard include/config/x86/visws/apic.h) \
|
||||
$(wildcard include/config/x86/f00f/bug.h) \
|
||||
$(wildcard include/config/x86/cyclone/timer.h) \
|
||||
$(wildcard include/config/acpi/boot.h) \
|
||||
$(wildcard include/config/pci/mmconfig.h) \
|
||||
include/asm/acpi.h \
|
||||
$(wildcard include/config/acpi/pci.h) \
|
||||
$(wildcard include/config/acpi/sleep.h) \
|
||||
include/asm/apicdef.h \
|
||||
include/asm/pgtable-2level-defs.h \
|
||||
include/asm/pgtable-2level.h \
|
||||
include/asm-generic/pgtable.h \
|
||||
include/linux/page-flags.h \
|
||||
$(wildcard include/config/swap.h) \
|
||||
include/asm-generic/pci-dma-compat.h \
|
||||
include/linux/dma-mapping.h \
|
||||
include/asm/dma-mapping.h \
|
||||
include/asm-generic/pci.h \
|
||||
include/linux/pnp.h \
|
||||
$(wildcard include/config/normal.h) \
|
||||
$(wildcard include/config/force.h) \
|
||||
$(wildcard include/config/isapnp.h) \
|
||||
$(wildcard include/config/pnpbios.h) \
|
||||
$(wildcard include/config/pnp.h) \
|
||||
include/linux/serial_core.h \
|
||||
$(wildcard include/config/type.h) \
|
||||
$(wildcard include/config/irq.h) \
|
||||
$(wildcard include/config/serial/core/console.h) \
|
||||
$(wildcard include/config/hard/pps.h) \
|
||||
include/linux/interrupt.h \
|
||||
$(wildcard include/config/generic/hardirqs.h) \
|
||||
$(wildcard include/config/generic/irq/probe.h) \
|
||||
include/linux/hardirq.h \
|
||||
include/linux/smp_lock.h \
|
||||
$(wildcard include/config/lock/kernel.h) \
|
||||
include/asm/hardirq.h \
|
||||
include/linux/irq.h \
|
||||
$(wildcard include/config/arch/s390.h) \
|
||||
include/asm/irq.h \
|
||||
$(wildcard include/config/irqbalance.h) \
|
||||
include/asm-i386/mach-default/irq_vectors.h \
|
||||
include/asm-i386/mach-default/irq_vectors_limits.h \
|
||||
include/asm/hw_irq.h \
|
||||
include/linux/profile.h \
|
||||
$(wildcard include/config/profiling.h) \
|
||||
include/asm/sections.h \
|
||||
include/asm-generic/sections.h \
|
||||
include/linux/irq_cpustat.h \
|
||||
include/linux/circ_buf.h \
|
||||
include/linux/tty.h \
|
||||
$(wildcard include/config/legacy/pty/count.h) \
|
||||
include/linux/major.h \
|
||||
include/linux/termios.h \
|
||||
include/asm/termios.h \
|
||||
include/asm/termbits.h \
|
||||
include/asm/ioctls.h \
|
||||
include/linux/tty_driver.h \
|
||||
include/linux/cdev.h \
|
||||
include/linux/tty_ldisc.h \
|
||||
drivers/serial/8250.h \
|
||||
$(wildcard include/config/serial/8250/share/irq.h) \
|
||||
|
||||
drivers/serial/8250_pnp.o: $(deps_drivers/serial/8250_pnp.o)
|
||||
|
||||
$(deps_drivers/serial/8250_pnp.o):
|
||||
1
extra/linux-2.6.10/drivers/serial/.built-in.o.cmd
Normal file
1
extra/linux-2.6.10/drivers/serial/.built-in.o.cmd
Normal file
@@ -0,0 +1 @@
|
||||
cmd_drivers/serial/built-in.o := ld -m elf_i386 -r -o drivers/serial/built-in.o drivers/serial/serial_core.o drivers/serial/8250.o drivers/serial/8250_pci.o drivers/serial/8250_pnp.o
|
||||
265
extra/linux-2.6.10/drivers/serial/.serial_core.o.cmd
Normal file
265
extra/linux-2.6.10/drivers/serial/.serial_core.o.cmd
Normal file
@@ -0,0 +1,265 @@
|
||||
cmd_drivers/serial/serial_core.o := gcc -Wp,-MD,drivers/serial/.serial_core.o.d -nostdinc -iwithprefix include -D__KERNEL__ -Iinclude -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -O2 -fomit-frame-pointer -pipe -msoft-float -mpreferred-stack-boundary=2 -fno-unit-at-a-time -march=pentium-mmx -Iinclude/asm-i386/mach-default -Wdeclaration-after-statement -DKBUILD_BASENAME=serial_core -DKBUILD_MODNAME=serial_core -c -o drivers/serial/serial_core.o drivers/serial/serial_core.c
|
||||
|
||||
deps_drivers/serial/serial_core.o := \
|
||||
drivers/serial/serial_core.c \
|
||||
$(wildcard include/config/serial/core/console.h) \
|
||||
$(wildcard include/config/type.h) \
|
||||
$(wildcard include/config/irq.h) \
|
||||
$(wildcard include/config/proc/fs.h) \
|
||||
include/linux/config.h \
|
||||
$(wildcard include/config/h.h) \
|
||||
include/linux/module.h \
|
||||
$(wildcard include/config/modules.h) \
|
||||
$(wildcard include/config/modversions.h) \
|
||||
$(wildcard include/config/module/unload.h) \
|
||||
$(wildcard include/config/kallsyms.h) \
|
||||
include/linux/sched.h \
|
||||
$(wildcard include/config/keys.h) \
|
||||
$(wildcard include/config/schedstats.h) \
|
||||
$(wildcard include/config/smp.h) \
|
||||
$(wildcard include/config/numa.h) \
|
||||
$(wildcard include/config/security.h) \
|
||||
$(wildcard include/config/preempt.h) \
|
||||
$(wildcard include/config/magic/sysrq.h) \
|
||||
include/asm/param.h \
|
||||
include/linux/capability.h \
|
||||
include/linux/types.h \
|
||||
$(wildcard include/config/uid16.h) \
|
||||
include/linux/posix_types.h \
|
||||
include/linux/stddef.h \
|
||||
include/linux/compiler.h \
|
||||
include/linux/compiler-gcc3.h \
|
||||
include/linux/compiler-gcc.h \
|
||||
include/asm/posix_types.h \
|
||||
include/asm/types.h \
|
||||
$(wildcard include/config/highmem64g.h) \
|
||||
$(wildcard include/config/lbd.h) \
|
||||
include/linux/spinlock.h \
|
||||
$(wildcard include/config/debug/spinlock.h) \
|
||||
$(wildcard include/config/lockmeter.h) \
|
||||
include/linux/preempt.h \
|
||||
include/linux/linkage.h \
|
||||
include/asm/linkage.h \
|
||||
$(wildcard include/config/regparm.h) \
|
||||
$(wildcard include/config/x86/alignment/16.h) \
|
||||
include/linux/thread_info.h \
|
||||
include/linux/bitops.h \
|
||||
include/asm/bitops.h \
|
||||
include/asm/thread_info.h \
|
||||
$(wildcard include/config/4kstacks.h) \
|
||||
$(wildcard include/config/debug/stack/usage.h) \
|
||||
include/asm/page.h \
|
||||
$(wildcard include/config/x86/use/3dnow.h) \
|
||||
$(wildcard include/config/x86/pae.h) \
|
||||
$(wildcard include/config/hugetlb/page.h) \
|
||||
$(wildcard include/config/highmem4g.h) \
|
||||
$(wildcard include/config/discontigmem.h) \
|
||||
include/asm/processor.h \
|
||||
$(wildcard include/config/mk8.h) \
|
||||
$(wildcard include/config/mk7.h) \
|
||||
include/asm/vm86.h \
|
||||
include/asm/math_emu.h \
|
||||
include/asm/sigcontext.h \
|
||||
include/asm/segment.h \
|
||||
include/asm/cpufeature.h \
|
||||
include/asm/msr.h \
|
||||
include/asm/system.h \
|
||||
$(wildcard include/config/x86/cmpxchg.h) \
|
||||
$(wildcard include/config/x86/oostore.h) \
|
||||
include/linux/kernel.h \
|
||||
$(wildcard include/config/debug/spinlock/sleep.h) \
|
||||
/usr/lib/gcc/i686-pc-linux-gnu/3.4.1/include/stdarg.h \
|
||||
include/asm/byteorder.h \
|
||||
$(wildcard include/config/x86/bswap.h) \
|
||||
include/linux/byteorder/little_endian.h \
|
||||
include/linux/byteorder/swab.h \
|
||||
include/linux/byteorder/generic.h \
|
||||
include/asm/bug.h \
|
||||
include/asm-generic/bug.h \
|
||||
include/linux/cache.h \
|
||||
include/asm/cache.h \
|
||||
$(wildcard include/config/x86/l1/cache/shift.h) \
|
||||
include/linux/threads.h \
|
||||
$(wildcard include/config/nr/cpus.h) \
|
||||
include/asm/percpu.h \
|
||||
include/asm-generic/percpu.h \
|
||||
include/linux/stringify.h \
|
||||
include/linux/timex.h \
|
||||
$(wildcard include/config/time/interpolation.h) \
|
||||
include/linux/time.h \
|
||||
include/linux/seqlock.h \
|
||||
include/asm/timex.h \
|
||||
$(wildcard include/config/x86/elan.h) \
|
||||
$(wildcard include/config/x86/tsc.h) \
|
||||
$(wildcard include/config/x86/generic.h) \
|
||||
include/linux/jiffies.h \
|
||||
include/asm/div64.h \
|
||||
include/linux/rbtree.h \
|
||||
include/linux/cpumask.h \
|
||||
$(wildcard include/config/hotplug/cpu.h) \
|
||||
include/linux/bitmap.h \
|
||||
include/linux/string.h \
|
||||
include/asm/string.h \
|
||||
include/asm/semaphore.h \
|
||||
include/asm/atomic.h \
|
||||
$(wildcard include/config/m386.h) \
|
||||
include/linux/wait.h \
|
||||
include/linux/list.h \
|
||||
include/linux/prefetch.h \
|
||||
include/asm/current.h \
|
||||
include/linux/rwsem.h \
|
||||
$(wildcard include/config/rwsem/generic/spinlock.h) \
|
||||
include/asm/rwsem.h \
|
||||
include/asm/ptrace.h \
|
||||
$(wildcard include/config/frame/pointer.h) \
|
||||
include/asm/mmu.h \
|
||||
include/linux/smp.h \
|
||||
include/linux/sem.h \
|
||||
$(wildcard include/config/sysvipc.h) \
|
||||
include/linux/ipc.h \
|
||||
include/asm/ipcbuf.h \
|
||||
include/asm/sembuf.h \
|
||||
include/linux/signal.h \
|
||||
include/asm/signal.h \
|
||||
include/asm/siginfo.h \
|
||||
include/asm-generic/siginfo.h \
|
||||
include/linux/resource.h \
|
||||
include/asm/resource.h \
|
||||
include/linux/securebits.h \
|
||||
include/linux/fs_struct.h \
|
||||
include/linux/completion.h \
|
||||
include/linux/pid.h \
|
||||
include/linux/percpu.h \
|
||||
include/linux/slab.h \
|
||||
$(wildcard include/config/.h) \
|
||||
include/linux/gfp.h \
|
||||
include/linux/mmzone.h \
|
||||
$(wildcard include/config/force/max/zoneorder.h) \
|
||||
include/linux/numa.h \
|
||||
include/linux/topology.h \
|
||||
$(wildcard include/config/sched/smt.h) \
|
||||
include/asm/topology.h \
|
||||
include/asm-generic/topology.h \
|
||||
include/linux/init.h \
|
||||
$(wildcard include/config/hotplug.h) \
|
||||
include/linux/kmalloc_sizes.h \
|
||||
$(wildcard include/config/mmu.h) \
|
||||
$(wildcard include/config/large/allocs.h) \
|
||||
include/linux/param.h \
|
||||
include/linux/timer.h \
|
||||
include/linux/aio.h \
|
||||
include/linux/workqueue.h \
|
||||
include/linux/aio_abi.h \
|
||||
include/linux/stat.h \
|
||||
include/asm/stat.h \
|
||||
include/linux/kmod.h \
|
||||
$(wildcard include/config/kmod.h) \
|
||||
include/linux/errno.h \
|
||||
include/asm/errno.h \
|
||||
include/asm-generic/errno.h \
|
||||
include/asm-generic/errno-base.h \
|
||||
include/linux/elf.h \
|
||||
include/asm/elf.h \
|
||||
include/asm/user.h \
|
||||
include/linux/utsname.h \
|
||||
include/linux/kobject.h \
|
||||
include/linux/sysfs.h \
|
||||
$(wildcard include/config/sysfs.h) \
|
||||
include/linux/kref.h \
|
||||
include/linux/kobject_uevent.h \
|
||||
$(wildcard include/config/kobject/uevent.h) \
|
||||
include/linux/moduleparam.h \
|
||||
include/asm/local.h \
|
||||
include/asm/module.h \
|
||||
$(wildcard include/config/m486.h) \
|
||||
$(wildcard include/config/m586.h) \
|
||||
$(wildcard include/config/m586tsc.h) \
|
||||
$(wildcard include/config/m586mmx.h) \
|
||||
$(wildcard include/config/m686.h) \
|
||||
$(wildcard include/config/mpentiumii.h) \
|
||||
$(wildcard include/config/mpentiumiii.h) \
|
||||
$(wildcard include/config/mpentiumm.h) \
|
||||
$(wildcard include/config/mpentium4.h) \
|
||||
$(wildcard include/config/mk6.h) \
|
||||
$(wildcard include/config/mcrusoe.h) \
|
||||
$(wildcard include/config/mefficeon.h) \
|
||||
$(wildcard include/config/mwinchipc6.h) \
|
||||
$(wildcard include/config/mwinchip2.h) \
|
||||
$(wildcard include/config/mwinchip3d.h) \
|
||||
$(wildcard include/config/mcyrixiii.h) \
|
||||
$(wildcard include/config/mviac3/2.h) \
|
||||
include/linux/tty.h \
|
||||
$(wildcard include/config/legacy/pty/count.h) \
|
||||
include/linux/fs.h \
|
||||
$(wildcard include/config/dnotify.h) \
|
||||
$(wildcard include/config/quota.h) \
|
||||
$(wildcard include/config/epoll.h) \
|
||||
$(wildcard include/config/auditsyscall.h) \
|
||||
include/linux/limits.h \
|
||||
include/linux/kdev_t.h \
|
||||
include/linux/ioctl.h \
|
||||
include/asm/ioctl.h \
|
||||
include/linux/dcache.h \
|
||||
include/linux/rcupdate.h \
|
||||
include/linux/prio_tree.h \
|
||||
include/linux/radix-tree.h \
|
||||
include/linux/audit.h \
|
||||
$(wildcard include/config/audit.h) \
|
||||
include/linux/quota.h \
|
||||
include/linux/dqblk_xfs.h \
|
||||
include/linux/dqblk_v1.h \
|
||||
include/linux/dqblk_v2.h \
|
||||
include/linux/nfs_fs_i.h \
|
||||
include/linux/nfs.h \
|
||||
include/linux/sunrpc/msg_prot.h \
|
||||
include/linux/fcntl.h \
|
||||
include/asm/fcntl.h \
|
||||
include/linux/err.h \
|
||||
include/linux/major.h \
|
||||
include/linux/termios.h \
|
||||
include/asm/termios.h \
|
||||
include/asm/termbits.h \
|
||||
include/asm/ioctls.h \
|
||||
include/linux/tty_driver.h \
|
||||
include/linux/cdev.h \
|
||||
include/linux/tty_ldisc.h \
|
||||
include/linux/console.h \
|
||||
include/linux/serial_core.h \
|
||||
$(wildcard include/config/hard/pps.h) \
|
||||
include/linux/interrupt.h \
|
||||
$(wildcard include/config/generic/hardirqs.h) \
|
||||
$(wildcard include/config/generic/irq/probe.h) \
|
||||
include/linux/hardirq.h \
|
||||
include/linux/smp_lock.h \
|
||||
$(wildcard include/config/lock/kernel.h) \
|
||||
include/asm/hardirq.h \
|
||||
include/linux/irq.h \
|
||||
$(wildcard include/config/arch/s390.h) \
|
||||
include/asm/irq.h \
|
||||
$(wildcard include/config/x86/local/apic.h) \
|
||||
$(wildcard include/config/irqbalance.h) \
|
||||
include/asm-i386/mach-default/irq_vectors.h \
|
||||
include/asm-i386/mach-default/irq_vectors_limits.h \
|
||||
$(wildcard include/config/pci/msi.h) \
|
||||
$(wildcard include/config/x86/io/apic.h) \
|
||||
include/asm/hw_irq.h \
|
||||
include/linux/profile.h \
|
||||
$(wildcard include/config/profiling.h) \
|
||||
include/asm/sections.h \
|
||||
include/asm-generic/sections.h \
|
||||
include/linux/irq_cpustat.h \
|
||||
include/linux/circ_buf.h \
|
||||
include/linux/device.h \
|
||||
include/linux/ioport.h \
|
||||
include/linux/pm.h \
|
||||
$(wildcard include/config/pm.h) \
|
||||
include/linux/serial.h \
|
||||
include/linux/delay.h \
|
||||
include/asm/delay.h \
|
||||
include/asm/uaccess.h \
|
||||
$(wildcard include/config/x86/intel/usercopy.h) \
|
||||
$(wildcard include/config/x86/wp/works/ok.h) \
|
||||
|
||||
drivers/serial/serial_core.o: $(deps_drivers/serial/serial_core.o)
|
||||
|
||||
$(deps_drivers/serial/serial_core.o):
|
||||
544
extra/linux-2.6.10/drivers/serial/21285.c
Normal file
544
extra/linux-2.6.10/drivers/serial/21285.c
Normal file
@@ -0,0 +1,544 @@
|
||||
/*
|
||||
* linux/drivers/char/21285.c
|
||||
*
|
||||
* Driver for the serial port on the 21285 StrongArm-110 core logic chip.
|
||||
*
|
||||
* Based on drivers/char/serial.c
|
||||
*
|
||||
* $Id: 21285.c,v 1.37 2002/07/28 10:03:27 rmk Exp $
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/hardware/dec21285.h>
|
||||
#include <asm/hardware.h>
|
||||
|
||||
#define BAUD_BASE (mem_fclk_21285/64)
|
||||
|
||||
#define SERIAL_21285_NAME "ttyFB"
|
||||
#define SERIAL_21285_MAJOR 204
|
||||
#define SERIAL_21285_MINOR 4
|
||||
|
||||
#define RXSTAT_DUMMY_READ 0x80000000
|
||||
#define RXSTAT_FRAME (1 << 0)
|
||||
#define RXSTAT_PARITY (1 << 1)
|
||||
#define RXSTAT_OVERRUN (1 << 2)
|
||||
#define RXSTAT_ANYERR (RXSTAT_FRAME|RXSTAT_PARITY|RXSTAT_OVERRUN)
|
||||
|
||||
#define H_UBRLCR_BREAK (1 << 0)
|
||||
#define H_UBRLCR_PARENB (1 << 1)
|
||||
#define H_UBRLCR_PAREVN (1 << 2)
|
||||
#define H_UBRLCR_STOPB (1 << 3)
|
||||
#define H_UBRLCR_FIFO (1 << 4)
|
||||
|
||||
static const char serial21285_name[] = "Footbridge UART";
|
||||
|
||||
#define tx_enabled(port) ((port)->unused[0])
|
||||
#define rx_enabled(port) ((port)->unused[1])
|
||||
|
||||
/*
|
||||
* The documented expression for selecting the divisor is:
|
||||
* BAUD_BASE / baud - 1
|
||||
* However, typically BAUD_BASE is not divisible by baud, so
|
||||
* we want to select the divisor that gives us the minimum
|
||||
* error. Therefore, we want:
|
||||
* int(BAUD_BASE / baud - 0.5) ->
|
||||
* int(BAUD_BASE / baud - (baud >> 1) / baud) ->
|
||||
* int((BAUD_BASE - (baud >> 1)) / baud)
|
||||
*/
|
||||
|
||||
static void
|
||||
serial21285_stop_tx(struct uart_port *port, unsigned int tty_stop)
|
||||
{
|
||||
if (tx_enabled(port)) {
|
||||
disable_irq(IRQ_CONTX);
|
||||
tx_enabled(port) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
serial21285_start_tx(struct uart_port *port, unsigned int tty_start)
|
||||
{
|
||||
if (!tx_enabled(port)) {
|
||||
enable_irq(IRQ_CONTX);
|
||||
tx_enabled(port) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void serial21285_stop_rx(struct uart_port *port)
|
||||
{
|
||||
if (rx_enabled(port)) {
|
||||
disable_irq(IRQ_CONRX);
|
||||
rx_enabled(port) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void serial21285_enable_ms(struct uart_port *port)
|
||||
{
|
||||
}
|
||||
|
||||
static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct uart_port *port = dev_id;
|
||||
struct tty_struct *tty = port->info->tty;
|
||||
unsigned int status, ch, flag, rxs, max_count = 256;
|
||||
|
||||
status = *CSR_UARTFLG;
|
||||
while (!(status & 0x10) && max_count--) {
|
||||
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
|
||||
if (tty->low_latency)
|
||||
tty_flip_buffer_push(tty);
|
||||
/*
|
||||
* If this failed then we will throw away the
|
||||
* bytes but must do so to clear interrupts
|
||||
*/
|
||||
}
|
||||
|
||||
ch = *CSR_UARTDR;
|
||||
flag = TTY_NORMAL;
|
||||
port->icount.rx++;
|
||||
|
||||
rxs = *CSR_RXSTAT | RXSTAT_DUMMY_READ;
|
||||
if (rxs & RXSTAT_ANYERR) {
|
||||
if (rxs & RXSTAT_PARITY)
|
||||
port->icount.parity++;
|
||||
else if (rxs & RXSTAT_FRAME)
|
||||
port->icount.frame++;
|
||||
if (rxs & RXSTAT_OVERRUN)
|
||||
port->icount.overrun++;
|
||||
|
||||
rxs &= port->read_status_mask;
|
||||
|
||||
if (rxs & RXSTAT_PARITY)
|
||||
flag = TTY_PARITY;
|
||||
else if (rxs & RXSTAT_FRAME)
|
||||
flag = TTY_FRAME;
|
||||
}
|
||||
|
||||
if ((rxs & port->ignore_status_mask) == 0) {
|
||||
tty_insert_flip_char(tty, ch, flag);
|
||||
}
|
||||
if ((rxs & RXSTAT_OVERRUN) &&
|
||||
tty->flip.count < TTY_FLIPBUF_SIZE) {
|
||||
/*
|
||||
* Overrun is special, since it's reported
|
||||
* immediately, and doesn't affect the current
|
||||
* character.
|
||||
*/
|
||||
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
|
||||
}
|
||||
status = *CSR_UARTFLG;
|
||||
}
|
||||
tty_flip_buffer_push(tty);
|
||||
|
||||
out:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct uart_port *port = dev_id;
|
||||
struct circ_buf *xmit = &port->info->xmit;
|
||||
int count = 256;
|
||||
|
||||
if (port->x_char) {
|
||||
*CSR_UARTDR = port->x_char;
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
goto out;
|
||||
}
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
|
||||
serial21285_stop_tx(port, 0);
|
||||
goto out;
|
||||
}
|
||||
|
||||
do {
|
||||
*CSR_UARTDR = xmit->buf[xmit->tail];
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
} while (--count > 0 && !(*CSR_UARTFLG & 0x20));
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
serial21285_stop_tx(port, 0);
|
||||
|
||||
out:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static unsigned int serial21285_tx_empty(struct uart_port *port)
|
||||
{
|
||||
return (*CSR_UARTFLG & 8) ? 0 : TIOCSER_TEMT;
|
||||
}
|
||||
|
||||
/* no modem control lines */
|
||||
static unsigned int serial21285_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
|
||||
}
|
||||
|
||||
static void serial21285_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
}
|
||||
|
||||
static void serial21285_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int h_lcr;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
h_lcr = *CSR_H_UBRLCR;
|
||||
if (break_state)
|
||||
h_lcr |= H_UBRLCR_BREAK;
|
||||
else
|
||||
h_lcr &= ~H_UBRLCR_BREAK;
|
||||
*CSR_H_UBRLCR = h_lcr;
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static int serial21285_startup(struct uart_port *port)
|
||||
{
|
||||
int ret;
|
||||
|
||||
tx_enabled(port) = 1;
|
||||
rx_enabled(port) = 1;
|
||||
|
||||
ret = request_irq(IRQ_CONRX, serial21285_rx_chars, 0,
|
||||
serial21285_name, port);
|
||||
if (ret == 0) {
|
||||
ret = request_irq(IRQ_CONTX, serial21285_tx_chars, 0,
|
||||
serial21285_name, port);
|
||||
if (ret)
|
||||
free_irq(IRQ_CONRX, port);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void serial21285_shutdown(struct uart_port *port)
|
||||
{
|
||||
free_irq(IRQ_CONTX, port);
|
||||
free_irq(IRQ_CONRX, port);
|
||||
}
|
||||
|
||||
static void
|
||||
serial21285_set_termios(struct uart_port *port, struct termios *termios,
|
||||
struct termios *old)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int baud, quot, h_lcr;
|
||||
|
||||
/*
|
||||
* We don't support modem control lines.
|
||||
*/
|
||||
termios->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR);
|
||||
termios->c_cflag |= CLOCAL;
|
||||
|
||||
/*
|
||||
* We don't support BREAK character recognition.
|
||||
*/
|
||||
termios->c_iflag &= ~(IGNBRK | BRKINT);
|
||||
|
||||
/*
|
||||
* Ask the core to calculate the divisor for us.
|
||||
*/
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
|
||||
quot = uart_get_divisor(port, baud);
|
||||
|
||||
switch (termios->c_cflag & CSIZE) {
|
||||
case CS5:
|
||||
h_lcr = 0x00;
|
||||
break;
|
||||
case CS6:
|
||||
h_lcr = 0x20;
|
||||
break;
|
||||
case CS7:
|
||||
h_lcr = 0x40;
|
||||
break;
|
||||
default: /* CS8 */
|
||||
h_lcr = 0x60;
|
||||
break;
|
||||
}
|
||||
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
h_lcr |= H_UBRLCR_STOPB;
|
||||
if (termios->c_cflag & PARENB) {
|
||||
h_lcr |= H_UBRLCR_PARENB;
|
||||
if (!(termios->c_cflag & PARODD))
|
||||
h_lcr |= H_UBRLCR_PAREVN;
|
||||
}
|
||||
|
||||
if (port->fifosize)
|
||||
h_lcr |= H_UBRLCR_FIFO;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
/*
|
||||
* Update the per-port timeout.
|
||||
*/
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
/*
|
||||
* Which character status flags are we interested in?
|
||||
*/
|
||||
port->read_status_mask = RXSTAT_OVERRUN;
|
||||
if (termios->c_iflag & INPCK)
|
||||
port->read_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY;
|
||||
|
||||
/*
|
||||
* Which character status flags should we ignore?
|
||||
*/
|
||||
port->ignore_status_mask = 0;
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
port->ignore_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY;
|
||||
if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR)
|
||||
port->ignore_status_mask |= RXSTAT_OVERRUN;
|
||||
|
||||
/*
|
||||
* Ignore all characters if CREAD is not set.
|
||||
*/
|
||||
if ((termios->c_cflag & CREAD) == 0)
|
||||
port->ignore_status_mask |= RXSTAT_DUMMY_READ;
|
||||
|
||||
quot -= 1;
|
||||
|
||||
*CSR_UARTCON = 0;
|
||||
*CSR_L_UBRLCR = quot & 0xff;
|
||||
*CSR_M_UBRLCR = (quot >> 8) & 0x0f;
|
||||
*CSR_H_UBRLCR = h_lcr;
|
||||
*CSR_UARTCON = 1;
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static const char *serial21285_type(struct uart_port *port)
|
||||
{
|
||||
return port->type == PORT_21285 ? "DC21285" : NULL;
|
||||
}
|
||||
|
||||
static void serial21285_release_port(struct uart_port *port)
|
||||
{
|
||||
release_mem_region(port->mapbase, 32);
|
||||
}
|
||||
|
||||
static int serial21285_request_port(struct uart_port *port)
|
||||
{
|
||||
return request_mem_region(port->mapbase, 32, serial21285_name)
|
||||
!= NULL ? 0 : -EBUSY;
|
||||
}
|
||||
|
||||
static void serial21285_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
if (flags & UART_CONFIG_TYPE && serial21285_request_port(port) == 0)
|
||||
port->type = PORT_21285;
|
||||
}
|
||||
|
||||
/*
|
||||
* verify the new serial_struct (for TIOCSSERIAL).
|
||||
*/
|
||||
static int serial21285_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||
{
|
||||
int ret = 0;
|
||||
if (ser->type != PORT_UNKNOWN && ser->type != PORT_21285)
|
||||
ret = -EINVAL;
|
||||
if (ser->irq != NO_IRQ)
|
||||
ret = -EINVAL;
|
||||
if (ser->baud_base != port->uartclk / 16)
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct uart_ops serial21285_ops = {
|
||||
.tx_empty = serial21285_tx_empty,
|
||||
.get_mctrl = serial21285_get_mctrl,
|
||||
.set_mctrl = serial21285_set_mctrl,
|
||||
.stop_tx = serial21285_stop_tx,
|
||||
.start_tx = serial21285_start_tx,
|
||||
.stop_rx = serial21285_stop_rx,
|
||||
.enable_ms = serial21285_enable_ms,
|
||||
.break_ctl = serial21285_break_ctl,
|
||||
.startup = serial21285_startup,
|
||||
.shutdown = serial21285_shutdown,
|
||||
.set_termios = serial21285_set_termios,
|
||||
.type = serial21285_type,
|
||||
.release_port = serial21285_release_port,
|
||||
.request_port = serial21285_request_port,
|
||||
.config_port = serial21285_config_port,
|
||||
.verify_port = serial21285_verify_port,
|
||||
};
|
||||
|
||||
static struct uart_port serial21285_port = {
|
||||
.membase = 0,
|
||||
.mapbase = 0x42000160,
|
||||
.iotype = SERIAL_IO_MEM,
|
||||
.irq = NO_IRQ,
|
||||
.uartclk = 0,
|
||||
.fifosize = 16,
|
||||
.ops = &serial21285_ops,
|
||||
.flags = ASYNC_BOOT_AUTOCONF,
|
||||
};
|
||||
|
||||
static void serial21285_setup_ports(void)
|
||||
{
|
||||
serial21285_port.uartclk = mem_fclk_21285 / 4;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_21285_CONSOLE
|
||||
|
||||
static void
|
||||
serial21285_console_write(struct console *co, const char *s,
|
||||
unsigned int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
while (*CSR_UARTFLG & 0x20)
|
||||
barrier();
|
||||
*CSR_UARTDR = s[i];
|
||||
if (s[i] == '\n') {
|
||||
while (*CSR_UARTFLG & 0x20)
|
||||
barrier();
|
||||
*CSR_UARTDR = '\r';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void __init
|
||||
serial21285_get_options(struct uart_port *port, int *baud,
|
||||
int *parity, int *bits)
|
||||
{
|
||||
if (*CSR_UARTCON == 1) {
|
||||
unsigned int tmp;
|
||||
|
||||
tmp = *CSR_H_UBRLCR;
|
||||
switch (tmp & 0x60) {
|
||||
case 0x00:
|
||||
*bits = 5;
|
||||
break;
|
||||
case 0x20:
|
||||
*bits = 6;
|
||||
break;
|
||||
case 0x40:
|
||||
*bits = 7;
|
||||
break;
|
||||
default:
|
||||
case 0x60:
|
||||
*bits = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tmp & H_UBRLCR_PARENB) {
|
||||
*parity = 'o';
|
||||
if (tmp & H_UBRLCR_PAREVN)
|
||||
*parity = 'e';
|
||||
}
|
||||
|
||||
tmp = *CSR_L_UBRLCR | (*CSR_M_UBRLCR << 8);
|
||||
|
||||
*baud = port->uartclk / (16 * (tmp + 1));
|
||||
}
|
||||
}
|
||||
|
||||
static int __init serial21285_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_port *port = &serial21285_port;
|
||||
int baud = 9600;
|
||||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
|
||||
if (machine_is_personal_server())
|
||||
baud = 57600;
|
||||
|
||||
/*
|
||||
* Check whether an invalid uart number has been specified, and
|
||||
* if so, search for the first available port that does have
|
||||
* console support.
|
||||
*/
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
else
|
||||
serial21285_get_options(port, &baud, &parity, &bits);
|
||||
|
||||
return uart_set_options(port, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
extern struct uart_driver serial21285_reg;
|
||||
|
||||
static struct console serial21285_console =
|
||||
{
|
||||
.name = SERIAL_21285_NAME,
|
||||
.write = serial21285_console_write,
|
||||
.device = uart_console_device,
|
||||
.setup = serial21285_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
.data = &serial21285_reg,
|
||||
};
|
||||
|
||||
static int __init rs285_console_init(void)
|
||||
{
|
||||
serial21285_setup_ports();
|
||||
register_console(&serial21285_console);
|
||||
return 0;
|
||||
}
|
||||
console_initcall(rs285_console_init);
|
||||
|
||||
#define SERIAL_21285_CONSOLE &serial21285_console
|
||||
#else
|
||||
#define SERIAL_21285_CONSOLE NULL
|
||||
#endif
|
||||
|
||||
static struct uart_driver serial21285_reg = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = "ttyFB",
|
||||
.dev_name = "ttyFB",
|
||||
.devfs_name = "ttyFB",
|
||||
.major = SERIAL_21285_MAJOR,
|
||||
.minor = SERIAL_21285_MINOR,
|
||||
.nr = 1,
|
||||
.cons = SERIAL_21285_CONSOLE,
|
||||
};
|
||||
|
||||
static int __init serial21285_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printk(KERN_INFO "Serial: 21285 driver $Revision: 1.37 $\n");
|
||||
|
||||
serial21285_setup_ports();
|
||||
|
||||
ret = uart_register_driver(&serial21285_reg);
|
||||
if (ret == 0)
|
||||
uart_add_one_port(&serial21285_reg, &serial21285_port);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit serial21285_exit(void)
|
||||
{
|
||||
uart_remove_one_port(&serial21285_reg, &serial21285_port);
|
||||
uart_unregister_driver(&serial21285_reg);
|
||||
}
|
||||
|
||||
module_init(serial21285_init);
|
||||
module_exit(serial21285_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver $Revision: 1.37 $");
|
||||
MODULE_ALIAS_CHARDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
|
||||
1619
extra/linux-2.6.10/drivers/serial/68328serial.c
Normal file
1619
extra/linux-2.6.10/drivers/serial/68328serial.c
Normal file
File diff suppressed because it is too large
Load Diff
194
extra/linux-2.6.10/drivers/serial/68328serial.h
Normal file
194
extra/linux-2.6.10/drivers/serial/68328serial.h
Normal file
@@ -0,0 +1,194 @@
|
||||
/* 68328serial.h: Definitions for the mc68328 serial driver.
|
||||
*
|
||||
* Copyright (C) 1995 David S. Miller <davem@caip.rutgers.edu>
|
||||
* Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
|
||||
* Copyright (C) 1998, 1999 D. Jeff Dionne <jeff@uclinux.org>
|
||||
* Copyright (C) 1999 Vladimir Gurevich <vgurevic@cisco.com>
|
||||
*
|
||||
* VZ Support/Fixes Evan Stawnyczy <e@lineo.ca>
|
||||
*/
|
||||
|
||||
#ifndef _MC683XX_SERIAL_H
|
||||
#define _MC683XX_SERIAL_H
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
struct serial_struct {
|
||||
int type;
|
||||
int line;
|
||||
int port;
|
||||
int irq;
|
||||
int flags;
|
||||
int xmit_fifo_size;
|
||||
int custom_divisor;
|
||||
int baud_base;
|
||||
unsigned short close_delay;
|
||||
char reserved_char[2];
|
||||
int hub6; /* FIXME: We don't have AT&T Hub6 boards! */
|
||||
unsigned short closing_wait; /* time to wait before closing */
|
||||
unsigned short closing_wait2; /* no longer used... */
|
||||
int reserved[4];
|
||||
};
|
||||
|
||||
/*
|
||||
* For the close wait times, 0 means wait forever for serial port to
|
||||
* flush its output. 65535 means don't wait at all.
|
||||
*/
|
||||
#define S_CLOSING_WAIT_INF 0
|
||||
#define S_CLOSING_WAIT_NONE 65535
|
||||
|
||||
/*
|
||||
* Definitions for S_struct (and serial_struct) flags field
|
||||
*/
|
||||
#define S_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes
|
||||
on the callout port */
|
||||
#define S_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */
|
||||
#define S_SAK 0x0004 /* Secure Attention Key (Orange book) */
|
||||
#define S_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */
|
||||
|
||||
#define S_SPD_MASK 0x0030
|
||||
#define S_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */
|
||||
|
||||
#define S_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */
|
||||
#define S_SPD_CUST 0x0030 /* Use user-specified divisor */
|
||||
|
||||
#define S_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */
|
||||
#define S_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */
|
||||
#define S_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */
|
||||
#define S_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */
|
||||
#define S_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */
|
||||
|
||||
#define S_FLAGS 0x0FFF /* Possible legal S flags */
|
||||
#define S_USR_MASK 0x0430 /* Legal flags that non-privileged
|
||||
* users can set or reset */
|
||||
|
||||
/* Internal flags used only by kernel/chr_drv/serial.c */
|
||||
#define S_INITIALIZED 0x80000000 /* Serial port was initialized */
|
||||
#define S_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */
|
||||
#define S_NORMAL_ACTIVE 0x20000000 /* Normal device is active */
|
||||
#define S_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */
|
||||
#define S_CLOSING 0x08000000 /* Serial port is closing */
|
||||
#define S_CTS_FLOW 0x04000000 /* Do CTS flow control */
|
||||
#define S_CHECK_CD 0x02000000 /* i.e., CLOCAL */
|
||||
|
||||
/* Software state per channel */
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/*
|
||||
* I believe this is the optimal setting that reduces the number of interrupts.
|
||||
* At high speeds the output might become a little "bursted" (use USTCNT_TXHE
|
||||
* if that bothers you), but in most cases it will not, since we try to
|
||||
* transmit characters every time rs_interrupt is called. Thus, quite often
|
||||
* you'll see that a receive interrupt occures before the transmit one.
|
||||
* -- Vladimir Gurevich
|
||||
*/
|
||||
#define USTCNT_TX_INTR_MASK (USTCNT_TXEE)
|
||||
|
||||
/*
|
||||
* 68328 and 68EZ328 UARTS are a little bit different. EZ328 has special
|
||||
* "Old data interrupt" which occures whenever the data stay in the FIFO
|
||||
* longer than 30 bits time. This allows us to use FIFO without compromising
|
||||
* latency. '328 does not have this feature and without the real 328-based
|
||||
* board I would assume that RXRE is the safest setting.
|
||||
*
|
||||
* For EZ328 I use RXHE (Half empty) interrupt to reduce the number of
|
||||
* interrupts. RXFE (receive queue full) causes the system to lose data
|
||||
* at least at 115200 baud
|
||||
*
|
||||
* If your board is busy doing other stuff, you might consider to use
|
||||
* RXRE (data ready intrrupt) instead.
|
||||
*
|
||||
* The other option is to make these INTR masks run-time configurable, so
|
||||
* that people can dynamically adapt them according to the current usage.
|
||||
* -- Vladimir Gurevich
|
||||
*/
|
||||
|
||||
/* (es) */
|
||||
#if defined(CONFIG_M68EZ328) || defined(CONFIG_M68VZ328)
|
||||
#define USTCNT_RX_INTR_MASK (USTCNT_RXHE | USTCNT_ODEN)
|
||||
#elif defined(CONFIG_M68328)
|
||||
#define USTCNT_RX_INTR_MASK (USTCNT_RXRE)
|
||||
#else
|
||||
#error Please, define the Rx interrupt events for your CPU
|
||||
#endif
|
||||
/* (/es) */
|
||||
|
||||
/*
|
||||
* This is our internal structure for each serial port's state.
|
||||
*
|
||||
* Many fields are paralleled by the structure used by the serial_struct
|
||||
* structure.
|
||||
*
|
||||
* For definitions of the flags field, see tty.h
|
||||
*/
|
||||
|
||||
struct m68k_serial {
|
||||
char soft_carrier; /* Use soft carrier on this channel */
|
||||
char break_abort; /* Is serial console in, so process brk/abrt */
|
||||
char is_cons; /* Is this our console. */
|
||||
|
||||
/* We need to know the current clock divisor
|
||||
* to read the bps rate the chip has currently
|
||||
* loaded.
|
||||
*/
|
||||
unsigned char clk_divisor; /* May be 1, 16, 32, or 64 */
|
||||
int baud;
|
||||
int magic;
|
||||
int baud_base;
|
||||
int port;
|
||||
int irq;
|
||||
int flags; /* defined in tty.h */
|
||||
int type; /* UART type */
|
||||
struct tty_struct *tty;
|
||||
int read_status_mask;
|
||||
int ignore_status_mask;
|
||||
int timeout;
|
||||
int xmit_fifo_size;
|
||||
int custom_divisor;
|
||||
int x_char; /* xon/xoff character */
|
||||
int close_delay;
|
||||
unsigned short closing_wait;
|
||||
unsigned short closing_wait2;
|
||||
unsigned long event;
|
||||
unsigned long last_active;
|
||||
int line;
|
||||
int count; /* # of fd on device */
|
||||
int blocked_open; /* # of blocked opens */
|
||||
unsigned char *xmit_buf;
|
||||
int xmit_head;
|
||||
int xmit_tail;
|
||||
int xmit_cnt;
|
||||
struct work_struct tqueue;
|
||||
struct work_struct tqueue_hangup;
|
||||
wait_queue_head_t open_wait;
|
||||
wait_queue_head_t close_wait;
|
||||
};
|
||||
|
||||
|
||||
#define SERIAL_MAGIC 0x5301
|
||||
|
||||
/*
|
||||
* The size of the serial xmit buffer is 1 page, or 4096 bytes
|
||||
*/
|
||||
#define SERIAL_XMIT_SIZE 4096
|
||||
|
||||
/*
|
||||
* Events are used to schedule things to happen at timer-interrupt
|
||||
* time, instead of at rs interrupt time.
|
||||
*/
|
||||
#define RS_EVENT_WRITE_WAKEUP 0
|
||||
|
||||
/*
|
||||
* Define the number of ports supported and their irqs.
|
||||
*/
|
||||
#ifndef CONFIG_68328_SERIAL_UART2
|
||||
#define NR_PORTS 1
|
||||
#define UART_IRQ_DEFNS {UART_IRQ_NUM}
|
||||
#else
|
||||
#define NR_PORTS 2
|
||||
#define UART_IRQ_DEFNS {UART1_IRQ_NUM, UART2_IRQ_NUM}
|
||||
#endif
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* !(_MC683XX_SERIAL_H) */
|
||||
3027
extra/linux-2.6.10/drivers/serial/68360serial.c
Normal file
3027
extra/linux-2.6.10/drivers/serial/68360serial.c
Normal file
File diff suppressed because it is too large
Load Diff
2583
extra/linux-2.6.10/drivers/serial/8250.c
Normal file
2583
extra/linux-2.6.10/drivers/serial/8250.c
Normal file
File diff suppressed because it is too large
Load Diff
85
extra/linux-2.6.10/drivers/serial/8250.h
Normal file
85
extra/linux-2.6.10/drivers/serial/8250.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* linux/drivers/char/8250.h
|
||||
*
|
||||
* Driver for 8250/16550-type serial ports
|
||||
*
|
||||
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
|
||||
*
|
||||
* Copyright (C) 2001 Russell King.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id: 8250.h,v 1.8 2002/07/21 21:32:30 rmk Exp $
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
int serial8250_register_port(struct uart_port *);
|
||||
void serial8250_unregister_port(int line);
|
||||
void serial8250_suspend_port(int line);
|
||||
void serial8250_resume_port(int line);
|
||||
|
||||
struct old_serial_port {
|
||||
unsigned int uart;
|
||||
unsigned int baud_base;
|
||||
unsigned int port;
|
||||
unsigned int irq;
|
||||
unsigned int flags;
|
||||
unsigned char hub6;
|
||||
unsigned char io_type;
|
||||
unsigned char *iomem_base;
|
||||
unsigned short iomem_reg_shift;
|
||||
};
|
||||
|
||||
/*
|
||||
* This replaces serial_uart_config in include/linux/serial.h
|
||||
*/
|
||||
struct serial8250_config {
|
||||
const char *name;
|
||||
unsigned short fifo_size;
|
||||
unsigned short tx_loadsz;
|
||||
unsigned char fcr;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
#define UART_CAP_FIFO (1 << 8) /* UART has FIFO */
|
||||
#define UART_CAP_EFR (1 << 9) /* UART has EFR */
|
||||
#define UART_CAP_SLEEP (1 << 10) /* UART has IER sleep */
|
||||
#define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */
|
||||
|
||||
#undef SERIAL_DEBUG_PCI
|
||||
|
||||
#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
|
||||
#define SERIAL_INLINE
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_INLINE
|
||||
#define _INLINE_ inline
|
||||
#else
|
||||
#define _INLINE_
|
||||
#endif
|
||||
|
||||
#define PROBE_RSA (1 << 0)
|
||||
#define PROBE_ANY (~0)
|
||||
|
||||
#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_SHARE_IRQ
|
||||
#define SERIAL8250_SHARE_IRQS 1
|
||||
#else
|
||||
#define SERIAL8250_SHARE_IRQS 0
|
||||
#endif
|
||||
|
||||
#if defined(__alpha__) && !defined(CONFIG_PCI)
|
||||
/*
|
||||
* Digital did something really horribly wrong with the OUT1 and OUT2
|
||||
* lines on at least some ALPHA's. The failure mode is that if either
|
||||
* is cleared, the machine locks up with endless interrupts.
|
||||
*/
|
||||
#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1)
|
||||
#else
|
||||
#define ALPHA_KLUDGE_MCR 0
|
||||
#endif
|
||||
BIN
extra/linux-2.6.10/drivers/serial/8250.o
Normal file
BIN
extra/linux-2.6.10/drivers/serial/8250.o
Normal file
Binary file not shown.
142
extra/linux-2.6.10/drivers/serial/8250_acorn.c
Normal file
142
extra/linux-2.6.10/drivers/serial/8250_acorn.c
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* linux/drivers/serial/acorn.c
|
||||
*
|
||||
* Copyright (C) 1996-2003 Russell King.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/ecard.h>
|
||||
#include <asm/string.h>
|
||||
|
||||
#include "8250.h"
|
||||
|
||||
#define MAX_PORTS 3
|
||||
|
||||
struct serial_card_type {
|
||||
unsigned int num_ports;
|
||||
unsigned int uartclk;
|
||||
unsigned int type;
|
||||
unsigned int offset[MAX_PORTS];
|
||||
};
|
||||
|
||||
struct serial_card_info {
|
||||
unsigned int num_ports;
|
||||
int ports[MAX_PORTS];
|
||||
};
|
||||
|
||||
static int __devinit
|
||||
serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
|
||||
{
|
||||
struct serial_card_info *info;
|
||||
struct serial_card_type *type = id->data;
|
||||
struct uart_port port;
|
||||
unsigned long bus_addr;
|
||||
unsigned char __iomem *virt_addr;
|
||||
unsigned int i;
|
||||
|
||||
info = kmalloc(sizeof(struct serial_card_info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(info, 0, sizeof(struct serial_card_info));
|
||||
info->num_ports = type->num_ports;
|
||||
|
||||
bus_addr = ecard_resource_start(ec, type->type);
|
||||
virt_addr = ioremap(bus_addr, ecard_resource_len(ec, type->type));
|
||||
if (!virt_addr) {
|
||||
kfree(info);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ecard_set_drvdata(ec, info);
|
||||
|
||||
memset(&port, 0, sizeof(struct uart_port));
|
||||
port.irq = ec->irq;
|
||||
port.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
|
||||
port.uartclk = type->uartclk;
|
||||
port.iotype = UPIO_MEM;
|
||||
port.regshift = 2;
|
||||
port.dev = &ec->dev;
|
||||
|
||||
for (i = 0; i < info->num_ports; i ++) {
|
||||
port.membase = virt_addr + type->offset[i];
|
||||
port.mapbase = bus_addr + type->offset[i];
|
||||
|
||||
info->ports[i] = serial8250_register_port(&port);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __devexit serial_card_remove(struct expansion_card *ec)
|
||||
{
|
||||
struct serial_card_info *info = ecard_get_drvdata(ec);
|
||||
int i;
|
||||
|
||||
ecard_set_drvdata(ec, NULL);
|
||||
|
||||
for (i = 0; i < info->num_ports; i++)
|
||||
if (info->ports[i] > 0)
|
||||
serial8250_unregister_port(info->ports[i]);
|
||||
|
||||
kfree(info);
|
||||
}
|
||||
|
||||
static struct serial_card_type atomwide_type = {
|
||||
.num_ports = 3,
|
||||
.uartclk = 7372800,
|
||||
.type = ECARD_RES_IOCSLOW,
|
||||
.offset = { 0x2800, 0x2400, 0x2000 },
|
||||
};
|
||||
|
||||
static struct serial_card_type serport_type = {
|
||||
.num_ports = 2,
|
||||
.uartclk = 3686400,
|
||||
.type = ECARD_RES_IOCSLOW,
|
||||
.offset = { 0x2000, 0x2020 },
|
||||
};
|
||||
|
||||
static const struct ecard_id serial_cids[] = {
|
||||
{ MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL, &atomwide_type },
|
||||
{ MANU_SERPORT, PROD_SERPORT_DSPORT, &serport_type },
|
||||
{ 0xffff, 0xffff }
|
||||
};
|
||||
|
||||
static struct ecard_driver serial_card_driver = {
|
||||
.probe = serial_card_probe,
|
||||
.remove = __devexit_p(serial_card_remove),
|
||||
.id_table = serial_cids,
|
||||
.drv = {
|
||||
.name = "8250_acorn",
|
||||
},
|
||||
};
|
||||
|
||||
static int __init serial_card_init(void)
|
||||
{
|
||||
return ecard_register_driver(&serial_card_driver);
|
||||
}
|
||||
|
||||
static void __exit serial_card_exit(void)
|
||||
{
|
||||
ecard_remove_driver(&serial_card_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Russell King");
|
||||
MODULE_DESCRIPTION("Acorn 8250-compatible serial port expansion card driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(serial_card_init);
|
||||
module_exit(serial_card_exit);
|
||||
171
extra/linux-2.6.10/drivers/serial/8250_acpi.c
Normal file
171
extra/linux-2.6.10/drivers/serial/8250_acpi.c
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2003 Matthew Wilcox for Hewlett-Packard
|
||||
* Copyright (C) 2004 Hewlett-Packard Co
|
||||
* Bjorn Helgaas <bjorn.helgaas@hp.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/serial_core.h>
|
||||
|
||||
#include <acpi/acpi_bus.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "8250.h"
|
||||
|
||||
struct serial_private {
|
||||
int line;
|
||||
};
|
||||
|
||||
static acpi_status acpi_serial_mmio(struct uart_port *port,
|
||||
struct acpi_resource_address64 *addr)
|
||||
{
|
||||
port->mapbase = addr->min_address_range;
|
||||
port->iotype = UPIO_MEM;
|
||||
port->flags |= UPF_IOREMAP;
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static acpi_status acpi_serial_port(struct uart_port *port,
|
||||
struct acpi_resource_io *io)
|
||||
{
|
||||
if (io->range_length) {
|
||||
port->iobase = io->min_base_address;
|
||||
port->iotype = UPIO_PORT;
|
||||
} else
|
||||
printk(KERN_ERR "%s: zero-length IO port range?\n", __FUNCTION__);
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static acpi_status acpi_serial_ext_irq(struct uart_port *port,
|
||||
struct acpi_resource_ext_irq *ext_irq)
|
||||
{
|
||||
if (ext_irq->number_of_interrupts > 0)
|
||||
port->irq = acpi_register_gsi(ext_irq->interrupts[0],
|
||||
ext_irq->edge_level, ext_irq->active_high_low);
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static acpi_status acpi_serial_irq(struct uart_port *port,
|
||||
struct acpi_resource_irq *irq)
|
||||
{
|
||||
if (irq->number_of_interrupts > 0)
|
||||
port->irq = acpi_register_gsi(irq->interrupts[0],
|
||||
irq->edge_level, irq->active_high_low);
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static acpi_status acpi_serial_resource(struct acpi_resource *res, void *data)
|
||||
{
|
||||
struct uart_port *port = (struct uart_port *) data;
|
||||
struct acpi_resource_address64 addr;
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_resource_to_address64(res, &addr);
|
||||
if (ACPI_SUCCESS(status))
|
||||
return acpi_serial_mmio(port, &addr);
|
||||
else if (res->id == ACPI_RSTYPE_IO)
|
||||
return acpi_serial_port(port, &res->data.io);
|
||||
else if (res->id == ACPI_RSTYPE_EXT_IRQ)
|
||||
return acpi_serial_ext_irq(port, &res->data.extended_irq);
|
||||
else if (res->id == ACPI_RSTYPE_IRQ)
|
||||
return acpi_serial_irq(port, &res->data.irq);
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static int acpi_serial_add(struct acpi_device *device)
|
||||
{
|
||||
struct serial_private *priv;
|
||||
acpi_status status;
|
||||
struct uart_port port;
|
||||
int result;
|
||||
|
||||
memset(&port, 0, sizeof(struct uart_port));
|
||||
|
||||
port.uartclk = 1843200;
|
||||
port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
|
||||
|
||||
priv = kmalloc(sizeof(struct serial_private), GFP_KERNEL);
|
||||
if (!priv) {
|
||||
result = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
memset(priv, 0, sizeof(*priv));
|
||||
|
||||
status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
|
||||
acpi_serial_resource, &port);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
result = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!port.mapbase && !port.iobase) {
|
||||
printk(KERN_ERR "%s: no iomem or port address in %s _CRS\n",
|
||||
__FUNCTION__, device->pnp.bus_id);
|
||||
result = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
priv->line = serial8250_register_port(&port);
|
||||
if (priv->line < 0) {
|
||||
printk(KERN_WARNING "Couldn't register serial port %s: %d\n",
|
||||
device->pnp.bus_id, priv->line);
|
||||
result = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
acpi_driver_data(device) = priv;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
kfree(priv);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int acpi_serial_remove(struct acpi_device *device, int type)
|
||||
{
|
||||
struct serial_private *priv;
|
||||
|
||||
if (!device || !acpi_driver_data(device))
|
||||
return -EINVAL;
|
||||
|
||||
priv = acpi_driver_data(device);
|
||||
serial8250_unregister_port(priv->line);
|
||||
kfree(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct acpi_driver acpi_serial_driver = {
|
||||
.name = "serial",
|
||||
.class = "",
|
||||
.ids = "PNP0501",
|
||||
.ops = {
|
||||
.add = acpi_serial_add,
|
||||
.remove = acpi_serial_remove,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init acpi_serial_init(void)
|
||||
{
|
||||
return acpi_bus_register_driver(&acpi_serial_driver);
|
||||
}
|
||||
|
||||
static void __exit acpi_serial_exit(void)
|
||||
{
|
||||
acpi_bus_unregister_driver(&acpi_serial_driver);
|
||||
}
|
||||
|
||||
module_init(acpi_serial_init);
|
||||
module_exit(acpi_serial_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Generic 8250/16x50 ACPI serial driver");
|
||||
255
extra/linux-2.6.10/drivers/serial/8250_early.c
Normal file
255
extra/linux-2.6.10/drivers/serial/8250_early.c
Normal file
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Early serial console for 8250/16550 devices
|
||||
*
|
||||
* (c) Copyright 2004 Hewlett-Packard Development Company, L.P.
|
||||
* Bjorn Helgaas <bjorn.helgaas@hp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Based on the 8250.c serial driver, Copyright (C) 2001 Russell King,
|
||||
* and on early_printk.c by Andi Kleen.
|
||||
*
|
||||
* This is for use before the serial driver has initialized, in
|
||||
* particular, before the UARTs have been discovered and named.
|
||||
* Instead of specifying the console device as, e.g., "ttyS0",
|
||||
* we locate the device directly by its MMIO or I/O port address.
|
||||
*
|
||||
* The user can specify the device directly, e.g.,
|
||||
* console=uart,io,0x3f8,9600n8
|
||||
* console=uart,mmio,0xff5e0000,115200n8
|
||||
* or platform code can call early_uart_console_init() to set
|
||||
* the early UART device.
|
||||
*
|
||||
* After the normal serial driver starts, we try to locate the
|
||||
* matching ttyS device and start a console there.
|
||||
*/
|
||||
|
||||
#include <linux/tty.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/serial.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/serial.h>
|
||||
|
||||
struct early_uart_device {
|
||||
struct uart_port port;
|
||||
char options[16]; /* e.g., 115200n8 */
|
||||
unsigned int baud;
|
||||
};
|
||||
|
||||
static struct early_uart_device early_device __initdata;
|
||||
static int early_uart_registered __initdata;
|
||||
|
||||
static unsigned int __init serial_in(struct uart_port *port, int offset)
|
||||
{
|
||||
if (port->iotype == UPIO_MEM)
|
||||
return readb(port->membase + offset);
|
||||
else
|
||||
return inb(port->iobase + offset);
|
||||
}
|
||||
|
||||
static void __init serial_out(struct uart_port *port, int offset, int value)
|
||||
{
|
||||
if (port->iotype == UPIO_MEM)
|
||||
writeb(value, port->membase + offset);
|
||||
else
|
||||
outb(value, port->iobase + offset);
|
||||
}
|
||||
|
||||
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
|
||||
|
||||
static void __init wait_for_xmitr(struct uart_port *port)
|
||||
{
|
||||
unsigned int status;
|
||||
|
||||
for (;;) {
|
||||
status = serial_in(port, UART_LSR);
|
||||
if ((status & BOTH_EMPTY) == BOTH_EMPTY)
|
||||
return;
|
||||
cpu_relax();
|
||||
}
|
||||
}
|
||||
|
||||
static void __init putc(struct uart_port *port, unsigned char c)
|
||||
{
|
||||
wait_for_xmitr(port);
|
||||
serial_out(port, UART_TX, c);
|
||||
}
|
||||
|
||||
static void __init early_uart_write(struct console *console, const char *s, unsigned int count)
|
||||
{
|
||||
struct uart_port *port = &early_device.port;
|
||||
unsigned int ier;
|
||||
|
||||
/* Save the IER and disable interrupts */
|
||||
ier = serial_in(port, UART_IER);
|
||||
serial_out(port, UART_IER, 0);
|
||||
|
||||
while (*s && count-- > 0) {
|
||||
putc(port, *s);
|
||||
if (*s == '\n')
|
||||
putc(port, '\r');
|
||||
s++;
|
||||
}
|
||||
|
||||
/* Wait for transmitter to become empty and restore the IER */
|
||||
wait_for_xmitr(port);
|
||||
serial_out(port, UART_IER, ier);
|
||||
}
|
||||
|
||||
static unsigned int __init probe_baud(struct uart_port *port)
|
||||
{
|
||||
unsigned char lcr, dll, dlm;
|
||||
unsigned int quot;
|
||||
|
||||
lcr = serial_in(port, UART_LCR);
|
||||
serial_out(port, UART_LCR, lcr | UART_LCR_DLAB);
|
||||
dll = serial_in(port, UART_DLL);
|
||||
dlm = serial_in(port, UART_DLM);
|
||||
serial_out(port, UART_LCR, lcr);
|
||||
|
||||
quot = (dlm << 8) | dll;
|
||||
return (port->uartclk / 16) / quot;
|
||||
}
|
||||
|
||||
static void __init init_port(struct early_uart_device *device)
|
||||
{
|
||||
struct uart_port *port = &device->port;
|
||||
unsigned int divisor;
|
||||
unsigned char c;
|
||||
|
||||
serial_out(port, UART_LCR, 0x3); /* 8n1 */
|
||||
serial_out(port, UART_IER, 0); /* no interrupt */
|
||||
serial_out(port, UART_FCR, 0); /* no fifo */
|
||||
serial_out(port, UART_MCR, 0x3); /* DTR + RTS */
|
||||
|
||||
divisor = port->uartclk / (16 * device->baud);
|
||||
c = serial_in(port, UART_LCR);
|
||||
serial_out(port, UART_LCR, c | UART_LCR_DLAB);
|
||||
serial_out(port, UART_DLL, divisor & 0xff);
|
||||
serial_out(port, UART_DLM, (divisor >> 8) & 0xff);
|
||||
serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
|
||||
}
|
||||
|
||||
static int __init parse_options(struct early_uart_device *device, char *options)
|
||||
{
|
||||
struct uart_port *port = &device->port;
|
||||
int mapsize = 64;
|
||||
int mmio, length;
|
||||
|
||||
if (!options)
|
||||
return -ENODEV;
|
||||
|
||||
port->uartclk = BASE_BAUD * 16;
|
||||
if (!strncmp(options, "mmio,", 5)) {
|
||||
port->iotype = UPIO_MEM;
|
||||
port->mapbase = simple_strtoul(options + 5, &options, 0);
|
||||
port->membase = ioremap(port->mapbase, mapsize);
|
||||
if (!port->membase) {
|
||||
printk(KERN_ERR "%s: Couldn't ioremap 0x%lx\n",
|
||||
__FUNCTION__, port->mapbase);
|
||||
return -ENOMEM;
|
||||
}
|
||||
mmio = 1;
|
||||
} else if (!strncmp(options, "io,", 3)) {
|
||||
port->iotype = UPIO_PORT;
|
||||
port->iobase = simple_strtoul(options + 3, &options, 0);
|
||||
mmio = 0;
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
if ((options = strchr(options, ','))) {
|
||||
options++;
|
||||
device->baud = simple_strtoul(options, 0, 0);
|
||||
length = min(strcspn(options, " "), sizeof(device->options));
|
||||
strncpy(device->options, options, length);
|
||||
} else {
|
||||
device->baud = probe_baud(port);
|
||||
snprintf(device->options, sizeof(device->options), "%u",
|
||||
device->baud);
|
||||
}
|
||||
|
||||
printk(KERN_INFO "Early serial console at %s 0x%lx (options '%s')\n",
|
||||
mmio ? "MMIO" : "I/O port",
|
||||
mmio ? port->mapbase : (unsigned long) port->iobase,
|
||||
device->options);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init early_uart_setup(struct console *console, char *options)
|
||||
{
|
||||
struct early_uart_device *device = &early_device;
|
||||
int err;
|
||||
|
||||
if (device->port.membase || device->port.iobase)
|
||||
return 0;
|
||||
|
||||
if ((err = parse_options(device, options)) < 0)
|
||||
return err;
|
||||
|
||||
init_port(device);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct console early_uart_console __initdata = {
|
||||
.name = "uart",
|
||||
.write = early_uart_write,
|
||||
.setup = early_uart_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
};
|
||||
|
||||
static int __init early_uart_console_init(void)
|
||||
{
|
||||
if (!early_uart_registered) {
|
||||
register_console(&early_uart_console);
|
||||
early_uart_registered = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
console_initcall(early_uart_console_init);
|
||||
|
||||
int __init early_serial_console_init(char *cmdline)
|
||||
{
|
||||
char *options;
|
||||
int err;
|
||||
|
||||
options = strstr(cmdline, "console=uart,");
|
||||
if (!options)
|
||||
return -ENODEV;
|
||||
|
||||
options = strchr(cmdline, ',') + 1;
|
||||
if ((err = early_uart_setup(NULL, options)) < 0)
|
||||
return err;
|
||||
return early_uart_console_init();
|
||||
}
|
||||
|
||||
static int __init early_uart_console_switch(void)
|
||||
{
|
||||
struct early_uart_device *device = &early_device;
|
||||
struct uart_port *port = &device->port;
|
||||
int mmio, line;
|
||||
|
||||
if (!(early_uart_console.flags & CON_ENABLED))
|
||||
return 0;
|
||||
|
||||
/* Try to start the normal driver on a matching line. */
|
||||
mmio = (port->iotype == UPIO_MEM);
|
||||
line = serial8250_start_console(port, device->options);
|
||||
if (line < 0)
|
||||
printk("No ttyS device at %s 0x%lx for console\n",
|
||||
mmio ? "MMIO" : "I/O port",
|
||||
mmio ? port->mapbase :
|
||||
(unsigned long) port->iobase);
|
||||
|
||||
unregister_console(&early_uart_console);
|
||||
if (mmio)
|
||||
iounmap(port->membase);
|
||||
|
||||
return 0;
|
||||
}
|
||||
late_initcall(early_uart_console_switch);
|
||||
120
extra/linux-2.6.10/drivers/serial/8250_gsc.c
Normal file
120
extra/linux-2.6.10/drivers/serial/8250_gsc.c
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Serial Device Initialisation for Lasi/Asp/Wax/Dino
|
||||
*
|
||||
* (c) Copyright Matthew Wilcox <willy@debian.org> 2001-2002
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/parisc-device.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/serial.h> /* for LASI_BASE_BAUD */
|
||||
|
||||
#include "8250.h"
|
||||
|
||||
static int __init
|
||||
serial_init_chip(struct parisc_device *dev)
|
||||
{
|
||||
static int serial_line_nr;
|
||||
struct uart_port port;
|
||||
unsigned long address;
|
||||
int err;
|
||||
|
||||
if (!dev->irq) {
|
||||
/* We find some unattached serial ports by walking native
|
||||
* busses. These should be silently ignored. Otherwise,
|
||||
* what we have here is a missing parent device, so tell
|
||||
* the user what they're missing.
|
||||
*/
|
||||
if (dev->parent->id.hw_type != HPHW_IOA) {
|
||||
printk(KERN_INFO "Serial: device 0x%lx not configured.\n"
|
||||
"Enable support for Wax, Lasi, Asp or Dino.\n", dev->hpa);
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
address = dev->hpa;
|
||||
if (dev->id.sversion != 0x8d) {
|
||||
address += 0x800;
|
||||
}
|
||||
|
||||
memset(&port, 0, sizeof(struct uart_port));
|
||||
port.mapbase = address;
|
||||
port.irq = dev->irq;
|
||||
port.iotype = UPIO_MEM;
|
||||
port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
|
||||
port.uartclk = LASI_BASE_BAUD * 16;
|
||||
port.dev = &dev->dev;
|
||||
|
||||
err = serial8250_register_port(&port);
|
||||
if (err < 0) {
|
||||
printk(KERN_WARNING "serial8250_register_port returned error %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct parisc_device_id serial_tbl[] = {
|
||||
{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00075 },
|
||||
{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008c },
|
||||
{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008d },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* Hack. Some machines have SERIAL_0 attached to Lasi and SERIAL_1
|
||||
* attached to Dino. Unfortunately, Dino appears before Lasi in the device
|
||||
* tree. To ensure that ttyS0 == SERIAL_0, we register two drivers; one
|
||||
* which only knows about Lasi and then a second which will find all the
|
||||
* other serial ports. HPUX ignores this problem.
|
||||
*/
|
||||
static struct parisc_device_id lasi_tbl[] = {
|
||||
{ HPHW_FIO, HVERSION_REV_ANY_ID, 0x03B, 0x0008C }, /* C1xx/C1xxL */
|
||||
{ HPHW_FIO, HVERSION_REV_ANY_ID, 0x03C, 0x0008C }, /* B132L */
|
||||
{ HPHW_FIO, HVERSION_REV_ANY_ID, 0x03D, 0x0008C }, /* B160L */
|
||||
{ HPHW_FIO, HVERSION_REV_ANY_ID, 0x03E, 0x0008C }, /* B132L+ */
|
||||
{ HPHW_FIO, HVERSION_REV_ANY_ID, 0x03F, 0x0008C }, /* B180L+ */
|
||||
{ HPHW_FIO, HVERSION_REV_ANY_ID, 0x046, 0x0008C }, /* Rocky2 120 */
|
||||
{ HPHW_FIO, HVERSION_REV_ANY_ID, 0x047, 0x0008C }, /* Rocky2 150 */
|
||||
{ HPHW_FIO, HVERSION_REV_ANY_ID, 0x04E, 0x0008C }, /* Kiji L2 132 */
|
||||
{ HPHW_FIO, HVERSION_REV_ANY_ID, 0x056, 0x0008C }, /* Raven+ */
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
||||
MODULE_DEVICE_TABLE(parisc, serial_tbl);
|
||||
|
||||
static struct parisc_driver lasi_driver = {
|
||||
.name = "Lasi RS232",
|
||||
.id_table = lasi_tbl,
|
||||
.probe = serial_init_chip,
|
||||
};
|
||||
|
||||
static struct parisc_driver serial_driver = {
|
||||
.name = "Serial RS232",
|
||||
.id_table = serial_tbl,
|
||||
.probe = serial_init_chip,
|
||||
};
|
||||
|
||||
int __init probe_serial_gsc(void)
|
||||
{
|
||||
register_parisc_driver(&lasi_driver);
|
||||
register_parisc_driver(&serial_driver);
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(probe_serial_gsc);
|
||||
329
extra/linux-2.6.10/drivers/serial/8250_hp300.c
Normal file
329
extra/linux-2.6.10/drivers/serial/8250_hp300.c
Normal file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Driver for the 98626/98644/internal serial interface on hp300/hp400
|
||||
* (based on the National Semiconductor INS8250/NS16550AF/WD16C552 UARTs)
|
||||
*
|
||||
* Ported from 2.2 and modified to use the normal 8250 driver
|
||||
* by Kars de Jong <jongk@linux-m68k.org>, May 2004.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serialP.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dio.h>
|
||||
#include <linux/console.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#if !defined(CONFIG_HPDCA) && !defined(CONFIG_HPAPCI)
|
||||
#warning CONFIG_8250 defined but neither CONFIG_HPDCA nor CONFIG_HPAPCI defined, are you sure?
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HPAPCI
|
||||
struct hp300_port
|
||||
{
|
||||
struct hp300_port *next; /* next port */
|
||||
int line; /* line (tty) number */
|
||||
};
|
||||
|
||||
static struct hp300_port *hp300_ports;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HPDCA
|
||||
|
||||
static int __devinit hpdca_init_one(struct dio_dev *d,
|
||||
const struct dio_device_id *ent);
|
||||
static void __devexit hpdca_remove_one(struct dio_dev *d);
|
||||
|
||||
static struct dio_device_id hpdca_dio_tbl[] = {
|
||||
{ DIO_ID_DCA0 },
|
||||
{ DIO_ID_DCA0REM },
|
||||
{ DIO_ID_DCA1 },
|
||||
{ DIO_ID_DCA1REM },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static struct dio_driver hpdca_driver = {
|
||||
.name = "hpdca",
|
||||
.id_table = hpdca_dio_tbl,
|
||||
.probe = hpdca_init_one,
|
||||
.remove = __devexit_p(hpdca_remove_one),
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
extern int hp300_uart_scode;
|
||||
|
||||
/* Offset to UART registers from base of DCA */
|
||||
#define UART_OFFSET 17
|
||||
|
||||
#define DCA_ID 0x01 /* ID (read), reset (write) */
|
||||
#define DCA_IC 0x03 /* Interrupt control */
|
||||
|
||||
/* Interrupt control */
|
||||
#define DCA_IC_IE 0x80 /* Master interrupt enable */
|
||||
|
||||
#define HPDCA_BAUD_BASE 153600
|
||||
|
||||
/* Base address of the Frodo part */
|
||||
#define FRODO_BASE (0x41c000)
|
||||
|
||||
/*
|
||||
* Where we find the 8250-like APCI ports, and how far apart they are.
|
||||
*/
|
||||
#define FRODO_APCIBASE 0x0
|
||||
#define FRODO_APCISPACE 0x20
|
||||
#define FRODO_APCI_OFFSET(x) (FRODO_APCIBASE + ((x) * FRODO_APCISPACE))
|
||||
|
||||
#define HPAPCI_BAUD_BASE 500400
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
/*
|
||||
* Parse the bootinfo to find descriptions for headless console and
|
||||
* debug serial ports and register them with the 8250 driver.
|
||||
* This function should be called before serial_console_init() is called
|
||||
* to make sure the serial console will be available for use. IA-64 kernel
|
||||
* calls this function from setup_arch() after the EFI and ACPI tables have
|
||||
* been parsed.
|
||||
*/
|
||||
int __init hp300_setup_serial_console(void)
|
||||
{
|
||||
int scode;
|
||||
struct uart_port port;
|
||||
|
||||
memset(&port, 0, sizeof(port));
|
||||
|
||||
if (hp300_uart_scode < 0 || hp300_uart_scode > DIO_SCMAX)
|
||||
return 0;
|
||||
|
||||
if (DIO_SCINHOLE(hp300_uart_scode))
|
||||
return 0;
|
||||
|
||||
scode = hp300_uart_scode;
|
||||
|
||||
/* Memory mapped I/O */
|
||||
port.iotype = UPIO_MEM;
|
||||
port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
|
||||
port.type = PORT_UNKNOWN;
|
||||
|
||||
/* Check for APCI console */
|
||||
if (scode == 256) {
|
||||
#ifdef CONFIG_HPAPCI
|
||||
printk(KERN_INFO "Serial console is HP APCI 1\n");
|
||||
|
||||
port.uartclk = HPAPCI_BAUD_BASE * 16;
|
||||
port.mapbase = (FRODO_BASE + FRODO_APCI_OFFSET(1));
|
||||
port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
|
||||
port.regshift = 2;
|
||||
add_preferred_console("ttyS", port.line, "9600n8");
|
||||
#else
|
||||
printk(KERN_WARNING "Serial console is APCI but support is disabled (CONFIG_HPAPCI)!\n");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#ifdef CONFIG_HPDCA
|
||||
unsigned long pa = dio_scodetophysaddr(scode);
|
||||
if (!pa) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "Serial console is HP DCA at select code %d\n", scode);
|
||||
|
||||
port.uartclk = HPDCA_BAUD_BASE * 16;
|
||||
port.mapbase = (pa + UART_OFFSET);
|
||||
port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
|
||||
port.regshift = 1;
|
||||
port.irq = DIO_IPL(pa + DIO_VIRADDRBASE);
|
||||
|
||||
/* Enable board-interrupts */
|
||||
out_8(pa + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);
|
||||
|
||||
if (DIO_ID(pa + DIO_VIRADDRBASE) & 0x80) {
|
||||
add_preferred_console("ttyS", port.line, "9600n8");
|
||||
}
|
||||
#else
|
||||
printk(KERN_WARNING "Serial console is DCA but support is disabled (CONFIG_HPDCA)!\n");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (early_serial_setup(&port) < 0) {
|
||||
printk(KERN_WARNING "hp300_setup_serial_console(): early_serial_setup() failed.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_SERIAL_8250_CONSOLE */
|
||||
|
||||
#ifdef CONFIG_HPDCA
|
||||
static int __devinit hpdca_init_one(struct dio_dev *d,
|
||||
const struct dio_device_id *ent)
|
||||
{
|
||||
struct serial_struct serial_req;
|
||||
int line;
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
if (hp300_uart_scode == d->scode) {
|
||||
/* Already got it. */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
memset(&serial_req, 0, sizeof(struct serial_struct));
|
||||
|
||||
/* Memory mapped I/O */
|
||||
serial_req.io_type = SERIAL_IO_MEM;
|
||||
serial_req.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
|
||||
serial_req.irq = d->ipl;
|
||||
serial_req.baud_base = HPDCA_BAUD_BASE;
|
||||
serial_req.iomap_base = (d->resource.start + UART_OFFSET);
|
||||
serial_req.iomem_base = (char *)(serial_req.iomap_base + DIO_VIRADDRBASE);
|
||||
serial_req.iomem_reg_shift = 1;
|
||||
line = register_serial(&serial_req);
|
||||
|
||||
if (line < 0) {
|
||||
printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d"
|
||||
" irq %d failed\n", d->scode, serial_req.irq);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Enable board-interrupts */
|
||||
out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);
|
||||
dio_set_drvdata(d, (void *)line);
|
||||
|
||||
/* Reset the DCA */
|
||||
out_8(d->resource.start + DIO_VIRADDRBASE + DCA_ID, 0xff);
|
||||
udelay(100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __init hp300_8250_init(void)
|
||||
{
|
||||
static int called = 0;
|
||||
int num_ports;
|
||||
#ifdef CONFIG_HPAPCI
|
||||
int line;
|
||||
unsigned long base;
|
||||
struct serial_struct serial_req;
|
||||
struct hp300_port *port;
|
||||
int i;
|
||||
#endif
|
||||
if (called)
|
||||
return -ENODEV;
|
||||
called = 1;
|
||||
|
||||
if (!MACH_IS_HP300)
|
||||
return -ENODEV;
|
||||
|
||||
num_ports = 0;
|
||||
|
||||
#ifdef CONFIG_HPDCA
|
||||
if (dio_module_init(&hpdca_driver) == 0)
|
||||
num_ports++;
|
||||
#endif
|
||||
#ifdef CONFIG_HPAPCI
|
||||
if (hp300_model < HP_400) {
|
||||
if (!num_ports)
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
}
|
||||
/* These models have the Frodo chip.
|
||||
* Port 0 is reserved for the Apollo Domain keyboard.
|
||||
* Port 1 is either the console or the DCA.
|
||||
*/
|
||||
for (i = 1; i < 4; i++) {
|
||||
/* Port 1 is the console on a 425e, on other machines it's mapped to
|
||||
* DCA.
|
||||
*/
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
if (i == 1) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create new serial device */
|
||||
port = kmalloc(sizeof(struct hp300_port), GFP_KERNEL);
|
||||
if (!port)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(&serial_req, 0, sizeof(struct serial_struct));
|
||||
|
||||
base = (FRODO_BASE + FRODO_APCI_OFFSET(i));
|
||||
|
||||
/* Memory mapped I/O */
|
||||
serial_req.io_type = SERIAL_IO_MEM;
|
||||
serial_req.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
|
||||
/* XXX - no interrupt support yet */
|
||||
serial_req.irq = 0;
|
||||
serial_req.baud_base = HPAPCI_BAUD_BASE;
|
||||
serial_req.iomap_base = base;
|
||||
serial_req.iomem_base = (char *)(serial_req.iomap_base + DIO_VIRADDRBASE);
|
||||
serial_req.iomem_reg_shift = 2;
|
||||
|
||||
line = register_serial(&serial_req);
|
||||
|
||||
if (line < 0) {
|
||||
printk(KERN_NOTICE "8250_hp300: register_serial() APCI %d"
|
||||
" irq %d failed\n", i, serial_req.irq);
|
||||
kfree(port);
|
||||
continue;
|
||||
}
|
||||
|
||||
port->line = line;
|
||||
port->next = hp300_ports;
|
||||
hp300_ports = port;
|
||||
|
||||
num_ports++;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Any boards found? */
|
||||
if (!num_ports)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HPDCA
|
||||
static void __devexit hpdca_remove_one(struct dio_dev *d)
|
||||
{
|
||||
int line;
|
||||
|
||||
line = (int) dio_get_drvdata(d);
|
||||
if (d->resource.start) {
|
||||
/* Disable board-interrupts */
|
||||
out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, 0);
|
||||
}
|
||||
unregister_serial(line);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void __exit hp300_8250_exit(void)
|
||||
{
|
||||
#ifdef CONFIG_HPAPCI
|
||||
struct hp300_port *port, *to_free;
|
||||
|
||||
for (port = hp300_ports; port; ) {
|
||||
unregister_serial(port->line);
|
||||
to_free = port;
|
||||
port = port->next;
|
||||
kfree(to_free);
|
||||
}
|
||||
|
||||
hp300_ports = NULL;
|
||||
#endif
|
||||
#ifdef CONFIG_HPDCA
|
||||
dio_unregister_driver(&hpdca_driver);
|
||||
#endif
|
||||
}
|
||||
|
||||
module_init(hp300_8250_init);
|
||||
module_exit(hp300_8250_exit);
|
||||
MODULE_DESCRIPTION("HP DCA/APCI serial driver");
|
||||
MODULE_AUTHOR("Kars de Jong <jongk@linux-m68k.org>");
|
||||
MODULE_LICENSE("GPL");
|
||||
2257
extra/linux-2.6.10/drivers/serial/8250_pci.c
Normal file
2257
extra/linux-2.6.10/drivers/serial/8250_pci.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
extra/linux-2.6.10/drivers/serial/8250_pci.o
Normal file
BIN
extra/linux-2.6.10/drivers/serial/8250_pci.o
Normal file
Binary file not shown.
455
extra/linux-2.6.10/drivers/serial/8250_pnp.c
Normal file
455
extra/linux-2.6.10/drivers/serial/8250_pnp.c
Normal file
@@ -0,0 +1,455 @@
|
||||
/*
|
||||
* linux/drivers/char/8250_pnp.c
|
||||
*
|
||||
* Probe module for 8250/16550-type ISAPNP serial ports.
|
||||
*
|
||||
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
|
||||
*
|
||||
* Copyright (C) 2001 Russell King, All Rights Reserved.
|
||||
*
|
||||
* Ported to the Linux PnP Layer - (C) Adam Belay.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id: 8250_pnp.c,v 1.10 2002/07/21 21:32:30 rmk Exp $
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pnp.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include "8250.h"
|
||||
|
||||
#define UNKNOWN_DEV 0x3000
|
||||
|
||||
|
||||
static const struct pnp_device_id pnp_dev_table[] = {
|
||||
/* Archtek America Corp. */
|
||||
/* Archtek SmartLink Modem 3334BT Plug & Play */
|
||||
{ "AAC000F", 0 },
|
||||
/* Anchor Datacomm BV */
|
||||
/* SXPro 144 External Data Fax Modem Plug & Play */
|
||||
{ "ADC0001", 0 },
|
||||
/* SXPro 288 External Data Fax Modem Plug & Play */
|
||||
{ "ADC0002", 0 },
|
||||
/* PROLiNK 1456VH ISA PnP K56flex Fax Modem */
|
||||
{ "AEI0250", 0 },
|
||||
/* Actiontec ISA PNP 56K X2 Fax Modem */
|
||||
{ "AEI1240", 0 },
|
||||
/* Rockwell 56K ACF II Fax+Data+Voice Modem */
|
||||
{ "AKY1021", 0 /*SPCI_FL_NO_SHIRQ*/ },
|
||||
/* AZT3005 PnP SOUND DEVICE */
|
||||
{ "AZT4001", 0 },
|
||||
/* Best Data Products Inc. Smart One 336F PnP Modem */
|
||||
{ "BDP3336", 0 },
|
||||
/* Boca Research */
|
||||
/* Boca Complete Ofc Communicator 14.4 Data-FAX */
|
||||
{ "BRI0A49", 0 },
|
||||
/* Boca Research 33,600 ACF Modem */
|
||||
{ "BRI1400", 0 },
|
||||
/* Boca 33.6 Kbps Internal FD34FSVD */
|
||||
{ "BRI3400", 0 },
|
||||
/* Boca 33.6 Kbps Internal FD34FSVD */
|
||||
{ "BRI0A49", 0 },
|
||||
/* Best Data Products Inc. Smart One 336F PnP Modem */
|
||||
{ "BDP3336", 0 },
|
||||
/* Computer Peripherals Inc */
|
||||
/* EuroViVa CommCenter-33.6 SP PnP */
|
||||
{ "CPI4050", 0 },
|
||||
/* Creative Labs */
|
||||
/* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */
|
||||
{ "CTL3001", 0 },
|
||||
/* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
|
||||
{ "CTL3011", 0 },
|
||||
/* Creative */
|
||||
/* Creative Modem Blaster Flash56 DI5601-1 */
|
||||
{ "DMB1032", 0 },
|
||||
/* Creative Modem Blaster V.90 DI5660 */
|
||||
{ "DMB2001", 0 },
|
||||
/* E-Tech */
|
||||
/* E-Tech CyberBULLET PC56RVP */
|
||||
{ "ETT0002", 0 },
|
||||
/* FUJITSU */
|
||||
/* Fujitsu 33600 PnP-I2 R Plug & Play */
|
||||
{ "FUJ0202", 0 },
|
||||
/* Fujitsu FMV-FX431 Plug & Play */
|
||||
{ "FUJ0205", 0 },
|
||||
/* Fujitsu 33600 PnP-I4 R Plug & Play */
|
||||
{ "FUJ0206", 0 },
|
||||
/* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */
|
||||
{ "FUJ0209", 0 },
|
||||
/* Archtek America Corp. */
|
||||
/* Archtek SmartLink Modem 3334BT Plug & Play */
|
||||
{ "GVC000F", 0 },
|
||||
/* Hayes */
|
||||
/* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */
|
||||
{ "HAY0001", 0 },
|
||||
/* Hayes Optima 336 V.34 + FAX + Voice PnP */
|
||||
{ "HAY000C", 0 },
|
||||
/* Hayes Optima 336B V.34 + FAX + Voice PnP */
|
||||
{ "HAY000D", 0 },
|
||||
/* Hayes Accura 56K Ext Fax Modem PnP */
|
||||
{ "HAY5670", 0 },
|
||||
/* Hayes Accura 56K Ext Fax Modem PnP */
|
||||
{ "HAY5674", 0 },
|
||||
/* Hayes Accura 56K Fax Modem PnP */
|
||||
{ "HAY5675", 0 },
|
||||
/* Hayes 288, V.34 + FAX */
|
||||
{ "HAYF000", 0 },
|
||||
/* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */
|
||||
{ "HAYF001", 0 },
|
||||
/* IBM */
|
||||
/* IBM Thinkpad 701 Internal Modem Voice */
|
||||
{ "IBM0033", 0 },
|
||||
/* Intertex */
|
||||
/* Intertex 28k8 33k6 Voice EXT PnP */
|
||||
{ "IXDC801", 0 },
|
||||
/* Intertex 33k6 56k Voice EXT PnP */
|
||||
{ "IXDC901", 0 },
|
||||
/* Intertex 28k8 33k6 Voice SP EXT PnP */
|
||||
{ "IXDD801", 0 },
|
||||
/* Intertex 33k6 56k Voice SP EXT PnP */
|
||||
{ "IXDD901", 0 },
|
||||
/* Intertex 28k8 33k6 Voice SP INT PnP */
|
||||
{ "IXDF401", 0 },
|
||||
/* Intertex 28k8 33k6 Voice SP EXT PnP */
|
||||
{ "IXDF801", 0 },
|
||||
/* Intertex 33k6 56k Voice SP EXT PnP */
|
||||
{ "IXDF901", 0 },
|
||||
/* Kortex International */
|
||||
/* KORTEX 28800 Externe PnP */
|
||||
{ "KOR4522", 0 },
|
||||
/* KXPro 33.6 Vocal ASVD PnP */
|
||||
{ "KORF661", 0 },
|
||||
/* Lasat */
|
||||
/* LASAT Internet 33600 PnP */
|
||||
{ "LAS4040", 0 },
|
||||
/* Lasat Safire 560 PnP */
|
||||
{ "LAS4540", 0 },
|
||||
/* Lasat Safire 336 PnP */
|
||||
{ "LAS5440", 0 },
|
||||
/* Microcom, Inc. */
|
||||
/* Microcom TravelPorte FAST V.34 Plug & Play */
|
||||
{ "MNP0281", 0 },
|
||||
/* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */
|
||||
{ "MNP0336", 0 },
|
||||
/* Microcom DeskPorte FAST EP 28.8 Plug & Play */
|
||||
{ "MNP0339", 0 },
|
||||
/* Microcom DeskPorte 28.8P Plug & Play */
|
||||
{ "MNP0342", 0 },
|
||||
/* Microcom DeskPorte FAST ES 28.8 Plug & Play */
|
||||
{ "MNP0500", 0 },
|
||||
/* Microcom DeskPorte FAST ES 28.8 Plug & Play */
|
||||
{ "MNP0501", 0 },
|
||||
/* Microcom DeskPorte 28.8S Internal Plug & Play */
|
||||
{ "MNP0502", 0 },
|
||||
/* Motorola */
|
||||
/* Motorola BitSURFR Plug & Play */
|
||||
{ "MOT1105", 0 },
|
||||
/* Motorola TA210 Plug & Play */
|
||||
{ "MOT1111", 0 },
|
||||
/* Motorola HMTA 200 (ISDN) Plug & Play */
|
||||
{ "MOT1114", 0 },
|
||||
/* Motorola BitSURFR Plug & Play */
|
||||
{ "MOT1115", 0 },
|
||||
/* Motorola Lifestyle 28.8 Internal */
|
||||
{ "MOT1190", 0 },
|
||||
/* Motorola V.3400 Plug & Play */
|
||||
{ "MOT1501", 0 },
|
||||
/* Motorola Lifestyle 28.8 V.34 Plug & Play */
|
||||
{ "MOT1502", 0 },
|
||||
/* Motorola Power 28.8 V.34 Plug & Play */
|
||||
{ "MOT1505", 0 },
|
||||
/* Motorola ModemSURFR External 28.8 Plug & Play */
|
||||
{ "MOT1509", 0 },
|
||||
/* Motorola Premier 33.6 Desktop Plug & Play */
|
||||
{ "MOT150A", 0 },
|
||||
/* Motorola VoiceSURFR 56K External PnP */
|
||||
{ "MOT150F", 0 },
|
||||
/* Motorola ModemSURFR 56K External PnP */
|
||||
{ "MOT1510", 0 },
|
||||
/* Motorola ModemSURFR 56K Internal PnP */
|
||||
{ "MOT1550", 0 },
|
||||
/* Motorola ModemSURFR Internal 28.8 Plug & Play */
|
||||
{ "MOT1560", 0 },
|
||||
/* Motorola Premier 33.6 Internal Plug & Play */
|
||||
{ "MOT1580", 0 },
|
||||
/* Motorola OnlineSURFR 28.8 Internal Plug & Play */
|
||||
{ "MOT15B0", 0 },
|
||||
/* Motorola VoiceSURFR 56K Internal PnP */
|
||||
{ "MOT15F0", 0 },
|
||||
/* Com 1 */
|
||||
/* Deskline K56 Phone System PnP */
|
||||
{ "MVX00A1", 0 },
|
||||
/* PC Rider K56 Phone System PnP */
|
||||
{ "MVX00F2", 0 },
|
||||
/* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */
|
||||
{ "nEC8241", 0 },
|
||||
/* Pace 56 Voice Internal Plug & Play Modem */
|
||||
{ "PMC2430", 0 },
|
||||
/* Generic */
|
||||
/* Generic standard PC COM port */
|
||||
{ "PNP0500", 0 },
|
||||
/* Generic 16550A-compatible COM port */
|
||||
{ "PNP0501", 0 },
|
||||
/* Compaq 14400 Modem */
|
||||
{ "PNPC000", 0 },
|
||||
/* Compaq 2400/9600 Modem */
|
||||
{ "PNPC001", 0 },
|
||||
/* Dial-Up Networking Serial Cable between 2 PCs */
|
||||
{ "PNPC031", 0 },
|
||||
/* Dial-Up Networking Parallel Cable between 2 PCs */
|
||||
{ "PNPC032", 0 },
|
||||
/* Standard 9600 bps Modem */
|
||||
{ "PNPC100", 0 },
|
||||
/* Standard 14400 bps Modem */
|
||||
{ "PNPC101", 0 },
|
||||
/* Standard 28800 bps Modem*/
|
||||
{ "PNPC102", 0 },
|
||||
/* Standard Modem*/
|
||||
{ "PNPC103", 0 },
|
||||
/* Standard 9600 bps Modem*/
|
||||
{ "PNPC104", 0 },
|
||||
/* Standard 14400 bps Modem*/
|
||||
{ "PNPC105", 0 },
|
||||
/* Standard 28800 bps Modem*/
|
||||
{ "PNPC106", 0 },
|
||||
/* Standard Modem */
|
||||
{ "PNPC107", 0 },
|
||||
/* Standard 9600 bps Modem */
|
||||
{ "PNPC108", 0 },
|
||||
/* Standard 14400 bps Modem */
|
||||
{ "PNPC109", 0 },
|
||||
/* Standard 28800 bps Modem */
|
||||
{ "PNPC10A", 0 },
|
||||
/* Standard Modem */
|
||||
{ "PNPC10B", 0 },
|
||||
/* Standard 9600 bps Modem */
|
||||
{ "PNPC10C", 0 },
|
||||
/* Standard 14400 bps Modem */
|
||||
{ "PNPC10D", 0 },
|
||||
/* Standard 28800 bps Modem */
|
||||
{ "PNPC10E", 0 },
|
||||
/* Standard Modem */
|
||||
{ "PNPC10F", 0 },
|
||||
/* Standard PCMCIA Card Modem */
|
||||
{ "PNP2000", 0 },
|
||||
/* Rockwell */
|
||||
/* Modular Technology */
|
||||
/* Rockwell 33.6 DPF Internal PnP */
|
||||
/* Modular Technology 33.6 Internal PnP */
|
||||
{ "ROK0030", 0 },
|
||||
/* Kortex International */
|
||||
/* KORTEX 14400 Externe PnP */
|
||||
{ "ROK0100", 0 },
|
||||
/* Viking Components, Inc */
|
||||
/* Viking 28.8 INTERNAL Fax+Data+Voice PnP */
|
||||
{ "ROK4920", 0 },
|
||||
/* Rockwell */
|
||||
/* British Telecom */
|
||||
/* Modular Technology */
|
||||
/* Rockwell 33.6 DPF External PnP */
|
||||
/* BT Prologue 33.6 External PnP */
|
||||
/* Modular Technology 33.6 External PnP */
|
||||
{ "RSS00A0", 0 },
|
||||
/* Viking 56K FAX INT */
|
||||
{ "RSS0262", 0 },
|
||||
/* K56 par,VV,Voice,Speakphone,AudioSpan,PnP */
|
||||
{ "RSS0250", 0 },
|
||||
/* SupraExpress 28.8 Data/Fax PnP modem */
|
||||
{ "SUP1310", 0 },
|
||||
/* SupraExpress 33.6 Data/Fax PnP modem */
|
||||
{ "SUP1421", 0 },
|
||||
/* SupraExpress 33.6 Data/Fax PnP modem */
|
||||
{ "SUP1590", 0 },
|
||||
/* SupraExpress 33.6 Data/Fax PnP modem */
|
||||
{ "SUP1760", 0 },
|
||||
/* Phoebe Micro */
|
||||
/* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */
|
||||
{ "TEX0011", 0 },
|
||||
/* Archtek America Corp. */
|
||||
/* Archtek SmartLink Modem 3334BT Plug & Play */
|
||||
{ "UAC000F", 0 },
|
||||
/* 3Com Corp. */
|
||||
/* Gateway Telepath IIvi 33.6 */
|
||||
{ "USR0000", 0 },
|
||||
/* U.S. Robotics Sporster 33.6K Fax INT PnP */
|
||||
{ "USR0002", 0 },
|
||||
/* Sportster Vi 14.4 PnP FAX Voicemail */
|
||||
{ "USR0004", 0 },
|
||||
/* U.S. Robotics 33.6K Voice INT PnP */
|
||||
{ "USR0006", 0 },
|
||||
/* U.S. Robotics 33.6K Voice EXT PnP */
|
||||
{ "USR0007", 0 },
|
||||
/* U.S. Robotics Courier V.Everything INT PnP */
|
||||
{ "USR0009", 0 },
|
||||
/* U.S. Robotics 33.6K Voice INT PnP */
|
||||
{ "USR2002", 0 },
|
||||
/* U.S. Robotics 56K Voice INT PnP */
|
||||
{ "USR2070", 0 },
|
||||
/* U.S. Robotics 56K Voice EXT PnP */
|
||||
{ "USR2080", 0 },
|
||||
/* U.S. Robotics 56K FAX INT */
|
||||
{ "USR3031", 0 },
|
||||
/* U.S. Robotics 56K FAX INT */
|
||||
{ "USR3050", 0 },
|
||||
/* U.S. Robotics 56K Voice INT PnP */
|
||||
{ "USR3070", 0 },
|
||||
/* U.S. Robotics 56K Voice EXT PnP */
|
||||
{ "USR3080", 0 },
|
||||
/* U.S. Robotics 56K Voice INT PnP */
|
||||
{ "USR3090", 0 },
|
||||
/* U.S. Robotics 56K Message */
|
||||
{ "USR9100", 0 },
|
||||
/* U.S. Robotics 56K FAX EXT PnP*/
|
||||
{ "USR9160", 0 },
|
||||
/* U.S. Robotics 56K FAX INT PnP*/
|
||||
{ "USR9170", 0 },
|
||||
/* U.S. Robotics 56K Voice EXT PnP*/
|
||||
{ "USR9180", 0 },
|
||||
/* U.S. Robotics 56K Voice INT PnP*/
|
||||
{ "USR9190", 0 },
|
||||
/* Rockwell's (PORALiNK) 33600 INT PNP */
|
||||
{ "WCI0003", 0 },
|
||||
/* Unkown PnP modems */
|
||||
{ "PNPCXXX", UNKNOWN_DEV },
|
||||
/* More unkown PnP modems */
|
||||
{ "PNPDXXX", UNKNOWN_DEV },
|
||||
{ "", 0 }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
|
||||
|
||||
static char *modem_names[] __devinitdata = {
|
||||
"MODEM", "Modem", "modem", "FAX", "Fax", "fax",
|
||||
"56K", "56k", "K56", "33.6", "28.8", "14.4",
|
||||
"33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
|
||||
"33600", "28800", "14400", "V.90", "V.34", "V.32", NULL
|
||||
};
|
||||
|
||||
static int __devinit check_name(char *name)
|
||||
{
|
||||
char **tmp;
|
||||
|
||||
for (tmp = modem_names; *tmp; tmp++)
|
||||
if (strstr(name, *tmp))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit check_resources(struct pnp_option *option)
|
||||
{
|
||||
struct pnp_option *tmp;
|
||||
if (!option)
|
||||
return 0;
|
||||
|
||||
for (tmp = option; tmp; tmp = tmp->next) {
|
||||
struct pnp_port *port;
|
||||
for (port = tmp->port; port; port = port->next)
|
||||
if ((port->size == 8) &&
|
||||
((port->min == 0x2f8) ||
|
||||
(port->min == 0x3f8) ||
|
||||
(port->min == 0x2e8) ||
|
||||
(port->min == 0x3e8)))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a complete unknown PnP device, try to use some heuristics to
|
||||
* detect modems. Currently use such heuristic set:
|
||||
* - dev->name or dev->bus->name must contain "modem" substring;
|
||||
* - device must have only one IO region (8 byte long) with base address
|
||||
* 0x2e8, 0x3e8, 0x2f8 or 0x3f8.
|
||||
*
|
||||
* Such detection looks very ugly, but can detect at least some of numerous
|
||||
* PnP modems, alternatively we must hardcode all modems in pnp_devices[]
|
||||
* table.
|
||||
*/
|
||||
static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags)
|
||||
{
|
||||
if (!(check_name(pnp_dev_name(dev)) || (dev->card && check_name(dev->card->name))))
|
||||
return -ENODEV;
|
||||
|
||||
if (check_resources(dev->independent))
|
||||
return 0;
|
||||
|
||||
if (check_resources(dev->dependent))
|
||||
return 0;
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int __devinit
|
||||
serial_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id)
|
||||
{
|
||||
struct uart_port port;
|
||||
int ret, line, flags = dev_id->driver_data;
|
||||
|
||||
if (flags & UNKNOWN_DEV) {
|
||||
ret = serial_pnp_guess_board(dev, &flags);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset(&port, 0, sizeof(struct uart_port));
|
||||
port.irq = pnp_irq(dev,0);
|
||||
port.iobase = pnp_port_start(dev, 0);
|
||||
|
||||
#ifdef SERIAL_DEBUG_PNP
|
||||
printk("Setup PNP port: port %x, irq %d, type %d\n",
|
||||
port.iobase, port.irq, port.iotype);
|
||||
#endif
|
||||
|
||||
port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
|
||||
port.uartclk = 1843200;
|
||||
port.dev = &dev->dev;
|
||||
|
||||
line = serial8250_register_port(&port);
|
||||
|
||||
if (line >= 0)
|
||||
pnp_set_drvdata(dev, (void *)(line + 1));
|
||||
return line >= 0 ? 0 : -ENODEV;
|
||||
|
||||
}
|
||||
|
||||
static void __devexit serial_pnp_remove(struct pnp_dev * dev)
|
||||
{
|
||||
int line = (int)pnp_get_drvdata(dev);
|
||||
if (line)
|
||||
serial8250_unregister_port(line - 1);
|
||||
}
|
||||
|
||||
static struct pnp_driver serial_pnp_driver = {
|
||||
.name = "serial",
|
||||
.id_table = pnp_dev_table,
|
||||
.probe = serial_pnp_probe,
|
||||
.remove = __devexit_p(serial_pnp_remove),
|
||||
};
|
||||
|
||||
static int __init serial8250_pnp_init(void)
|
||||
{
|
||||
return pnp_register_driver(&serial_pnp_driver);
|
||||
}
|
||||
|
||||
static void __exit serial8250_pnp_exit(void)
|
||||
{
|
||||
pnp_unregister_driver(&serial_pnp_driver);
|
||||
}
|
||||
|
||||
module_init(serial8250_pnp_init);
|
||||
module_exit(serial8250_pnp_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Generic 8250/16x50 PnP serial driver");
|
||||
BIN
extra/linux-2.6.10/drivers/serial/8250_pnp.o
Normal file
BIN
extra/linux-2.6.10/drivers/serial/8250_pnp.o
Normal file
Binary file not shown.
782
extra/linux-2.6.10/drivers/serial/Kconfig
Normal file
782
extra/linux-2.6.10/drivers/serial/Kconfig
Normal file
@@ -0,0 +1,782 @@
|
||||
#
|
||||
# Serial device configuration
|
||||
#
|
||||
# $Id: Kconfig,v 1.11 2004/03/11 18:08:04 lethal Exp $
|
||||
#
|
||||
|
||||
menu "Serial drivers"
|
||||
|
||||
#
|
||||
# The new 8250/16550 serial drivers
|
||||
config SERIAL_8250
|
||||
tristate "8250/16550 and compatible serial support"
|
||||
depends on (BROKEN || !(SPARC64 || SPARC32))
|
||||
select SERIAL_CORE
|
||||
---help---
|
||||
This selects whether you want to include the driver for the standard
|
||||
serial ports. The standard answer is Y. People who might say N
|
||||
here are those that are setting up dedicated Ethernet WWW/FTP
|
||||
servers, or users that have one of the various bus mice instead of a
|
||||
serial mouse and don't intend to use their machine's standard serial
|
||||
port for anything. (Note that the Cyclades and Stallion multi
|
||||
serial port drivers do not need this driver built in for them to
|
||||
work.)
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called serial.
|
||||
[WARNING: Do not compile this driver as a module if you are using
|
||||
non-standard serial ports, since the configuration information will
|
||||
be lost when the driver is unloaded. This limitation may be lifted
|
||||
in the future.]
|
||||
|
||||
BTW1: If you have a mouseman serial mouse which is not recognized by
|
||||
the X window system, try running gpm first.
|
||||
|
||||
BTW2: If you intend to use a software modem (also called Winmodem)
|
||||
under Linux, forget it. These modems are crippled and require
|
||||
proprietary drivers which are only available under Windows.
|
||||
|
||||
Most people will say Y or M here, so that they can use serial mice,
|
||||
modems and similar devices connecting to the standard serial ports.
|
||||
|
||||
config SERIAL_8250_CONSOLE
|
||||
bool "Console on 8250/16550 and compatible serial port"
|
||||
depends on SERIAL_8250=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
---help---
|
||||
If you say Y here, it will be possible to use a serial port as the
|
||||
system console (the system console is the device which receives all
|
||||
kernel messages and warnings and which allows logins in single user
|
||||
mode). This could be useful if some terminal or printer is connected
|
||||
to that serial port.
|
||||
|
||||
Even if you say Y here, the currently visible virtual console
|
||||
(/dev/tty0) will still be used as the system console by default, but
|
||||
you can alter that using a kernel command line option such as
|
||||
"console=ttyS1". (Try "man bootparam" or see the documentation of
|
||||
your boot loader (grub or lilo or loadlin) about how to pass options
|
||||
to the kernel at boot time.)
|
||||
|
||||
If you don't have a VGA card installed and you say Y here, the
|
||||
kernel will automatically use the first serial line, /dev/ttyS0, as
|
||||
system console.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config SERIAL_8250_CS
|
||||
tristate "8250/16550 PCMCIA device support"
|
||||
depends on PCMCIA && SERIAL_8250
|
||||
---help---
|
||||
Say Y here to enable support for 16-bit PCMCIA serial devices,
|
||||
including serial port cards, modems, and the modem functions of
|
||||
multi-function Ethernet/modem cards. (PCMCIA- or PC-cards are
|
||||
credit-card size devices often used with laptops.)
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called serial_cs.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config SERIAL_8250_ACPI
|
||||
bool "8250/16550 device discovery via ACPI namespace"
|
||||
default y if IA64
|
||||
depends on ACPI_BUS && SERIAL_8250
|
||||
---help---
|
||||
If you wish to enable serial port discovery via the ACPI
|
||||
namespace, say Y here. If unsure, say N.
|
||||
|
||||
config SERIAL_8250_NR_UARTS
|
||||
int "Maximum number of non-legacy 8250/16550 serial ports"
|
||||
depends on SERIAL_8250
|
||||
default "4"
|
||||
---help---
|
||||
Set this to the number of non-legacy serial ports you want
|
||||
the driver to support. This includes any ports discovered
|
||||
via ACPI or PCI enumeration and any ports that may be added
|
||||
at run-time via hot-plug.
|
||||
|
||||
config SERIAL_8250_EXTENDED
|
||||
bool "Extended 8250/16550 serial driver options"
|
||||
depends on SERIAL_8250
|
||||
help
|
||||
If you wish to use any non-standard features of the standard "dumb"
|
||||
driver, say Y here. This includes HUB6 support, shared serial
|
||||
interrupts, special multiport support, support for more than the
|
||||
four COM 1/2/3/4 boards, etc.
|
||||
|
||||
Note that the answer to this question won't directly affect the
|
||||
kernel: saying N will just cause the configurator to skip all
|
||||
the questions about serial driver options. If unsure, say N.
|
||||
|
||||
config SERIAL_8250_MANY_PORTS
|
||||
bool "Support more than 4 legacy serial ports"
|
||||
depends on SERIAL_8250_EXTENDED && !IA64
|
||||
help
|
||||
Say Y here if you have dumb serial boards other than the four
|
||||
standard COM 1/2/3/4 ports. This may happen if you have an AST
|
||||
FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available
|
||||
from <http://www.tldp.org/docs.html#howto>), or other custom
|
||||
serial port hardware which acts similar to standard serial port
|
||||
hardware. If you only use the standard COM 1/2/3/4 ports, you can
|
||||
say N here to save some memory. You can also say Y if you have an
|
||||
"intelligent" multiport card such as Cyclades, Digiboards, etc.
|
||||
|
||||
config SERIAL_8250_SHARE_IRQ
|
||||
bool "Support for sharing serial interrupts"
|
||||
depends on SERIAL_8250_EXTENDED
|
||||
help
|
||||
Some serial boards have hardware support which allows multiple dumb
|
||||
serial ports on the same board to share a single IRQ. To enable
|
||||
support for this in the serial driver, say Y here.
|
||||
|
||||
config SERIAL_8250_DETECT_IRQ
|
||||
bool "Autodetect IRQ on standard ports (unsafe)"
|
||||
depends on SERIAL_8250_EXTENDED
|
||||
help
|
||||
Say Y here if you want the kernel to try to guess which IRQ
|
||||
to use for your serial port.
|
||||
|
||||
This is considered unsafe; it is far better to configure the IRQ in
|
||||
a boot script using the setserial command.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config SERIAL_8250_MULTIPORT
|
||||
bool "Support special multiport boards"
|
||||
depends on SERIAL_8250_EXTENDED
|
||||
help
|
||||
Some multiport serial ports have special ports which are used to
|
||||
signal when there are any serial ports on the board which need
|
||||
servicing. Say Y here to enable the serial driver to take advantage
|
||||
of those special I/O ports.
|
||||
|
||||
config SERIAL_8250_RSA
|
||||
bool "Support RSA serial ports"
|
||||
depends on SERIAL_8250_EXTENDED
|
||||
help
|
||||
::: To be written :::
|
||||
|
||||
comment "Non-8250 serial port support"
|
||||
|
||||
config SERIAL_8250_ACORN
|
||||
tristate "Acorn expansion card serial port support"
|
||||
depends on ARM && ARCH_ACORN && SERIAL_8250
|
||||
help
|
||||
If you have an Atomwide Serial card or Serial Port card for an Acorn
|
||||
system, say Y to this option. The driver can handle 1, 2, or 3 port
|
||||
cards. If unsure, say N.
|
||||
|
||||
config SERIAL_AMBA_PL010
|
||||
tristate "ARM AMBA PL010 serial port support"
|
||||
depends on ARM_AMBA
|
||||
select SERIAL_CORE
|
||||
help
|
||||
This selects the ARM(R) AMBA(R) PrimeCell PL010 UART. If you have
|
||||
an Integrator/AP or Integrator/PP2 platform, say Y or M here.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config SERIAL_AMBA_PL010_CONSOLE
|
||||
bool "Support for console on AMBA serial port"
|
||||
depends on SERIAL_AMBA_PL010=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
---help---
|
||||
Say Y here if you wish to use an AMBA PrimeCell UART as the system
|
||||
console (the system console is the device which receives all kernel
|
||||
messages and warnings and which allows logins in single user mode).
|
||||
|
||||
Even if you say Y here, the currently visible framebuffer console
|
||||
(/dev/tty0) will still be used as the system console by default, but
|
||||
you can alter that using a kernel command line option such as
|
||||
"console=ttyAM0". (Try "man bootparam" or see the documentation of
|
||||
your boot loader (lilo or loadlin) about how to pass options to the
|
||||
kernel at boot time.)
|
||||
|
||||
config SERIAL_AMBA_PL011
|
||||
tristate "ARM AMBA PL011 serial port support"
|
||||
depends on ARM_AMBA
|
||||
select SERIAL_CORE
|
||||
help
|
||||
This selects the ARM(R) AMBA(R) PrimeCell PL011 UART. If you have
|
||||
an Integrator/PP2, Integrator/CP or Versatile platform, say Y or M
|
||||
here.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config SERIAL_AMBA_PL011_CONSOLE
|
||||
bool "Support for console on AMBA serial port"
|
||||
depends on SERIAL_AMBA_PL011=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
---help---
|
||||
Say Y here if you wish to use an AMBA PrimeCell UART as the system
|
||||
console (the system console is the device which receives all kernel
|
||||
messages and warnings and which allows logins in single user mode).
|
||||
|
||||
Even if you say Y here, the currently visible framebuffer console
|
||||
(/dev/tty0) will still be used as the system console by default, but
|
||||
you can alter that using a kernel command line option such as
|
||||
"console=ttyAM0". (Try "man bootparam" or see the documentation of
|
||||
your boot loader (lilo or loadlin) about how to pass options to the
|
||||
kernel at boot time.)
|
||||
|
||||
config SERIAL_CLPS711X
|
||||
tristate "CLPS711X serial port support"
|
||||
depends on ARM && ARCH_CLPS711X
|
||||
select SERIAL_CORE
|
||||
help
|
||||
::: To be written :::
|
||||
|
||||
config SERIAL_CLPS711X_CONSOLE
|
||||
bool "Support for console on CLPS711X serial port"
|
||||
depends on SERIAL_CLPS711X=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
Even if you say Y here, the currently visible virtual console
|
||||
(/dev/tty0) will still be used as the system console by default, but
|
||||
you can alter that using a kernel command line option such as
|
||||
"console=ttyCL1". (Try "man bootparam" or see the documentation of
|
||||
your boot loader (lilo or loadlin) about how to pass options to the
|
||||
kernel at boot time.)
|
||||
|
||||
config SERIAL_S3C2410
|
||||
tristate "Samsung S3C2410 Serial port support"
|
||||
depends on ARM && ARCH_S3C2410
|
||||
select SERIAL_CORE
|
||||
help
|
||||
Support for the on-chip UARTs on the Samsung S3C2410X CPU,
|
||||
providing /dev/ttySAC0, 1 and 2 (note, some machines may not
|
||||
provide all of these ports, depending on how the serial port
|
||||
pins are configured.
|
||||
|
||||
config SERIAL_S3C2410_CONSOLE
|
||||
bool "Support for console on S3C2410 serial port"
|
||||
depends on SERIAL_S3C2410=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
Allow selection of the S3C2410 on-board serial ports for use as
|
||||
an virtual console.
|
||||
|
||||
Even if you say Y here, the currently visible virtual console
|
||||
(/dev/tty0) will still be used as the system console by default, but
|
||||
you can alter that using a kernel command line option such as
|
||||
"console=ttySACx". (Try "man bootparam" or see the documentation of
|
||||
your boot loader about how to pass options to the kernel at
|
||||
boot time.)
|
||||
|
||||
config SERIAL_BAST_SIO
|
||||
bool "Support for BAST SuperIO serial ports"
|
||||
depends on ARCH_BAST && SERIAL_8250=y
|
||||
help
|
||||
Support for registerin the SuperIO chip on BAST board with
|
||||
the 8250/16550 uart code.
|
||||
|
||||
config SERIAL_DZ
|
||||
bool "DECstation DZ serial driver"
|
||||
depends on MACH_DECSTATION && MIPS32
|
||||
select SERIAL_CORE
|
||||
help
|
||||
DZ11-family serial controllers for VAXstations, including the
|
||||
DC7085, M7814, and M7819.
|
||||
|
||||
config SERIAL_DZ_CONSOLE
|
||||
bool "Support console on DECstation DZ serial driver"
|
||||
depends on SERIAL_DZ=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
If you say Y here, it will be possible to use a serial port as the
|
||||
system console (the system console is the device which receives all
|
||||
kernel messages and warnings and which allows logins in single user
|
||||
mode). Note that the firmware uses ttyS0 as the serial console on
|
||||
the Maxine and ttyS2 on the others.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config SERIAL_21285
|
||||
tristate "DC21285 serial port support"
|
||||
depends on ARM && FOOTBRIDGE
|
||||
select SERIAL_CORE
|
||||
help
|
||||
If you have a machine based on a 21285 (Footbridge) StrongARM(R)/
|
||||
PCI bridge you can enable its onboard serial port by enabling this
|
||||
option.
|
||||
|
||||
config SERIAL_21285_CONSOLE
|
||||
bool "Console on DC21285 serial port"
|
||||
depends on SERIAL_21285=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
If you have enabled the serial port on the 21285 footbridge you can
|
||||
make it the console by answering Y to this option.
|
||||
|
||||
Even if you say Y here, the currently visible virtual console
|
||||
(/dev/tty0) will still be used as the system console by default, but
|
||||
you can alter that using a kernel command line option such as
|
||||
"console=ttyFB". (Try "man bootparam" or see the documentation of
|
||||
your boot loader (lilo or loadlin) about how to pass options to the
|
||||
kernel at boot time.)
|
||||
|
||||
config SERIAL_UART00
|
||||
bool "Excalibur serial port (uart00) support"
|
||||
depends on ARM && ARCH_CAMELOT
|
||||
select SERIAL_CORE
|
||||
help
|
||||
Say Y here if you want to use the hard logic uart on Excalibur. This
|
||||
driver also supports soft logic implentations of this uart core.
|
||||
|
||||
config SERIAL_UART00_CONSOLE
|
||||
bool "Support for console on Excalibur serial port"
|
||||
depends on SERIAL_UART00
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
Say Y here if you want to support a serial console on an Excalibur
|
||||
hard logic uart or uart00 IP core.
|
||||
|
||||
Even if you say Y here, the currently visible virtual console
|
||||
(/dev/tty0) will still be used as the system console by default, but
|
||||
you can alter that using a kernel command line option such as
|
||||
"console=ttyS1". (Try "man bootparam" or see the documentation of
|
||||
your boot loader (lilo or loadlin) about how to pass options to the
|
||||
kernel at boot time.)
|
||||
|
||||
config SERIAL_PXA
|
||||
bool "PXA serial port support"
|
||||
depends on ARM && ARCH_PXA
|
||||
select SERIAL_CORE
|
||||
help
|
||||
If you have a machine based on an Intel XScale PXA2xx CPU you
|
||||
can enable its onboard serial ports by enabling this option.
|
||||
|
||||
config SERIAL_PXA_CONSOLE
|
||||
bool "Console on PXA serial port"
|
||||
depends on SERIAL_PXA
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
If you have enabled the serial port on the Intel XScale PXA
|
||||
CPU you can make it the console by answering Y to this option.
|
||||
|
||||
Even if you say Y here, the currently visible virtual console
|
||||
(/dev/tty0) will still be used as the system console by default, but
|
||||
you can alter that using a kernel command line option such as
|
||||
"console=ttySA0". (Try "man bootparam" or see the documentation of
|
||||
your boot loader (lilo or loadlin) about how to pass options to the
|
||||
kernel at boot time.)
|
||||
|
||||
config SERIAL_SA1100
|
||||
bool "SA1100 serial port support"
|
||||
depends on ARM && ARCH_SA1100
|
||||
select SERIAL_CORE
|
||||
help
|
||||
If you have a machine based on a SA1100/SA1110 StrongARM(R) CPU you
|
||||
can enable its onboard serial port by enabling this option.
|
||||
Please read <file:Documentation/arm/SA1100/serial_UART> for further
|
||||
info.
|
||||
|
||||
config SERIAL_SA1100_CONSOLE
|
||||
bool "Console on SA1100 serial port"
|
||||
depends on SERIAL_SA1100
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
If you have enabled the serial port on the SA1100/SA1110 StrongARM
|
||||
CPU you can make it the console by answering Y to this option.
|
||||
|
||||
Even if you say Y here, the currently visible virtual console
|
||||
(/dev/tty0) will still be used as the system console by default, but
|
||||
you can alter that using a kernel command line option such as
|
||||
"console=ttySA0". (Try "man bootparam" or see the documentation of
|
||||
your boot loader (lilo or loadlin) about how to pass options to the
|
||||
kernel at boot time.)
|
||||
|
||||
config SERIAL_IMX
|
||||
bool "IMX serial port support"
|
||||
depends on ARM && ARCH_IMX
|
||||
select SERIAL_CORE
|
||||
help
|
||||
If you have a machine based on a Motorola IMX CPU you
|
||||
can enable its onboard serial port by enabling this option.
|
||||
|
||||
config SERIAL_IMX_CONSOLE
|
||||
bool "Console on IMX serial port"
|
||||
depends on SERIAL_IMX
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
If you have enabled the serial port on the Motorola IMX
|
||||
CPU you can make it the console by answering Y to this option.
|
||||
|
||||
Even if you say Y here, the currently visible virtual console
|
||||
(/dev/tty0) will still be used as the system console by default, but
|
||||
you can alter that using a kernel command line option such as
|
||||
"console=ttySA0". (Try "man bootparam" or see the documentation of
|
||||
your boot loader (lilo or loadlin) about how to pass options to the
|
||||
kernel at boot time.)
|
||||
|
||||
config SERIAL_SUNCORE
|
||||
bool
|
||||
depends on SPARC32 || SPARC64
|
||||
select SERIAL_CORE
|
||||
select SERIAL_CORE_CONSOLE
|
||||
default y
|
||||
|
||||
config SERIAL_SUNZILOG
|
||||
tristate "Sun Zilog8530 serial support"
|
||||
depends on SPARC32 || SPARC64
|
||||
help
|
||||
This driver supports the Zilog8530 serial ports found on many Sparc
|
||||
systems. Say Y or M if you want to be able to these serial ports.
|
||||
|
||||
config SERIAL_SUNZILOG_CONSOLE
|
||||
bool "Console on Sun Zilog8530 serial port"
|
||||
depends on SERIAL_SUNZILOG=y
|
||||
help
|
||||
If you would like to be able to use the Zilog8530 serial port
|
||||
on your Sparc system as the console, you can do so by answering
|
||||
Y to this option.
|
||||
|
||||
config SERIAL_SUNSU
|
||||
tristate "Sun SU serial support"
|
||||
depends on (SPARC32 || SPARC64) && PCI
|
||||
help
|
||||
This driver supports the 8250 serial ports that run the keyboard and
|
||||
mouse on (PCI) UltraSPARC systems. Say Y or M if you want to be able
|
||||
to these serial ports.
|
||||
|
||||
config SERIAL_SUNSU_CONSOLE
|
||||
bool "Console on Sun SU serial port"
|
||||
depends on SERIAL_SUNSU=y
|
||||
help
|
||||
If you would like to be able to use the SU serial port
|
||||
on your Sparc system as the console, you can do so by answering
|
||||
Y to this option.
|
||||
|
||||
config SERIAL_MUX
|
||||
tristate "Serial MUX support"
|
||||
depends on PARISC
|
||||
select SERIAL_CORE
|
||||
default y
|
||||
---help---
|
||||
Saying Y here will enable the hardware MUX serial driver for
|
||||
the Nova and K class systems. The hardware MUX is not 8250/16550
|
||||
compatible therefore the /dev/ttyB0 device is shared between the
|
||||
Serial MUX and the PDC software console. The following steps
|
||||
need to be completed to use the Serial MUX:
|
||||
|
||||
1. create the device entry (mknod /dev/ttyB0 c 11 0)
|
||||
2. Edit the /etc/inittab to start a getty listening on /dev/ttyB0
|
||||
3. Add device ttyB0 to /etc/securetty (if you want to log on as
|
||||
root on this console.)
|
||||
4. Change the kernel command console parameter to: console=ttyB0
|
||||
|
||||
config SERIAL_MUX_CONSOLE
|
||||
bool "Support for console on serial MUX"
|
||||
depends on SERIAL_MUX
|
||||
select SERIAL_CORE_CONSOLE
|
||||
default y
|
||||
|
||||
config PDC_CONSOLE
|
||||
bool "PDC software console support"
|
||||
depends on PARISC && !SERIAL_MUX && VT
|
||||
default n
|
||||
help
|
||||
Saying Y here will enable the software based PDC console to be
|
||||
used as the system console. This is useful for machines in
|
||||
which the hardware based console has not been written yet. The
|
||||
following steps must be competed to use the PDC console:
|
||||
|
||||
1. create the device entry (mknod /dev/ttyB0 c 11 0)
|
||||
2. Edit the /etc/inittab to start a getty listening on /dev/ttyB0
|
||||
3. Add device ttyB0 to /etc/securetty (if you want to log on as
|
||||
root on this console.)
|
||||
4. Change the kernel command console parameter to: console=ttyB0
|
||||
|
||||
config SERIAL_SUNSAB
|
||||
tristate "Sun Siemens SAB82532 serial support"
|
||||
depends on (SPARC32 || SPARC64) && PCI
|
||||
help
|
||||
This driver supports the Siemens SAB82532 DUSCC serial ports on newer
|
||||
(PCI) UltraSPARC systems. Say Y or M if you want to be able to these
|
||||
serial ports.
|
||||
|
||||
config SERIAL_SUNSAB_CONSOLE
|
||||
bool "Console on Sun Siemens SAB82532 serial port"
|
||||
depends on SERIAL_SUNSAB=y
|
||||
help
|
||||
If you would like to be able to use the SAB82532 serial port
|
||||
on your Sparc system as the console, you can do so by answering
|
||||
Y to this option.
|
||||
|
||||
config SERIAL_IP22_ZILOG
|
||||
tristate "IP22 Zilog8530 serial support"
|
||||
depends on SGI_IP22
|
||||
select SERIAL_CORE
|
||||
help
|
||||
This driver supports the Zilog8530 serial ports found on SGI IP22
|
||||
systems. Say Y or M if you want to be able to these serial ports.
|
||||
|
||||
config SERIAL_IP22_ZILOG_CONSOLE
|
||||
bool "Console on IP22 Zilog8530 serial port"
|
||||
depends on SERIAL_IP22_ZILOG=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
|
||||
config V850E_UART
|
||||
bool "NEC V850E on-chip UART support"
|
||||
depends on V850E_MA1 || V850E_ME2 || V850E_TEG || V850E2_ANNA || V850E_AS85EP1
|
||||
select SERIAL_CORE
|
||||
default y
|
||||
|
||||
config V850E_UARTB
|
||||
bool
|
||||
depends V850E_UART && V850E_ME2
|
||||
default y
|
||||
|
||||
config V850E_UART_CONSOLE
|
||||
bool "Use NEC V850E on-chip UART for console"
|
||||
depends on V850E_UART
|
||||
select SERIAL_CORE_CONSOLE
|
||||
|
||||
config SERIAL_SH_SCI
|
||||
tristate "SH SCI(F) serial port support"
|
||||
depends on SUPERH || H8300
|
||||
select SERIAL_CORE
|
||||
|
||||
config SERIAL_SH_SCI_CONSOLE
|
||||
bool "Support for console on SH SCI(F)"
|
||||
depends on SERIAL_SH_SCI=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
|
||||
config SERIAL_AU1X00
|
||||
bool "Enable Au1x00 UART Support"
|
||||
depends on MIPS && SOC_AU1X00
|
||||
select SERIAL_CORE
|
||||
help
|
||||
If you have an Alchemy AU1X00 processor (MIPS based) and you want
|
||||
to use serial ports, say Y. Otherwise, say N.
|
||||
|
||||
config SERIAL_AU1X00_CONSOLE
|
||||
bool "Enable Au1x00 serial console"
|
||||
depends on SERIAL_AU1X00
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
If you have an Alchemy AU1X00 processor (MIPS based) and you want
|
||||
to use a console on a serial port, say Y. Otherwise, say N.
|
||||
|
||||
config SERIAL_CORE
|
||||
tristate
|
||||
|
||||
config SERIAL_CORE_CONSOLE
|
||||
bool
|
||||
|
||||
config SERIAL_68328
|
||||
bool "68328 serial support"
|
||||
depends on M68328 || M68EZ328 || M68VZ328
|
||||
help
|
||||
This driver supports the built-in serial port of the Motorola 68328
|
||||
(standard, EZ and VZ varities).
|
||||
|
||||
config SERIAL_68328_RTS_CTS
|
||||
bool "Support RTS/CTS on 68328 serial port"
|
||||
depends on SERIAL_68328
|
||||
|
||||
config SERIAL_COLDFIRE
|
||||
bool "ColdFire serial support"
|
||||
depends on COLDFIRE
|
||||
help
|
||||
This driver supports the built-in serial ports of the Motorola ColdFire
|
||||
family of CPUs.
|
||||
|
||||
config SERIAL_68360_SMC
|
||||
bool "68360 SMC uart support"
|
||||
depends on M68360
|
||||
help
|
||||
This driver supports the SMC serial ports of the Motorola 68360 CPU.
|
||||
|
||||
config SERIAL_68360_SCC
|
||||
bool "68360 SCC uart support"
|
||||
depends on M68360
|
||||
help
|
||||
This driver supports the SCC serial ports of the Motorola 68360 CPU.
|
||||
|
||||
config SERIAL_68360
|
||||
bool
|
||||
depends on SERIAL_68360_SMC || SERIAL_68360_SCC
|
||||
default y
|
||||
|
||||
config SERIAL_PMACZILOG
|
||||
tristate "PowerMac z85c30 ESCC support"
|
||||
depends on PPC_OF
|
||||
select SERIAL_CORE
|
||||
help
|
||||
This driver supports the Zilog z85C30 serial ports found on
|
||||
PowerMac machines.
|
||||
Say Y or M if you want to be able to these serial ports.
|
||||
|
||||
config SERIAL_PMACZILOG_CONSOLE
|
||||
bool "Console on PowerMac z85c30 serial port"
|
||||
depends on SERIAL_PMACZILOG=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
If you would like to be able to use the z85c30 serial port
|
||||
on your PowerMac as the console, you can do so by answering
|
||||
Y to this option.
|
||||
|
||||
config SERIAL_LH7A40X
|
||||
tristate "Sharp LH7A40X embedded UART support"
|
||||
depends on ARM && ARCH_LH7A40X
|
||||
select SERIAL_CORE
|
||||
help
|
||||
This enables support for the three on-board UARTs of the
|
||||
Sharp LH7A40X series CPUs. Choose Y or M.
|
||||
|
||||
config SERIAL_LH7A40X_CONSOLE
|
||||
bool "Support for connsole on Sharp LH7A40X serial port"
|
||||
depends on SERIAL_LH7A40X=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
Say Y here if you wish to use one of the serial ports as the
|
||||
system console--the system console is the device which
|
||||
receives all kernel messages and warnings and which allows
|
||||
logins in single user mode.
|
||||
|
||||
Even if you say Y here, the currently visible framebuffer console
|
||||
(/dev/tty0) will still be used as the default system console, but
|
||||
you can alter that using a kernel command line, for example
|
||||
"console=ttyAM1".
|
||||
|
||||
config SERIAL_CPM
|
||||
tristate "CPM SCC/SMC serial port support"
|
||||
depends on CPM2 || 8xx
|
||||
select SERIAL_CORE
|
||||
help
|
||||
This driver supports the SCC and SMC serial ports on Motorola
|
||||
embedded PowerPC that contain a CPM1 (8xx) or CPM2 (8xxx)
|
||||
|
||||
config SERIAL_CPM_CONSOLE
|
||||
bool "Support for console on CPM SCC/SMC serial port"
|
||||
depends on SERIAL_CPM=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
Say Y here if you wish to use a SCC or SMC CPM UART as the system
|
||||
console (the system console is the device which receives all kernel
|
||||
messages and warnings and which allows logins in single user mode).
|
||||
|
||||
Even if you say Y here, the currently visible framebuffer console
|
||||
(/dev/tty0) will still be used as the system console by default, but
|
||||
you can alter that using a kernel command line option such as
|
||||
"console=ttyCPM0". (Try "man bootparam" or see the documentation of
|
||||
your boot loader (lilo or loadlin) about how to pass options to the
|
||||
kernel at boot time.)
|
||||
|
||||
config SERIAL_CPM_SCC1
|
||||
bool "Support for SCC1 serial port"
|
||||
depends on SERIAL_CPM=y
|
||||
help
|
||||
Select the is option to use SCC1 as a serial port
|
||||
|
||||
config SERIAL_CPM_SCC2
|
||||
bool "Support for SCC2 serial port"
|
||||
depends on SERIAL_CPM=y
|
||||
help
|
||||
Select the is option to use SCC2 as a serial port
|
||||
|
||||
config SERIAL_CPM_SCC3
|
||||
bool "Support for SCC3 serial port"
|
||||
depends on SERIAL_CPM=y
|
||||
help
|
||||
Select the is option to use SCC3 as a serial port
|
||||
|
||||
config SERIAL_CPM_SCC4
|
||||
bool "Support for SCC4 serial port"
|
||||
depends on SERIAL_CPM=y
|
||||
help
|
||||
Select the is option to use SCC4 as a serial port
|
||||
|
||||
config SERIAL_CPM_SMC1
|
||||
bool "Support for SMC1 serial port"
|
||||
depends on SERIAL_CPM=y
|
||||
help
|
||||
Select the is option to use SMC1 as a serial port
|
||||
|
||||
config SERIAL_CPM_SMC2
|
||||
bool "Support for SMC2 serial port"
|
||||
depends on SERIAL_CPM=y
|
||||
help
|
||||
Select the is option to use SMC2 as a serial port
|
||||
|
||||
config SERIAL_SGI_L1_CONSOLE
|
||||
bool "SGI Altix L1 serial console support"
|
||||
depends on IA64_GENERIC || IA64_SGI_SN2
|
||||
select SERIAL_CORE
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
If you have an SGI Altix and you would like to use the system
|
||||
controller serial port as your console (you want this!),
|
||||
say Y. Otherwise, say N.
|
||||
|
||||
config SERIAL_MPC52xx
|
||||
tristate "Freescale MPC52xx family PSC serial support"
|
||||
depends on PPC_MPC52xx
|
||||
select SERIAL_CORE
|
||||
help
|
||||
This drivers support the MPC52xx PSC serial ports. If you would
|
||||
like to use them, you must answer Y or M to this option. Not that
|
||||
for use as console, it must be included in kernel and not as a
|
||||
module.
|
||||
|
||||
config SERIAL_MPC52xx_CONSOLE
|
||||
bool "Console on a Freescale MPC52xx family PSC serial port"
|
||||
depends on SERIAL_MPC52xx=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
Select this options if you'd like to use one of the PSC serial port
|
||||
of the Freescale MPC52xx family as a console.
|
||||
|
||||
config SERIAL_MPC52xx_CONSOLE_BAUD
|
||||
int "Freescale MPC52xx family PSC serial port baud"
|
||||
depends on SERIAL_MPC52xx_CONSOLE=y
|
||||
default "9600"
|
||||
help
|
||||
Select the MPC52xx console baud rate.
|
||||
This value is only used if the bootloader doesn't pass in the
|
||||
console baudrate
|
||||
|
||||
config SERIAL_ICOM
|
||||
tristate "IBM Multiport Serial Adapter"
|
||||
depends on PPC_ISERIES || PPC_PSERIES
|
||||
select SERIAL_CORE
|
||||
help
|
||||
This driver is for a family of multiport serial adapters
|
||||
including 2 port RVX, 2 port internal modem, 4 port internal
|
||||
modem and a split 1 port RVX and 1 port internal modem.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called icom.
|
||||
|
||||
config SERIAL_M32R_SIO
|
||||
bool "M32R SIO I/F"
|
||||
depends on M32R
|
||||
default y
|
||||
select SERIAL_CORE
|
||||
help
|
||||
Say Y here if you want to use the M32R serial controller.
|
||||
|
||||
config SERIAL_M32R_SIO_CONSOLE
|
||||
bool "use SIO console"
|
||||
depends on SERIAL_M32R_SIO=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
help
|
||||
Say Y here if you want to support a serial console.
|
||||
|
||||
If you use an M3T-M32700UT or an OPSPUT platform,
|
||||
please say also y for SERIAL_M32R_PLDSIO.
|
||||
|
||||
config SERIAL_M32R_PLDSIO
|
||||
bool "M32R SIO I/F on a PLD"
|
||||
depends on SERIAL_M32R_SIO=y
|
||||
default n
|
||||
help
|
||||
Say Y here if you want to use the M32R serial controller
|
||||
on a PLD (Programmable Logic Device).
|
||||
|
||||
If you use an M3T-M32700UT or an OPSPUT platform,
|
||||
please say Y.
|
||||
|
||||
endmenu
|
||||
49
extra/linux-2.6.10/drivers/serial/Makefile
Normal file
49
extra/linux-2.6.10/drivers/serial/Makefile
Normal file
@@ -0,0 +1,49 @@
|
||||
#
|
||||
# Makefile for the kernel serial device drivers.
|
||||
#
|
||||
# $Id: Makefile,v 1.8 2002/07/21 21:32:30 rmk Exp $
|
||||
#
|
||||
|
||||
serial-8250-y :=
|
||||
serial-8250-$(CONFIG_SERIAL_8250_ACPI) += 8250_acpi.o
|
||||
serial-8250-$(CONFIG_GSC) += 8250_gsc.o
|
||||
serial-8250-$(CONFIG_PCI) += 8250_pci.o
|
||||
serial-8250-$(CONFIG_PNP) += 8250_pnp.o
|
||||
serial-8250-$(CONFIG_HP300) += 8250_hp300.o
|
||||
|
||||
obj-$(CONFIG_SERIAL_CORE) += serial_core.o
|
||||
obj-$(CONFIG_SERIAL_21285) += 21285.o
|
||||
obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y)
|
||||
obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o
|
||||
obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o
|
||||
obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o
|
||||
obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
|
||||
obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
|
||||
obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
|
||||
obj-$(CONFIG_SERIAL_PXA) += pxa.o
|
||||
obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
|
||||
obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
|
||||
obj-$(CONFIG_SERIAL_UART00) += uart00.o
|
||||
obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
|
||||
obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
|
||||
obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
|
||||
obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o
|
||||
obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o
|
||||
obj-$(CONFIG_SERIAL_MUX) += mux.o
|
||||
obj-$(CONFIG_SERIAL_68328) += 68328serial.o
|
||||
obj-$(CONFIG_SERIAL_68360) += 68360serial.o
|
||||
obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o
|
||||
obj-$(CONFIG_V850E_UART) += v850e_uart.o
|
||||
obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o
|
||||
obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o
|
||||
obj-$(CONFIG_SERIAL_AU1X00) += au1x00_uart.o
|
||||
obj-$(CONFIG_SERIAL_DZ) += dz.o
|
||||
obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o
|
||||
obj-$(CONFIG_SERIAL_BAST_SIO) += bast_sio.o
|
||||
obj-$(CONFIG_SERIAL_SGI_L1_CONSOLE) += sn_console.o
|
||||
obj-$(CONFIG_SERIAL_CPM) += cpm_uart/
|
||||
obj-$(CONFIG_SERIAL_IMX) += imx.o
|
||||
obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o
|
||||
obj-$(CONFIG_SERIAL_ICOM) += icom.o
|
||||
obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o
|
||||
obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
|
||||
840
extra/linux-2.6.10/drivers/serial/amba-pl010.c
Normal file
840
extra/linux-2.6.10/drivers/serial/amba-pl010.c
Normal file
@@ -0,0 +1,840 @@
|
||||
/*
|
||||
* linux/drivers/char/amba.c
|
||||
*
|
||||
* Driver for AMBA serial ports
|
||||
*
|
||||
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
|
||||
*
|
||||
* Copyright 1999 ARM Limited
|
||||
* Copyright (C) 2000 Deep Blue Solutions Ltd.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* $Id: amba.c,v 1.41 2002/07/28 10:03:27 rmk Exp $
|
||||
*
|
||||
* This is a generic driver for ARM AMBA-type serial ports. They
|
||||
* have a lot of 16550-like features, but are not register compatible.
|
||||
* Note that although they do have CTS, DCD and DSR inputs, they do
|
||||
* not have an RI input, nor do they have DTR or RTS outputs. If
|
||||
* required, these have to be supplied via some other means (eg, GPIO)
|
||||
* and hooked into this driver.
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
|
||||
#if defined(CONFIG_SERIAL_AMBA_PL010_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
||||
#define SUPPORT_SYSRQ
|
||||
#endif
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/hardware/amba.h>
|
||||
#include <asm/hardware/amba_serial.h>
|
||||
|
||||
#define UART_NR 2
|
||||
|
||||
#define SERIAL_AMBA_MAJOR 204
|
||||
#define SERIAL_AMBA_MINOR 16
|
||||
#define SERIAL_AMBA_NR UART_NR
|
||||
|
||||
#define AMBA_ISR_PASS_LIMIT 256
|
||||
|
||||
/*
|
||||
* Access macros for the AMBA UARTs
|
||||
*/
|
||||
#define UART_GET_INT_STATUS(p) readb((p)->membase + UART010_IIR)
|
||||
#define UART_PUT_ICR(p, c) writel((c), (p)->membase + UART010_ICR)
|
||||
#define UART_GET_FR(p) readb((p)->membase + UART01x_FR)
|
||||
#define UART_GET_CHAR(p) readb((p)->membase + UART01x_DR)
|
||||
#define UART_PUT_CHAR(p, c) writel((c), (p)->membase + UART01x_DR)
|
||||
#define UART_GET_RSR(p) readb((p)->membase + UART01x_RSR)
|
||||
#define UART_GET_CR(p) readb((p)->membase + UART010_CR)
|
||||
#define UART_PUT_CR(p,c) writel((c), (p)->membase + UART010_CR)
|
||||
#define UART_GET_LCRL(p) readb((p)->membase + UART010_LCRL)
|
||||
#define UART_PUT_LCRL(p,c) writel((c), (p)->membase + UART010_LCRL)
|
||||
#define UART_GET_LCRM(p) readb((p)->membase + UART010_LCRM)
|
||||
#define UART_PUT_LCRM(p,c) writel((c), (p)->membase + UART010_LCRM)
|
||||
#define UART_GET_LCRH(p) readb((p)->membase + UART010_LCRH)
|
||||
#define UART_PUT_LCRH(p,c) writel((c), (p)->membase + UART010_LCRH)
|
||||
#define UART_RX_DATA(s) (((s) & UART01x_FR_RXFE) == 0)
|
||||
#define UART_TX_READY(s) (((s) & UART01x_FR_TXFF) == 0)
|
||||
#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART01x_FR_TMSK) == 0)
|
||||
|
||||
#define UART_DUMMY_RSR_RX /*256*/0
|
||||
#define UART_PORT_SIZE 64
|
||||
|
||||
/*
|
||||
* On the Integrator platform, the port RTS and DTR are provided by
|
||||
* bits in the following SC_CTRLS register bits:
|
||||
* RTS DTR
|
||||
* UART0 7 6
|
||||
* UART1 5 4
|
||||
*/
|
||||
#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET)
|
||||
#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET)
|
||||
|
||||
/*
|
||||
* We wrap our port structure around the generic uart_port.
|
||||
*/
|
||||
struct uart_amba_port {
|
||||
struct uart_port port;
|
||||
unsigned int dtr_mask;
|
||||
unsigned int rts_mask;
|
||||
unsigned int old_status;
|
||||
};
|
||||
|
||||
static void pl010_stop_tx(struct uart_port *port, unsigned int tty_stop)
|
||||
{
|
||||
unsigned int cr;
|
||||
|
||||
cr = UART_GET_CR(port);
|
||||
cr &= ~UART010_CR_TIE;
|
||||
UART_PUT_CR(port, cr);
|
||||
}
|
||||
|
||||
static void pl010_start_tx(struct uart_port *port, unsigned int tty_start)
|
||||
{
|
||||
unsigned int cr;
|
||||
|
||||
cr = UART_GET_CR(port);
|
||||
cr |= UART010_CR_TIE;
|
||||
UART_PUT_CR(port, cr);
|
||||
}
|
||||
|
||||
static void pl010_stop_rx(struct uart_port *port)
|
||||
{
|
||||
unsigned int cr;
|
||||
|
||||
cr = UART_GET_CR(port);
|
||||
cr &= ~(UART010_CR_RIE | UART010_CR_RTIE);
|
||||
UART_PUT_CR(port, cr);
|
||||
}
|
||||
|
||||
static void pl010_enable_ms(struct uart_port *port)
|
||||
{
|
||||
unsigned int cr;
|
||||
|
||||
cr = UART_GET_CR(port);
|
||||
cr |= UART010_CR_MSIE;
|
||||
UART_PUT_CR(port, cr);
|
||||
}
|
||||
|
||||
static void
|
||||
#ifdef SUPPORT_SYSRQ
|
||||
pl010_rx_chars(struct uart_port *port, struct pt_regs *regs)
|
||||
#else
|
||||
pl010_rx_chars(struct uart_port *port)
|
||||
#endif
|
||||
{
|
||||
struct tty_struct *tty = port->info->tty;
|
||||
unsigned int status, ch, flag, rsr, max_count = 256;
|
||||
|
||||
status = UART_GET_FR(port);
|
||||
while (UART_RX_DATA(status) && max_count--) {
|
||||
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
|
||||
if (tty->low_latency)
|
||||
tty_flip_buffer_push(tty);
|
||||
/*
|
||||
* If this failed then we will throw away the
|
||||
* bytes but must do so to clear interrupts.
|
||||
*/
|
||||
}
|
||||
|
||||
ch = UART_GET_CHAR(port);
|
||||
flag = TTY_NORMAL;
|
||||
|
||||
port->icount.rx++;
|
||||
|
||||
/*
|
||||
* Note that the error handling code is
|
||||
* out of the main execution path
|
||||
*/
|
||||
rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX;
|
||||
if (rsr & UART01x_RSR_ANY) {
|
||||
if (rsr & UART01x_RSR_BE) {
|
||||
rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE);
|
||||
port->icount.brk++;
|
||||
if (uart_handle_break(port))
|
||||
goto ignore_char;
|
||||
} else if (rsr & UART01x_RSR_PE)
|
||||
port->icount.parity++;
|
||||
else if (rsr & UART01x_RSR_FE)
|
||||
port->icount.frame++;
|
||||
if (rsr & UART01x_RSR_OE)
|
||||
port->icount.overrun++;
|
||||
|
||||
rsr &= port->read_status_mask;
|
||||
|
||||
if (rsr & UART01x_RSR_BE)
|
||||
flag = TTY_BREAK;
|
||||
else if (rsr & UART01x_RSR_PE)
|
||||
flag = TTY_PARITY;
|
||||
else if (rsr & UART01x_RSR_FE)
|
||||
flag = TTY_FRAME;
|
||||
}
|
||||
|
||||
if (uart_handle_sysrq_char(port, ch, regs))
|
||||
goto ignore_char;
|
||||
|
||||
if ((rsr & port->ignore_status_mask) == 0) {
|
||||
tty_insert_flip_char(tty, ch, flag);
|
||||
}
|
||||
if ((rsr & UART01x_RSR_OE) &&
|
||||
tty->flip.count < TTY_FLIPBUF_SIZE) {
|
||||
/*
|
||||
* Overrun is special, since it's reported
|
||||
* immediately, and doesn't affect the current
|
||||
* character
|
||||
*/
|
||||
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
|
||||
}
|
||||
ignore_char:
|
||||
status = UART_GET_FR(port);
|
||||
}
|
||||
tty_flip_buffer_push(tty);
|
||||
return;
|
||||
}
|
||||
|
||||
static void pl010_tx_chars(struct uart_port *port)
|
||||
{
|
||||
struct circ_buf *xmit = &port->info->xmit;
|
||||
int count;
|
||||
|
||||
if (port->x_char) {
|
||||
UART_PUT_CHAR(port, port->x_char);
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
return;
|
||||
}
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
|
||||
pl010_stop_tx(port, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
count = port->fifosize >> 1;
|
||||
do {
|
||||
UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
} while (--count > 0);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
pl010_stop_tx(port, 0);
|
||||
}
|
||||
|
||||
static void pl010_modem_status(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned int status, delta;
|
||||
|
||||
UART_PUT_ICR(&uap->port, 0);
|
||||
|
||||
status = UART_GET_FR(&uap->port) & UART01x_FR_MODEM_ANY;
|
||||
|
||||
delta = status ^ uap->old_status;
|
||||
uap->old_status = status;
|
||||
|
||||
if (!delta)
|
||||
return;
|
||||
|
||||
if (delta & UART01x_FR_DCD)
|
||||
uart_handle_dcd_change(&uap->port, status & UART01x_FR_DCD);
|
||||
|
||||
if (delta & UART01x_FR_DSR)
|
||||
uap->port.icount.dsr++;
|
||||
|
||||
if (delta & UART01x_FR_CTS)
|
||||
uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS);
|
||||
|
||||
wake_up_interruptible(&uap->port.info->delta_msr_wait);
|
||||
}
|
||||
|
||||
static irqreturn_t pl010_int(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct uart_port *port = dev_id;
|
||||
unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
|
||||
int handled = 0;
|
||||
|
||||
spin_lock(&port->lock);
|
||||
|
||||
status = UART_GET_INT_STATUS(port);
|
||||
if (status) {
|
||||
do {
|
||||
if (status & (UART010_IIR_RTIS | UART010_IIR_RIS))
|
||||
#ifdef SUPPORT_SYSRQ
|
||||
pl010_rx_chars(port, regs);
|
||||
#else
|
||||
pl010_rx_chars(port);
|
||||
#endif
|
||||
if (status & UART010_IIR_MIS)
|
||||
pl010_modem_status(port);
|
||||
if (status & UART010_IIR_TIS)
|
||||
pl010_tx_chars(port);
|
||||
|
||||
if (pass_counter-- == 0)
|
||||
break;
|
||||
|
||||
status = UART_GET_INT_STATUS(port);
|
||||
} while (status & (UART010_IIR_RTIS | UART010_IIR_RIS |
|
||||
UART010_IIR_TIS));
|
||||
handled = 1;
|
||||
}
|
||||
|
||||
spin_unlock(&port->lock);
|
||||
|
||||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
|
||||
static unsigned int pl010_tx_empty(struct uart_port *port)
|
||||
{
|
||||
return UART_GET_FR(port) & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT;
|
||||
}
|
||||
|
||||
static unsigned int pl010_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
unsigned int result = 0;
|
||||
unsigned int status;
|
||||
|
||||
status = UART_GET_FR(port);
|
||||
if (status & UART01x_FR_DCD)
|
||||
result |= TIOCM_CAR;
|
||||
if (status & UART01x_FR_DSR)
|
||||
result |= TIOCM_DSR;
|
||||
if (status & UART01x_FR_CTS)
|
||||
result |= TIOCM_CTS;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned int ctrls = 0, ctrlc = 0;
|
||||
|
||||
if (mctrl & TIOCM_RTS)
|
||||
ctrlc |= uap->rts_mask;
|
||||
else
|
||||
ctrls |= uap->rts_mask;
|
||||
|
||||
if (mctrl & TIOCM_DTR)
|
||||
ctrlc |= uap->dtr_mask;
|
||||
else
|
||||
ctrls |= uap->dtr_mask;
|
||||
|
||||
__raw_writel(ctrls, SC_CTRLS);
|
||||
__raw_writel(ctrlc, SC_CTRLC);
|
||||
}
|
||||
|
||||
static void pl010_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int lcr_h;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
lcr_h = UART_GET_LCRH(port);
|
||||
if (break_state == -1)
|
||||
lcr_h |= UART01x_LCRH_BRK;
|
||||
else
|
||||
lcr_h &= ~UART01x_LCRH_BRK;
|
||||
UART_PUT_LCRH(port, lcr_h);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static int pl010_startup(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
int retval;
|
||||
|
||||
/*
|
||||
* Allocate the IRQ
|
||||
*/
|
||||
retval = request_irq(port->irq, pl010_int, 0, "uart-pl010", port);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/*
|
||||
* initialise the old status of the modem signals
|
||||
*/
|
||||
uap->old_status = UART_GET_FR(port) & UART01x_FR_MODEM_ANY;
|
||||
|
||||
/*
|
||||
* Finally, enable interrupts
|
||||
*/
|
||||
UART_PUT_CR(port, UART01x_CR_UARTEN | UART010_CR_RIE |
|
||||
UART010_CR_RTIE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pl010_shutdown(struct uart_port *port)
|
||||
{
|
||||
/*
|
||||
* Free the interrupt
|
||||
*/
|
||||
free_irq(port->irq, port);
|
||||
|
||||
/*
|
||||
* disable all interrupts, disable the port
|
||||
*/
|
||||
UART_PUT_CR(port, 0);
|
||||
|
||||
/* disable break condition and fifos */
|
||||
UART_PUT_LCRH(port, UART_GET_LCRH(port) &
|
||||
~(UART01x_LCRH_BRK | UART01x_LCRH_FEN));
|
||||
}
|
||||
|
||||
static void
|
||||
pl010_set_termios(struct uart_port *port, struct termios *termios,
|
||||
struct termios *old)
|
||||
{
|
||||
unsigned int lcr_h, old_cr;
|
||||
unsigned long flags;
|
||||
unsigned int baud, quot;
|
||||
|
||||
/*
|
||||
* Ask the core to calculate the divisor for us.
|
||||
*/
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
|
||||
quot = uart_get_divisor(port, baud);
|
||||
|
||||
switch (termios->c_cflag & CSIZE) {
|
||||
case CS5:
|
||||
lcr_h = UART01x_LCRH_WLEN_5;
|
||||
break;
|
||||
case CS6:
|
||||
lcr_h = UART01x_LCRH_WLEN_6;
|
||||
break;
|
||||
case CS7:
|
||||
lcr_h = UART01x_LCRH_WLEN_7;
|
||||
break;
|
||||
default: // CS8
|
||||
lcr_h = UART01x_LCRH_WLEN_8;
|
||||
break;
|
||||
}
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
lcr_h |= UART01x_LCRH_STP2;
|
||||
if (termios->c_cflag & PARENB) {
|
||||
lcr_h |= UART01x_LCRH_PEN;
|
||||
if (!(termios->c_cflag & PARODD))
|
||||
lcr_h |= UART01x_LCRH_EPS;
|
||||
}
|
||||
if (port->fifosize > 1)
|
||||
lcr_h |= UART01x_LCRH_FEN;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
/*
|
||||
* Update the per-port timeout.
|
||||
*/
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
port->read_status_mask = UART01x_RSR_OE;
|
||||
if (termios->c_iflag & INPCK)
|
||||
port->read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
|
||||
if (termios->c_iflag & (BRKINT | PARMRK))
|
||||
port->read_status_mask |= UART01x_RSR_BE;
|
||||
|
||||
/*
|
||||
* Characters to ignore
|
||||
*/
|
||||
port->ignore_status_mask = 0;
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
port->ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
|
||||
if (termios->c_iflag & IGNBRK) {
|
||||
port->ignore_status_mask |= UART01x_RSR_BE;
|
||||
/*
|
||||
* If we're ignoring parity and break indicators,
|
||||
* ignore overruns too (for real raw support).
|
||||
*/
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
port->ignore_status_mask |= UART01x_RSR_OE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignore all characters if CREAD is not set.
|
||||
*/
|
||||
if ((termios->c_cflag & CREAD) == 0)
|
||||
port->ignore_status_mask |= UART_DUMMY_RSR_RX;
|
||||
|
||||
/* first, disable everything */
|
||||
old_cr = UART_GET_CR(port) & ~UART010_CR_MSIE;
|
||||
|
||||
if (UART_ENABLE_MS(port, termios->c_cflag))
|
||||
old_cr |= UART010_CR_MSIE;
|
||||
|
||||
UART_PUT_CR(port, 0);
|
||||
|
||||
/* Set baud rate */
|
||||
quot -= 1;
|
||||
UART_PUT_LCRM(port, ((quot & 0xf00) >> 8));
|
||||
UART_PUT_LCRL(port, (quot & 0xff));
|
||||
|
||||
/*
|
||||
* ----------v----------v----------v----------v-----
|
||||
* NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
|
||||
* ----------^----------^----------^----------^-----
|
||||
*/
|
||||
UART_PUT_LCRH(port, lcr_h);
|
||||
UART_PUT_CR(port, old_cr);
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static const char *pl010_type(struct uart_port *port)
|
||||
{
|
||||
return port->type == PORT_AMBA ? "AMBA" : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the memory region(s) being used by 'port'
|
||||
*/
|
||||
static void pl010_release_port(struct uart_port *port)
|
||||
{
|
||||
release_mem_region(port->mapbase, UART_PORT_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Request the memory region(s) being used by 'port'
|
||||
*/
|
||||
static int pl010_request_port(struct uart_port *port)
|
||||
{
|
||||
return request_mem_region(port->mapbase, UART_PORT_SIZE, "uart-pl010")
|
||||
!= NULL ? 0 : -EBUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure/autoconfigure the port.
|
||||
*/
|
||||
static void pl010_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
if (flags & UART_CONFIG_TYPE) {
|
||||
port->type = PORT_AMBA;
|
||||
pl010_request_port(port);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* verify the new serial_struct (for TIOCSSERIAL).
|
||||
*/
|
||||
static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||
{
|
||||
int ret = 0;
|
||||
if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
|
||||
ret = -EINVAL;
|
||||
if (ser->irq < 0 || ser->irq >= NR_IRQS)
|
||||
ret = -EINVAL;
|
||||
if (ser->baud_base < 9600)
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct uart_ops amba_pl010_pops = {
|
||||
.tx_empty = pl010_tx_empty,
|
||||
.set_mctrl = pl010_set_mctrl,
|
||||
.get_mctrl = pl010_get_mctrl,
|
||||
.stop_tx = pl010_stop_tx,
|
||||
.start_tx = pl010_start_tx,
|
||||
.stop_rx = pl010_stop_rx,
|
||||
.enable_ms = pl010_enable_ms,
|
||||
.break_ctl = pl010_break_ctl,
|
||||
.startup = pl010_startup,
|
||||
.shutdown = pl010_shutdown,
|
||||
.set_termios = pl010_set_termios,
|
||||
.type = pl010_type,
|
||||
.release_port = pl010_release_port,
|
||||
.request_port = pl010_request_port,
|
||||
.config_port = pl010_config_port,
|
||||
.verify_port = pl010_verify_port,
|
||||
};
|
||||
|
||||
static struct uart_amba_port amba_ports[UART_NR] = {
|
||||
{
|
||||
.port = {
|
||||
.membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE),
|
||||
.mapbase = INTEGRATOR_UART0_BASE,
|
||||
.iotype = SERIAL_IO_MEM,
|
||||
.irq = IRQ_UARTINT0,
|
||||
.uartclk = 14745600,
|
||||
.fifosize = 16,
|
||||
.ops = &amba_pl010_pops,
|
||||
.flags = ASYNC_BOOT_AUTOCONF,
|
||||
.line = 0,
|
||||
},
|
||||
.dtr_mask = 1 << 5,
|
||||
.rts_mask = 1 << 4,
|
||||
},
|
||||
{
|
||||
.port = {
|
||||
.membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE),
|
||||
.mapbase = INTEGRATOR_UART1_BASE,
|
||||
.iotype = SERIAL_IO_MEM,
|
||||
.irq = IRQ_UARTINT1,
|
||||
.uartclk = 14745600,
|
||||
.fifosize = 16,
|
||||
.ops = &amba_pl010_pops,
|
||||
.flags = ASYNC_BOOT_AUTOCONF,
|
||||
.line = 1,
|
||||
},
|
||||
.dtr_mask = 1 << 7,
|
||||
.rts_mask = 1 << 6,
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE
|
||||
|
||||
static void
|
||||
pl010_console_write(struct console *co, const char *s, unsigned int count)
|
||||
{
|
||||
struct uart_port *port = &amba_ports[co->index].port;
|
||||
unsigned int status, old_cr;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* First save the CR then disable the interrupts
|
||||
*/
|
||||
old_cr = UART_GET_CR(port);
|
||||
UART_PUT_CR(port, UART01x_CR_UARTEN);
|
||||
|
||||
/*
|
||||
* Now, do each character
|
||||
*/
|
||||
for (i = 0; i < count; i++) {
|
||||
do {
|
||||
status = UART_GET_FR(port);
|
||||
} while (!UART_TX_READY(status));
|
||||
UART_PUT_CHAR(port, s[i]);
|
||||
if (s[i] == '\n') {
|
||||
do {
|
||||
status = UART_GET_FR(port);
|
||||
} while (!UART_TX_READY(status));
|
||||
UART_PUT_CHAR(port, '\r');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, wait for transmitter to become empty
|
||||
* and restore the TCR
|
||||
*/
|
||||
do {
|
||||
status = UART_GET_FR(port);
|
||||
} while (status & UART01x_FR_BUSY);
|
||||
UART_PUT_CR(port, old_cr);
|
||||
}
|
||||
|
||||
static void __init
|
||||
pl010_console_get_options(struct uart_port *port, int *baud,
|
||||
int *parity, int *bits)
|
||||
{
|
||||
if (UART_GET_CR(port) & UART01x_CR_UARTEN) {
|
||||
unsigned int lcr_h, quot;
|
||||
lcr_h = UART_GET_LCRH(port);
|
||||
|
||||
*parity = 'n';
|
||||
if (lcr_h & UART01x_LCRH_PEN) {
|
||||
if (lcr_h & UART01x_LCRH_EPS)
|
||||
*parity = 'e';
|
||||
else
|
||||
*parity = 'o';
|
||||
}
|
||||
|
||||
if ((lcr_h & 0x60) == UART01x_LCRH_WLEN_7)
|
||||
*bits = 7;
|
||||
else
|
||||
*bits = 8;
|
||||
|
||||
quot = UART_GET_LCRL(port) | UART_GET_LCRM(port) << 8;
|
||||
*baud = port->uartclk / (16 * (quot + 1));
|
||||
}
|
||||
}
|
||||
|
||||
static int __init pl010_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_port *port;
|
||||
int baud = 38400;
|
||||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
|
||||
/*
|
||||
* Check whether an invalid uart number has been specified, and
|
||||
* if so, search for the first available port that does have
|
||||
* console support.
|
||||
*/
|
||||
if (co->index >= UART_NR)
|
||||
co->index = 0;
|
||||
port = &amba_ports[co->index].port;
|
||||
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
else
|
||||
pl010_console_get_options(port, &baud, &parity, &bits);
|
||||
|
||||
return uart_set_options(port, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
extern struct uart_driver amba_reg;
|
||||
static struct console amba_console = {
|
||||
.name = "ttyAM",
|
||||
.write = pl010_console_write,
|
||||
.device = uart_console_device,
|
||||
.setup = pl010_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
.data = &amba_reg,
|
||||
};
|
||||
|
||||
static int __init amba_console_init(void)
|
||||
{
|
||||
/*
|
||||
* All port initializations are done statically
|
||||
*/
|
||||
register_console(&amba_console);
|
||||
return 0;
|
||||
}
|
||||
console_initcall(amba_console_init);
|
||||
|
||||
static int __init amba_late_console_init(void)
|
||||
{
|
||||
if (!(amba_console.flags & CON_ENABLED))
|
||||
register_console(&amba_console);
|
||||
return 0;
|
||||
}
|
||||
late_initcall(amba_late_console_init);
|
||||
|
||||
#define AMBA_CONSOLE &amba_console
|
||||
#else
|
||||
#define AMBA_CONSOLE NULL
|
||||
#endif
|
||||
|
||||
static struct uart_driver amba_reg = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = "ttyAM",
|
||||
.dev_name = "ttyAM",
|
||||
.major = SERIAL_AMBA_MAJOR,
|
||||
.minor = SERIAL_AMBA_MINOR,
|
||||
.nr = UART_NR,
|
||||
.cons = AMBA_CONSOLE,
|
||||
};
|
||||
|
||||
static int pl010_probe(struct amba_device *dev, void *id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < UART_NR; i++) {
|
||||
if (amba_ports[i].port.mapbase != dev->res.start)
|
||||
continue;
|
||||
|
||||
amba_ports[i].port.dev = &dev->dev;
|
||||
uart_add_one_port(&amba_reg, &amba_ports[i].port);
|
||||
amba_set_drvdata(dev, &amba_ports[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pl010_remove(struct amba_device *dev)
|
||||
{
|
||||
struct uart_amba_port *uap = amba_get_drvdata(dev);
|
||||
|
||||
if (uap)
|
||||
uart_remove_one_port(&amba_reg, &uap->port);
|
||||
|
||||
amba_set_drvdata(dev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pl010_suspend(struct amba_device *dev, u32 state)
|
||||
{
|
||||
struct uart_amba_port *uap = amba_get_drvdata(dev);
|
||||
|
||||
if (uap)
|
||||
uart_suspend_port(&amba_reg, &uap->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pl010_resume(struct amba_device *dev)
|
||||
{
|
||||
struct uart_amba_port *uap = amba_get_drvdata(dev);
|
||||
|
||||
if (uap)
|
||||
uart_resume_port(&amba_reg, &uap->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct amba_id pl010_ids[] __initdata = {
|
||||
{
|
||||
.id = 0x00041010,
|
||||
.mask = 0x000fffff,
|
||||
},
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static struct amba_driver pl010_driver = {
|
||||
.drv = {
|
||||
.name = "uart-pl010",
|
||||
},
|
||||
.id_table = pl010_ids,
|
||||
.probe = pl010_probe,
|
||||
.remove = pl010_remove,
|
||||
.suspend = pl010_suspend,
|
||||
.resume = pl010_resume,
|
||||
};
|
||||
|
||||
static int __init pl010_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printk(KERN_INFO "Serial: AMBA driver $Revision: 1.41 $\n");
|
||||
|
||||
ret = uart_register_driver(&amba_reg);
|
||||
if (ret == 0) {
|
||||
ret = amba_driver_register(&pl010_driver);
|
||||
if (ret)
|
||||
uart_unregister_driver(&amba_reg);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit pl010_exit(void)
|
||||
{
|
||||
amba_driver_unregister(&pl010_driver);
|
||||
uart_unregister_driver(&amba_reg);
|
||||
}
|
||||
|
||||
module_init(pl010_init);
|
||||
module_exit(pl010_exit);
|
||||
|
||||
MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd");
|
||||
MODULE_DESCRIPTION("ARM AMBA serial port driver $Revision: 1.41 $");
|
||||
MODULE_LICENSE("GPL");
|
||||
869
extra/linux-2.6.10/drivers/serial/amba-pl011.c
Normal file
869
extra/linux-2.6.10/drivers/serial/amba-pl011.c
Normal file
@@ -0,0 +1,869 @@
|
||||
/*
|
||||
* linux/drivers/char/amba.c
|
||||
*
|
||||
* Driver for AMBA serial ports
|
||||
*
|
||||
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
|
||||
*
|
||||
* Copyright 1999 ARM Limited
|
||||
* Copyright (C) 2000 Deep Blue Solutions Ltd.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* $Id: amba.c,v 1.41 2002/07/28 10:03:27 rmk Exp $
|
||||
*
|
||||
* This is a generic driver for ARM AMBA-type serial ports. They
|
||||
* have a lot of 16550-like features, but are not register compatible.
|
||||
* Note that although they do have CTS, DCD and DSR inputs, they do
|
||||
* not have an RI input, nor do they have DTR or RTS outputs. If
|
||||
* required, these have to be supplied via some other means (eg, GPIO)
|
||||
* and hooked into this driver.
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
|
||||
#if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
||||
#define SUPPORT_SYSRQ
|
||||
#endif
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/hardware/amba.h>
|
||||
#include <asm/hardware/clock.h>
|
||||
#include <asm/hardware/amba_serial.h>
|
||||
|
||||
#define UART_NR 14
|
||||
|
||||
#define SERIAL_AMBA_MAJOR 204
|
||||
#define SERIAL_AMBA_MINOR 64
|
||||
#define SERIAL_AMBA_NR UART_NR
|
||||
|
||||
#define AMBA_ISR_PASS_LIMIT 256
|
||||
|
||||
#define UART_DUMMY_RSR_RX 256
|
||||
|
||||
/*
|
||||
* We wrap our port structure around the generic uart_port.
|
||||
*/
|
||||
struct uart_amba_port {
|
||||
struct uart_port port;
|
||||
struct clk *clk;
|
||||
unsigned int im; /* interrupt mask */
|
||||
unsigned int old_status;
|
||||
};
|
||||
|
||||
static void pl011_stop_tx(struct uart_port *port, unsigned int tty_stop)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
|
||||
uap->im &= ~UART011_TXIM;
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
}
|
||||
|
||||
static void pl011_start_tx(struct uart_port *port, unsigned int tty_start)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
|
||||
uap->im |= UART011_TXIM;
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
}
|
||||
|
||||
static void pl011_stop_rx(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
|
||||
uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM|
|
||||
UART011_PEIM|UART011_BEIM|UART011_OEIM);
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
}
|
||||
|
||||
static void pl011_enable_ms(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
|
||||
uap->im |= UART011_RIMIM|UART011_CTSMIM|UART011_DCDMIM|UART011_DSRMIM;
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
}
|
||||
|
||||
static void
|
||||
#ifdef SUPPORT_SYSRQ
|
||||
pl011_rx_chars(struct uart_amba_port *uap, struct pt_regs *regs)
|
||||
#else
|
||||
pl011_rx_chars(struct uart_amba_port *uap)
|
||||
#endif
|
||||
{
|
||||
struct tty_struct *tty = uap->port.info->tty;
|
||||
unsigned int status, ch, flag, rsr, max_count = 256;
|
||||
|
||||
status = readw(uap->port.membase + UART01x_FR);
|
||||
while ((status & UART01x_FR_RXFE) == 0 && max_count--) {
|
||||
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
|
||||
if (tty->low_latency)
|
||||
tty_flip_buffer_push(tty);
|
||||
/*
|
||||
* If this failed then we will throw away the
|
||||
* bytes but must do so to clear interrupts
|
||||
*/
|
||||
}
|
||||
|
||||
ch = readw(uap->port.membase + UART01x_DR);
|
||||
flag = TTY_NORMAL;
|
||||
uap->port.icount.rx++;
|
||||
|
||||
/*
|
||||
* Note that the error handling code is
|
||||
* out of the main execution path
|
||||
*/
|
||||
rsr = readw(uap->port.membase + UART01x_RSR) | UART_DUMMY_RSR_RX;
|
||||
if (rsr & UART01x_RSR_ANY) {
|
||||
if (rsr & UART01x_RSR_BE) {
|
||||
rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE);
|
||||
uap->port.icount.brk++;
|
||||
if (uart_handle_break(&uap->port))
|
||||
goto ignore_char;
|
||||
} else if (rsr & UART01x_RSR_PE)
|
||||
uap->port.icount.parity++;
|
||||
else if (rsr & UART01x_RSR_FE)
|
||||
uap->port.icount.frame++;
|
||||
if (rsr & UART01x_RSR_OE)
|
||||
uap->port.icount.overrun++;
|
||||
|
||||
rsr &= uap->port.read_status_mask;
|
||||
|
||||
if (rsr & UART01x_RSR_BE)
|
||||
flag = TTY_BREAK;
|
||||
else if (rsr & UART01x_RSR_PE)
|
||||
flag = TTY_PARITY;
|
||||
else if (rsr & UART01x_RSR_FE)
|
||||
flag = TTY_FRAME;
|
||||
}
|
||||
|
||||
if (uart_handle_sysrq_char(&uap->port, ch, regs))
|
||||
goto ignore_char;
|
||||
|
||||
if ((rsr & uap->port.ignore_status_mask) == 0) {
|
||||
tty_insert_flip_char(tty, ch, flag);
|
||||
}
|
||||
if ((rsr & UART01x_RSR_OE) &&
|
||||
tty->flip.count < TTY_FLIPBUF_SIZE) {
|
||||
/*
|
||||
* Overrun is special, since it's reported
|
||||
* immediately, and doesn't affect the current
|
||||
* character
|
||||
*/
|
||||
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
|
||||
}
|
||||
ignore_char:
|
||||
status = readw(uap->port.membase + UART01x_FR);
|
||||
}
|
||||
tty_flip_buffer_push(tty);
|
||||
return;
|
||||
}
|
||||
|
||||
static void pl011_tx_chars(struct uart_amba_port *uap)
|
||||
{
|
||||
struct circ_buf *xmit = &uap->port.info->xmit;
|
||||
int count;
|
||||
|
||||
if (uap->port.x_char) {
|
||||
writew(uap->port.x_char, uap->port.membase + UART01x_DR);
|
||||
uap->port.icount.tx++;
|
||||
uap->port.x_char = 0;
|
||||
return;
|
||||
}
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
|
||||
pl011_stop_tx(&uap->port, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
count = uap->port.fifosize >> 1;
|
||||
do {
|
||||
writew(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
uap->port.icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
} while (--count > 0);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(&uap->port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
pl011_stop_tx(&uap->port, 0);
|
||||
}
|
||||
|
||||
static void pl011_modem_status(struct uart_amba_port *uap)
|
||||
{
|
||||
unsigned int status, delta;
|
||||
|
||||
status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
|
||||
|
||||
delta = status ^ uap->old_status;
|
||||
uap->old_status = status;
|
||||
|
||||
if (!delta)
|
||||
return;
|
||||
|
||||
if (delta & UART01x_FR_DCD)
|
||||
uart_handle_dcd_change(&uap->port, status & UART01x_FR_DCD);
|
||||
|
||||
if (delta & UART01x_FR_DSR)
|
||||
uap->port.icount.dsr++;
|
||||
|
||||
if (delta & UART01x_FR_CTS)
|
||||
uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS);
|
||||
|
||||
wake_up_interruptible(&uap->port.info->delta_msr_wait);
|
||||
}
|
||||
|
||||
static irqreturn_t pl011_int(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct uart_amba_port *uap = dev_id;
|
||||
unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
|
||||
int handled = 0;
|
||||
|
||||
spin_lock(&uap->port.lock);
|
||||
|
||||
status = readw(uap->port.membase + UART011_MIS);
|
||||
if (status) {
|
||||
do {
|
||||
writew(status & ~(UART011_TXIS|UART011_RTIS|
|
||||
UART011_RXIS),
|
||||
uap->port.membase + UART011_ICR);
|
||||
|
||||
if (status & (UART011_RTIS|UART011_RXIS))
|
||||
#ifdef SUPPORT_SYSRQ
|
||||
pl011_rx_chars(uap, regs);
|
||||
#else
|
||||
pl011_rx_chars(uap);
|
||||
#endif
|
||||
if (status & (UART011_DSRMIS|UART011_DCDMIS|
|
||||
UART011_CTSMIS|UART011_RIMIS))
|
||||
pl011_modem_status(uap);
|
||||
if (status & UART011_TXIS)
|
||||
pl011_tx_chars(uap);
|
||||
|
||||
if (pass_counter-- == 0)
|
||||
break;
|
||||
|
||||
status = readw(uap->port.membase + UART011_MIS);
|
||||
} while (status != 0);
|
||||
handled = 1;
|
||||
}
|
||||
|
||||
spin_unlock(&uap->port.lock);
|
||||
|
||||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
|
||||
static unsigned int pl01x_tx_empty(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned int status = readw(uap->port.membase + UART01x_FR);
|
||||
return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
|
||||
}
|
||||
|
||||
static unsigned int pl01x_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned int result = 0;
|
||||
unsigned int status = readw(uap->port.membase + UART01x_FR);
|
||||
|
||||
#define BIT(uartbit, tiocmbit) \
|
||||
if (status & uartbit) \
|
||||
result |= tiocmbit
|
||||
|
||||
BIT(UART01x_FR_DCD, TIOCM_CAR);
|
||||
BIT(UART01x_FR_DSR, TIOCM_DSR);
|
||||
BIT(UART01x_FR_CTS, TIOCM_CTS);
|
||||
BIT(UART011_FR_RI, TIOCM_RNG);
|
||||
#undef BIT
|
||||
return result;
|
||||
}
|
||||
|
||||
static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned int cr;
|
||||
|
||||
cr = readw(uap->port.membase + UART011_CR);
|
||||
|
||||
#define BIT(tiocmbit, uartbit) \
|
||||
if (mctrl & tiocmbit) \
|
||||
cr |= uartbit; \
|
||||
else \
|
||||
cr &= ~uartbit
|
||||
|
||||
BIT(TIOCM_RTS, UART011_CR_RTS);
|
||||
BIT(TIOCM_DTR, UART011_CR_DTR);
|
||||
BIT(TIOCM_OUT1, UART011_CR_OUT1);
|
||||
BIT(TIOCM_OUT2, UART011_CR_OUT2);
|
||||
BIT(TIOCM_LOOP, UART011_CR_LBE);
|
||||
#undef BIT
|
||||
|
||||
writew(cr, uap->port.membase + UART011_CR);
|
||||
}
|
||||
|
||||
static void pl011_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned long flags;
|
||||
unsigned int lcr_h;
|
||||
|
||||
spin_lock_irqsave(&uap->port.lock, flags);
|
||||
lcr_h = readw(uap->port.membase + UART011_LCRH);
|
||||
if (break_state == -1)
|
||||
lcr_h |= UART01x_LCRH_BRK;
|
||||
else
|
||||
lcr_h &= ~UART01x_LCRH_BRK;
|
||||
writew(lcr_h, uap->port.membase + UART011_LCRH);
|
||||
spin_unlock_irqrestore(&uap->port.lock, flags);
|
||||
}
|
||||
|
||||
static int pl011_startup(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned int cr;
|
||||
int retval;
|
||||
|
||||
/*
|
||||
* Try to enable the clock producer.
|
||||
*/
|
||||
retval = clk_enable(uap->clk);
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
uap->port.uartclk = clk_get_rate(uap->clk);
|
||||
|
||||
/*
|
||||
* Allocate the IRQ
|
||||
*/
|
||||
retval = request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
|
||||
if (retval)
|
||||
goto clk_dis;
|
||||
|
||||
writew(UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
|
||||
uap->port.membase + UART011_IFLS);
|
||||
|
||||
/*
|
||||
* Provoke TX FIFO interrupt into asserting.
|
||||
*/
|
||||
cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE;
|
||||
writew(cr, uap->port.membase + UART011_CR);
|
||||
writew(0, uap->port.membase + UART011_FBRD);
|
||||
writew(1, uap->port.membase + UART011_IBRD);
|
||||
writew(0, uap->port.membase + UART011_LCRH);
|
||||
writew(0, uap->port.membase + UART01x_DR);
|
||||
while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
|
||||
barrier();
|
||||
|
||||
cr = UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
|
||||
writew(cr, uap->port.membase + UART011_CR);
|
||||
|
||||
/*
|
||||
* initialise the old status of the modem signals
|
||||
*/
|
||||
uap->old_status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
|
||||
|
||||
/*
|
||||
* Finally, enable interrupts
|
||||
*/
|
||||
spin_lock_irq(&uap->port.lock);
|
||||
uap->im = UART011_RXIM | UART011_RTIM;
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
spin_unlock_irq(&uap->port.lock);
|
||||
|
||||
return 0;
|
||||
|
||||
clk_dis:
|
||||
clk_disable(uap->clk);
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void pl011_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
||||
unsigned long val;
|
||||
|
||||
/*
|
||||
* disable all interrupts
|
||||
*/
|
||||
spin_lock_irq(&uap->port.lock);
|
||||
uap->im = 0;
|
||||
writew(uap->im, uap->port.membase + UART011_IMSC);
|
||||
writew(0xffff, uap->port.membase + UART011_ICR);
|
||||
spin_unlock_irq(&uap->port.lock);
|
||||
|
||||
/*
|
||||
* Free the interrupt
|
||||
*/
|
||||
free_irq(uap->port.irq, uap);
|
||||
|
||||
/*
|
||||
* disable the port
|
||||
*/
|
||||
writew(UART01x_CR_UARTEN | UART011_CR_TXE, uap->port.membase + UART011_CR);
|
||||
|
||||
/*
|
||||
* disable break condition and fifos
|
||||
*/
|
||||
val = readw(uap->port.membase + UART011_LCRH);
|
||||
val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
|
||||
writew(val, uap->port.membase + UART011_LCRH);
|
||||
|
||||
/*
|
||||
* Shut down the clock producer
|
||||
*/
|
||||
clk_disable(uap->clk);
|
||||
}
|
||||
|
||||
static void
|
||||
pl011_set_termios(struct uart_port *port, struct termios *termios,
|
||||
struct termios *old)
|
||||
{
|
||||
unsigned int lcr_h, old_cr;
|
||||
unsigned long flags;
|
||||
unsigned int baud, quot;
|
||||
|
||||
/*
|
||||
* Ask the core to calculate the divisor for us.
|
||||
*/
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
|
||||
quot = port->uartclk * 4 / baud;
|
||||
|
||||
switch (termios->c_cflag & CSIZE) {
|
||||
case CS5:
|
||||
lcr_h = UART01x_LCRH_WLEN_5;
|
||||
break;
|
||||
case CS6:
|
||||
lcr_h = UART01x_LCRH_WLEN_6;
|
||||
break;
|
||||
case CS7:
|
||||
lcr_h = UART01x_LCRH_WLEN_7;
|
||||
break;
|
||||
default: // CS8
|
||||
lcr_h = UART01x_LCRH_WLEN_8;
|
||||
break;
|
||||
}
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
lcr_h |= UART01x_LCRH_STP2;
|
||||
if (termios->c_cflag & PARENB) {
|
||||
lcr_h |= UART01x_LCRH_PEN;
|
||||
if (!(termios->c_cflag & PARODD))
|
||||
lcr_h |= UART01x_LCRH_EPS;
|
||||
}
|
||||
if (port->fifosize > 1)
|
||||
lcr_h |= UART01x_LCRH_FEN;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
/*
|
||||
* Update the per-port timeout.
|
||||
*/
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
port->read_status_mask = UART01x_RSR_OE;
|
||||
if (termios->c_iflag & INPCK)
|
||||
port->read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
|
||||
if (termios->c_iflag & (BRKINT | PARMRK))
|
||||
port->read_status_mask |= UART01x_RSR_BE;
|
||||
|
||||
/*
|
||||
* Characters to ignore
|
||||
*/
|
||||
port->ignore_status_mask = 0;
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
port->ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
|
||||
if (termios->c_iflag & IGNBRK) {
|
||||
port->ignore_status_mask |= UART01x_RSR_BE;
|
||||
/*
|
||||
* If we're ignoring parity and break indicators,
|
||||
* ignore overruns too (for real raw support).
|
||||
*/
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
port->ignore_status_mask |= UART01x_RSR_OE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignore all characters if CREAD is not set.
|
||||
*/
|
||||
if ((termios->c_cflag & CREAD) == 0)
|
||||
port->ignore_status_mask |= UART_DUMMY_RSR_RX;
|
||||
|
||||
if (UART_ENABLE_MS(port, termios->c_cflag))
|
||||
pl011_enable_ms(port);
|
||||
|
||||
/* first, disable everything */
|
||||
old_cr = readw(port->membase + UART011_CR);
|
||||
writew(0, port->membase + UART011_CR);
|
||||
|
||||
/* Set baud rate */
|
||||
writew(quot & 0x3f, port->membase + UART011_FBRD);
|
||||
writew(quot >> 6, port->membase + UART011_IBRD);
|
||||
|
||||
/*
|
||||
* ----------v----------v----------v----------v-----
|
||||
* NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
|
||||
* ----------^----------^----------^----------^-----
|
||||
*/
|
||||
writew(lcr_h, port->membase + UART011_LCRH);
|
||||
writew(old_cr, port->membase + UART011_CR);
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static const char *pl011_type(struct uart_port *port)
|
||||
{
|
||||
return port->type == PORT_AMBA ? "AMBA/PL011" : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the memory region(s) being used by 'port'
|
||||
*/
|
||||
static void pl010_release_port(struct uart_port *port)
|
||||
{
|
||||
release_mem_region(port->mapbase, SZ_4K);
|
||||
}
|
||||
|
||||
/*
|
||||
* Request the memory region(s) being used by 'port'
|
||||
*/
|
||||
static int pl010_request_port(struct uart_port *port)
|
||||
{
|
||||
return request_mem_region(port->mapbase, SZ_4K, "uart-pl011")
|
||||
!= NULL ? 0 : -EBUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure/autoconfigure the port.
|
||||
*/
|
||||
static void pl010_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
if (flags & UART_CONFIG_TYPE) {
|
||||
port->type = PORT_AMBA;
|
||||
pl010_request_port(port);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* verify the new serial_struct (for TIOCSSERIAL).
|
||||
*/
|
||||
static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||
{
|
||||
int ret = 0;
|
||||
if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
|
||||
ret = -EINVAL;
|
||||
if (ser->irq < 0 || ser->irq >= NR_IRQS)
|
||||
ret = -EINVAL;
|
||||
if (ser->baud_base < 9600)
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct uart_ops amba_pl011_pops = {
|
||||
.tx_empty = pl01x_tx_empty,
|
||||
.set_mctrl = pl011_set_mctrl,
|
||||
.get_mctrl = pl01x_get_mctrl,
|
||||
.stop_tx = pl011_stop_tx,
|
||||
.start_tx = pl011_start_tx,
|
||||
.stop_rx = pl011_stop_rx,
|
||||
.enable_ms = pl011_enable_ms,
|
||||
.break_ctl = pl011_break_ctl,
|
||||
.startup = pl011_startup,
|
||||
.shutdown = pl011_shutdown,
|
||||
.set_termios = pl011_set_termios,
|
||||
.type = pl011_type,
|
||||
.release_port = pl010_release_port,
|
||||
.request_port = pl010_request_port,
|
||||
.config_port = pl010_config_port,
|
||||
.verify_port = pl010_verify_port,
|
||||
};
|
||||
|
||||
static struct uart_amba_port *amba_ports[UART_NR];
|
||||
|
||||
#ifdef CONFIG_SERIAL_AMBA_PL011_CONSOLE
|
||||
|
||||
static inline void
|
||||
pl011_console_write_char(struct uart_amba_port *uap, char ch)
|
||||
{
|
||||
unsigned int status;
|
||||
|
||||
do {
|
||||
status = readw(uap->port.membase + UART01x_FR);
|
||||
} while (status & UART01x_FR_TXFF);
|
||||
writew(ch, uap->port.membase + UART01x_DR);
|
||||
}
|
||||
|
||||
static void
|
||||
pl011_console_write(struct console *co, const char *s, unsigned int count)
|
||||
{
|
||||
struct uart_amba_port *uap = amba_ports[co->index];
|
||||
unsigned int status, old_cr, new_cr;
|
||||
int i;
|
||||
|
||||
clk_enable(uap->clk);
|
||||
|
||||
/*
|
||||
* First save the CR then disable the interrupts
|
||||
*/
|
||||
old_cr = readw(uap->port.membase + UART011_CR);
|
||||
new_cr = old_cr & ~UART011_CR_CTSEN;
|
||||
new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
|
||||
writew(new_cr, uap->port.membase + UART011_CR);
|
||||
|
||||
/*
|
||||
* Now, do each character
|
||||
*/
|
||||
for (i = 0; i < count; i++) {
|
||||
pl011_console_write_char(uap, s[i]);
|
||||
if (s[i] == '\n')
|
||||
pl011_console_write_char(uap, '\r');
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, wait for transmitter to become empty
|
||||
* and restore the TCR
|
||||
*/
|
||||
do {
|
||||
status = readw(uap->port.membase + UART01x_FR);
|
||||
} while (status & UART01x_FR_BUSY);
|
||||
writew(old_cr, uap->port.membase + UART011_CR);
|
||||
|
||||
clk_disable(uap->clk);
|
||||
}
|
||||
|
||||
static void __init
|
||||
pl011_console_get_options(struct uart_amba_port *uap, int *baud,
|
||||
int *parity, int *bits)
|
||||
{
|
||||
if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) {
|
||||
unsigned int lcr_h, ibrd, fbrd;
|
||||
|
||||
lcr_h = readw(uap->port.membase + UART011_LCRH);
|
||||
|
||||
*parity = 'n';
|
||||
if (lcr_h & UART01x_LCRH_PEN) {
|
||||
if (lcr_h & UART01x_LCRH_EPS)
|
||||
*parity = 'e';
|
||||
else
|
||||
*parity = 'o';
|
||||
}
|
||||
|
||||
if ((lcr_h & 0x60) == UART01x_LCRH_WLEN_7)
|
||||
*bits = 7;
|
||||
else
|
||||
*bits = 8;
|
||||
|
||||
ibrd = readw(uap->port.membase + UART011_IBRD);
|
||||
fbrd = readw(uap->port.membase + UART011_FBRD);
|
||||
|
||||
*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init pl011_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_amba_port *uap;
|
||||
int baud = 38400;
|
||||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
|
||||
/*
|
||||
* Check whether an invalid uart number has been specified, and
|
||||
* if so, search for the first available port that does have
|
||||
* console support.
|
||||
*/
|
||||
if (co->index >= UART_NR)
|
||||
co->index = 0;
|
||||
uap = amba_ports[co->index];
|
||||
|
||||
uap->port.uartclk = clk_get_rate(uap->clk);
|
||||
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
else
|
||||
pl011_console_get_options(uap, &baud, &parity, &bits);
|
||||
|
||||
return uart_set_options(&uap->port, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
extern struct uart_driver amba_reg;
|
||||
static struct console amba_console = {
|
||||
.name = "ttyAMA",
|
||||
.write = pl011_console_write,
|
||||
.device = uart_console_device,
|
||||
.setup = pl011_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
.data = &amba_reg,
|
||||
};
|
||||
|
||||
#define AMBA_CONSOLE (&amba_console)
|
||||
#else
|
||||
#define AMBA_CONSOLE NULL
|
||||
#endif
|
||||
|
||||
static struct uart_driver amba_reg = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = "ttyAMA",
|
||||
.dev_name = "ttyAMA",
|
||||
.major = SERIAL_AMBA_MAJOR,
|
||||
.minor = SERIAL_AMBA_MINOR,
|
||||
.nr = UART_NR,
|
||||
.cons = AMBA_CONSOLE,
|
||||
};
|
||||
|
||||
static int pl011_probe(struct amba_device *dev, void *id)
|
||||
{
|
||||
struct uart_amba_port *uap;
|
||||
void __iomem *base;
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
|
||||
if (amba_ports[i] == NULL)
|
||||
break;
|
||||
|
||||
if (i == ARRAY_SIZE(amba_ports)) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
uap = kmalloc(sizeof(struct uart_amba_port), GFP_KERNEL);
|
||||
if (uap == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
base = ioremap(dev->res.start, PAGE_SIZE);
|
||||
if (!base) {
|
||||
ret = -ENOMEM;
|
||||
goto free;
|
||||
}
|
||||
|
||||
memset(uap, 0, sizeof(struct uart_amba_port));
|
||||
uap->clk = clk_get(&dev->dev, "UARTCLK");
|
||||
if (IS_ERR(uap->clk)) {
|
||||
ret = PTR_ERR(uap->clk);
|
||||
goto unmap;
|
||||
}
|
||||
|
||||
ret = clk_use(uap->clk);
|
||||
if (ret)
|
||||
goto putclk;
|
||||
|
||||
uap->port.dev = &dev->dev;
|
||||
uap->port.mapbase = dev->res.start;
|
||||
uap->port.membase = base;
|
||||
uap->port.iotype = UPIO_MEM;
|
||||
uap->port.irq = dev->irq[0];
|
||||
uap->port.fifosize = 16;
|
||||
uap->port.ops = &amba_pl011_pops;
|
||||
uap->port.flags = UPF_BOOT_AUTOCONF;
|
||||
uap->port.line = i;
|
||||
|
||||
amba_ports[i] = uap;
|
||||
|
||||
amba_set_drvdata(dev, uap);
|
||||
ret = uart_add_one_port(&amba_reg, &uap->port);
|
||||
if (ret) {
|
||||
amba_set_drvdata(dev, NULL);
|
||||
amba_ports[i] = NULL;
|
||||
clk_unuse(uap->clk);
|
||||
putclk:
|
||||
clk_put(uap->clk);
|
||||
unmap:
|
||||
iounmap(base);
|
||||
free:
|
||||
kfree(uap);
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pl011_remove(struct amba_device *dev)
|
||||
{
|
||||
struct uart_amba_port *uap = amba_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
amba_set_drvdata(dev, NULL);
|
||||
|
||||
uart_remove_one_port(&amba_reg, &uap->port);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
|
||||
if (amba_ports[i] == uap)
|
||||
amba_ports[i] = NULL;
|
||||
|
||||
iounmap(uap->port.membase);
|
||||
clk_unuse(uap->clk);
|
||||
clk_put(uap->clk);
|
||||
kfree(uap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct amba_id pl011_ids[] __initdata = {
|
||||
{
|
||||
.id = 0x00041011,
|
||||
.mask = 0x000fffff,
|
||||
},
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static struct amba_driver pl011_driver = {
|
||||
.drv = {
|
||||
.name = "uart-pl011",
|
||||
},
|
||||
.id_table = pl011_ids,
|
||||
.probe = pl011_probe,
|
||||
.remove = pl011_remove,
|
||||
};
|
||||
|
||||
static int __init pl011_init(void)
|
||||
{
|
||||
int ret;
|
||||
printk(KERN_INFO "Serial: AMBA PL011 UART driver\n");
|
||||
|
||||
ret = uart_register_driver(&amba_reg);
|
||||
if (ret == 0) {
|
||||
ret = amba_driver_register(&pl011_driver);
|
||||
if (ret)
|
||||
uart_unregister_driver(&amba_reg);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit pl011_exit(void)
|
||||
{
|
||||
amba_driver_unregister(&pl011_driver);
|
||||
uart_unregister_driver(&amba_reg);
|
||||
}
|
||||
|
||||
module_init(pl011_init);
|
||||
module_exit(pl011_exit);
|
||||
|
||||
MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd");
|
||||
MODULE_DESCRIPTION("ARM AMBA serial port driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
1375
extra/linux-2.6.10/drivers/serial/au1x00_uart.c
Normal file
1375
extra/linux-2.6.10/drivers/serial/au1x00_uart.c
Normal file
File diff suppressed because it is too large
Load Diff
80
extra/linux-2.6.10/drivers/serial/bast_sio.c
Normal file
80
extra/linux-2.6.10/drivers/serial/bast_sio.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/* linux/drivers/serial/bast_sio.c
|
||||
*
|
||||
* Copyright (c) 2004 Simtec Electronics
|
||||
* Ben Dooks <ben@simtec.co.uk>
|
||||
*
|
||||
* http://www.simtec.co.uk/products/EB2410ITX/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Modifications:
|
||||
* 23-Sep-2004 BJD Added copyright header
|
||||
* 23-Sep-2004 BJD Added serial port remove code
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/config.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/serial.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <asm/arch/map.h>
|
||||
#include <asm/arch/irqs.h>
|
||||
#include <asm/arch/bast-map.h>
|
||||
#include <asm/arch/bast-irq.h>
|
||||
|
||||
static int __init serial_bast_register(unsigned long port, unsigned int irq)
|
||||
{
|
||||
struct serial_struct serial_req;
|
||||
|
||||
serial_req.flags = UPF_AUTOPROBE | UPF_SHARE_IRQ;
|
||||
serial_req.baud_base = BASE_BAUD;
|
||||
serial_req.irq = irq;
|
||||
serial_req.io_type = UPIO_MEM;
|
||||
serial_req.iomap_base = port;
|
||||
serial_req.iomem_base = ioremap(port, 0x10);
|
||||
serial_req.iomem_reg_shift = 0;
|
||||
|
||||
return register_serial(&serial_req);
|
||||
}
|
||||
|
||||
#define SERIAL_BASE (S3C2410_CS2 + BAST_PA_SUPERIO)
|
||||
|
||||
static int port[2] = { -1, -1 };
|
||||
|
||||
static int __init serial_bast_init(void)
|
||||
{
|
||||
if (machine_is_bast()) {
|
||||
port[0] = serial_bast_register(SERIAL_BASE + 0x2f8, IRQ_PCSERIAL1);
|
||||
port[1] = serial_bast_register(SERIAL_BASE + 0x3f8, IRQ_PCSERIAL2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit serial_bast_exit(void)
|
||||
{
|
||||
if (port[0] != -1)
|
||||
unregister_serial(port[0]);
|
||||
if (port[1] != -1)
|
||||
unregister_serial(port[1]);
|
||||
}
|
||||
|
||||
|
||||
module_init(serial_bast_init);
|
||||
module_exit(serial_bast_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Ben Dooks, ben@simtec.co.uk");
|
||||
MODULE_DESCRIPTION("BAST Onboard Serial setup");
|
||||
|
||||
|
||||
BIN
extra/linux-2.6.10/drivers/serial/built-in.o
Normal file
BIN
extra/linux-2.6.10/drivers/serial/built-in.o
Normal file
Binary file not shown.
609
extra/linux-2.6.10/drivers/serial/clps711x.c
Normal file
609
extra/linux-2.6.10/drivers/serial/clps711x.c
Normal file
@@ -0,0 +1,609 @@
|
||||
/*
|
||||
* linux/drivers/char/clps711x.c
|
||||
*
|
||||
* Driver for CLPS711x serial ports
|
||||
*
|
||||
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
|
||||
*
|
||||
* Copyright 1999 ARM Limited
|
||||
* Copyright (C) 2000 Deep Blue Solutions Ltd.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* $Id: clps711x.c,v 1.42 2002/07/28 10:03:28 rmk Exp $
|
||||
*
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
|
||||
#if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
||||
#define SUPPORT_SYSRQ
|
||||
#endif
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/hardware/clps7111.h>
|
||||
|
||||
#define UART_NR 2
|
||||
|
||||
#define SERIAL_CLPS711X_MAJOR 204
|
||||
#define SERIAL_CLPS711X_MINOR 40
|
||||
#define SERIAL_CLPS711X_NR UART_NR
|
||||
|
||||
/*
|
||||
* We use the relevant SYSCON register as a base address for these ports.
|
||||
*/
|
||||
#define UBRLCR(port) ((port)->iobase + UBRLCR1 - SYSCON1)
|
||||
#define UARTDR(port) ((port)->iobase + UARTDR1 - SYSCON1)
|
||||
#define SYSFLG(port) ((port)->iobase + SYSFLG1 - SYSCON1)
|
||||
#define SYSCON(port) ((port)->iobase + SYSCON1 - SYSCON1)
|
||||
|
||||
#define TX_IRQ(port) ((port)->irq)
|
||||
#define RX_IRQ(port) ((port)->irq + 1)
|
||||
|
||||
#define UART_ANY_ERR (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR)
|
||||
|
||||
#define tx_enabled(port) ((port)->unused[0])
|
||||
|
||||
static void
|
||||
clps711xuart_stop_tx(struct uart_port *port, unsigned int tty_stop)
|
||||
{
|
||||
if (tx_enabled(port)) {
|
||||
disable_irq(TX_IRQ(port));
|
||||
tx_enabled(port) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clps711xuart_start_tx(struct uart_port *port, unsigned int tty_start)
|
||||
{
|
||||
if (!tx_enabled(port)) {
|
||||
enable_irq(TX_IRQ(port));
|
||||
tx_enabled(port) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void clps711xuart_stop_rx(struct uart_port *port)
|
||||
{
|
||||
disable_irq(RX_IRQ(port));
|
||||
}
|
||||
|
||||
static void clps711xuart_enable_ms(struct uart_port *port)
|
||||
{
|
||||
}
|
||||
|
||||
static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct uart_port *port = dev_id;
|
||||
struct tty_struct *tty = port->info->tty;
|
||||
unsigned int status, ch, flg, ignored = 0;
|
||||
|
||||
status = clps_readl(SYSFLG(port));
|
||||
while (!(status & SYSFLG_URXFE)) {
|
||||
ch = clps_readl(UARTDR(port));
|
||||
|
||||
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
|
||||
goto ignore_char;
|
||||
port->icount.rx++;
|
||||
|
||||
flg = TTY_NORMAL;
|
||||
|
||||
/*
|
||||
* Note that the error handling code is
|
||||
* out of the main execution path
|
||||
*/
|
||||
if (ch & UART_ANY_ERR)
|
||||
goto handle_error;
|
||||
|
||||
if (uart_handle_sysrq_char(port, ch, regs))
|
||||
goto ignore_char;
|
||||
|
||||
error_return:
|
||||
tty_insert_flip_char(tty, ch, flg);
|
||||
ignore_char:
|
||||
status = clps_readl(SYSFLG(port));
|
||||
}
|
||||
out:
|
||||
tty_flip_buffer_push(tty);
|
||||
return IRQ_HANDLED;
|
||||
|
||||
handle_error:
|
||||
if (ch & UARTDR_PARERR)
|
||||
port->icount.parity++;
|
||||
else if (ch & UARTDR_FRMERR)
|
||||
port->icount.frame++;
|
||||
if (ch & UARTDR_OVERR)
|
||||
port->icount.overrun++;
|
||||
|
||||
if (ch & port->ignore_status_mask) {
|
||||
if (++ignored > 100)
|
||||
goto out;
|
||||
goto ignore_char;
|
||||
}
|
||||
ch &= port->read_status_mask;
|
||||
|
||||
if (ch & UARTDR_PARERR)
|
||||
flg = TTY_PARITY;
|
||||
else if (ch & UARTDR_FRMERR)
|
||||
flg = TTY_FRAME;
|
||||
|
||||
if (ch & UARTDR_OVERR) {
|
||||
/*
|
||||
* CHECK: does overrun affect the current character?
|
||||
* ASSUMPTION: it does not.
|
||||
*/
|
||||
tty_insert_flip_char(tty, ch, flg);
|
||||
ch = 0;
|
||||
flg = TTY_OVERRUN;
|
||||
}
|
||||
#ifdef SUPPORT_SYSRQ
|
||||
port->sysrq = 0;
|
||||
#endif
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct uart_port *port = dev_id;
|
||||
struct circ_buf *xmit = &port->info->xmit;
|
||||
int count;
|
||||
|
||||
if (port->x_char) {
|
||||
clps_writel(port->x_char, UARTDR(port));
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
|
||||
clps711xuart_stop_tx(port, 0);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
count = port->fifosize >> 1;
|
||||
do {
|
||||
clps_writel(xmit->buf[xmit->tail], UARTDR(port));
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
} while (--count > 0);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
clps711xuart_stop_tx(port, 0);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static unsigned int clps711xuart_tx_empty(struct uart_port *port)
|
||||
{
|
||||
unsigned int status = clps_readl(SYSFLG(port));
|
||||
return status & SYSFLG_UBUSY ? 0 : TIOCSER_TEMT;
|
||||
}
|
||||
|
||||
static unsigned int clps711xuart_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
unsigned int port_addr;
|
||||
unsigned int result = 0;
|
||||
unsigned int status;
|
||||
|
||||
port_addr = SYSFLG(port);
|
||||
if (port_addr == SYSFLG1) {
|
||||
status = clps_readl(SYSFLG1);
|
||||
if (status & SYSFLG1_DCD)
|
||||
result |= TIOCM_CAR;
|
||||
if (status & SYSFLG1_DSR)
|
||||
result |= TIOCM_DSR;
|
||||
if (status & SYSFLG1_CTS)
|
||||
result |= TIOCM_CTS;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
clps711xuart_set_mctrl_null(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
}
|
||||
|
||||
static void clps711xuart_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int ubrlcr;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
ubrlcr = clps_readl(UBRLCR(port));
|
||||
if (break_state == -1)
|
||||
ubrlcr |= UBRLCR_BREAK;
|
||||
else
|
||||
ubrlcr &= ~UBRLCR_BREAK;
|
||||
clps_writel(ubrlcr, UBRLCR(port));
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static int clps711xuart_startup(struct uart_port *port)
|
||||
{
|
||||
unsigned int syscon;
|
||||
int retval;
|
||||
|
||||
tx_enabled(port) = 1;
|
||||
|
||||
/*
|
||||
* Allocate the IRQs
|
||||
*/
|
||||
retval = request_irq(TX_IRQ(port), clps711xuart_int_tx, 0,
|
||||
"clps711xuart_tx", port);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
retval = request_irq(RX_IRQ(port), clps711xuart_int_rx, 0,
|
||||
"clps711xuart_rx", port);
|
||||
if (retval) {
|
||||
free_irq(TX_IRQ(port), port);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* enable the port
|
||||
*/
|
||||
syscon = clps_readl(SYSCON(port));
|
||||
syscon |= SYSCON_UARTEN;
|
||||
clps_writel(syscon, SYSCON(port));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clps711xuart_shutdown(struct uart_port *port)
|
||||
{
|
||||
unsigned int ubrlcr, syscon;
|
||||
|
||||
/*
|
||||
* Free the interrupt
|
||||
*/
|
||||
free_irq(TX_IRQ(port), port); /* TX interrupt */
|
||||
free_irq(RX_IRQ(port), port); /* RX interrupt */
|
||||
|
||||
/*
|
||||
* disable the port
|
||||
*/
|
||||
syscon = clps_readl(SYSCON(port));
|
||||
syscon &= ~SYSCON_UARTEN;
|
||||
clps_writel(syscon, SYSCON(port));
|
||||
|
||||
/*
|
||||
* disable break condition and fifos
|
||||
*/
|
||||
ubrlcr = clps_readl(UBRLCR(port));
|
||||
ubrlcr &= ~(UBRLCR_FIFOEN | UBRLCR_BREAK);
|
||||
clps_writel(ubrlcr, UBRLCR(port));
|
||||
}
|
||||
|
||||
static void
|
||||
clps711xuart_set_termios(struct uart_port *port, struct termios *termios,
|
||||
struct termios *old)
|
||||
{
|
||||
unsigned int ubrlcr, baud, quot;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* We don't implement CREAD.
|
||||
*/
|
||||
termios->c_cflag |= CREAD;
|
||||
|
||||
/*
|
||||
* Ask the core to calculate the divisor for us.
|
||||
*/
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
|
||||
quot = uart_get_divisor(port, baud);
|
||||
|
||||
switch (termios->c_cflag & CSIZE) {
|
||||
case CS5:
|
||||
ubrlcr = UBRLCR_WRDLEN5;
|
||||
break;
|
||||
case CS6:
|
||||
ubrlcr = UBRLCR_WRDLEN6;
|
||||
break;
|
||||
case CS7:
|
||||
ubrlcr = UBRLCR_WRDLEN7;
|
||||
break;
|
||||
default: // CS8
|
||||
ubrlcr = UBRLCR_WRDLEN8;
|
||||
break;
|
||||
}
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
ubrlcr |= UBRLCR_XSTOP;
|
||||
if (termios->c_cflag & PARENB) {
|
||||
ubrlcr |= UBRLCR_PRTEN;
|
||||
if (!(termios->c_cflag & PARODD))
|
||||
ubrlcr |= UBRLCR_EVENPRT;
|
||||
}
|
||||
if (port->fifosize > 1)
|
||||
ubrlcr |= UBRLCR_FIFOEN;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
/*
|
||||
* Update the per-port timeout.
|
||||
*/
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
port->read_status_mask = UARTDR_OVERR;
|
||||
if (termios->c_iflag & INPCK)
|
||||
port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR;
|
||||
|
||||
/*
|
||||
* Characters to ignore
|
||||
*/
|
||||
port->ignore_status_mask = 0;
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
port->ignore_status_mask |= UARTDR_FRMERR | UARTDR_PARERR;
|
||||
if (termios->c_iflag & IGNBRK) {
|
||||
/*
|
||||
* If we're ignoring parity and break indicators,
|
||||
* ignore overruns to (for real raw support).
|
||||
*/
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
port->ignore_status_mask |= UARTDR_OVERR;
|
||||
}
|
||||
|
||||
quot -= 1;
|
||||
|
||||
clps_writel(ubrlcr | quot, UBRLCR(port));
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static const char *clps711xuart_type(struct uart_port *port)
|
||||
{
|
||||
return port->type == PORT_CLPS711X ? "CLPS711x" : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure/autoconfigure the port.
|
||||
*/
|
||||
static void clps711xuart_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
if (flags & UART_CONFIG_TYPE)
|
||||
port->type = PORT_CLPS711X;
|
||||
}
|
||||
|
||||
static void clps711xuart_release_port(struct uart_port *port)
|
||||
{
|
||||
}
|
||||
|
||||
static int clps711xuart_request_port(struct uart_port *port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct uart_ops clps711x_pops = {
|
||||
.tx_empty = clps711xuart_tx_empty,
|
||||
.set_mctrl = clps711xuart_set_mctrl_null,
|
||||
.get_mctrl = clps711xuart_get_mctrl,
|
||||
.stop_tx = clps711xuart_stop_tx,
|
||||
.start_tx = clps711xuart_start_tx,
|
||||
.stop_rx = clps711xuart_stop_rx,
|
||||
.enable_ms = clps711xuart_enable_ms,
|
||||
.break_ctl = clps711xuart_break_ctl,
|
||||
.startup = clps711xuart_startup,
|
||||
.shutdown = clps711xuart_shutdown,
|
||||
.set_termios = clps711xuart_set_termios,
|
||||
.type = clps711xuart_type,
|
||||
.config_port = clps711xuart_config_port,
|
||||
.release_port = clps711xuart_release_port,
|
||||
.request_port = clps711xuart_request_port,
|
||||
};
|
||||
|
||||
static struct uart_port clps711x_ports[UART_NR] = {
|
||||
{
|
||||
.iobase = SYSCON1,
|
||||
.irq = IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */
|
||||
.uartclk = 3686400,
|
||||
.fifosize = 16,
|
||||
.ops = &clps711x_pops,
|
||||
.line = 0,
|
||||
.flags = ASYNC_BOOT_AUTOCONF,
|
||||
},
|
||||
{
|
||||
.iobase = SYSCON2,
|
||||
.irq = IRQ_UTXINT2, /* IRQ_URXINT2 */
|
||||
.uartclk = 3686400,
|
||||
.fifosize = 16,
|
||||
.ops = &clps711x_pops,
|
||||
.line = 1,
|
||||
.flags = ASYNC_BOOT_AUTOCONF,
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
|
||||
/*
|
||||
* Print a string to the serial port trying not to disturb
|
||||
* any possible real use of the port...
|
||||
*
|
||||
* The console_lock must be held when we get here.
|
||||
*
|
||||
* Note that this is called with interrupts already disabled
|
||||
*/
|
||||
static void
|
||||
clps711xuart_console_write(struct console *co, const char *s,
|
||||
unsigned int count)
|
||||
{
|
||||
struct uart_port *port = clps711x_ports + co->index;
|
||||
unsigned int status, syscon;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Ensure that the port is enabled.
|
||||
*/
|
||||
syscon = clps_readl(SYSCON(port));
|
||||
clps_writel(syscon | SYSCON_UARTEN, SYSCON(port));
|
||||
|
||||
/*
|
||||
* Now, do each character
|
||||
*/
|
||||
for (i = 0; i < count; i++) {
|
||||
do {
|
||||
status = clps_readl(SYSFLG(port));
|
||||
} while (status & SYSFLG_UTXFF);
|
||||
clps_writel(s[i], UARTDR(port));
|
||||
if (s[i] == '\n') {
|
||||
do {
|
||||
status = clps_readl(SYSFLG(port));
|
||||
} while (status & SYSFLG_UTXFF);
|
||||
clps_writel('\r', UARTDR(port));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, wait for transmitter to become empty
|
||||
* and restore the uart state.
|
||||
*/
|
||||
do {
|
||||
status = clps_readl(SYSFLG(port));
|
||||
} while (status & SYSFLG_UBUSY);
|
||||
|
||||
clps_writel(syscon, SYSCON(port));
|
||||
}
|
||||
|
||||
static void __init
|
||||
clps711xuart_console_get_options(struct uart_port *port, int *baud,
|
||||
int *parity, int *bits)
|
||||
{
|
||||
if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) {
|
||||
unsigned int ubrlcr, quot;
|
||||
|
||||
ubrlcr = clps_readl(UBRLCR(port));
|
||||
|
||||
*parity = 'n';
|
||||
if (ubrlcr & UBRLCR_PRTEN) {
|
||||
if (ubrlcr & UBRLCR_EVENPRT)
|
||||
*parity = 'e';
|
||||
else
|
||||
*parity = 'o';
|
||||
}
|
||||
|
||||
if ((ubrlcr & UBRLCR_WRDLEN_MASK) == UBRLCR_WRDLEN7)
|
||||
*bits = 7;
|
||||
else
|
||||
*bits = 8;
|
||||
|
||||
quot = ubrlcr & UBRLCR_BAUD_MASK;
|
||||
*baud = port->uartclk / (16 * (quot + 1));
|
||||
}
|
||||
}
|
||||
|
||||
static int __init clps711xuart_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_port *port;
|
||||
int baud = 38400;
|
||||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
|
||||
/*
|
||||
* Check whether an invalid uart number has been specified, and
|
||||
* if so, search for the first available port that does have
|
||||
* console support.
|
||||
*/
|
||||
port = uart_get_console(clps711x_ports, UART_NR, co);
|
||||
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
else
|
||||
clps711xuart_console_get_options(port, &baud, &parity, &bits);
|
||||
|
||||
return uart_set_options(port, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
extern struct uart_driver clps711x_reg;
|
||||
static struct console clps711x_console = {
|
||||
.name = "ttyCL",
|
||||
.write = clps711xuart_console_write,
|
||||
.device = uart_console_device,
|
||||
.setup = clps711xuart_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
.data = &clps711x_reg,
|
||||
};
|
||||
|
||||
static int __init clps711xuart_console_init(void)
|
||||
{
|
||||
register_console(&clps711x_console);
|
||||
return 0;
|
||||
}
|
||||
console_initcall(clps711xuart_console_init);
|
||||
|
||||
#define CLPS711X_CONSOLE &clps711x_console
|
||||
#else
|
||||
#define CLPS711X_CONSOLE NULL
|
||||
#endif
|
||||
|
||||
static struct uart_driver clps711x_reg = {
|
||||
.driver_name = "ttyCL",
|
||||
.dev_name = "ttyCL",
|
||||
.major = SERIAL_CLPS711X_MAJOR,
|
||||
.minor = SERIAL_CLPS711X_MINOR,
|
||||
.nr = UART_NR,
|
||||
|
||||
.cons = CLPS711X_CONSOLE,
|
||||
};
|
||||
|
||||
static int __init clps711xuart_init(void)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
printk(KERN_INFO "Serial: CLPS711x driver $Revision: 1.42 $\n");
|
||||
|
||||
ret = uart_register_driver(&clps711x_reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < UART_NR; i++)
|
||||
uart_add_one_port(&clps711x_reg, &clps711x_ports[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit clps711xuart_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < UART_NR; i++)
|
||||
uart_remove_one_port(&clps711x_reg, &clps711x_ports[i]);
|
||||
|
||||
uart_unregister_driver(&clps711x_reg);
|
||||
}
|
||||
|
||||
module_init(clps711xuart_init);
|
||||
module_exit(clps711xuart_exit);
|
||||
|
||||
MODULE_AUTHOR("Deep Blue Solutions Ltd");
|
||||
MODULE_DESCRIPTION("CLPS-711x generic serial driver $Revision: 1.42 $");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_CHARDEV(SERIAL_CLPS711X_MAJOR, SERIAL_CLPS711X_MINOR);
|
||||
11
extra/linux-2.6.10/drivers/serial/cpm_uart/Makefile
Normal file
11
extra/linux-2.6.10/drivers/serial/cpm_uart/Makefile
Normal file
@@ -0,0 +1,11 @@
|
||||
#
|
||||
# Makefile for the Motorola 8xx FEC ethernet controller
|
||||
#
|
||||
|
||||
obj-$(CONFIG_SERIAL_CPM) += cpm_uart.o
|
||||
|
||||
# Select the correct platform objects.
|
||||
cpm_uart-objs-$(CONFIG_CPM2) += cpm_uart_cpm2.o
|
||||
cpm_uart-objs-$(CONFIG_8xx) += cpm_uart_cpm1.o
|
||||
|
||||
cpm_uart-objs := cpm_uart_core.o $(cpm_uart-objs-y)
|
||||
89
extra/linux-2.6.10/drivers/serial/cpm_uart/cpm_uart.h
Normal file
89
extra/linux-2.6.10/drivers/serial/cpm_uart/cpm_uart.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* linux/drivers/serial/cpm_uart.h
|
||||
*
|
||||
* Driver for CPM (SCC/SMC) serial ports
|
||||
*
|
||||
* Copyright (C) 2004 Freescale Semiconductor, Inc.
|
||||
*
|
||||
*/
|
||||
#ifndef CPM_UART_H
|
||||
#define CPM_UART_H
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
#if defined(CONFIG_CPM2)
|
||||
#include "cpm_uart_cpm2.h"
|
||||
#elif defined(CONFIG_8xx)
|
||||
#include "cpm_uart_cpm1.h"
|
||||
#endif
|
||||
|
||||
#define SERIAL_CPM_MAJOR 204
|
||||
#define SERIAL_CPM_MINOR 46
|
||||
|
||||
#define IS_SMC(pinfo) (pinfo->flags & FLAG_SMC)
|
||||
#define IS_DISCARDING(pinfo) (pinfo->flags & FLAG_DISCARDING)
|
||||
#define FLAG_DISCARDING 0x00000004 /* when set, don't discard */
|
||||
#define FLAG_SMC 0x00000002
|
||||
#define FLAG_CONSOLE 0x00000001
|
||||
|
||||
#define UART_SMC1 0
|
||||
#define UART_SMC2 1
|
||||
#define UART_SCC1 2
|
||||
#define UART_SCC2 3
|
||||
#define UART_SCC3 4
|
||||
#define UART_SCC4 5
|
||||
|
||||
#define UART_NR 6
|
||||
|
||||
#define RX_NUM_FIFO 4
|
||||
#define RX_BUF_SIZE 32
|
||||
#define TX_NUM_FIFO 4
|
||||
#define TX_BUF_SIZE 32
|
||||
|
||||
struct uart_cpm_port {
|
||||
struct uart_port port;
|
||||
u16 rx_nrfifos;
|
||||
u16 rx_fifosize;
|
||||
u16 tx_nrfifos;
|
||||
u16 tx_fifosize;
|
||||
smc_t *smcp;
|
||||
smc_uart_t *smcup;
|
||||
scc_t *sccp;
|
||||
scc_uart_t *sccup;
|
||||
volatile cbd_t *rx_bd_base;
|
||||
volatile cbd_t *rx_cur;
|
||||
volatile cbd_t *tx_bd_base;
|
||||
volatile cbd_t *tx_cur;
|
||||
unsigned char *tx_buf;
|
||||
unsigned char *rx_buf;
|
||||
u32 flags;
|
||||
void (*set_lineif)(struct uart_cpm_port *);
|
||||
u8 brg;
|
||||
uint dp_addr;
|
||||
void *mem_addr;
|
||||
dma_addr_t dma_addr;
|
||||
/* helpers */
|
||||
int baud;
|
||||
int bits;
|
||||
/* Keep track of 'odd' SMC2 wirings */
|
||||
int is_portb;
|
||||
};
|
||||
|
||||
extern int cpm_uart_port_map[UART_NR];
|
||||
extern int cpm_uart_nr;
|
||||
extern struct uart_cpm_port cpm_uart_ports[UART_NR];
|
||||
|
||||
/* these are located in their respective files */
|
||||
void cpm_line_cr_cmd(int line, int cmd);
|
||||
int cpm_uart_init_portdesc(void);
|
||||
int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con);
|
||||
void cpm_uart_freebuf(struct uart_cpm_port *pinfo);
|
||||
|
||||
void smc1_lineif(struct uart_cpm_port *pinfo);
|
||||
void smc2_lineif(struct uart_cpm_port *pinfo);
|
||||
void scc1_lineif(struct uart_cpm_port *pinfo);
|
||||
void scc2_lineif(struct uart_cpm_port *pinfo);
|
||||
void scc3_lineif(struct uart_cpm_port *pinfo);
|
||||
void scc4_lineif(struct uart_cpm_port *pinfo);
|
||||
|
||||
#endif /* CPM_UART_H */
|
||||
1171
extra/linux-2.6.10/drivers/serial/cpm_uart/cpm_uart_core.c
Normal file
1171
extra/linux-2.6.10/drivers/serial/cpm_uart/cpm_uart_core.c
Normal file
File diff suppressed because it is too large
Load Diff
290
extra/linux-2.6.10/drivers/serial/cpm_uart/cpm_uart_cpm1.c
Normal file
290
extra/linux-2.6.10/drivers/serial/cpm_uart/cpm_uart_cpm1.c
Normal file
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* linux/drivers/serial/cpm_uart.c
|
||||
*
|
||||
* Driver for CPM (SCC/SMC) serial ports; CPM1 definitions
|
||||
*
|
||||
* Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2)
|
||||
* Pantelis Antoniou (panto@intracom.gr) (CPM1)
|
||||
*
|
||||
* Copyright (C) 2004 Freescale Semiconductor, Inc.
|
||||
* (C) 2004 Intracom, S.A.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "cpm_uart.h"
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
void cpm_line_cr_cmd(int line, int cmd)
|
||||
{
|
||||
ushort val;
|
||||
volatile cpm8xx_t *cp = cpmp;
|
||||
|
||||
switch (line) {
|
||||
case UART_SMC1:
|
||||
val = mk_cr_cmd(CPM_CR_CH_SMC1, cmd) | CPM_CR_FLG;
|
||||
break;
|
||||
case UART_SMC2:
|
||||
val = mk_cr_cmd(CPM_CR_CH_SMC2, cmd) | CPM_CR_FLG;
|
||||
break;
|
||||
case UART_SCC1:
|
||||
val = mk_cr_cmd(CPM_CR_CH_SCC1, cmd) | CPM_CR_FLG;
|
||||
break;
|
||||
case UART_SCC2:
|
||||
val = mk_cr_cmd(CPM_CR_CH_SCC2, cmd) | CPM_CR_FLG;
|
||||
break;
|
||||
case UART_SCC3:
|
||||
val = mk_cr_cmd(CPM_CR_CH_SCC3, cmd) | CPM_CR_FLG;
|
||||
break;
|
||||
case UART_SCC4:
|
||||
val = mk_cr_cmd(CPM_CR_CH_SCC4, cmd) | CPM_CR_FLG;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
||||
}
|
||||
cp->cp_cpcr = val;
|
||||
while (cp->cp_cpcr & CPM_CR_FLG) ;
|
||||
}
|
||||
|
||||
void smc1_lineif(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
volatile cpm8xx_t *cp = cpmp;
|
||||
unsigned int iobits = 0x000000c0;
|
||||
|
||||
if (!pinfo->is_portb) {
|
||||
cp->cp_pbpar |= iobits;
|
||||
cp->cp_pbdir &= ~iobits;
|
||||
cp->cp_pbodr &= ~iobits;
|
||||
} else {
|
||||
((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits;
|
||||
((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
|
||||
((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
|
||||
}
|
||||
|
||||
pinfo->brg = 1;
|
||||
}
|
||||
|
||||
void smc2_lineif(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
/* XXX SMC2: insert port configuration here */
|
||||
pinfo->brg = 2;
|
||||
}
|
||||
|
||||
void scc1_lineif(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
/* XXX SCC1: insert port configuration here */
|
||||
pinfo->brg = 1;
|
||||
}
|
||||
|
||||
void scc2_lineif(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
/* XXX SCC2: insert port configuration here */
|
||||
pinfo->brg = 2;
|
||||
}
|
||||
|
||||
void scc3_lineif(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
/* XXX SCC3: insert port configuration here */
|
||||
pinfo->brg = 3;
|
||||
}
|
||||
|
||||
void scc4_lineif(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
/* XXX SCC4: insert port configuration here */
|
||||
pinfo->brg = 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate DP-Ram and memory buffers. We need to allocate a transmit and
|
||||
* receive buffer descriptors from dual port ram, and a character
|
||||
* buffer area from host mem. If we are allocating for the console we need
|
||||
* to do it from bootmem
|
||||
*/
|
||||
int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
|
||||
{
|
||||
int dpmemsz, memsz;
|
||||
u8 *dp_mem;
|
||||
uint dp_offset;
|
||||
u8 *mem_addr;
|
||||
dma_addr_t dma_addr = 0;
|
||||
|
||||
pr_debug("CPM uart[%d]:allocbuf\n", pinfo->port.line);
|
||||
|
||||
dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos);
|
||||
dp_offset = cpm_dpalloc(dpmemsz, 8);
|
||||
if (IS_DPERR(dp_offset)) {
|
||||
printk(KERN_ERR
|
||||
"cpm_uart_cpm1.c: could not allocate buffer descriptors\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
dp_mem = cpm_dpram_addr(dp_offset);
|
||||
|
||||
memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
|
||||
L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
|
||||
if (is_con) {
|
||||
mem_addr = (u8 *) m8xx_cpm_hostalloc(memsz);
|
||||
dma_addr = 0;
|
||||
} else
|
||||
mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (mem_addr == NULL) {
|
||||
cpm_dpfree(dp_offset);
|
||||
printk(KERN_ERR
|
||||
"cpm_uart_cpm1.c: could not allocate coherent memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pinfo->dp_addr = dp_offset;
|
||||
pinfo->mem_addr = mem_addr;
|
||||
pinfo->dma_addr = dma_addr;
|
||||
|
||||
pinfo->rx_buf = mem_addr;
|
||||
pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
|
||||
* pinfo->rx_fifosize);
|
||||
|
||||
pinfo->rx_bd_base = (volatile cbd_t *)dp_mem;
|
||||
pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
|
||||
pinfo->rx_fifosize) +
|
||||
L1_CACHE_ALIGN(pinfo->tx_nrfifos *
|
||||
pinfo->tx_fifosize), pinfo->mem_addr,
|
||||
pinfo->dma_addr);
|
||||
|
||||
cpm_dpfree(pinfo->dp_addr);
|
||||
}
|
||||
|
||||
/* Setup any dynamic params in the uart desc */
|
||||
int cpm_uart_init_portdesc(void)
|
||||
{
|
||||
pr_debug("CPM uart[-]:init portdesc\n");
|
||||
|
||||
cpm_uart_nr = 0;
|
||||
#ifdef CONFIG_SERIAL_CPM_SMC1
|
||||
cpm_uart_ports[UART_SMC1].smcp = &cpmp->cp_smc[0];
|
||||
/*
|
||||
* Is SMC1 being relocated?
|
||||
*/
|
||||
# ifdef CONFIG_I2C_SPI_SMC1_UCODE_PATCH
|
||||
cpm_uart_ports[UART_SMC1].smcup =
|
||||
(smc_uart_t *) & cpmp->cp_dparam[0x3C0];
|
||||
# else
|
||||
cpm_uart_ports[UART_SMC1].smcup =
|
||||
(smc_uart_t *) & cpmp->cp_dparam[PROFF_SMC1];
|
||||
# endif
|
||||
cpm_uart_ports[UART_SMC1].port.mapbase =
|
||||
(unsigned long)&cpmp->cp_smc[0];
|
||||
cpm_uart_ports[UART_SMC1].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
|
||||
cpm_uart_ports[UART_SMC1].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
|
||||
cpm_uart_ports[UART_SMC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
|
||||
cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_CPM_SMC2
|
||||
cpm_uart_ports[UART_SMC2].smcp = &cpmp->cp_smc[1];
|
||||
cpm_uart_ports[UART_SMC2].smcup =
|
||||
(smc_uart_t *) & cpmp->cp_dparam[PROFF_SMC2];
|
||||
cpm_uart_ports[UART_SMC2].port.mapbase =
|
||||
(unsigned long)&cpmp->cp_smc[1];
|
||||
cpm_uart_ports[UART_SMC2].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
|
||||
cpm_uart_ports[UART_SMC2].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
|
||||
cpm_uart_ports[UART_SMC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
|
||||
cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_CPM_SCC1
|
||||
cpm_uart_ports[UART_SCC1].sccp = &cpmp->cp_scc[0];
|
||||
cpm_uart_ports[UART_SCC1].sccup =
|
||||
(scc_uart_t *) & cpmp->cp_dparam[PROFF_SCC1];
|
||||
cpm_uart_ports[UART_SCC1].port.mapbase =
|
||||
(unsigned long)&cpmp->cp_scc[0];
|
||||
cpm_uart_ports[UART_SCC1].sccp->scc_sccm &=
|
||||
~(UART_SCCM_TX | UART_SCCM_RX);
|
||||
cpm_uart_ports[UART_SCC1].sccp->scc_gsmrl &=
|
||||
~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
cpm_uart_ports[UART_SCC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
|
||||
cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_CPM_SCC2
|
||||
cpm_uart_ports[UART_SCC2].sccp = &cpmp->cp_scc[1];
|
||||
cpm_uart_ports[UART_SCC2].sccup =
|
||||
(scc_uart_t *) & cpmp->cp_dparam[PROFF_SCC2];
|
||||
cpm_uart_ports[UART_SCC2].port.mapbase =
|
||||
(unsigned long)&cpmp->cp_scc[1];
|
||||
cpm_uart_ports[UART_SCC2].sccp->scc_sccm &=
|
||||
~(UART_SCCM_TX | UART_SCCM_RX);
|
||||
cpm_uart_ports[UART_SCC2].sccp->scc_gsmrl &=
|
||||
~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
cpm_uart_ports[UART_SCC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
|
||||
cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_CPM_SCC3
|
||||
cpm_uart_ports[UART_SCC3].sccp = &cpmp->cp_scc[2];
|
||||
cpm_uart_ports[UART_SCC3].sccup =
|
||||
(scc_uart_t *) & cpmp->cp_dparam[PROFF_SCC3];
|
||||
cpm_uart_ports[UART_SCC3].port.mapbase =
|
||||
(unsigned long)&cpmp->cp_scc[2];
|
||||
cpm_uart_ports[UART_SCC3].sccp->scc_sccm &=
|
||||
~(UART_SCCM_TX | UART_SCCM_RX);
|
||||
cpm_uart_ports[UART_SCC3].sccp->scc_gsmrl &=
|
||||
~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
cpm_uart_ports[UART_SCC3].port.uartclk = (((bd_t *) __res)->bi_intfreq);
|
||||
cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_CPM_SCC4
|
||||
cpm_uart_ports[UART_SCC4].sccp = &cpmp->cp_scc[3];
|
||||
cpm_uart_ports[UART_SCC4].sccup =
|
||||
(scc_uart_t *) & cpmp->cp_dparam[PROFF_SCC4];
|
||||
cpm_uart_ports[UART_SCC4].port.mapbase =
|
||||
(unsigned long)&cpmp->cp_scc[3];
|
||||
cpm_uart_ports[UART_SCC4].sccp->scc_sccm &=
|
||||
~(UART_SCCM_TX | UART_SCCM_RX);
|
||||
cpm_uart_ports[UART_SCC4].sccp->scc_gsmrl &=
|
||||
~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
cpm_uart_ports[UART_SCC4].port.uartclk = (((bd_t *) __res)->bi_intfreq);
|
||||
cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
45
extra/linux-2.6.10/drivers/serial/cpm_uart/cpm_uart_cpm1.h
Normal file
45
extra/linux-2.6.10/drivers/serial/cpm_uart/cpm_uart_cpm1.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* linux/drivers/serial/cpm_uart_cpm1.h
|
||||
*
|
||||
* Driver for CPM (SCC/SMC) serial ports
|
||||
*
|
||||
* definitions for cpm1
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CPM_UART_CPM1_H
|
||||
#define CPM_UART_CPM1_H
|
||||
|
||||
#include <asm/commproc.h>
|
||||
|
||||
/* defines for IRQs */
|
||||
#define SMC1_IRQ (CPM_IRQ_OFFSET + CPMVEC_SMC1)
|
||||
#define SMC2_IRQ (CPM_IRQ_OFFSET + CPMVEC_SMC2)
|
||||
#define SCC1_IRQ (CPM_IRQ_OFFSET + CPMVEC_SCC1)
|
||||
#define SCC2_IRQ (CPM_IRQ_OFFSET + CPMVEC_SCC2)
|
||||
#define SCC3_IRQ (CPM_IRQ_OFFSET + CPMVEC_SCC3)
|
||||
#define SCC4_IRQ (CPM_IRQ_OFFSET + CPMVEC_SCC4)
|
||||
|
||||
/* the CPM address */
|
||||
#define CPM_ADDR IMAP_ADDR
|
||||
|
||||
static inline void cpm_set_brg(int brg, int baud)
|
||||
{
|
||||
cpm_setbrg(brg, baud);
|
||||
}
|
||||
|
||||
static inline void cpm_set_scc_fcr(volatile scc_uart_t * sup)
|
||||
{
|
||||
sup->scc_genscc.scc_rfcr = SMC_EB;
|
||||
sup->scc_genscc.scc_tfcr = SMC_EB;
|
||||
}
|
||||
|
||||
static inline void cpm_set_smc_fcr(volatile smc_uart_t * up)
|
||||
{
|
||||
up->smc_rfcr = SMC_EB;
|
||||
up->smc_tfcr = SMC_EB;
|
||||
}
|
||||
|
||||
#define DPRAM_BASE ((unsigned char *)&cpmp->cp_dpmem[0])
|
||||
|
||||
#endif
|
||||
328
extra/linux-2.6.10/drivers/serial/cpm_uart/cpm_uart_cpm2.c
Normal file
328
extra/linux-2.6.10/drivers/serial/cpm_uart/cpm_uart_cpm2.c
Normal file
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* linux/drivers/serial/cpm_uart_cpm2.c
|
||||
*
|
||||
* Driver for CPM (SCC/SMC) serial ports; CPM2 definitions
|
||||
*
|
||||
* Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2)
|
||||
* Pantelis Antoniou (panto@intracom.gr) (CPM1)
|
||||
*
|
||||
* Copyright (C) 2004 Freescale Semiconductor, Inc.
|
||||
* (C) 2004 Intracom, S.A.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "cpm_uart.h"
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
void cpm_line_cr_cmd(int line, int cmd)
|
||||
{
|
||||
volatile cpm_cpm2_t *cp = cpmp;
|
||||
ulong val;
|
||||
|
||||
switch (line) {
|
||||
case UART_SMC1:
|
||||
val = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0,
|
||||
cmd) | CPM_CR_FLG;
|
||||
break;
|
||||
case UART_SMC2:
|
||||
val = mk_cr_cmd(CPM_CR_SMC2_PAGE, CPM_CR_SMC2_SBLOCK, 0,
|
||||
cmd) | CPM_CR_FLG;
|
||||
break;
|
||||
case UART_SCC1:
|
||||
val = mk_cr_cmd(CPM_CR_SCC1_PAGE, CPM_CR_SCC1_SBLOCK, 0,
|
||||
cmd) | CPM_CR_FLG;
|
||||
break;
|
||||
case UART_SCC2:
|
||||
val = mk_cr_cmd(CPM_CR_SCC2_PAGE, CPM_CR_SCC2_SBLOCK, 0,
|
||||
cmd) | CPM_CR_FLG;
|
||||
break;
|
||||
case UART_SCC3:
|
||||
val = mk_cr_cmd(CPM_CR_SCC3_PAGE, CPM_CR_SCC3_SBLOCK, 0,
|
||||
cmd) | CPM_CR_FLG;
|
||||
break;
|
||||
case UART_SCC4:
|
||||
val = mk_cr_cmd(CPM_CR_SCC4_PAGE, CPM_CR_SCC4_SBLOCK, 0,
|
||||
cmd) | CPM_CR_FLG;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
||||
}
|
||||
cp->cp_cpcr = val;
|
||||
while (cp->cp_cpcr & CPM_CR_FLG) ;
|
||||
}
|
||||
|
||||
void smc1_lineif(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
|
||||
|
||||
/* SMC1 is only on port D */
|
||||
io->iop_ppard |= 0x00c00000;
|
||||
io->iop_pdird |= 0x00400000;
|
||||
io->iop_pdird &= ~0x00800000;
|
||||
io->iop_psord &= ~0x00c00000;
|
||||
|
||||
/* Wire BRG1 to SMC1 */
|
||||
cpm2_immr->im_cpmux.cmx_smr &= 0x0f;
|
||||
pinfo->brg = 1;
|
||||
}
|
||||
|
||||
void smc2_lineif(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
|
||||
|
||||
/* SMC2 is only on port A */
|
||||
io->iop_ppara |= 0x00c00000;
|
||||
io->iop_pdira |= 0x00400000;
|
||||
io->iop_pdira &= ~0x00800000;
|
||||
io->iop_psora &= ~0x00c00000;
|
||||
|
||||
/* Wire BRG2 to SMC2 */
|
||||
cpm2_immr->im_cpmux.cmx_smr &= 0xf0;
|
||||
pinfo->brg = 2;
|
||||
}
|
||||
|
||||
void scc1_lineif(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
|
||||
|
||||
/* Use Port D for SCC1 instead of other functions. */
|
||||
io->iop_ppard |= 0x00000003;
|
||||
io->iop_psord &= ~0x00000001; /* Rx */
|
||||
io->iop_psord |= 0x00000002; /* Tx */
|
||||
io->iop_pdird &= ~0x00000001; /* Rx */
|
||||
io->iop_pdird |= 0x00000002; /* Tx */
|
||||
|
||||
/* Wire BRG1 to SCC1 */
|
||||
cpm2_immr->im_cpmux.cmx_scr &= ~0x00ffffff;
|
||||
cpm2_immr->im_cpmux.cmx_scr |= 0x00000000;
|
||||
pinfo->brg = 1;
|
||||
}
|
||||
|
||||
void scc2_lineif(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
|
||||
io->iop_pparb |= 0x008b0000;
|
||||
io->iop_pdirb |= 0x00880000;
|
||||
io->iop_psorb |= 0x00880000;
|
||||
io->iop_pdirb &= ~0x00030000;
|
||||
io->iop_psorb &= ~0x00030000;
|
||||
cpm2_immr->im_cpmux.cmx_scr &= ~0xff00ffff;
|
||||
cpm2_immr->im_cpmux.cmx_scr |= 0x00090000;
|
||||
pinfo->brg = 2;
|
||||
}
|
||||
|
||||
void scc3_lineif(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
|
||||
io->iop_pparb |= 0x008b0000;
|
||||
io->iop_pdirb |= 0x00880000;
|
||||
io->iop_psorb |= 0x00880000;
|
||||
io->iop_pdirb &= ~0x00030000;
|
||||
io->iop_psorb &= ~0x00030000;
|
||||
cpm2_immr->im_cpmux.cmx_scr &= ~0xffff00ff;
|
||||
cpm2_immr->im_cpmux.cmx_scr |= 0x00001200;
|
||||
pinfo->brg = 3;
|
||||
}
|
||||
|
||||
void scc4_lineif(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
|
||||
|
||||
io->iop_ppard |= 0x00000600;
|
||||
io->iop_psord &= ~0x00000600; /* Tx/Rx */
|
||||
io->iop_pdird &= ~0x00000200; /* Rx */
|
||||
io->iop_pdird |= 0x00000400; /* Tx */
|
||||
|
||||
cpm2_immr->im_cpmux.cmx_scr &= ~0xffffff00;
|
||||
cpm2_immr->im_cpmux.cmx_scr |= 0x0000001b;
|
||||
pinfo->brg = 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate DP-Ram and memory buffers. We need to allocate a transmit and
|
||||
* receive buffer descriptors from dual port ram, and a character
|
||||
* buffer area from host mem. If we are allocating for the console we need
|
||||
* to do it from bootmem
|
||||
*/
|
||||
int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
|
||||
{
|
||||
int dpmemsz, memsz;
|
||||
u8 *dp_mem;
|
||||
uint dp_offset;
|
||||
u8 *mem_addr;
|
||||
dma_addr_t dma_addr = 0;
|
||||
|
||||
pr_debug("CPM uart[%d]:allocbuf\n", pinfo->port.line);
|
||||
|
||||
dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos);
|
||||
dp_offset = cpm_dpalloc(dpmemsz, 8);
|
||||
if (IS_DPERR(dp_offset)) {
|
||||
printk(KERN_ERR
|
||||
"cpm_uart_cpm.c: could not allocate buffer descriptors\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dp_mem = cpm_dpram_addr(dp_offset);
|
||||
|
||||
memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
|
||||
L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
|
||||
if (is_con)
|
||||
mem_addr = alloc_bootmem(memsz);
|
||||
else
|
||||
mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (mem_addr == NULL) {
|
||||
cpm_dpfree(dp_offset);
|
||||
printk(KERN_ERR
|
||||
"cpm_uart_cpm.c: could not allocate coherent memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pinfo->dp_addr = dp_offset;
|
||||
pinfo->mem_addr = mem_addr;
|
||||
pinfo->dma_addr = dma_addr;
|
||||
|
||||
pinfo->rx_buf = mem_addr;
|
||||
pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
|
||||
* pinfo->rx_fifosize);
|
||||
|
||||
pinfo->rx_bd_base = (volatile cbd_t *)dp_mem;
|
||||
pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
|
||||
pinfo->rx_fifosize) +
|
||||
L1_CACHE_ALIGN(pinfo->tx_nrfifos *
|
||||
pinfo->tx_fifosize), pinfo->mem_addr,
|
||||
pinfo->dma_addr);
|
||||
|
||||
cpm_dpfree(pinfo->dp_addr);
|
||||
}
|
||||
|
||||
/* Setup any dynamic params in the uart desc */
|
||||
int cpm_uart_init_portdesc(void)
|
||||
{
|
||||
pr_debug("CPM uart[-]:init portdesc\n");
|
||||
|
||||
cpm_uart_nr = 0;
|
||||
#ifdef CONFIG_SERIAL_CPM_SMC1
|
||||
cpm_uart_ports[UART_SMC1].smcp = (smc_t *) & cpm2_immr->im_smc[0];
|
||||
cpm_uart_ports[UART_SMC1].smcup =
|
||||
(smc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SMC1];
|
||||
cpm_uart_ports[UART_SMC1].port.mapbase =
|
||||
(unsigned long)&cpm2_immr->im_smc[0];
|
||||
cpm_uart_ports[UART_SMC1].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
|
||||
cpm_uart_ports[UART_SMC1].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
|
||||
cpm_uart_ports[UART_SMC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
|
||||
cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_CPM_SMC2
|
||||
cpm_uart_ports[UART_SMC2].smcp = (smc_t *) & cpm2_immr->im_smc[1];
|
||||
cpm_uart_ports[UART_SMC2].smcup =
|
||||
(smc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SMC2];
|
||||
cpm_uart_ports[UART_SMC2].port.mapbase =
|
||||
(unsigned long)&cpm2_immr->im_smc[1];
|
||||
cpm_uart_ports[UART_SMC2].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
|
||||
cpm_uart_ports[UART_SMC2].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
|
||||
cpm_uart_ports[UART_SMC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
|
||||
cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_CPM_SCC1
|
||||
cpm_uart_ports[UART_SCC1].sccp = (scc_t *) & cpm2_immr->im_scc[0];
|
||||
cpm_uart_ports[UART_SCC1].sccup =
|
||||
(scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC1];
|
||||
cpm_uart_ports[UART_SCC1].port.mapbase =
|
||||
(unsigned long)&cpm2_immr->im_scc[0];
|
||||
cpm_uart_ports[UART_SCC1].sccp->scc_sccm &=
|
||||
~(UART_SCCM_TX | UART_SCCM_RX);
|
||||
cpm_uart_ports[UART_SCC1].sccp->scc_gsmrl &=
|
||||
~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
cpm_uart_ports[UART_SCC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
|
||||
cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_CPM_SCC2
|
||||
cpm_uart_ports[UART_SCC2].sccp = (scc_t *) & cpm2_immr->im_scc[1];
|
||||
cpm_uart_ports[UART_SCC2].sccup =
|
||||
(scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC2];
|
||||
cpm_uart_ports[UART_SCC2].port.mapbase =
|
||||
(unsigned long)&cpm2_immr->im_scc[1];
|
||||
cpm_uart_ports[UART_SCC2].sccp->scc_sccm &=
|
||||
~(UART_SCCM_TX | UART_SCCM_RX);
|
||||
cpm_uart_ports[UART_SCC2].sccp->scc_gsmrl &=
|
||||
~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
cpm_uart_ports[UART_SCC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
|
||||
cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_CPM_SCC3
|
||||
cpm_uart_ports[UART_SCC3].sccp = (scc_t *) & cpm2_immr->im_scc[2];
|
||||
cpm_uart_ports[UART_SCC3].sccup =
|
||||
(scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC3];
|
||||
cpm_uart_ports[UART_SCC3].port.mapbase =
|
||||
(unsigned long)&cpm2_immr->im_scc[2];
|
||||
cpm_uart_ports[UART_SCC3].sccp->scc_sccm &=
|
||||
~(UART_SCCM_TX | UART_SCCM_RX);
|
||||
cpm_uart_ports[UART_SCC3].sccp->scc_gsmrl &=
|
||||
~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
cpm_uart_ports[UART_SCC3].port.uartclk = (((bd_t *) __res)->bi_intfreq);
|
||||
cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_CPM_SCC4
|
||||
cpm_uart_ports[UART_SCC4].sccp = (scc_t *) & cpm2_immr->im_scc[3];
|
||||
cpm_uart_ports[UART_SCC4].sccup =
|
||||
(scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC4];
|
||||
cpm_uart_ports[UART_SCC4].port.mapbase =
|
||||
(unsigned long)&cpm2_immr->im_scc[3];
|
||||
cpm_uart_ports[UART_SCC4].sccp->scc_sccm &=
|
||||
~(UART_SCCM_TX | UART_SCCM_RX);
|
||||
cpm_uart_ports[UART_SCC4].sccp->scc_gsmrl &=
|
||||
~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
cpm_uart_ports[UART_SCC4].port.uartclk = (((bd_t *) __res)->bi_intfreq);
|
||||
cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
45
extra/linux-2.6.10/drivers/serial/cpm_uart/cpm_uart_cpm2.h
Normal file
45
extra/linux-2.6.10/drivers/serial/cpm_uart/cpm_uart_cpm2.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* linux/drivers/serial/cpm_uart_cpm2.h
|
||||
*
|
||||
* Driver for CPM (SCC/SMC) serial ports
|
||||
*
|
||||
* definitions for cpm2
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CPM_UART_CPM2_H
|
||||
#define CPM_UART_CPM2_H
|
||||
|
||||
#include <asm/cpm2.h>
|
||||
|
||||
/* defines for IRQs */
|
||||
#define SMC1_IRQ SIU_INT_SMC1
|
||||
#define SMC2_IRQ SIU_INT_SMC2
|
||||
#define SCC1_IRQ SIU_INT_SCC1
|
||||
#define SCC2_IRQ SIU_INT_SCC2
|
||||
#define SCC3_IRQ SIU_INT_SCC3
|
||||
#define SCC4_IRQ SIU_INT_SCC4
|
||||
|
||||
/* the CPM address */
|
||||
#define CPM_ADDR CPM_MAP_ADDR
|
||||
|
||||
static inline void cpm_set_brg(int brg, int baud)
|
||||
{
|
||||
cpm_setbrg(brg, baud);
|
||||
}
|
||||
|
||||
static inline void cpm_set_scc_fcr(volatile scc_uart_t * sup)
|
||||
{
|
||||
sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
|
||||
sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
|
||||
}
|
||||
|
||||
static inline void cpm_set_smc_fcr(volatile smc_uart_t * up)
|
||||
{
|
||||
up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB;
|
||||
up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
|
||||
}
|
||||
|
||||
#define DPRAM_BASE ((unsigned char *)&cpm2_immr->im_dprambase[0])
|
||||
|
||||
#endif
|
||||
5061
extra/linux-2.6.10/drivers/serial/crisv10.c
Normal file
5061
extra/linux-2.6.10/drivers/serial/crisv10.c
Normal file
File diff suppressed because it is too large
Load Diff
137
extra/linux-2.6.10/drivers/serial/crisv10.h
Normal file
137
extra/linux-2.6.10/drivers/serial/crisv10.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* serial.h: Arch-dep definitions for the Etrax100 serial driver.
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000 Axis Communications AB
|
||||
*/
|
||||
|
||||
#ifndef _ETRAX_SERIAL_H
|
||||
#define _ETRAX_SERIAL_H
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/circ_buf.h>
|
||||
#include <asm/termios.h>
|
||||
|
||||
/* Software state per channel */
|
||||
|
||||
#ifdef __KERNEL__
|
||||
/*
|
||||
* This is our internal structure for each serial port's state.
|
||||
*
|
||||
* Many fields are paralleled by the structure used by the serial_struct
|
||||
* structure.
|
||||
*
|
||||
* For definitions of the flags field, see tty.h
|
||||
*/
|
||||
|
||||
#define SERIAL_RECV_DESCRIPTORS 8
|
||||
|
||||
struct etrax_recv_buffer {
|
||||
struct etrax_recv_buffer *next;
|
||||
unsigned short length;
|
||||
unsigned char error;
|
||||
unsigned char pad;
|
||||
|
||||
unsigned char buffer[0];
|
||||
};
|
||||
|
||||
struct e100_serial {
|
||||
int baud;
|
||||
volatile u8 *port; /* R_SERIALx_CTRL */
|
||||
u32 irq; /* bitnr in R_IRQ_MASK2 for dmaX_descr */
|
||||
|
||||
/* Output registers */
|
||||
volatile u8 *oclrintradr; /* adr to R_DMA_CHx_CLR_INTR */
|
||||
volatile u32 *ofirstadr; /* adr to R_DMA_CHx_FIRST */
|
||||
volatile u8 *ocmdadr; /* adr to R_DMA_CHx_CMD */
|
||||
const volatile u8 *ostatusadr; /* adr to R_DMA_CHx_STATUS */
|
||||
|
||||
/* Input registers */
|
||||
volatile u8 *iclrintradr; /* adr to R_DMA_CHx_CLR_INTR */
|
||||
volatile u32 *ifirstadr; /* adr to R_DMA_CHx_FIRST */
|
||||
volatile u8 *icmdadr; /* adr to R_DMA_CHx_CMD */
|
||||
volatile u32 *idescradr; /* adr to R_DMA_CHx_DESCR */
|
||||
|
||||
int flags; /* defined in tty.h */
|
||||
|
||||
u8 rx_ctrl; /* shadow for R_SERIALx_REC_CTRL */
|
||||
u8 tx_ctrl; /* shadow for R_SERIALx_TR_CTRL */
|
||||
u8 iseteop; /* bit number for R_SET_EOP for the input dma */
|
||||
int enabled; /* Set to 1 if the port is enabled in HW config */
|
||||
|
||||
u8 dma_out_enabled:1; /* Set to 1 if DMA should be used */
|
||||
u8 dma_in_enabled:1; /* Set to 1 if DMA should be used */
|
||||
|
||||
/* end of fields defined in rs_table[] in .c-file */
|
||||
u8 uses_dma_in; /* Set to 1 if DMA is used */
|
||||
u8 uses_dma_out; /* Set to 1 if DMA is used */
|
||||
u8 forced_eop; /* a fifo eop has been forced */
|
||||
int baud_base; /* For special baudrates */
|
||||
int custom_divisor; /* For special baudrates */
|
||||
struct etrax_dma_descr tr_descr;
|
||||
struct etrax_dma_descr rec_descr[SERIAL_RECV_DESCRIPTORS];
|
||||
int cur_rec_descr;
|
||||
|
||||
volatile int tr_running; /* 1 if output is running */
|
||||
|
||||
struct tty_struct *tty;
|
||||
int read_status_mask;
|
||||
int ignore_status_mask;
|
||||
int x_char; /* xon/xoff character */
|
||||
int close_delay;
|
||||
unsigned short closing_wait;
|
||||
unsigned short closing_wait2;
|
||||
unsigned long event;
|
||||
unsigned long last_active;
|
||||
int line;
|
||||
int type; /* PORT_ETRAX */
|
||||
int count; /* # of fd on device */
|
||||
int blocked_open; /* # of blocked opens */
|
||||
struct circ_buf xmit;
|
||||
struct etrax_recv_buffer *first_recv_buffer;
|
||||
struct etrax_recv_buffer *last_recv_buffer;
|
||||
unsigned int recv_cnt;
|
||||
unsigned int max_recv_cnt;
|
||||
|
||||
struct work_struct work;
|
||||
struct async_icount icount; /* error-statistics etc.*/
|
||||
struct termios normal_termios;
|
||||
struct termios callout_termios;
|
||||
#ifdef DECLARE_WAITQUEUE
|
||||
wait_queue_head_t open_wait;
|
||||
wait_queue_head_t close_wait;
|
||||
#else
|
||||
struct wait_queue *open_wait;
|
||||
struct wait_queue *close_wait;
|
||||
#endif
|
||||
|
||||
unsigned long char_time_usec; /* The time for 1 char, in usecs */
|
||||
unsigned long flush_time_usec; /* How often we should flush */
|
||||
unsigned long last_tx_active_usec; /* Last tx usec in the jiffies */
|
||||
unsigned long last_tx_active; /* Last tx time in jiffies */
|
||||
unsigned long last_rx_active_usec; /* Last rx usec in the jiffies */
|
||||
unsigned long last_rx_active; /* Last rx time in jiffies */
|
||||
|
||||
int break_detected_cnt;
|
||||
int errorcode;
|
||||
|
||||
#ifdef CONFIG_ETRAX_RS485
|
||||
struct rs485_control rs485; /* RS-485 support */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* this PORT is not in the standard serial.h. it's not actually used for
|
||||
* anything since we only have one type of async serial-port anyway in this
|
||||
* system.
|
||||
*/
|
||||
|
||||
#define PORT_ETRAX 1
|
||||
|
||||
/*
|
||||
* Events are used to schedule things to happen at timer-interrupt
|
||||
* time, instead of at rs interrupt time.
|
||||
*/
|
||||
#define RS_EVENT_WRITE_WAKEUP 0
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* !_ETRAX_SERIAL_H */
|
||||
822
extra/linux-2.6.10/drivers/serial/dz.c
Normal file
822
extra/linux-2.6.10/drivers/serial/dz.c
Normal file
@@ -0,0 +1,822 @@
|
||||
/*
|
||||
* dz.c: Serial port driver for DECStations equiped
|
||||
* with the DZ chipset.
|
||||
*
|
||||
* Copyright (C) 1998 Olivier A. D. Lebaillif
|
||||
*
|
||||
* Email: olivier.lebaillif@ifrsys.com
|
||||
*
|
||||
* [31-AUG-98] triemer
|
||||
* Changed IRQ to use Harald's dec internals interrupts.h
|
||||
* removed base_addr code - moving address assignment to setup.c
|
||||
* Changed name of dz_init to rs_init to be consistent with tc code
|
||||
* [13-NOV-98] triemer fixed code to receive characters
|
||||
* after patches by harald to irq code.
|
||||
* [09-JAN-99] triemer minor fix for schedule - due to removal of timeout
|
||||
* field from "current" - somewhere between 2.1.121 and 2.1.131
|
||||
Qua Jun 27 15:02:26 BRT 2001
|
||||
* [27-JUN-2001] Arnaldo Carvalho de Melo <acme@conectiva.com.br> - cleanups
|
||||
*
|
||||
* Parts (C) 1999 David Airlie, airlied@linux.ie
|
||||
* [07-SEP-99] Bugfixes
|
||||
*
|
||||
* [06-Jan-2002] Russell King <rmk@arm.linux.org.uk>
|
||||
* Converted to new serial core
|
||||
*/
|
||||
|
||||
#undef DEBUG_DZ
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/dec/interrupts.h>
|
||||
#include <asm/dec/kn01.h>
|
||||
#include <asm/dec/kn02.h>
|
||||
#include <asm/dec/machtype.h>
|
||||
#include <asm/dec/prom.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#define CONSOLE_LINE (3) /* for definition of struct console */
|
||||
|
||||
#include "dz.h"
|
||||
|
||||
#define DZ_INTR_DEBUG 1
|
||||
|
||||
static char *dz_name = "DECstation DZ serial driver version ";
|
||||
static char *dz_version = "1.02";
|
||||
|
||||
struct dz_port {
|
||||
struct uart_port port;
|
||||
unsigned int cflag;
|
||||
};
|
||||
|
||||
static struct dz_port dz_ports[DZ_NB_PORT];
|
||||
|
||||
#ifdef DEBUG_DZ
|
||||
/*
|
||||
* debugging code to send out chars via prom
|
||||
*/
|
||||
static void debug_console(const char *s, int count)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (*s == 10)
|
||||
prom_printf("%c", 13);
|
||||
prom_printf("%c", *s++);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ------------------------------------------------------------
|
||||
* dz_in () and dz_out ()
|
||||
*
|
||||
* These routines are used to access the registers of the DZ
|
||||
* chip, hiding relocation differences between implementation.
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static inline unsigned short dz_in(struct dz_port *dport, unsigned offset)
|
||||
{
|
||||
volatile unsigned short *addr =
|
||||
(volatile unsigned short *) (dport->port.membase + offset);
|
||||
return *addr;
|
||||
}
|
||||
|
||||
static inline void dz_out(struct dz_port *dport, unsigned offset,
|
||||
unsigned short value)
|
||||
{
|
||||
volatile unsigned short *addr =
|
||||
(volatile unsigned short *) (dport->port.membase + offset);
|
||||
*addr = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* ------------------------------------------------------------
|
||||
* rs_stop () and rs_start ()
|
||||
*
|
||||
* These routines are called before setting or resetting
|
||||
* tty->stopped. They enable or disable transmitter interrupts,
|
||||
* as necessary.
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void dz_stop_tx(struct uart_port *uport, unsigned int tty_stop)
|
||||
{
|
||||
struct dz_port *dport = (struct dz_port *)uport;
|
||||
unsigned short tmp, mask = 1 << dport->port.line;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dport->port.lock, flags);
|
||||
tmp = dz_in(dport, DZ_TCR); /* read the TX flag */
|
||||
tmp &= ~mask; /* clear the TX flag */
|
||||
dz_out(dport, DZ_TCR, tmp);
|
||||
spin_unlock_irqrestore(&dport->port.lock, flags);
|
||||
}
|
||||
|
||||
static void dz_start_tx(struct uart_port *uport, unsigned int tty_start)
|
||||
{
|
||||
struct dz_port *dport = (struct dz_port *)uport;
|
||||
unsigned short tmp, mask = 1 << dport->port.line;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dport->port.lock, flags);
|
||||
tmp = dz_in(dport, DZ_TCR); /* read the TX flag */
|
||||
tmp |= mask; /* set the TX flag */
|
||||
dz_out(dport, DZ_TCR, tmp);
|
||||
spin_unlock_irqrestore(&dport->port.lock, flags);
|
||||
}
|
||||
|
||||
static void dz_stop_rx(struct uart_port *uport)
|
||||
{
|
||||
struct dz_port *dport = (struct dz_port *)uport;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dport->port.lock, flags);
|
||||
dport->cflag &= ~DZ_CREAD;
|
||||
dz_out(dport, DZ_LPR, dport->cflag);
|
||||
spin_unlock_irqrestore(&dport->port.lock, flags);
|
||||
}
|
||||
|
||||
static void dz_enable_ms(struct uart_port *port)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
/*
|
||||
* ------------------------------------------------------------
|
||||
* Here starts the interrupt handling routines. All of the
|
||||
* following subroutines are declared as inline and are folded
|
||||
* into dz_interrupt. They were separated out for readability's
|
||||
* sake.
|
||||
*
|
||||
* Note: rs_interrupt() is a "fast" interrupt, which means that it
|
||||
* runs with interrupts turned off. People who may want to modify
|
||||
* rs_interrupt() should try to keep the interrupt handler as fast as
|
||||
* possible. After you are done making modifications, it is not a bad
|
||||
* idea to do:
|
||||
*
|
||||
* make drivers/serial/dz.s
|
||||
*
|
||||
* and look at the resulting assemble code in dz.s.
|
||||
*
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* ------------------------------------------------------------
|
||||
* receive_char ()
|
||||
*
|
||||
* This routine deals with inputs from any lines.
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
static inline void dz_receive_chars(struct dz_port *dport)
|
||||
{
|
||||
struct tty_struct *tty = NULL;
|
||||
struct uart_icount *icount;
|
||||
int ignore = 0;
|
||||
unsigned short status, tmp;
|
||||
unsigned char ch, flag;
|
||||
|
||||
/* this code is going to be a problem...
|
||||
the call to tty_flip_buffer is going to need
|
||||
to be rethought...
|
||||
*/
|
||||
do {
|
||||
status = dz_in(dport, DZ_RBUF);
|
||||
|
||||
/* punt so we don't get duplicate characters */
|
||||
if (!(status & DZ_DVAL))
|
||||
goto ignore_char;
|
||||
|
||||
|
||||
ch = UCHAR(status); /* grab the char */
|
||||
flag = TTY_NORMAL;
|
||||
|
||||
#if 0
|
||||
if (info->is_console) {
|
||||
if (ch == 0)
|
||||
return; /* it's a break ... */
|
||||
}
|
||||
#endif
|
||||
|
||||
tty = dport->port.info->tty;/* now tty points to the proper dev */
|
||||
icount = &dport->port.icount;
|
||||
|
||||
if (!tty)
|
||||
break;
|
||||
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
|
||||
break;
|
||||
|
||||
icount->rx++;
|
||||
|
||||
/* keep track of the statistics */
|
||||
if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) {
|
||||
if (status & DZ_PERR) /* parity error */
|
||||
icount->parity++;
|
||||
else if (status & DZ_FERR) /* frame error */
|
||||
icount->frame++;
|
||||
if (status & DZ_OERR) /* overrun error */
|
||||
icount->overrun++;
|
||||
|
||||
/* check to see if we should ignore the character
|
||||
and mask off conditions that should be ignored
|
||||
*/
|
||||
|
||||
if (status & dport->port.ignore_status_mask) {
|
||||
if (++ignore > 100)
|
||||
break;
|
||||
goto ignore_char;
|
||||
}
|
||||
/* mask off the error conditions we want to ignore */
|
||||
tmp = status & dport->port.read_status_mask;
|
||||
|
||||
if (tmp & DZ_PERR) {
|
||||
flag = TTY_PARITY;
|
||||
#ifdef DEBUG_DZ
|
||||
debug_console("PERR\n", 5);
|
||||
#endif
|
||||
} else if (tmp & DZ_FERR) {
|
||||
flag = TTY_FRAME;
|
||||
#ifdef DEBUG_DZ
|
||||
debug_console("FERR\n", 5);
|
||||
#endif
|
||||
}
|
||||
if (tmp & DZ_OERR) {
|
||||
#ifdef DEBUG_DZ
|
||||
debug_console("OERR\n", 5);
|
||||
#endif
|
||||
tty_insert_flip_char(tty, ch, flag);
|
||||
ch = 0;
|
||||
flag = TTY_OVERRUN;
|
||||
}
|
||||
}
|
||||
tty_insert_flip_char(tty, ch, flag);
|
||||
ignore_char:
|
||||
} while (status & DZ_DVAL);
|
||||
|
||||
if (tty)
|
||||
tty_flip_buffer_push(tty);
|
||||
}
|
||||
|
||||
/*
|
||||
* ------------------------------------------------------------
|
||||
* transmit_char ()
|
||||
*
|
||||
* This routine deals with outputs to any lines.
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
static inline void dz_transmit_chars(struct dz_port *dport)
|
||||
{
|
||||
struct circ_buf *xmit = &dport->port.info->xmit;
|
||||
unsigned char tmp;
|
||||
|
||||
if (dport->port.x_char) { /* XON/XOFF chars */
|
||||
dz_out(dport, DZ_TDR, dport->port.x_char);
|
||||
dport->port.icount.tx++;
|
||||
dport->port.x_char = 0;
|
||||
return;
|
||||
}
|
||||
/* if nothing to do or stopped or hardware stopped */
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) {
|
||||
dz_stop_tx(&dport->port, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* if something to do ... (rember the dz has no output fifo so we go
|
||||
* one char at a time :-<
|
||||
*/
|
||||
tmp = xmit->buf[xmit->tail];
|
||||
xmit->tail = (xmit->tail + 1) & (DZ_XMIT_SIZE - 1);
|
||||
dz_out(dport, DZ_TDR, tmp);
|
||||
dport->port.icount.tx++;
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < DZ_WAKEUP_CHARS)
|
||||
uart_write_wakeup(&dport->port);
|
||||
|
||||
/* Are we done */
|
||||
if (uart_circ_empty(xmit))
|
||||
dz_stop_tx(&dport->port, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* ------------------------------------------------------------
|
||||
* check_modem_status ()
|
||||
*
|
||||
* Only valid for the MODEM line duh !
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
static inline void check_modem_status(struct dz_port *dport)
|
||||
{
|
||||
unsigned short status;
|
||||
|
||||
/* if not ne modem line just return */
|
||||
if (dport->port.line != DZ_MODEM)
|
||||
return;
|
||||
|
||||
status = dz_in(dport, DZ_MSR);
|
||||
|
||||
/* it's easy, since DSR2 is the only bit in the register */
|
||||
if (status)
|
||||
dport->port.icount.dsr++;
|
||||
}
|
||||
|
||||
/*
|
||||
* ------------------------------------------------------------
|
||||
* dz_interrupt ()
|
||||
*
|
||||
* this is the main interrupt routine for the DZ chip.
|
||||
* It deals with the multiple ports.
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
static irqreturn_t dz_interrupt(int irq, void *dev, struct pt_regs *regs)
|
||||
{
|
||||
struct dz_port *dport;
|
||||
unsigned short status;
|
||||
|
||||
/* get the reason why we just got an irq */
|
||||
status = dz_in((struct dz_port *)dev, DZ_CSR);
|
||||
dport = &dz_ports[LINE(status)];
|
||||
|
||||
if (status & DZ_RDONE)
|
||||
dz_receive_chars(dport);
|
||||
|
||||
if (status & DZ_TRDY)
|
||||
dz_transmit_chars(dport);
|
||||
|
||||
/* FIXME: what about check modem status??? --rmk */
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------
|
||||
* Here ends the DZ interrupt routines.
|
||||
* -------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static unsigned int dz_get_mctrl(struct uart_port *uport)
|
||||
{
|
||||
struct dz_port *dport = (struct dz_port *)uport;
|
||||
unsigned int mctrl = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
|
||||
|
||||
if (dport->port.line == DZ_MODEM) {
|
||||
/*
|
||||
* CHECKME: This is a guess from the other code... --rmk
|
||||
*/
|
||||
if (dz_in(dport, DZ_MSR) & DZ_MODEM_DSR)
|
||||
mctrl &= ~TIOCM_DSR;
|
||||
}
|
||||
|
||||
return mctrl;
|
||||
}
|
||||
|
||||
static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl)
|
||||
{
|
||||
struct dz_port *dport = (struct dz_port *)uport;
|
||||
unsigned short tmp;
|
||||
|
||||
if (dport->port.line == DZ_MODEM) {
|
||||
tmp = dz_in(dport, DZ_TCR);
|
||||
if (mctrl & TIOCM_DTR)
|
||||
tmp &= ~DZ_MODEM_DTR;
|
||||
else
|
||||
tmp |= DZ_MODEM_DTR;
|
||||
dz_out(dport, DZ_TCR, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------
|
||||
* startup ()
|
||||
*
|
||||
* various initialization tasks
|
||||
* -------------------------------------------------------------------
|
||||
*/
|
||||
static int dz_startup(struct uart_port *uport)
|
||||
{
|
||||
struct dz_port *dport = (struct dz_port *)uport;
|
||||
unsigned long flags;
|
||||
unsigned short tmp;
|
||||
|
||||
/* The dz lines for the mouse/keyboard must be
|
||||
* opened using their respective drivers.
|
||||
*/
|
||||
if ((dport->port.line == DZ_KEYBOARD) ||
|
||||
(dport->port.line == DZ_MOUSE))
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock_irqsave(&dport->port.lock, flags);
|
||||
|
||||
/* enable the interrupt and the scanning */
|
||||
tmp = dz_in(dport, DZ_CSR);
|
||||
tmp |= DZ_RIE | DZ_TIE | DZ_MSE;
|
||||
dz_out(dport, DZ_CSR, tmp);
|
||||
|
||||
spin_unlock_irqrestore(&dport->port.lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------
|
||||
* shutdown ()
|
||||
*
|
||||
* This routine will shutdown a serial port; interrupts are disabled, and
|
||||
* DTR is dropped if the hangup on close termio flag is on.
|
||||
* -------------------------------------------------------------------
|
||||
*/
|
||||
static void dz_shutdown(struct uart_port *uport)
|
||||
{
|
||||
dz_stop_tx(uport, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* get_lsr_info - get line status register info
|
||||
*
|
||||
* Purpose: Let user call ioctl() to get info when the UART physically
|
||||
* is emptied. On bus types like RS485, the transmitter must
|
||||
* release the bus after transmitting. This must be done when
|
||||
* the transmit shift register is empty, not be done when the
|
||||
* transmit holding register is empty. This functionality
|
||||
* allows an RS485 driver to be written in user space.
|
||||
*/
|
||||
static unsigned int dz_tx_empty(struct uart_port *uport)
|
||||
{
|
||||
struct dz_port *dport = (struct dz_port *)uport;
|
||||
unsigned short status = dz_in(dport, DZ_LPR);
|
||||
|
||||
/* FIXME: this appears to be obviously broken --rmk. */
|
||||
return status ? TIOCSER_TEMT : 0;
|
||||
}
|
||||
|
||||
static void dz_break_ctl(struct uart_port *uport, int break_state)
|
||||
{
|
||||
struct dz_port *dport = (struct dz_port *)uport;
|
||||
unsigned long flags;
|
||||
unsigned short tmp, mask = 1 << uport->line;
|
||||
|
||||
spin_lock_irqsave(&uport->lock, flags);
|
||||
tmp = dz_in(dport, DZ_TCR);
|
||||
if (break_state)
|
||||
tmp |= mask;
|
||||
else
|
||||
tmp &= ~mask;
|
||||
dz_out(dport, DZ_TCR, tmp);
|
||||
spin_unlock_irqrestore(&uport->lock, flags);
|
||||
}
|
||||
|
||||
static void dz_set_termios(struct uart_port *uport, struct termios *termios,
|
||||
struct termios *old_termios)
|
||||
{
|
||||
struct dz_port *dport = (struct dz_port *)uport;
|
||||
unsigned long flags;
|
||||
unsigned int cflag, baud;
|
||||
|
||||
cflag = dport->port.line;
|
||||
|
||||
switch (termios->c_cflag & CSIZE) {
|
||||
case CS5:
|
||||
cflag |= DZ_CS5;
|
||||
break;
|
||||
case CS6:
|
||||
cflag |= DZ_CS6;
|
||||
break;
|
||||
case CS7:
|
||||
cflag |= DZ_CS7;
|
||||
break;
|
||||
case CS8:
|
||||
default:
|
||||
cflag |= DZ_CS8;
|
||||
}
|
||||
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
cflag |= DZ_CSTOPB;
|
||||
if (termios->c_cflag & PARENB)
|
||||
cflag |= DZ_PARENB;
|
||||
if (termios->c_cflag & PARODD)
|
||||
cflag |= DZ_PARODD;
|
||||
|
||||
baud = uart_get_baud_rate(uport, termios, old_termios, 50, 9600);
|
||||
switch (baud) {
|
||||
case 50:
|
||||
cflag |= DZ_B50;
|
||||
break;
|
||||
case 75:
|
||||
cflag |= DZ_B75;
|
||||
break;
|
||||
case 110:
|
||||
cflag |= DZ_B110;
|
||||
break;
|
||||
case 134:
|
||||
cflag |= DZ_B134;
|
||||
break;
|
||||
case 150:
|
||||
cflag |= DZ_B150;
|
||||
break;
|
||||
case 300:
|
||||
cflag |= DZ_B300;
|
||||
break;
|
||||
case 600:
|
||||
cflag |= DZ_B600;
|
||||
break;
|
||||
case 1200:
|
||||
cflag |= DZ_B1200;
|
||||
break;
|
||||
case 1800:
|
||||
cflag |= DZ_B1800;
|
||||
break;
|
||||
case 2000:
|
||||
cflag |= DZ_B2000;
|
||||
break;
|
||||
case 2400:
|
||||
cflag |= DZ_B2400;
|
||||
break;
|
||||
case 3600:
|
||||
cflag |= DZ_B3600;
|
||||
break;
|
||||
case 4800:
|
||||
cflag |= DZ_B4800;
|
||||
break;
|
||||
case 7200:
|
||||
cflag |= DZ_B7200;
|
||||
break;
|
||||
case 9600:
|
||||
default:
|
||||
cflag |= DZ_B9600;
|
||||
}
|
||||
|
||||
if (termios->c_cflag & CREAD)
|
||||
cflag |= DZ_RXENAB;
|
||||
|
||||
spin_lock_irqsave(&dport->port.lock, flags);
|
||||
|
||||
dz_out(dport, DZ_LPR, cflag);
|
||||
dport->cflag = cflag;
|
||||
|
||||
/* setup accept flag */
|
||||
dport->port.read_status_mask = DZ_OERR;
|
||||
if (termios->c_iflag & INPCK)
|
||||
dport->port.read_status_mask |= DZ_FERR | DZ_PERR;
|
||||
|
||||
/* characters to ignore */
|
||||
uport->ignore_status_mask = 0;
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
dport->port.ignore_status_mask |= DZ_FERR | DZ_PERR;
|
||||
|
||||
spin_unlock_irqrestore(&dport->port.lock, flags);
|
||||
}
|
||||
|
||||
static const char *dz_type(struct uart_port *port)
|
||||
{
|
||||
return "DZ";
|
||||
}
|
||||
|
||||
static void dz_release_port(struct uart_port *port)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
static int dz_request_port(struct uart_port *port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dz_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
if (flags & UART_CONFIG_TYPE)
|
||||
port->type = PORT_DZ;
|
||||
}
|
||||
|
||||
/*
|
||||
* verify the new serial_struct (for TIOCSSERIAL).
|
||||
*/
|
||||
static int dz_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||
{
|
||||
int ret = 0;
|
||||
if (ser->type != PORT_UNKNOWN && ser->type != PORT_DZ)
|
||||
ret = -EINVAL;
|
||||
if (ser->irq != port->irq)
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct uart_ops dz_ops = {
|
||||
.tx_empty = dz_tx_empty,
|
||||
.get_mctrl = dz_get_mctrl,
|
||||
.set_mctrl = dz_set_mctrl,
|
||||
.stop_tx = dz_stop_tx,
|
||||
.start_tx = dz_start_tx,
|
||||
.stop_rx = dz_stop_rx,
|
||||
.enable_ms = dz_enable_ms,
|
||||
.break_ctl = dz_break_ctl,
|
||||
.startup = dz_startup,
|
||||
.shutdown = dz_shutdown,
|
||||
.set_termios = dz_set_termios,
|
||||
.type = dz_type,
|
||||
.release_port = dz_release_port,
|
||||
.request_port = dz_request_port,
|
||||
.config_port = dz_config_port,
|
||||
.verify_port = dz_verify_port,
|
||||
};
|
||||
|
||||
static void __init dz_init_ports(void)
|
||||
{
|
||||
static int first = 1;
|
||||
struct dz_port *dport;
|
||||
unsigned long base;
|
||||
int i;
|
||||
|
||||
if (!first)
|
||||
return;
|
||||
first = 0;
|
||||
|
||||
if (mips_machtype == MACH_DS23100 ||
|
||||
mips_machtype == MACH_DS5100)
|
||||
base = (unsigned long) KN01_DZ11_BASE;
|
||||
else
|
||||
base = (unsigned long) KN02_DZ11_BASE;
|
||||
|
||||
for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) {
|
||||
spin_lock_init(&dport->port.lock);
|
||||
dport->port.membase = (char *) base;
|
||||
dport->port.iotype = SERIAL_IO_PORT;
|
||||
dport->port.irq = dec_interrupt[DEC_IRQ_DZ11];
|
||||
dport->port.line = i;
|
||||
dport->port.fifosize = 1;
|
||||
dport->port.ops = &dz_ops;
|
||||
dport->port.flags = UPF_BOOT_AUTOCONF;
|
||||
}
|
||||
}
|
||||
|
||||
static void dz_reset(struct dz_port *dport)
|
||||
{
|
||||
dz_out(dport, DZ_CSR, DZ_CLR);
|
||||
|
||||
while (dz_in(dport, DZ_CSR) & DZ_CLR);
|
||||
/* FIXME: cpu_relax? */
|
||||
|
||||
iob();
|
||||
|
||||
/* enable scanning */
|
||||
dz_out(dport, DZ_CSR, DZ_MSE);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_DZ_CONSOLE
|
||||
static void dz_console_put_char(struct dz_port *dport, unsigned char ch)
|
||||
{
|
||||
unsigned long flags;
|
||||
int loops = 2500;
|
||||
unsigned short tmp = ch;
|
||||
/* this code sends stuff out to serial device - spinning its
|
||||
wheels and waiting. */
|
||||
|
||||
spin_lock_irqsave(&dport->port.lock, flags);
|
||||
|
||||
/* spin our wheels */
|
||||
while (((dz_in(dport, DZ_CSR) & DZ_TRDY) != DZ_TRDY) && loops--)
|
||||
/* FIXME: cpu_relax, udelay? --rmk */
|
||||
;
|
||||
|
||||
/* Actually transmit the character. */
|
||||
dz_out(dport, DZ_TDR, tmp);
|
||||
|
||||
spin_unlock_irqrestore(&dport->port.lock, flags);
|
||||
}
|
||||
/*
|
||||
* -------------------------------------------------------------------
|
||||
* dz_console_print ()
|
||||
*
|
||||
* dz_console_print is registered for printk.
|
||||
* The console must be locked when we get here.
|
||||
* -------------------------------------------------------------------
|
||||
*/
|
||||
static void dz_console_print(struct console *cons,
|
||||
const char *str,
|
||||
unsigned int count)
|
||||
{
|
||||
struct dz_port *dport = &dz_ports[CONSOLE_LINE];
|
||||
#ifdef DEBUG_DZ
|
||||
prom_printf((char *) str);
|
||||
#endif
|
||||
while (count--) {
|
||||
if (*str == '\n')
|
||||
dz_console_put_char(dport, '\r');
|
||||
dz_console_put_char(dport, *str++);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init dz_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct dz_port *dport = &dz_ports[CONSOLE_LINE];
|
||||
int baud = 9600;
|
||||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
int ret;
|
||||
unsigned short mask, tmp;
|
||||
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
|
||||
dz_reset(dport);
|
||||
|
||||
ret = uart_set_options(&dport->port, co, baud, parity, bits, flow);
|
||||
if (ret == 0) {
|
||||
mask = 1 << dport->port.line;
|
||||
tmp = dz_in(dport, DZ_TCR); /* read the TX flag */
|
||||
if (!(tmp & mask)) {
|
||||
tmp |= mask; /* set the TX flag */
|
||||
dz_out(dport, DZ_TCR, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct console dz_sercons =
|
||||
{
|
||||
.name = "ttyS",
|
||||
.write = dz_console_print,
|
||||
.device = uart_console_device,
|
||||
.setup = dz_console_setup,
|
||||
.flags = CON_CONSDEV | CON_PRINTBUFFER,
|
||||
.index = CONSOLE_LINE,
|
||||
};
|
||||
|
||||
void __init dz_serial_console_init(void)
|
||||
{
|
||||
dz_init_ports();
|
||||
|
||||
register_console(&dz_sercons);
|
||||
}
|
||||
|
||||
#define SERIAL_DZ_CONSOLE &dz_sercons
|
||||
#else
|
||||
#define SERIAL_DZ_CONSOLE NULL
|
||||
#endif /* CONFIG_SERIAL_DZ_CONSOLE */
|
||||
|
||||
static struct uart_driver dz_reg = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = "serial",
|
||||
#ifdef CONFIG_DEVFS
|
||||
.dev_name = "tts/%d",
|
||||
#else
|
||||
.dev_name = "ttyS%d",
|
||||
#endif
|
||||
.major = TTY_MAJOR,
|
||||
.minor = 64,
|
||||
.nr = DZ_NB_PORT,
|
||||
.cons = SERIAL_DZ_CONSOLE,
|
||||
};
|
||||
|
||||
int __init dz_init(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret, i;
|
||||
|
||||
printk("%s%s\n", dz_name, dz_version);
|
||||
|
||||
dz_init_ports();
|
||||
|
||||
save_flags(flags);
|
||||
cli();
|
||||
|
||||
#ifndef CONFIG_SERIAL_DZ_CONSOLE
|
||||
/* reset the chip */
|
||||
dz_reset(&dz_ports[0]);
|
||||
#endif
|
||||
|
||||
/* order matters here... the trick is that flags
|
||||
is updated... in request_irq - to immediatedly obliterate
|
||||
it is unwise. */
|
||||
restore_flags(flags);
|
||||
|
||||
if (request_irq(dz_ports[0].port.irq, dz_interrupt,
|
||||
SA_INTERRUPT, "DZ", &dz_ports[0]))
|
||||
panic("Unable to register DZ interrupt");
|
||||
|
||||
ret = uart_register_driver(&dz_reg);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < DZ_NB_PORT; i++)
|
||||
uart_add_one_port(&dz_reg, &dz_ports[i].port);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("DECstation DZ serial driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
118
extra/linux-2.6.10/drivers/serial/dz.h
Normal file
118
extra/linux-2.6.10/drivers/serial/dz.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* dz.h: Serial port driver for DECStations equiped
|
||||
* with the DZ chipset.
|
||||
*
|
||||
* Copyright (C) 1998 Olivier A. D. Lebaillif
|
||||
*
|
||||
* Email: olivier.lebaillif@ifrsys.com
|
||||
*
|
||||
*/
|
||||
#ifndef DZ_SERIAL_H
|
||||
#define DZ_SERIAL_H
|
||||
|
||||
/*
|
||||
* Definitions for the Control and Status Received.
|
||||
*/
|
||||
#define DZ_TRDY 0x8000 /* Transmitter empty */
|
||||
#define DZ_TIE 0x4000 /* Transmitter Interrupt Enable */
|
||||
#define DZ_RDONE 0x0080 /* Receiver data ready */
|
||||
#define DZ_RIE 0x0040 /* Receive Interrupt Enable */
|
||||
#define DZ_MSE 0x0020 /* Master Scan Enable */
|
||||
#define DZ_CLR 0x0010 /* Master reset */
|
||||
#define DZ_MAINT 0x0008 /* Loop Back Mode */
|
||||
|
||||
/*
|
||||
* Definitions for the Received buffer.
|
||||
*/
|
||||
#define DZ_RBUF_MASK 0x00FF /* Data Mask in the Receive Buffer */
|
||||
#define DZ_LINE_MASK 0x0300 /* Line Mask in the Receive Buffer */
|
||||
#define DZ_DVAL 0x8000 /* Valid Data indicator */
|
||||
#define DZ_OERR 0x4000 /* Overrun error indicator */
|
||||
#define DZ_FERR 0x2000 /* Frame error indicator */
|
||||
#define DZ_PERR 0x1000 /* Parity error indicator */
|
||||
|
||||
#define LINE(x) (x & DZ_LINE_MASK) >> 8 /* Get the line number from the input buffer */
|
||||
#define UCHAR(x) (unsigned char)(x & DZ_RBUF_MASK)
|
||||
|
||||
/*
|
||||
* Definitions for the Transmit Register.
|
||||
*/
|
||||
#define DZ_LINE_KEYBOARD 0x0001
|
||||
#define DZ_LINE_MOUSE 0x0002
|
||||
#define DZ_LINE_MODEM 0x0004
|
||||
#define DZ_LINE_PRINTER 0x0008
|
||||
|
||||
#define DZ_MODEM_DTR 0x0400 /* DTR for the modem line (2) */
|
||||
|
||||
/*
|
||||
* Definitions for the Modem Status Register.
|
||||
*/
|
||||
#define DZ_MODEM_DSR 0x0200 /* DSR for the modem line (2) */
|
||||
|
||||
/*
|
||||
* Definitions for the Transmit Data Register.
|
||||
*/
|
||||
#define DZ_BRK0 0x0100 /* Break assertion for line 0 */
|
||||
#define DZ_BRK1 0x0200 /* Break assertion for line 1 */
|
||||
#define DZ_BRK2 0x0400 /* Break assertion for line 2 */
|
||||
#define DZ_BRK3 0x0800 /* Break assertion for line 3 */
|
||||
|
||||
/*
|
||||
* Definitions for the Line Parameter Register.
|
||||
*/
|
||||
#define DZ_KEYBOARD 0x0000 /* line 0 = keyboard */
|
||||
#define DZ_MOUSE 0x0001 /* line 1 = mouse */
|
||||
#define DZ_MODEM 0x0002 /* line 2 = modem */
|
||||
#define DZ_PRINTER 0x0003 /* line 3 = printer */
|
||||
|
||||
#define DZ_CSIZE 0x0018 /* Number of bits per byte (mask) */
|
||||
#define DZ_CS5 0x0000 /* 5 bits per byte */
|
||||
#define DZ_CS6 0x0008 /* 6 bits per byte */
|
||||
#define DZ_CS7 0x0010 /* 7 bits per byte */
|
||||
#define DZ_CS8 0x0018 /* 8 bits per byte */
|
||||
|
||||
#define DZ_CSTOPB 0x0020 /* 2 stop bits instead of one */
|
||||
|
||||
#define DZ_PARENB 0x0040 /* Parity enable */
|
||||
#define DZ_PARODD 0x0080 /* Odd parity instead of even */
|
||||
|
||||
#define DZ_CBAUD 0x0E00 /* Baud Rate (mask) */
|
||||
#define DZ_B50 0x0000
|
||||
#define DZ_B75 0x0100
|
||||
#define DZ_B110 0x0200
|
||||
#define DZ_B134 0x0300
|
||||
#define DZ_B150 0x0400
|
||||
#define DZ_B300 0x0500
|
||||
#define DZ_B600 0x0600
|
||||
#define DZ_B1200 0x0700
|
||||
#define DZ_B1800 0x0800
|
||||
#define DZ_B2000 0x0900
|
||||
#define DZ_B2400 0x0A00
|
||||
#define DZ_B3600 0x0B00
|
||||
#define DZ_B4800 0x0C00
|
||||
#define DZ_B7200 0x0D00
|
||||
#define DZ_B9600 0x0E00
|
||||
|
||||
#define DZ_CREAD 0x1000 /* Enable receiver */
|
||||
#define DZ_RXENAB 0x1000 /* enable receive char */
|
||||
/*
|
||||
* Addresses for the DZ registers
|
||||
*/
|
||||
#define DZ_CSR 0x00 /* Control and Status Register */
|
||||
#define DZ_RBUF 0x08 /* Receive Buffer */
|
||||
#define DZ_LPR 0x08 /* Line Parameters Register */
|
||||
#define DZ_TCR 0x10 /* Transmitter Control Register */
|
||||
#define DZ_MSR 0x18 /* Modem Status Register */
|
||||
#define DZ_TDR 0x18 /* Transmit Data Register */
|
||||
|
||||
#define DZ_NB_PORT 4
|
||||
|
||||
#define DZ_XMIT_SIZE 4096 /* buffer size */
|
||||
#define DZ_WAKEUP_CHARS DZ_XMIT_SIZE/4
|
||||
|
||||
#ifdef MODULE
|
||||
int init_module (void)
|
||||
void cleanup_module (void)
|
||||
#endif
|
||||
|
||||
#endif /* DZ_SERIAL_H */
|
||||
1696
extra/linux-2.6.10/drivers/serial/icom.c
Normal file
1696
extra/linux-2.6.10/drivers/serial/icom.c
Normal file
File diff suppressed because it is too large
Load Diff
290
extra/linux-2.6.10/drivers/serial/icom.h
Normal file
290
extra/linux-2.6.10/drivers/serial/icom.h
Normal file
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* icom.h
|
||||
*
|
||||
* Copyright (C) 2001 Michael Anderson, IBM Corporation
|
||||
*
|
||||
* Serial device driver include file.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include<linux/serial_core.h>
|
||||
|
||||
#define BAUD_TABLE_LIMIT ((sizeof(icom_acfg_baud)/sizeof(int)) - 1)
|
||||
static int icom_acfg_baud[] = {
|
||||
300,
|
||||
600,
|
||||
900,
|
||||
1200,
|
||||
1800,
|
||||
2400,
|
||||
3600,
|
||||
4800,
|
||||
7200,
|
||||
9600,
|
||||
14400,
|
||||
19200,
|
||||
28800,
|
||||
38400,
|
||||
57600,
|
||||
76800,
|
||||
115200,
|
||||
153600,
|
||||
230400,
|
||||
307200,
|
||||
460800,
|
||||
};
|
||||
|
||||
struct icom_regs {
|
||||
u32 control; /* Adapter Control Register */
|
||||
u32 interrupt; /* Adapter Interrupt Register */
|
||||
u32 int_mask; /* Adapter Interrupt Mask Reg */
|
||||
u32 int_pri; /* Adapter Interrupt Priority r */
|
||||
u32 int_reg_b; /* Adapter non-masked Interrupt */
|
||||
u32 resvd01;
|
||||
u32 resvd02;
|
||||
u32 resvd03;
|
||||
u32 control_2; /* Adapter Control Register 2 */
|
||||
u32 interrupt_2; /* Adapter Interrupt Register 2 */
|
||||
u32 int_mask_2; /* Adapter Interrupt Mask 2 */
|
||||
u32 int_pri_2; /* Adapter Interrupt Prior 2 */
|
||||
u32 int_reg_2b; /* Adapter non-masked 2 */
|
||||
};
|
||||
|
||||
struct func_dram {
|
||||
u32 reserved[108]; /* 0-1B0 reserved by personality code */
|
||||
u32 RcvStatusAddr; /* 1B0-1B3 Status Address for Next rcv */
|
||||
u8 RcvStnAddr; /* 1B4 Receive Station Addr */
|
||||
u8 IdleState; /* 1B5 Idle State */
|
||||
u8 IdleMonitor; /* 1B6 Idle Monitor */
|
||||
u8 FlagFillIdleTimer; /* 1B7 Flag Fill Idle Timer */
|
||||
u32 XmitStatusAddr; /* 1B8-1BB Transmit Status Address */
|
||||
u8 StartXmitCmd; /* 1BC Start Xmit Command */
|
||||
u8 HDLCConfigReg; /* 1BD Reserved */
|
||||
u8 CauseCode; /* 1BE Cause code for fatal error */
|
||||
u8 xchar; /* 1BF High priority send */
|
||||
u32 reserved3; /* 1C0-1C3 Reserved */
|
||||
u8 PrevCmdReg; /* 1C4 Reserved */
|
||||
u8 CmdReg; /* 1C5 Command Register */
|
||||
u8 async_config2; /* 1C6 Async Config Byte 2 */
|
||||
u8 async_config3; /* 1C7 Async Config Byte 3 */
|
||||
u8 dce_resvd[20]; /* 1C8-1DB DCE Rsvd */
|
||||
u8 dce_resvd21; /* 1DC DCE Rsvd (21st byte */
|
||||
u8 misc_flags; /* 1DD misc flags */
|
||||
#define V2_HARDWARE 0x40
|
||||
#define ICOM_HDW_ACTIVE 0x01
|
||||
u8 call_length; /* 1DE Phone #/CFI buff ln */
|
||||
u8 call_length2; /* 1DF Upper byte (unused) */
|
||||
u32 call_addr; /* 1E0-1E3 Phn #/CFI buff addr */
|
||||
u16 timer_value; /* 1E4-1E5 general timer value */
|
||||
u8 timer_command; /* 1E6 general timer cmd */
|
||||
u8 dce_command; /* 1E7 dce command reg */
|
||||
u8 dce_cmd_status; /* 1E8 dce command stat */
|
||||
u8 x21_r1_ioff; /* 1E9 dce ready counter */
|
||||
u8 x21_r0_ioff; /* 1EA dce not ready ctr */
|
||||
u8 x21_ralt_ioff; /* 1EB dce CNR counter */
|
||||
u8 x21_r1_ion; /* 1EC dce ready I on ctr */
|
||||
u8 rsvd_ier; /* 1ED Rsvd for IER (if ne */
|
||||
u8 ier; /* 1EE Interrupt Enable */
|
||||
u8 isr; /* 1EF Input Signal Reg */
|
||||
u8 osr; /* 1F0 Output Signal Reg */
|
||||
u8 reset; /* 1F1 Reset/Reload Reg */
|
||||
u8 disable; /* 1F2 Disable Reg */
|
||||
u8 sync; /* 1F3 Sync Reg */
|
||||
u8 error_stat; /* 1F4 Error Status */
|
||||
u8 cable_id; /* 1F5 Cable ID */
|
||||
u8 cs_length; /* 1F6 CS Load Length */
|
||||
u8 mac_length; /* 1F7 Mac Load Length */
|
||||
u32 cs_load_addr; /* 1F8-1FB Call Load PCI Addr */
|
||||
u32 mac_load_addr; /* 1FC-1FF Mac Load PCI Addr */
|
||||
};
|
||||
|
||||
/*
|
||||
* adapter defines and structures
|
||||
*/
|
||||
#define ICOM_CONTROL_START_A 0x00000008
|
||||
#define ICOM_CONTROL_STOP_A 0x00000004
|
||||
#define ICOM_CONTROL_START_B 0x00000002
|
||||
#define ICOM_CONTROL_STOP_B 0x00000001
|
||||
#define ICOM_CONTROL_START_C 0x00000008
|
||||
#define ICOM_CONTROL_STOP_C 0x00000004
|
||||
#define ICOM_CONTROL_START_D 0x00000002
|
||||
#define ICOM_CONTROL_STOP_D 0x00000001
|
||||
#define ICOM_IRAM_OFFSET 0x1000
|
||||
#define ICOM_IRAM_SIZE 0x0C00
|
||||
#define ICOM_DCE_IRAM_OFFSET 0x0A00
|
||||
#define ICOM_CABLE_ID_VALID 0x01
|
||||
#define ICOM_CABLE_ID_MASK 0xF0
|
||||
#define ICOM_DISABLE 0x80
|
||||
#define CMD_XMIT_RCV_ENABLE 0xC0
|
||||
#define CMD_XMIT_ENABLE 0x40
|
||||
#define CMD_RCV_DISABLE 0x00
|
||||
#define CMD_RCV_ENABLE 0x80
|
||||
#define CMD_RESTART 0x01
|
||||
#define CMD_HOLD_XMIT 0x02
|
||||
#define CMD_SND_BREAK 0x04
|
||||
#define RS232_CABLE 0x06
|
||||
#define V24_CABLE 0x0E
|
||||
#define V35_CABLE 0x0C
|
||||
#define V36_CABLE 0x02
|
||||
#define NO_CABLE 0x00
|
||||
#define START_DOWNLOAD 0x80
|
||||
#define ICOM_INT_MASK_PRC_A 0x00003FFF
|
||||
#define ICOM_INT_MASK_PRC_B 0x3FFF0000
|
||||
#define ICOM_INT_MASK_PRC_C 0x00003FFF
|
||||
#define ICOM_INT_MASK_PRC_D 0x3FFF0000
|
||||
#define INT_RCV_COMPLETED 0x1000
|
||||
#define INT_XMIT_COMPLETED 0x2000
|
||||
#define INT_IDLE_DETECT 0x0800
|
||||
#define INT_RCV_DISABLED 0x0400
|
||||
#define INT_XMIT_DISABLED 0x0200
|
||||
#define INT_RCV_XMIT_SHUTDOWN 0x0100
|
||||
#define INT_FATAL_ERROR 0x0080
|
||||
#define INT_CABLE_PULL 0x0020
|
||||
#define INT_SIGNAL_CHANGE 0x0010
|
||||
#define HDLC_PPP_PURE_ASYNC 0x02
|
||||
#define HDLC_FF_FILL 0x00
|
||||
#define HDLC_HDW_FLOW 0x01
|
||||
#define START_XMIT 0x80
|
||||
#define ICOM_ACFG_DRIVE1 0x20
|
||||
#define ICOM_ACFG_NO_PARITY 0x00
|
||||
#define ICOM_ACFG_PARITY_ENAB 0x02
|
||||
#define ICOM_ACFG_PARITY_ODD 0x01
|
||||
#define ICOM_ACFG_8BPC 0x00
|
||||
#define ICOM_ACFG_7BPC 0x04
|
||||
#define ICOM_ACFG_6BPC 0x08
|
||||
#define ICOM_ACFG_5BPC 0x0C
|
||||
#define ICOM_ACFG_1STOP_BIT 0x00
|
||||
#define ICOM_ACFG_2STOP_BIT 0x10
|
||||
#define ICOM_DTR 0x80
|
||||
#define ICOM_RTS 0x40
|
||||
#define ICOM_RI 0x08
|
||||
#define ICOM_DSR 0x80
|
||||
#define ICOM_DCD 0x20
|
||||
#define ICOM_CTS 0x40
|
||||
|
||||
#define NUM_XBUFFS 1
|
||||
#define NUM_RBUFFS 2
|
||||
#define RCV_BUFF_SZ 0x0200
|
||||
#define XMIT_BUFF_SZ 0x1000
|
||||
struct statusArea {
|
||||
/**********************************************/
|
||||
/* Transmit Status Area */
|
||||
/**********************************************/
|
||||
struct xmit_status_area{
|
||||
u32 leNext; /* Next entry in Little Endian on Adapter */
|
||||
u32 leNextASD;
|
||||
u32 leBuffer; /* Buffer for entry in LE for Adapter */
|
||||
u16 leLengthASD;
|
||||
u16 leOffsetASD;
|
||||
u16 leLength; /* Length of data in segment */
|
||||
u16 flags;
|
||||
#define SA_FLAGS_DONE 0x0080 /* Done with Segment */
|
||||
#define SA_FLAGS_CONTINUED 0x8000 /* More Segments */
|
||||
#define SA_FLAGS_IDLE 0x4000 /* Mark IDLE after frm */
|
||||
#define SA_FLAGS_READY_TO_XMIT 0x0800
|
||||
#define SA_FLAGS_STAT_MASK 0x007F
|
||||
} xmit[NUM_XBUFFS];
|
||||
|
||||
/**********************************************/
|
||||
/* Receive Status Area */
|
||||
/**********************************************/
|
||||
struct {
|
||||
u32 leNext; /* Next entry in Little Endian on Adapter */
|
||||
u32 leNextASD;
|
||||
u32 leBuffer; /* Buffer for entry in LE for Adapter */
|
||||
u16 WorkingLength; /* size of segment */
|
||||
u16 reserv01;
|
||||
u16 leLength; /* Length of data in segment */
|
||||
u16 flags;
|
||||
#define SA_FL_RCV_DONE 0x0010 /* Data ready */
|
||||
#define SA_FLAGS_OVERRUN 0x0040
|
||||
#define SA_FLAGS_PARITY_ERROR 0x0080
|
||||
#define SA_FLAGS_FRAME_ERROR 0x0001
|
||||
#define SA_FLAGS_FRAME_TRUNC 0x0002
|
||||
#define SA_FLAGS_BREAK_DET 0x0004 /* set conditionally by device driver, not hardware */
|
||||
#define SA_FLAGS_RCV_MASK 0xFFE6
|
||||
} rcv[NUM_RBUFFS];
|
||||
};
|
||||
|
||||
struct icom_adapter;
|
||||
|
||||
|
||||
#define ICOM_MAJOR 243
|
||||
#define ICOM_MINOR_START 0
|
||||
|
||||
struct icom_port {
|
||||
struct uart_port uart_port;
|
||||
u8 imbed_modem;
|
||||
#define ICOM_UNKNOWN 1
|
||||
#define ICOM_RVX 2
|
||||
#define ICOM_IMBED_MODEM 3
|
||||
unsigned char cable_id;
|
||||
unsigned char read_status_mask;
|
||||
unsigned char ignore_status_mask;
|
||||
unsigned long int_reg;
|
||||
struct icom_regs *global_reg;
|
||||
struct func_dram *dram;
|
||||
int port;
|
||||
struct statusArea *statStg;
|
||||
dma_addr_t statStg_pci;
|
||||
u32 *xmitRestart;
|
||||
dma_addr_t xmitRestart_pci;
|
||||
unsigned char *xmit_buf;
|
||||
dma_addr_t xmit_buf_pci;
|
||||
unsigned char *recv_buf;
|
||||
dma_addr_t recv_buf_pci;
|
||||
int next_rcv;
|
||||
int put_length;
|
||||
int status;
|
||||
#define ICOM_PORT_ACTIVE 1 /* Port exists. */
|
||||
#define ICOM_PORT_OFF 0 /* Port does not exist. */
|
||||
int load_in_progress;
|
||||
struct icom_adapter *adapter;
|
||||
};
|
||||
|
||||
struct icom_adapter {
|
||||
unsigned long base_addr;
|
||||
unsigned long base_addr_pci;
|
||||
unsigned char irq_number;
|
||||
struct pci_dev *pci_dev;
|
||||
struct icom_port port_info[4];
|
||||
int index;
|
||||
int version;
|
||||
#define ADAPTER_V1 0x0001
|
||||
#define ADAPTER_V2 0x0002
|
||||
u32 subsystem_id;
|
||||
#define FOUR_PORT_MODEL 0x0252
|
||||
#define V2_TWO_PORTS_RVX 0x021A
|
||||
#define V2_ONE_PORT_RVX_ONE_PORT_IMBED_MDM 0x0251
|
||||
int numb_ports;
|
||||
struct list_head icom_adapter_entry;
|
||||
struct kobject kobj;
|
||||
};
|
||||
|
||||
/* prototype */
|
||||
extern void iCom_sercons_init(void);
|
||||
|
||||
struct lookup_proc_table {
|
||||
u32 *global_control_reg;
|
||||
unsigned long processor_id;
|
||||
};
|
||||
|
||||
struct lookup_int_table {
|
||||
u32 *global_int_mask;
|
||||
unsigned long processor_id;
|
||||
};
|
||||
|
||||
#define MSECS_TO_JIFFIES(ms) (((ms)*HZ+999)/1000)
|
||||
902
extra/linux-2.6.10/drivers/serial/imx.c
Normal file
902
extra/linux-2.6.10/drivers/serial/imx.c
Normal file
@@ -0,0 +1,902 @@
|
||||
/*
|
||||
* linux/drivers/serial/imx.c
|
||||
*
|
||||
* Driver for Motorola IMX serial ports
|
||||
*
|
||||
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
|
||||
*
|
||||
* Author: Sascha Hauer <sascha@saschahauer.de>
|
||||
* Copyright (C) 2004 Pengutronix
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
|
||||
#if defined(CONFIG_SERIAL_IMX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
||||
#define SUPPORT_SYSRQ
|
||||
#endif
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/hardware.h>
|
||||
|
||||
/* We've been assigned a range on the "Low-density serial ports" major */
|
||||
#define SERIAL_IMX_MAJOR 204
|
||||
#define MINOR_START 41
|
||||
|
||||
#define NR_PORTS 2
|
||||
|
||||
#define IMX_ISR_PASS_LIMIT 256
|
||||
|
||||
/*
|
||||
* This is the size of our serial port register set.
|
||||
*/
|
||||
#define UART_PORT_SIZE 0x100
|
||||
|
||||
/*
|
||||
* This determines how often we check the modem status signals
|
||||
* for any change. They generally aren't connected to an IRQ
|
||||
* so we have to poll them. We also check immediately before
|
||||
* filling the TX fifo incase CTS has been dropped.
|
||||
*/
|
||||
#define MCTRL_TIMEOUT (250*HZ/1000)
|
||||
|
||||
#define DRIVER_NAME "IMX-uart"
|
||||
|
||||
struct imx_port {
|
||||
struct uart_port port;
|
||||
struct timer_list timer;
|
||||
unsigned int old_status;
|
||||
int txirq,rxirq;
|
||||
};
|
||||
|
||||
/*
|
||||
* Handle any change of modem status signal since we were last called.
|
||||
*/
|
||||
static void imx_mctrl_check(struct imx_port *sport)
|
||||
{
|
||||
unsigned int status, changed;
|
||||
|
||||
status = sport->port.ops->get_mctrl(&sport->port);
|
||||
changed = status ^ sport->old_status;
|
||||
|
||||
if (changed == 0)
|
||||
return;
|
||||
|
||||
sport->old_status = status;
|
||||
|
||||
if (changed & TIOCM_RI)
|
||||
sport->port.icount.rng++;
|
||||
if (changed & TIOCM_DSR)
|
||||
sport->port.icount.dsr++;
|
||||
if (changed & TIOCM_CAR)
|
||||
uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
|
||||
if (changed & TIOCM_CTS)
|
||||
uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
|
||||
|
||||
wake_up_interruptible(&sport->port.info->delta_msr_wait);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is our per-port timeout handler, for checking the
|
||||
* modem status signals.
|
||||
*/
|
||||
static void imx_timeout(unsigned long data)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)data;
|
||||
unsigned long flags;
|
||||
|
||||
if (sport->port.info) {
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
imx_mctrl_check(sport);
|
||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||
|
||||
mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* interrupts disabled on entry
|
||||
*/
|
||||
static void imx_stop_tx(struct uart_port *port, unsigned int tty_stop)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
UCR1((u32)sport->port.membase) &= ~UCR1_TXMPTYEN;
|
||||
}
|
||||
|
||||
/*
|
||||
* interrupts disabled on entry
|
||||
*/
|
||||
static void imx_stop_rx(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
UCR2((u32)sport->port.membase) &= ~UCR2_RXEN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the modem control timer to fire immediately.
|
||||
*/
|
||||
static void imx_enable_ms(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
|
||||
mod_timer(&sport->timer, jiffies);
|
||||
}
|
||||
|
||||
static inline void imx_transmit_buffer(struct imx_port *sport)
|
||||
{
|
||||
struct circ_buf *xmit = &sport->port.info->xmit;
|
||||
|
||||
do {
|
||||
/* send xmit->buf[xmit->tail]
|
||||
* out the port here */
|
||||
URTX0((u32)sport->port.membase) = xmit->buf[xmit->tail];
|
||||
xmit->tail = (xmit->tail + 1) &
|
||||
(UART_XMIT_SIZE - 1);
|
||||
sport->port.icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
} while (!(UTS((u32)sport->port.membase) & UTS_TXFULL));
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
imx_stop_tx(&sport->port, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* interrupts disabled on entry
|
||||
*/
|
||||
static void imx_start_tx(struct uart_port *port, unsigned int tty_start)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
|
||||
UCR1((u32)sport->port.membase) |= UCR1_TXMPTYEN;
|
||||
|
||||
if(UTS((u32)sport->port.membase) & UTS_TXEMPTY)
|
||||
imx_transmit_buffer(sport);
|
||||
}
|
||||
|
||||
static irqreturn_t imx_txint(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)dev_id;
|
||||
struct circ_buf *xmit = &sport->port.info->xmit;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sport->port.lock,flags);
|
||||
if (sport->port.x_char)
|
||||
{
|
||||
/* Send next char */
|
||||
URTX0((u32)sport->port.membase) = sport->port.x_char;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
|
||||
imx_stop_tx(&sport->port, 0);
|
||||
goto out;
|
||||
}
|
||||
|
||||
imx_transmit_buffer(sport);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(&sport->port);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&sport->port.lock,flags);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t imx_rxint(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct imx_port *sport = dev_id;
|
||||
unsigned int rx,flg,ignored = 0;
|
||||
struct tty_struct *tty = sport->port.info->tty;
|
||||
unsigned long flags;
|
||||
|
||||
rx = URXD0((u32)sport->port.membase);
|
||||
spin_lock_irqsave(&sport->port.lock,flags);
|
||||
|
||||
do {
|
||||
flg = TTY_NORMAL;
|
||||
sport->port.icount.rx++;
|
||||
|
||||
if( USR2((u32)sport->port.membase) & USR2_BRCD ) {
|
||||
USR2((u32)sport->port.membase) |= USR2_BRCD;
|
||||
if(uart_handle_break(&sport->port))
|
||||
goto ignore_char;
|
||||
}
|
||||
|
||||
if (uart_handle_sysrq_char
|
||||
(&sport->port, (unsigned char)rx, regs))
|
||||
goto ignore_char;
|
||||
|
||||
if( rx & (URXD_PRERR | URXD_OVRRUN | URXD_FRMERR) )
|
||||
goto handle_error;
|
||||
|
||||
error_return:
|
||||
tty_insert_flip_char(tty, rx, flg);
|
||||
|
||||
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
|
||||
goto out;
|
||||
|
||||
ignore_char:
|
||||
rx = URXD0((u32)sport->port.membase);
|
||||
} while(rx & URXD_CHARRDY);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&sport->port.lock,flags);
|
||||
tty_flip_buffer_push(tty);
|
||||
return IRQ_HANDLED;
|
||||
|
||||
handle_error:
|
||||
if (rx & URXD_PRERR)
|
||||
sport->port.icount.parity++;
|
||||
else if (rx & URXD_FRMERR)
|
||||
sport->port.icount.frame++;
|
||||
if (rx & URXD_OVRRUN)
|
||||
sport->port.icount.overrun++;
|
||||
|
||||
if (rx & sport->port.ignore_status_mask) {
|
||||
if (++ignored > 100)
|
||||
goto out;
|
||||
goto ignore_char;
|
||||
}
|
||||
|
||||
rx &= sport->port.read_status_mask;
|
||||
|
||||
if (rx & URXD_PRERR)
|
||||
flg = TTY_PARITY;
|
||||
else if (rx & URXD_FRMERR)
|
||||
flg = TTY_FRAME;
|
||||
if (rx & URXD_OVRRUN)
|
||||
flg = TTY_OVERRUN;
|
||||
|
||||
#ifdef SUPPORT_SYSRQ
|
||||
sport->port.sysrq = 0;
|
||||
#endif
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TIOCSER_TEMT when transmitter is not busy.
|
||||
*/
|
||||
static unsigned int imx_tx_empty(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
|
||||
return USR2((u32)sport->port.membase) & USR2_TXDC ? TIOCSER_TEMT : 0;
|
||||
}
|
||||
|
||||
static unsigned int imx_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
|
||||
}
|
||||
|
||||
static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupts always disabled.
|
||||
*/
|
||||
static void imx_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
|
||||
if ( break_state != 0 )
|
||||
UCR1((u32)sport->port.membase) |= UCR1_SNDBRK;
|
||||
else
|
||||
UCR1((u32)sport->port.membase) &= ~UCR1_SNDBRK;
|
||||
|
||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||
}
|
||||
|
||||
#define TXTL 2 /* reset default */
|
||||
#define RXTL 1 /* reset default */
|
||||
|
||||
static int imx_startup(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
int retval;
|
||||
unsigned int val;
|
||||
unsigned long flags;
|
||||
|
||||
/* set receiver / transmitter trigger level. We assume
|
||||
* that RFDIV has been set by the arch setup or by the bootloader.
|
||||
*/
|
||||
val = (UFCR((u32)sport->port.membase) & UFCR_RFDIV) | TXTL<<10 | RXTL;
|
||||
UFCR((u32)sport->port.membase) = val;
|
||||
|
||||
/* disable the DREN bit (Data Ready interrupt enable) before
|
||||
* requesting IRQs
|
||||
*/
|
||||
UCR4((u32)sport->port.membase) &= ~UCR4_DREN;
|
||||
|
||||
/*
|
||||
* Allocate the IRQ
|
||||
*/
|
||||
retval = request_irq(sport->rxirq, imx_rxint, 0,
|
||||
DRIVER_NAME, sport);
|
||||
if (retval) goto error_out2;
|
||||
|
||||
retval = request_irq(sport->txirq, imx_txint, 0,
|
||||
"imx-uart", sport);
|
||||
if (retval) goto error_out1;
|
||||
|
||||
/*
|
||||
* Finally, clear and enable interrupts
|
||||
*/
|
||||
|
||||
UCR1((u32)sport->port.membase) |=
|
||||
(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_UARTEN);
|
||||
|
||||
UCR2((u32)sport->port.membase) |= (UCR2_RXEN | UCR2_TXEN);
|
||||
/*
|
||||
* Enable modem status interrupts
|
||||
*/
|
||||
spin_lock_irqsave(&sport->port.lock,flags);
|
||||
imx_enable_ms(&sport->port);
|
||||
spin_unlock_irqrestore(&sport->port.lock,flags);
|
||||
|
||||
return 0;
|
||||
|
||||
error_out1:
|
||||
free_irq(sport->rxirq, sport);
|
||||
error_out2:
|
||||
free_irq(sport->txirq, sport);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void imx_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
|
||||
/*
|
||||
* Stop our timer.
|
||||
*/
|
||||
del_timer_sync(&sport->timer);
|
||||
|
||||
/*
|
||||
* Free the interrupts
|
||||
*/
|
||||
free_irq(sport->txirq, sport);
|
||||
free_irq(sport->rxirq, sport);
|
||||
|
||||
/*
|
||||
* Disable all interrupts, port and break condition.
|
||||
*/
|
||||
|
||||
UCR1((u32)sport->port.membase) &=
|
||||
~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_UARTEN);
|
||||
}
|
||||
|
||||
static void
|
||||
imx_set_termios(struct uart_port *port, struct termios *termios,
|
||||
struct termios *old)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
unsigned long flags;
|
||||
unsigned int ucr2, old_ucr1, old_txrxen, baud, quot;
|
||||
unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
|
||||
|
||||
/*
|
||||
* If we don't support modem control lines, don't allow
|
||||
* these to be set.
|
||||
*/
|
||||
if (0) {
|
||||
termios->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR);
|
||||
termios->c_cflag |= CLOCAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* We only support CS7 and CS8.
|
||||
*/
|
||||
while ((termios->c_cflag & CSIZE) != CS7 &&
|
||||
(termios->c_cflag & CSIZE) != CS8) {
|
||||
termios->c_cflag &= ~CSIZE;
|
||||
termios->c_cflag |= old_csize;
|
||||
old_csize = CS8;
|
||||
}
|
||||
|
||||
if ((termios->c_cflag & CSIZE) == CS8)
|
||||
ucr2 = UCR2_WS | UCR2_SRST | UCR2_IRTS;
|
||||
else
|
||||
ucr2 = UCR2_SRST | UCR2_IRTS;
|
||||
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
ucr2 |= UCR2_STPB;
|
||||
if (termios->c_cflag & PARENB) {
|
||||
ucr2 |= UCR2_PREN;
|
||||
if (!(termios->c_cflag & PARODD))
|
||||
ucr2 |= UCR2_PROE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ask the core to calculate the divisor for us.
|
||||
*/
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
|
||||
quot = uart_get_divisor(port, baud);
|
||||
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
|
||||
sport->port.read_status_mask = 0;
|
||||
if (termios->c_iflag & INPCK)
|
||||
sport->port.read_status_mask |= (URXD_FRMERR | URXD_PRERR);
|
||||
if (termios->c_iflag & (BRKINT | PARMRK))
|
||||
sport->port.read_status_mask |= URXD_BRK;
|
||||
|
||||
/*
|
||||
* Characters to ignore
|
||||
*/
|
||||
sport->port.ignore_status_mask = 0;
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
sport->port.ignore_status_mask |= URXD_PRERR;
|
||||
if (termios->c_iflag & IGNBRK) {
|
||||
sport->port.ignore_status_mask |= URXD_BRK;
|
||||
/*
|
||||
* If we're ignoring parity and break indicators,
|
||||
* ignore overruns too (for real raw support).
|
||||
*/
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
sport->port.ignore_status_mask |= URXD_OVRRUN;
|
||||
}
|
||||
|
||||
del_timer_sync(&sport->timer);
|
||||
|
||||
/*
|
||||
* Update the per-port timeout.
|
||||
*/
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
/*
|
||||
* disable interrupts and drain transmitter
|
||||
*/
|
||||
old_ucr1 = UCR1((u32)sport->port.membase);
|
||||
UCR1((u32)sport->port.membase) &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN);
|
||||
|
||||
while ( !(USR2((u32)sport->port.membase) & USR2_TXDC))
|
||||
barrier();
|
||||
|
||||
/* then, disable everything */
|
||||
old_txrxen = UCR2((u32)sport->port.membase) & ( UCR2_TXEN | UCR2_RXEN );
|
||||
UCR2((u32)sport->port.membase) &= ~( UCR2_TXEN | UCR2_RXEN);
|
||||
|
||||
/* set the parity, stop bits and data size */
|
||||
UCR2((u32)sport->port.membase) = ucr2;
|
||||
|
||||
/* set the baud rate. We assume uartclk = 16 MHz
|
||||
*
|
||||
* baud * 16 UBIR - 1
|
||||
* --------- = --------
|
||||
* uartclk UBMR - 1
|
||||
*/
|
||||
UBIR((u32)sport->port.membase) = (baud / 100) - 1;
|
||||
UBMR((u32)sport->port.membase) = 10000 - 1;
|
||||
|
||||
UCR1((u32)sport->port.membase) = old_ucr1;
|
||||
UCR2((u32)sport->port.membase) |= old_txrxen;
|
||||
|
||||
if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
|
||||
imx_enable_ms(&sport->port);
|
||||
|
||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||
}
|
||||
|
||||
static const char *imx_type(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
|
||||
return sport->port.type == PORT_IMX ? "IMX" : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the memory region(s) being used by 'port'.
|
||||
*/
|
||||
static void imx_release_port(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
|
||||
release_mem_region(sport->port.mapbase, UART_PORT_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Request the memory region(s) being used by 'port'.
|
||||
*/
|
||||
static int imx_request_port(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
|
||||
return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
|
||||
"imx-uart") != NULL ? 0 : -EBUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure/autoconfigure the port.
|
||||
*/
|
||||
static void imx_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
|
||||
if (flags & UART_CONFIG_TYPE &&
|
||||
imx_request_port(&sport->port) == 0)
|
||||
sport->port.type = PORT_IMX;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify the new serial_struct (for TIOCSSERIAL).
|
||||
* The only change we allow are to the flags and type, and
|
||||
* even then only between PORT_IMX and PORT_UNKNOWN
|
||||
*/
|
||||
static int
|
||||
imx_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
int ret = 0;
|
||||
|
||||
if (ser->type != PORT_UNKNOWN && ser->type != PORT_IMX)
|
||||
ret = -EINVAL;
|
||||
if (sport->port.irq != ser->irq)
|
||||
ret = -EINVAL;
|
||||
if (ser->io_type != UPIO_MEM)
|
||||
ret = -EINVAL;
|
||||
if (sport->port.uartclk / 16 != ser->baud_base)
|
||||
ret = -EINVAL;
|
||||
if ((void *)sport->port.mapbase != ser->iomem_base)
|
||||
ret = -EINVAL;
|
||||
if (sport->port.iobase != ser->port)
|
||||
ret = -EINVAL;
|
||||
if (ser->hub6 != 0)
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct uart_ops imx_pops = {
|
||||
.tx_empty = imx_tx_empty,
|
||||
.set_mctrl = imx_set_mctrl,
|
||||
.get_mctrl = imx_get_mctrl,
|
||||
.stop_tx = imx_stop_tx,
|
||||
.start_tx = imx_start_tx,
|
||||
.stop_rx = imx_stop_rx,
|
||||
.enable_ms = imx_enable_ms,
|
||||
.break_ctl = imx_break_ctl,
|
||||
.startup = imx_startup,
|
||||
.shutdown = imx_shutdown,
|
||||
.set_termios = imx_set_termios,
|
||||
.type = imx_type,
|
||||
.release_port = imx_release_port,
|
||||
.request_port = imx_request_port,
|
||||
.config_port = imx_config_port,
|
||||
.verify_port = imx_verify_port,
|
||||
};
|
||||
|
||||
static struct imx_port imx_ports[] = {
|
||||
{
|
||||
.txirq = UART1_MINT_TX,
|
||||
.rxirq = UART1_MINT_RX,
|
||||
.port = {
|
||||
.type = PORT_IMX,
|
||||
.iotype = SERIAL_IO_MEM,
|
||||
.membase = (void *)IMX_UART1_BASE,
|
||||
.mapbase = IMX_UART1_BASE, /* FIXME */
|
||||
.irq = UART1_MINT_RX,
|
||||
.uartclk = 16000000,
|
||||
.fifosize = 8,
|
||||
.flags = ASYNC_BOOT_AUTOCONF,
|
||||
.ops = &imx_pops,
|
||||
.line = 0,
|
||||
},
|
||||
}, {
|
||||
.txirq = UART2_MINT_TX,
|
||||
.rxirq = UART2_MINT_RX,
|
||||
.port = {
|
||||
.type = PORT_IMX,
|
||||
.iotype = SERIAL_IO_MEM,
|
||||
.membase = (void *)IMX_UART2_BASE,
|
||||
.mapbase = IMX_UART2_BASE, /* FIXME */
|
||||
.irq = UART2_MINT_RX,
|
||||
.uartclk = 16000000,
|
||||
.fifosize = 8,
|
||||
.flags = ASYNC_BOOT_AUTOCONF,
|
||||
.ops = &imx_pops,
|
||||
.line = 1,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Setup the IMX serial ports.
|
||||
* Note also that we support "console=ttySMXx" where "x" is either 0 or 1.
|
||||
* Which serial port this ends up being depends on the machine you're
|
||||
* running this kernel on. I'm not convinced that this is a good idea,
|
||||
* but that's the way it traditionally works.
|
||||
*
|
||||
*/
|
||||
static void __init imx_init_ports(void)
|
||||
{
|
||||
static int first = 1;
|
||||
int i;
|
||||
|
||||
if (!first)
|
||||
return;
|
||||
first = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(imx_ports); i++) {
|
||||
init_timer(&imx_ports[i].timer);
|
||||
imx_ports[i].timer.function = imx_timeout;
|
||||
imx_ports[i].timer.data = (unsigned long)&imx_ports[i];
|
||||
}
|
||||
|
||||
imx_gpio_mode(PC9_PF_UART1_CTS);
|
||||
imx_gpio_mode(PC10_PF_UART1_RTS);
|
||||
imx_gpio_mode(PC11_PF_UART1_TXD);
|
||||
imx_gpio_mode(PC12_PF_UART1_RXD);
|
||||
imx_gpio_mode(PB28_PF_UART2_CTS);
|
||||
imx_gpio_mode(PB29_PF_UART2_RTS);
|
||||
|
||||
imx_gpio_mode(PB30_PF_UART2_TXD);
|
||||
imx_gpio_mode(PB31_PF_UART2_RXD);
|
||||
|
||||
#if 0 /* We don't need these, on the mx1 the _modem_ side of the uart
|
||||
* is implemented.
|
||||
*/
|
||||
imx_gpio_mode(PD7_AF_UART2_DTR);
|
||||
imx_gpio_mode(PD8_AF_UART2_DCD);
|
||||
imx_gpio_mode(PD9_AF_UART2_RI);
|
||||
imx_gpio_mode(PD10_AF_UART2_DSR);
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_IMX_CONSOLE
|
||||
|
||||
/*
|
||||
* Interrupts are disabled on entering
|
||||
*/
|
||||
static void
|
||||
imx_console_write(struct console *co, const char *s, unsigned int count)
|
||||
{
|
||||
struct imx_port *sport = &imx_ports[co->index];
|
||||
unsigned int old_ucr1, old_ucr2, i;
|
||||
|
||||
/*
|
||||
* First, save UCR1/2 and then disable interrupts
|
||||
*/
|
||||
old_ucr1 = UCR1((u32)sport->port.membase);
|
||||
old_ucr2 = UCR2((u32)sport->port.membase);
|
||||
|
||||
UCR1((u32)sport->port.membase) =
|
||||
(old_ucr1 | UCR1_UARTCLKEN | UCR1_UARTEN)
|
||||
& ~(UCR1_TXMPTYEN | UCR1_RRDYEN);
|
||||
UCR2((u32)sport->port.membase) = old_ucr2 | UCR2_TXEN;
|
||||
|
||||
/*
|
||||
* Now, do each character
|
||||
*/
|
||||
for (i = 0; i < count; i++) {
|
||||
|
||||
while ((UTS((u32)sport->port.membase) & UTS_TXFULL))
|
||||
barrier();
|
||||
|
||||
URTX0((u32)sport->port.membase) = s[i];
|
||||
|
||||
if (s[i] == '\n') {
|
||||
while ((UTS((u32)sport->port.membase) & UTS_TXFULL))
|
||||
barrier();
|
||||
URTX0((u32)sport->port.membase) = '\r';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, wait for transmitter to become empty
|
||||
* and restore UCR1/2
|
||||
*/
|
||||
while (!(USR2((u32)sport->port.membase) & USR2_TXDC));
|
||||
|
||||
UCR1((u32)sport->port.membase) = old_ucr1;
|
||||
UCR2((u32)sport->port.membase) = old_ucr2;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the port was already initialised (eg, by a boot loader),
|
||||
* try to determine the current setup.
|
||||
*/
|
||||
static void __init
|
||||
imx_console_get_options(struct imx_port *sport, int *baud,
|
||||
int *parity, int *bits)
|
||||
{
|
||||
if ( UCR1((u32)sport->port.membase) | UCR1_UARTEN ) {
|
||||
/* ok, the port was enabled */
|
||||
unsigned int ucr2, ubir,ubmr, uartclk;
|
||||
|
||||
ucr2 = UCR2((u32)sport->port.membase);
|
||||
|
||||
*parity = 'n';
|
||||
if (ucr2 & UCR2_PREN) {
|
||||
if (ucr2 & UCR2_PROE)
|
||||
*parity = 'o';
|
||||
else
|
||||
*parity = 'e';
|
||||
}
|
||||
|
||||
if (ucr2 & UCR2_WS)
|
||||
*bits = 8;
|
||||
else
|
||||
*bits = 7;
|
||||
|
||||
ubir = UBIR((u32)sport->port.membase) & 0xffff;
|
||||
ubmr = UBMR((u32)sport->port.membase) & 0xffff;
|
||||
uartclk = sport->port.uartclk;
|
||||
|
||||
*baud = ((uartclk/16) * (ubir + 1)) / (ubmr + 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init
|
||||
imx_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct imx_port *sport;
|
||||
int baud = 9600;
|
||||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
|
||||
/*
|
||||
* Check whether an invalid uart number has been specified, and
|
||||
* if so, search for the first available port that does have
|
||||
* console support.
|
||||
*/
|
||||
if (co->index == -1 || co->index >= ARRAY_SIZE(imx_ports))
|
||||
co->index = 0;
|
||||
sport = &imx_ports[co->index];
|
||||
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
else
|
||||
imx_console_get_options(sport, &baud, &parity, &bits);
|
||||
|
||||
return uart_set_options(&sport->port, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
extern struct uart_driver imx_reg;
|
||||
static struct console imx_console = {
|
||||
.name = "ttySMX",
|
||||
.write = imx_console_write,
|
||||
.device = uart_console_device,
|
||||
.setup = imx_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
.data = &imx_reg,
|
||||
};
|
||||
|
||||
static int __init imx_rs_console_init(void)
|
||||
{
|
||||
imx_init_ports();
|
||||
register_console(&imx_console);
|
||||
return 0;
|
||||
}
|
||||
console_initcall(imx_rs_console_init);
|
||||
|
||||
#define IMX_CONSOLE &imx_console
|
||||
#else
|
||||
#define IMX_CONSOLE NULL
|
||||
#endif
|
||||
|
||||
static struct uart_driver imx_reg = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = DRIVER_NAME,
|
||||
.dev_name = "ttySMX",
|
||||
.devfs_name = "ttsmx/",
|
||||
.major = SERIAL_IMX_MAJOR,
|
||||
.minor = MINOR_START,
|
||||
.nr = ARRAY_SIZE(imx_ports),
|
||||
.cons = IMX_CONSOLE,
|
||||
};
|
||||
|
||||
static int serial_imx_suspend(struct device *_dev, u32 state, u32 level)
|
||||
{
|
||||
struct imx_port *sport = dev_get_drvdata(_dev);
|
||||
|
||||
if (sport && level == SUSPEND_DISABLE)
|
||||
uart_suspend_port(&imx_reg, &sport->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serial_imx_resume(struct device *_dev, u32 level)
|
||||
{
|
||||
struct imx_port *sport = dev_get_drvdata(_dev);
|
||||
|
||||
if (sport && level == RESUME_ENABLE)
|
||||
uart_resume_port(&imx_reg, &sport->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serial_imx_probe(struct device *_dev)
|
||||
{
|
||||
struct platform_device *dev = to_platform_device(_dev);
|
||||
|
||||
imx_ports[dev->id].port.dev = _dev;
|
||||
uart_add_one_port(&imx_reg, &imx_ports[dev->id].port);
|
||||
dev_set_drvdata(_dev, &imx_ports[dev->id]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serial_imx_remove(struct device *_dev)
|
||||
{
|
||||
struct imx_port *sport = dev_get_drvdata(_dev);
|
||||
|
||||
dev_set_drvdata(_dev, NULL);
|
||||
|
||||
if (sport)
|
||||
uart_remove_one_port(&imx_reg, &sport->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct device_driver serial_imx_driver = {
|
||||
.name = "imx-uart",
|
||||
.bus = &platform_bus_type,
|
||||
.probe = serial_imx_probe,
|
||||
.remove = serial_imx_remove,
|
||||
|
||||
.suspend = serial_imx_suspend,
|
||||
.resume = serial_imx_resume,
|
||||
};
|
||||
|
||||
static int __init imx_serial_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printk(KERN_INFO "Serial: IMX driver\n");
|
||||
|
||||
imx_init_ports();
|
||||
|
||||
ret = uart_register_driver(&imx_reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = driver_register(&serial_imx_driver);
|
||||
if (ret != 0)
|
||||
uart_unregister_driver(&imx_reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit imx_serial_exit(void)
|
||||
{
|
||||
uart_unregister_driver(&imx_reg);
|
||||
}
|
||||
|
||||
module_init(imx_serial_init);
|
||||
module_exit(imx_serial_exit);
|
||||
|
||||
MODULE_AUTHOR("Sascha Hauer");
|
||||
MODULE_DESCRIPTION("IMX generic serial port driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
1307
extra/linux-2.6.10/drivers/serial/ip22zilog.c
Normal file
1307
extra/linux-2.6.10/drivers/serial/ip22zilog.c
Normal file
File diff suppressed because it is too large
Load Diff
281
extra/linux-2.6.10/drivers/serial/ip22zilog.h
Normal file
281
extra/linux-2.6.10/drivers/serial/ip22zilog.h
Normal file
@@ -0,0 +1,281 @@
|
||||
#ifndef _IP22_ZILOG_H
|
||||
#define _IP22_ZILOG_H
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
struct zilog_channel {
|
||||
#ifdef __BIG_ENDIAN
|
||||
volatile unsigned char unused0[3];
|
||||
volatile unsigned char control;
|
||||
volatile unsigned char unused1[3];
|
||||
volatile unsigned char data;
|
||||
#else /* __LITTLE_ENDIAN */
|
||||
volatile unsigned char control;
|
||||
volatile unsigned char unused0[3];
|
||||
volatile unsigned char data;
|
||||
volatile unsigned char unused1[3];
|
||||
#endif
|
||||
};
|
||||
|
||||
struct zilog_layout {
|
||||
struct zilog_channel channelB;
|
||||
struct zilog_channel channelA;
|
||||
};
|
||||
|
||||
#define NUM_ZSREGS 16
|
||||
|
||||
/* Conversion routines to/from brg time constants from/to bits
|
||||
* per second.
|
||||
*/
|
||||
#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2))
|
||||
#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2)
|
||||
|
||||
/* The Zilog register set */
|
||||
|
||||
#define FLAG 0x7e
|
||||
|
||||
/* Write Register 0 */
|
||||
#define R0 0 /* Register selects */
|
||||
#define R1 1
|
||||
#define R2 2
|
||||
#define R3 3
|
||||
#define R4 4
|
||||
#define R5 5
|
||||
#define R6 6
|
||||
#define R7 7
|
||||
#define R8 8
|
||||
#define R9 9
|
||||
#define R10 10
|
||||
#define R11 11
|
||||
#define R12 12
|
||||
#define R13 13
|
||||
#define R14 14
|
||||
#define R15 15
|
||||
|
||||
#define NULLCODE 0 /* Null Code */
|
||||
#define POINT_HIGH 0x8 /* Select upper half of registers */
|
||||
#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */
|
||||
#define SEND_ABORT 0x18 /* HDLC Abort */
|
||||
#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */
|
||||
#define RES_Tx_P 0x28 /* Reset TxINT Pending */
|
||||
#define ERR_RES 0x30 /* Error Reset */
|
||||
#define RES_H_IUS 0x38 /* Reset highest IUS */
|
||||
|
||||
#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */
|
||||
#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */
|
||||
#define RES_EOM_L 0xC0 /* Reset EOM latch */
|
||||
|
||||
/* Write Register 1 */
|
||||
|
||||
#define EXT_INT_ENAB 0x1 /* Ext Int Enable */
|
||||
#define TxINT_ENAB 0x2 /* Tx Int Enable */
|
||||
#define PAR_SPEC 0x4 /* Parity is special condition */
|
||||
|
||||
#define RxINT_DISAB 0 /* Rx Int Disable */
|
||||
#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */
|
||||
#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */
|
||||
#define INT_ERR_Rx 0x18 /* Int on error only */
|
||||
#define RxINT_MASK 0x18
|
||||
|
||||
#define WT_RDY_RT 0x20 /* Wait/Ready on R/T */
|
||||
#define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */
|
||||
#define WT_RDY_ENAB 0x80 /* Wait/Ready Enable */
|
||||
|
||||
/* Write Register #2 (Interrupt Vector) */
|
||||
|
||||
/* Write Register 3 */
|
||||
|
||||
#define RxENAB 0x1 /* Rx Enable */
|
||||
#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */
|
||||
#define ADD_SM 0x4 /* Address Search Mode (SDLC) */
|
||||
#define RxCRC_ENAB 0x8 /* Rx CRC Enable */
|
||||
#define ENT_HM 0x10 /* Enter Hunt Mode */
|
||||
#define AUTO_ENAB 0x20 /* Auto Enables */
|
||||
#define Rx5 0x0 /* Rx 5 Bits/Character */
|
||||
#define Rx7 0x40 /* Rx 7 Bits/Character */
|
||||
#define Rx6 0x80 /* Rx 6 Bits/Character */
|
||||
#define Rx8 0xc0 /* Rx 8 Bits/Character */
|
||||
#define RxN_MASK 0xc0
|
||||
|
||||
/* Write Register 4 */
|
||||
|
||||
#define PAR_ENAB 0x1 /* Parity Enable */
|
||||
#define PAR_EVEN 0x2 /* Parity Even/Odd* */
|
||||
|
||||
#define SYNC_ENAB 0 /* Sync Modes Enable */
|
||||
#define SB1 0x4 /* 1 stop bit/char */
|
||||
#define SB15 0x8 /* 1.5 stop bits/char */
|
||||
#define SB2 0xc /* 2 stop bits/char */
|
||||
|
||||
#define MONSYNC 0 /* 8 Bit Sync character */
|
||||
#define BISYNC 0x10 /* 16 bit sync character */
|
||||
#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */
|
||||
#define EXTSYNC 0x30 /* External Sync Mode */
|
||||
|
||||
#define X1CLK 0x0 /* x1 clock mode */
|
||||
#define X16CLK 0x40 /* x16 clock mode */
|
||||
#define X32CLK 0x80 /* x32 clock mode */
|
||||
#define X64CLK 0xC0 /* x64 clock mode */
|
||||
#define XCLK_MASK 0xC0
|
||||
|
||||
/* Write Register 5 */
|
||||
|
||||
#define TxCRC_ENAB 0x1 /* Tx CRC Enable */
|
||||
#define RTS 0x2 /* RTS */
|
||||
#define SDLC_CRC 0x4 /* SDLC/CRC-16 */
|
||||
#define TxENAB 0x8 /* Tx Enable */
|
||||
#define SND_BRK 0x10 /* Send Break */
|
||||
#define Tx5 0x0 /* Tx 5 bits (or less)/character */
|
||||
#define Tx7 0x20 /* Tx 7 bits/character */
|
||||
#define Tx6 0x40 /* Tx 6 bits/character */
|
||||
#define Tx8 0x60 /* Tx 8 bits/character */
|
||||
#define TxN_MASK 0x60
|
||||
#define DTR 0x80 /* DTR */
|
||||
|
||||
/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
|
||||
|
||||
/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
|
||||
|
||||
/* Write Register 8 (transmit buffer) */
|
||||
|
||||
/* Write Register 9 (Master interrupt control) */
|
||||
#define VIS 1 /* Vector Includes Status */
|
||||
#define NV 2 /* No Vector */
|
||||
#define DLC 4 /* Disable Lower Chain */
|
||||
#define MIE 8 /* Master Interrupt Enable */
|
||||
#define STATHI 0x10 /* Status high */
|
||||
#define NORESET 0 /* No reset on write to R9 */
|
||||
#define CHRB 0x40 /* Reset channel B */
|
||||
#define CHRA 0x80 /* Reset channel A */
|
||||
#define FHWRES 0xc0 /* Force hardware reset */
|
||||
|
||||
/* Write Register 10 (misc control bits) */
|
||||
#define BIT6 1 /* 6 bit/8bit sync */
|
||||
#define LOOPMODE 2 /* SDLC Loop mode */
|
||||
#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */
|
||||
#define MARKIDLE 8 /* Mark/flag on idle */
|
||||
#define GAOP 0x10 /* Go active on poll */
|
||||
#define NRZ 0 /* NRZ mode */
|
||||
#define NRZI 0x20 /* NRZI mode */
|
||||
#define FM1 0x40 /* FM1 (transition = 1) */
|
||||
#define FM0 0x60 /* FM0 (transition = 0) */
|
||||
#define CRCPS 0x80 /* CRC Preset I/O */
|
||||
|
||||
/* Write Register 11 (Clock Mode control) */
|
||||
#define TRxCXT 0 /* TRxC = Xtal output */
|
||||
#define TRxCTC 1 /* TRxC = Transmit clock */
|
||||
#define TRxCBR 2 /* TRxC = BR Generator Output */
|
||||
#define TRxCDP 3 /* TRxC = DPLL output */
|
||||
#define TRxCOI 4 /* TRxC O/I */
|
||||
#define TCRTxCP 0 /* Transmit clock = RTxC pin */
|
||||
#define TCTRxCP 8 /* Transmit clock = TRxC pin */
|
||||
#define TCBR 0x10 /* Transmit clock = BR Generator output */
|
||||
#define TCDPLL 0x18 /* Transmit clock = DPLL output */
|
||||
#define RCRTxCP 0 /* Receive clock = RTxC pin */
|
||||
#define RCTRxCP 0x20 /* Receive clock = TRxC pin */
|
||||
#define RCBR 0x40 /* Receive clock = BR Generator output */
|
||||
#define RCDPLL 0x60 /* Receive clock = DPLL output */
|
||||
#define RTxCX 0x80 /* RTxC Xtal/No Xtal */
|
||||
|
||||
/* Write Register 12 (lower byte of baud rate generator time constant) */
|
||||
|
||||
/* Write Register 13 (upper byte of baud rate generator time constant) */
|
||||
|
||||
/* Write Register 14 (Misc control bits) */
|
||||
#define BRENAB 1 /* Baud rate generator enable */
|
||||
#define BRSRC 2 /* Baud rate generator source */
|
||||
#define DTRREQ 4 /* DTR/Request function */
|
||||
#define AUTOECHO 8 /* Auto Echo */
|
||||
#define LOOPBAK 0x10 /* Local loopback */
|
||||
#define SEARCH 0x20 /* Enter search mode */
|
||||
#define RMC 0x40 /* Reset missing clock */
|
||||
#define DISDPLL 0x60 /* Disable DPLL */
|
||||
#define SSBR 0x80 /* Set DPLL source = BR generator */
|
||||
#define SSRTxC 0xa0 /* Set DPLL source = RTxC */
|
||||
#define SFMM 0xc0 /* Set FM mode */
|
||||
#define SNRZI 0xe0 /* Set NRZI mode */
|
||||
|
||||
/* Write Register 15 (external/status interrupt control) */
|
||||
#define ZCIE 2 /* Zero count IE */
|
||||
#define DCDIE 8 /* DCD IE */
|
||||
#define SYNCIE 0x10 /* Sync/hunt IE */
|
||||
#define CTSIE 0x20 /* CTS IE */
|
||||
#define TxUIE 0x40 /* Tx Underrun/EOM IE */
|
||||
#define BRKIE 0x80 /* Break/Abort IE */
|
||||
|
||||
|
||||
/* Read Register 0 */
|
||||
#define Rx_CH_AV 0x1 /* Rx Character Available */
|
||||
#define ZCOUNT 0x2 /* Zero count */
|
||||
#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */
|
||||
#define DCD 0x8 /* DCD */
|
||||
#define SYNC 0x10 /* Sync/hunt */
|
||||
#define CTS 0x20 /* CTS */
|
||||
#define TxEOM 0x40 /* Tx underrun */
|
||||
#define BRK_ABRT 0x80 /* Break/Abort */
|
||||
|
||||
/* Read Register 1 */
|
||||
#define ALL_SNT 0x1 /* All sent */
|
||||
/* Residue Data for 8 Rx bits/char programmed */
|
||||
#define RES3 0x8 /* 0/3 */
|
||||
#define RES4 0x4 /* 0/4 */
|
||||
#define RES5 0xc /* 0/5 */
|
||||
#define RES6 0x2 /* 0/6 */
|
||||
#define RES7 0xa /* 0/7 */
|
||||
#define RES8 0x6 /* 0/8 */
|
||||
#define RES18 0xe /* 1/8 */
|
||||
#define RES28 0x0 /* 2/8 */
|
||||
/* Special Rx Condition Interrupts */
|
||||
#define PAR_ERR 0x10 /* Parity error */
|
||||
#define Rx_OVR 0x20 /* Rx Overrun Error */
|
||||
#define CRC_ERR 0x40 /* CRC/Framing Error */
|
||||
#define END_FR 0x80 /* End of Frame (SDLC) */
|
||||
|
||||
/* Read Register 2 (channel b only) - Interrupt vector */
|
||||
#define CHB_Tx_EMPTY 0x00
|
||||
#define CHB_EXT_STAT 0x02
|
||||
#define CHB_Rx_AVAIL 0x04
|
||||
#define CHB_SPECIAL 0x06
|
||||
#define CHA_Tx_EMPTY 0x08
|
||||
#define CHA_EXT_STAT 0x0a
|
||||
#define CHA_Rx_AVAIL 0x0c
|
||||
#define CHA_SPECIAL 0x0e
|
||||
#define STATUS_MASK 0x0e
|
||||
|
||||
/* Read Register 3 (interrupt pending register) ch a only */
|
||||
#define CHBEXT 0x1 /* Channel B Ext/Stat IP */
|
||||
#define CHBTxIP 0x2 /* Channel B Tx IP */
|
||||
#define CHBRxIP 0x4 /* Channel B Rx IP */
|
||||
#define CHAEXT 0x8 /* Channel A Ext/Stat IP */
|
||||
#define CHATxIP 0x10 /* Channel A Tx IP */
|
||||
#define CHARxIP 0x20 /* Channel A Rx IP */
|
||||
|
||||
/* Read Register 8 (receive data register) */
|
||||
|
||||
/* Read Register 10 (misc status bits) */
|
||||
#define ONLOOP 2 /* On loop */
|
||||
#define LOOPSEND 0x10 /* Loop sending */
|
||||
#define CLK2MIS 0x40 /* Two clocks missing */
|
||||
#define CLK1MIS 0x80 /* One clock missing */
|
||||
|
||||
/* Read Register 12 (lower byte of baud rate generator constant) */
|
||||
|
||||
/* Read Register 13 (upper byte of baud rate generator constant) */
|
||||
|
||||
/* Read Register 15 (value of WR 15) */
|
||||
|
||||
/* Misc macros */
|
||||
#define ZS_CLEARERR(channel) do { writeb(ERR_RES, &channel->control); \
|
||||
udelay(5); } while(0)
|
||||
|
||||
#define ZS_CLEARSTAT(channel) do { writeb(RES_EXT_INT, &channel->control); \
|
||||
udelay(5); } while(0)
|
||||
|
||||
#define ZS_CLEARFIFO(channel) do { readb(&channel->data); \
|
||||
udelay(2); \
|
||||
readb(&channel->data); \
|
||||
udelay(2); \
|
||||
readb(&channel->data); \
|
||||
udelay(2); } while(0)
|
||||
|
||||
#endif /* _IP22_ZILOG_H */
|
||||
1373
extra/linux-2.6.10/drivers/serial/m32r_sio.c
Normal file
1373
extra/linux-2.6.10/drivers/serial/m32r_sio.c
Normal file
File diff suppressed because it is too large
Load Diff
56
extra/linux-2.6.10/drivers/serial/m32r_sio.h
Normal file
56
extra/linux-2.6.10/drivers/serial/m32r_sio.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* m32r_sio.h
|
||||
*
|
||||
* Driver for M32R serial ports
|
||||
*
|
||||
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
|
||||
* Based on drivers/serial/8250.h.
|
||||
*
|
||||
* Copyright (C) 2001 Russell King.
|
||||
* Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
struct m32r_sio_probe {
|
||||
struct module *owner;
|
||||
int (*pci_init_one)(struct pci_dev *dev);
|
||||
void (*pci_remove_one)(struct pci_dev *dev);
|
||||
void (*pnp_init)(void);
|
||||
};
|
||||
|
||||
int m32r_sio_register_probe(struct m32r_sio_probe *probe);
|
||||
void m32r_sio_unregister_probe(struct m32r_sio_probe *probe);
|
||||
void m32r_sio_get_irq_map(unsigned int *map);
|
||||
void m32r_sio_suspend_port(int line);
|
||||
void m32r_sio_resume_port(int line);
|
||||
|
||||
struct old_serial_port {
|
||||
unsigned int uart;
|
||||
unsigned int baud_base;
|
||||
unsigned int port;
|
||||
unsigned int irq;
|
||||
unsigned int flags;
|
||||
unsigned char hub6;
|
||||
unsigned char io_type;
|
||||
unsigned char *iomem_base;
|
||||
unsigned short iomem_reg_shift;
|
||||
};
|
||||
|
||||
#define _INLINE_ inline
|
||||
|
||||
#define PROBE_RSA (1 << 0)
|
||||
#define PROBE_ANY (~0)
|
||||
|
||||
#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
|
||||
|
||||
#ifdef CONFIG_SERIAL_SIO_SHARE_IRQ
|
||||
#define M32R_SIO_SHARE_IRQS 1
|
||||
#else
|
||||
#define M32R_SIO_SHARE_IRQS 0
|
||||
#endif
|
||||
343
extra/linux-2.6.10/drivers/serial/m32r_sio_reg.h
Normal file
343
extra/linux-2.6.10/drivers/serial/m32r_sio_reg.h
Normal file
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* m32r_sio_reg.h
|
||||
*
|
||||
* Copyright (C) 1992, 1994 by Theodore Ts'o.
|
||||
* Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
|
||||
*
|
||||
* Redistribution of this file is permitted under the terms of the GNU
|
||||
* Public License (GPL)
|
||||
*
|
||||
* These are the UART port assignments, expressed as offsets from the base
|
||||
* register. These assignments should hold for any serial port based on
|
||||
* a 8250, 16450, or 16550(A).
|
||||
*/
|
||||
|
||||
#ifndef _M32R_SIO_REG_H
|
||||
#define _M32R_SIO_REG_H
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
#ifdef CONFIG_SERIAL_M32R_PLDSIO
|
||||
|
||||
#define SIOCR 0x000
|
||||
#define SIOMOD0 0x002
|
||||
#define SIOMOD1 0x004
|
||||
#define SIOSTS 0x006
|
||||
#define SIOTRCR 0x008
|
||||
#define SIOBAUR 0x00a
|
||||
// #define SIORBAUR 0x018
|
||||
#define SIOTXB 0x00c
|
||||
#define SIORXB 0x00e
|
||||
|
||||
#define UART_RX ((unsigned long) PLD_ESIO0RXB)
|
||||
/* In: Receive buffer (DLAB=0) */
|
||||
#define UART_TX ((unsigned long) PLD_ESIO0TXB)
|
||||
/* Out: Transmit buffer (DLAB=0) */
|
||||
#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */
|
||||
#define UART_TRG 0 /* (LCR=BF) FCTR bit 7 selects Rx or Tx
|
||||
* In: Fifo count
|
||||
* Out: Fifo custom trigger levels
|
||||
* XR16C85x only */
|
||||
|
||||
#define UART_DLM 0 /* Out: Divisor Latch High (DLAB=1) */
|
||||
#define UART_IER ((unsigned long) PLD_ESIO0INTCR)
|
||||
/* Out: Interrupt Enable Register */
|
||||
#define UART_FCTR 0 /* (LCR=BF) Feature Control Register
|
||||
* XR16C85x only */
|
||||
|
||||
#define UART_IIR 0 /* In: Interrupt ID Register */
|
||||
#define UART_FCR 0 /* Out: FIFO Control Register */
|
||||
#define UART_EFR 0 /* I/O: Extended Features Register */
|
||||
/* (DLAB=1, 16C660 only) */
|
||||
|
||||
#define UART_LCR 0 /* Out: Line Control Register */
|
||||
#define UART_MCR 0 /* Out: Modem Control Register */
|
||||
#define UART_LSR ((unsigned long) PLD_ESIO0STS)
|
||||
/* In: Line Status Register */
|
||||
#define UART_MSR 0 /* In: Modem Status Register */
|
||||
#define UART_SCR 0 /* I/O: Scratch Register */
|
||||
#define UART_EMSR 0 /* (LCR=BF) Extended Mode Select Register
|
||||
* FCTR bit 6 selects SCR or EMSR
|
||||
* XR16c85x only */
|
||||
|
||||
#else /* not CONFIG_SERIAL_M32R_PLDSIO */
|
||||
|
||||
#define SIOCR 0x000
|
||||
#define SIOMOD0 0x004
|
||||
#define SIOMOD1 0x008
|
||||
#define SIOSTS 0x00c
|
||||
#define SIOTRCR 0x010
|
||||
#define SIOBAUR 0x014
|
||||
#define SIORBAUR 0x018
|
||||
#define SIOTXB 0x01c
|
||||
#define SIORXB 0x020
|
||||
|
||||
#define UART_RX M32R_SIO0_RXB_PORTL /* In: Receive buffer (DLAB=0) */
|
||||
#define UART_TX M32R_SIO0_TXB_PORTL /* Out: Transmit buffer (DLAB=0) */
|
||||
#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */
|
||||
#define UART_TRG 0 /* (LCR=BF) FCTR bit 7 selects Rx or Tx
|
||||
* In: Fifo count
|
||||
* Out: Fifo custom trigger levels
|
||||
* XR16C85x only */
|
||||
|
||||
#define UART_DLM 0 /* Out: Divisor Latch High (DLAB=1) */
|
||||
#define UART_IER M32R_SIO0_TRCR_PORTL /* Out: Interrupt Enable Register */
|
||||
#define UART_FCTR 0 /* (LCR=BF) Feature Control Register
|
||||
* XR16C85x only */
|
||||
|
||||
#define UART_IIR 0 /* In: Interrupt ID Register */
|
||||
#define UART_FCR 0 /* Out: FIFO Control Register */
|
||||
#define UART_EFR 0 /* I/O: Extended Features Register */
|
||||
/* (DLAB=1, 16C660 only) */
|
||||
|
||||
#define UART_LCR 0 /* Out: Line Control Register */
|
||||
#define UART_MCR 0 /* Out: Modem Control Register */
|
||||
#define UART_LSR M32R_SIO0_STS_PORTL /* In: Line Status Register */
|
||||
#define UART_MSR 0 /* In: Modem Status Register */
|
||||
#define UART_SCR 0 /* I/O: Scratch Register */
|
||||
#define UART_EMSR 0 /* (LCR=BF) Extended Mode Select Register
|
||||
* FCTR bit 6 selects SCR or EMSR
|
||||
* XR16c85x only */
|
||||
|
||||
#endif /* CONFIG_SERIAL_M32R_PLDSIO */
|
||||
|
||||
#define UART_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
|
||||
|
||||
/*
|
||||
* These are the definitions for the FIFO Control Register
|
||||
* (16650 only)
|
||||
*/
|
||||
#define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */
|
||||
#define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */
|
||||
#define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */
|
||||
#define UART_FCR_DMA_SELECT 0x08 /* For DMA applications */
|
||||
#define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */
|
||||
#define UART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */
|
||||
#define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */
|
||||
#define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */
|
||||
#define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */
|
||||
/* 16650 redefinitions */
|
||||
#define UART_FCR6_R_TRIGGER_8 0x00 /* Mask for receive trigger set at 1 */
|
||||
#define UART_FCR6_R_TRIGGER_16 0x40 /* Mask for receive trigger set at 4 */
|
||||
#define UART_FCR6_R_TRIGGER_24 0x80 /* Mask for receive trigger set at 8 */
|
||||
#define UART_FCR6_R_TRIGGER_28 0xC0 /* Mask for receive trigger set at 14 */
|
||||
#define UART_FCR6_T_TRIGGER_16 0x00 /* Mask for transmit trigger set at 16 */
|
||||
#define UART_FCR6_T_TRIGGER_8 0x10 /* Mask for transmit trigger set at 8 */
|
||||
#define UART_FCR6_T_TRIGGER_24 0x20 /* Mask for transmit trigger set at 24 */
|
||||
#define UART_FCR6_T_TRIGGER_30 0x30 /* Mask for transmit trigger set at 30 */
|
||||
/* TI 16750 definitions */
|
||||
#define UART_FCR7_64BYTE 0x20 /* Go into 64 byte mode */
|
||||
|
||||
/*
|
||||
* These are the definitions for the Line Control Register
|
||||
*
|
||||
* Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting
|
||||
* UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
|
||||
*/
|
||||
#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
|
||||
#define UART_LCR_SBC 0x40 /* Set break control */
|
||||
#define UART_LCR_SPAR 0x20 /* Stick parity (?) */
|
||||
#define UART_LCR_EPAR 0x10 /* Even parity select */
|
||||
#define UART_LCR_PARITY 0x08 /* Parity Enable */
|
||||
#define UART_LCR_STOP 0x04 /* Stop bits: 0=1 stop bit, 1= 2 stop bits */
|
||||
#define UART_LCR_WLEN5 0x00 /* Wordlength: 5 bits */
|
||||
#define UART_LCR_WLEN6 0x01 /* Wordlength: 6 bits */
|
||||
#define UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */
|
||||
#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */
|
||||
|
||||
/*
|
||||
* These are the definitions for the Line Status Register
|
||||
*/
|
||||
#define UART_LSR_TEMT 0x02 /* Transmitter empty */
|
||||
#define UART_LSR_THRE 0x01 /* Transmit-hold-register empty */
|
||||
#define UART_LSR_BI 0x00 /* Break interrupt indicator */
|
||||
#define UART_LSR_FE 0x80 /* Frame error indicator */
|
||||
#define UART_LSR_PE 0x40 /* Parity error indicator */
|
||||
#define UART_LSR_OE 0x20 /* Overrun error indicator */
|
||||
#define UART_LSR_DR 0x04 /* Receiver data ready */
|
||||
|
||||
/*
|
||||
* These are the definitions for the Interrupt Identification Register
|
||||
*/
|
||||
#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
|
||||
#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
|
||||
|
||||
#define UART_IIR_MSI 0x00 /* Modem status interrupt */
|
||||
#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
|
||||
#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
|
||||
#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
|
||||
|
||||
/*
|
||||
* These are the definitions for the Interrupt Enable Register
|
||||
*/
|
||||
#define UART_IER_MSI 0x00 /* Enable Modem status interrupt */
|
||||
#define UART_IER_RLSI 0x08 /* Enable receiver line status interrupt */
|
||||
#define UART_IER_THRI 0x03 /* Enable Transmitter holding register int. */
|
||||
#define UART_IER_RDI 0x04 /* Enable receiver data interrupt */
|
||||
/*
|
||||
* Sleep mode for ST16650 and TI16750.
|
||||
* Note that for 16650, EFR-bit 4 must be selected as well.
|
||||
*/
|
||||
#define UART_IERX_SLEEP 0x10 /* Enable sleep mode */
|
||||
|
||||
/*
|
||||
* These are the definitions for the Modem Control Register
|
||||
*/
|
||||
#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
|
||||
#define UART_MCR_OUT2 0x08 /* Out2 complement */
|
||||
#define UART_MCR_OUT1 0x04 /* Out1 complement */
|
||||
#define UART_MCR_RTS 0x02 /* RTS complement */
|
||||
#define UART_MCR_DTR 0x01 /* DTR complement */
|
||||
|
||||
/*
|
||||
* These are the definitions for the Modem Status Register
|
||||
*/
|
||||
#define UART_MSR_DCD 0x80 /* Data Carrier Detect */
|
||||
#define UART_MSR_RI 0x40 /* Ring Indicator */
|
||||
#define UART_MSR_DSR 0x20 /* Data Set Ready */
|
||||
#define UART_MSR_CTS 0x10 /* Clear to Send */
|
||||
#define UART_MSR_DDCD 0x08 /* Delta DCD */
|
||||
#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */
|
||||
#define UART_MSR_DDSR 0x02 /* Delta DSR */
|
||||
#define UART_MSR_DCTS 0x01 /* Delta CTS */
|
||||
#define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */
|
||||
|
||||
/*
|
||||
* These are the definitions for the Extended Features Register
|
||||
* (StarTech 16C660 only, when DLAB=1)
|
||||
*/
|
||||
#define UART_EFR_CTS 0x80 /* CTS flow control */
|
||||
#define UART_EFR_RTS 0x40 /* RTS flow control */
|
||||
#define UART_EFR_SCD 0x20 /* Special character detect */
|
||||
#define UART_EFR_ECB 0x10 /* Enhanced control bit */
|
||||
/*
|
||||
* the low four bits control software flow control
|
||||
*/
|
||||
|
||||
/*
|
||||
* These register definitions are for the 16C950
|
||||
*/
|
||||
#define UART_ASR 0x01 /* Additional Status Register */
|
||||
#define UART_RFL 0x03 /* Receiver FIFO level */
|
||||
#define UART_TFL 0x04 /* Transmitter FIFO level */
|
||||
#define UART_ICR 0x05 /* Index Control Register */
|
||||
|
||||
/* The 16950 ICR registers */
|
||||
#define UART_ACR 0x00 /* Additional Control Register */
|
||||
#define UART_CPR 0x01 /* Clock Prescalar Register */
|
||||
#define UART_TCR 0x02 /* Times Clock Register */
|
||||
#define UART_CKS 0x03 /* Clock Select Register */
|
||||
#define UART_TTL 0x04 /* Transmitter Interrupt Trigger Level */
|
||||
#define UART_RTL 0x05 /* Receiver Interrupt Trigger Level */
|
||||
#define UART_FCL 0x06 /* Flow Control Level Lower */
|
||||
#define UART_FCH 0x07 /* Flow Control Level Higher */
|
||||
#define UART_ID1 0x08 /* ID #1 */
|
||||
#define UART_ID2 0x09 /* ID #2 */
|
||||
#define UART_ID3 0x0A /* ID #3 */
|
||||
#define UART_REV 0x0B /* Revision */
|
||||
#define UART_CSR 0x0C /* Channel Software Reset */
|
||||
#define UART_NMR 0x0D /* Nine-bit Mode Register */
|
||||
#define UART_CTR 0xFF
|
||||
|
||||
/*
|
||||
* The 16C950 Additional Control Reigster
|
||||
*/
|
||||
#define UART_ACR_RXDIS 0x01 /* Receiver disable */
|
||||
#define UART_ACR_TXDIS 0x02 /* Receiver disable */
|
||||
#define UART_ACR_DSRFC 0x04 /* DSR Flow Control */
|
||||
#define UART_ACR_TLENB 0x20 /* 950 trigger levels enable */
|
||||
#define UART_ACR_ICRRD 0x40 /* ICR Read enable */
|
||||
#define UART_ACR_ASREN 0x80 /* Additional status enable */
|
||||
|
||||
/*
|
||||
* These are the definitions for the Feature Control Register
|
||||
* (XR16C85x only, when LCR=bf; doubles with the Interrupt Enable
|
||||
* Register, UART register #1)
|
||||
*/
|
||||
#define UART_FCTR_RTS_NODELAY 0x00 /* RTS flow control delay */
|
||||
#define UART_FCTR_RTS_4DELAY 0x01
|
||||
#define UART_FCTR_RTS_6DELAY 0x02
|
||||
#define UART_FCTR_RTS_8DELAY 0x03
|
||||
#define UART_FCTR_IRDA 0x04 /* IrDa data encode select */
|
||||
#define UART_FCTR_TX_INT 0x08 /* Tx interrupt type select */
|
||||
#define UART_FCTR_TRGA 0x00 /* Tx/Rx 550 trigger table select */
|
||||
#define UART_FCTR_TRGB 0x10 /* Tx/Rx 650 trigger table select */
|
||||
#define UART_FCTR_TRGC 0x20 /* Tx/Rx 654 trigger table select */
|
||||
#define UART_FCTR_TRGD 0x30 /* Tx/Rx 850 programmable trigger select */
|
||||
#define UART_FCTR_SCR_SWAP 0x40 /* Scratch pad register swap */
|
||||
#define UART_FCTR_RX 0x00 /* Programmable trigger mode select */
|
||||
#define UART_FCTR_TX 0x80 /* Programmable trigger mode select */
|
||||
|
||||
/*
|
||||
* These are the definitions for the Enhanced Mode Select Register
|
||||
* (XR16C85x only, when LCR=bf and FCTR bit 6=1; doubles with the
|
||||
* Scratch register, UART register #7)
|
||||
*/
|
||||
#define UART_EMSR_FIFO_COUNT 0x01 /* Rx/Tx select */
|
||||
#define UART_EMSR_ALT_COUNT 0x02 /* Alternating count select */
|
||||
|
||||
/*
|
||||
* These are the definitions for the Programmable Trigger
|
||||
* Register (XR16C85x only, when LCR=bf; doubles with the UART RX/TX
|
||||
* register, UART register #0)
|
||||
*/
|
||||
#define UART_TRG_1 0x01
|
||||
#define UART_TRG_4 0x04
|
||||
#define UART_TRG_8 0x08
|
||||
#define UART_TRG_16 0x10
|
||||
#define UART_TRG_32 0x20
|
||||
#define UART_TRG_64 0x40
|
||||
#define UART_TRG_96 0x60
|
||||
#define UART_TRG_120 0x78
|
||||
#define UART_TRG_128 0x80
|
||||
|
||||
/*
|
||||
* These definitions are for the RSA-DV II/S card, from
|
||||
*
|
||||
* Kiyokazu SUTO <suto@ks-and-ks.ne.jp>
|
||||
*/
|
||||
|
||||
#define UART_RSA_BASE (-8)
|
||||
|
||||
#define UART_RSA_MSR ((UART_RSA_BASE) + 0) /* I/O: Mode Select Register */
|
||||
|
||||
#define UART_RSA_MSR_SWAP (1 << 0) /* Swap low/high 8 bytes in I/O port addr */
|
||||
#define UART_RSA_MSR_FIFO (1 << 2) /* Enable the external FIFO */
|
||||
#define UART_RSA_MSR_FLOW (1 << 3) /* Enable the auto RTS/CTS flow control */
|
||||
#define UART_RSA_MSR_ITYP (1 << 4) /* Level (1) / Edge triger (0) */
|
||||
|
||||
#define UART_RSA_IER ((UART_RSA_BASE) + 1) /* I/O: Interrupt Enable Register */
|
||||
|
||||
#define UART_RSA_IER_Rx_FIFO_H (1 << 0) /* Enable Rx FIFO half full int. */
|
||||
#define UART_RSA_IER_Tx_FIFO_H (1 << 1) /* Enable Tx FIFO half full int. */
|
||||
#define UART_RSA_IER_Tx_FIFO_E (1 << 2) /* Enable Tx FIFO empty int. */
|
||||
#define UART_RSA_IER_Rx_TOUT (1 << 3) /* Enable char receive timeout int */
|
||||
#define UART_RSA_IER_TIMER (1 << 4) /* Enable timer interrupt */
|
||||
|
||||
#define UART_RSA_SRR ((UART_RSA_BASE) + 2) /* IN: Status Read Register */
|
||||
|
||||
#define UART_RSA_SRR_Tx_FIFO_NEMP (1 << 0) /* Tx FIFO is not empty (1) */
|
||||
#define UART_RSA_SRR_Tx_FIFO_NHFL (1 << 1) /* Tx FIFO is not half full (1) */
|
||||
#define UART_RSA_SRR_Tx_FIFO_NFUL (1 << 2) /* Tx FIFO is not full (1) */
|
||||
#define UART_RSA_SRR_Rx_FIFO_NEMP (1 << 3) /* Rx FIFO is not empty (1) */
|
||||
#define UART_RSA_SRR_Rx_FIFO_NHFL (1 << 4) /* Rx FIFO is not half full (1) */
|
||||
#define UART_RSA_SRR_Rx_FIFO_NFUL (1 << 5) /* Rx FIFO is not full (1) */
|
||||
#define UART_RSA_SRR_Rx_TOUT (1 << 6) /* Character reception timeout occurred (1) */
|
||||
#define UART_RSA_SRR_TIMER (1 << 7) /* Timer interrupt occurred */
|
||||
|
||||
#define UART_RSA_FRR ((UART_RSA_BASE) + 2) /* OUT: FIFO Reset Register */
|
||||
|
||||
#define UART_RSA_TIVSR ((UART_RSA_BASE) + 3) /* I/O: Timer Interval Value Set Register */
|
||||
|
||||
#define UART_RSA_TCR ((UART_RSA_BASE) + 4) /* OUT: Timer Control Register */
|
||||
|
||||
#define UART_RSA_TCR_SWITCH (1 << 0) /* Timer on */
|
||||
|
||||
/*
|
||||
* The RSA DSV/II board has two fixed clock frequencies. One is the
|
||||
* standard rate, and the other is 8 times faster.
|
||||
*/
|
||||
#define SERIAL_RSA_BAUD_BASE (921600)
|
||||
#define SERIAL_RSA_BAUD_BASE_LO (SERIAL_RSA_BAUD_BASE / 8)
|
||||
|
||||
#endif /* _M32R_SIO_REG_H */
|
||||
1878
extra/linux-2.6.10/drivers/serial/mcfserial.c
Normal file
1878
extra/linux-2.6.10/drivers/serial/mcfserial.c
Normal file
File diff suppressed because it is too large
Load Diff
75
extra/linux-2.6.10/drivers/serial/mcfserial.h
Normal file
75
extra/linux-2.6.10/drivers/serial/mcfserial.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* mcfserial.c -- serial driver for ColdFire internal UARTS.
|
||||
*
|
||||
* Copyright (c) 1999 Greg Ungerer <gerg@snapgear.com>
|
||||
* Copyright (c) 2000-2001 Lineo, Inc. <www.lineo.com>
|
||||
* Copyright (c) 2002 SnapGear Inc., <www.snapgear.com>
|
||||
*
|
||||
* Based on code from 68332serial.c which was:
|
||||
*
|
||||
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
||||
* Copyright (C) 1998 TSHG
|
||||
* Copyright (c) 1999 Rt-Control Inc. <jeff@uclinux.org>
|
||||
*/
|
||||
#ifndef _MCF_SERIAL_H
|
||||
#define _MCF_SERIAL_H
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/serial.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/*
|
||||
* Define a local serial stats structure.
|
||||
*/
|
||||
|
||||
struct mcf_stats {
|
||||
unsigned int rx;
|
||||
unsigned int tx;
|
||||
unsigned int rxbreak;
|
||||
unsigned int rxframing;
|
||||
unsigned int rxparity;
|
||||
unsigned int rxoverrun;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This is our internal structure for each serial port's state.
|
||||
* Each serial port has one of these structures associated with it.
|
||||
*/
|
||||
|
||||
struct mcf_serial {
|
||||
int magic;
|
||||
volatile unsigned char *addr; /* UART memory address */
|
||||
int irq;
|
||||
int flags; /* defined in tty.h */
|
||||
int type; /* UART type */
|
||||
struct tty_struct *tty;
|
||||
unsigned char imr; /* Software imr register */
|
||||
unsigned int baud;
|
||||
int sigs;
|
||||
int custom_divisor;
|
||||
int x_char; /* xon/xoff character */
|
||||
int baud_base;
|
||||
int close_delay;
|
||||
unsigned short closing_wait;
|
||||
unsigned short closing_wait2;
|
||||
unsigned long event;
|
||||
int line;
|
||||
int count; /* # of fd on device */
|
||||
int blocked_open; /* # of blocked opens */
|
||||
unsigned char *xmit_buf;
|
||||
int xmit_head;
|
||||
int xmit_tail;
|
||||
int xmit_cnt;
|
||||
struct mcf_stats stats;
|
||||
struct work_struct tqueue;
|
||||
struct work_struct tqueue_hangup;
|
||||
wait_queue_head_t open_wait;
|
||||
wait_queue_head_t close_wait;
|
||||
|
||||
};
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _MCF_SERIAL_H */
|
||||
869
extra/linux-2.6.10/drivers/serial/mpc52xx_uart.c
Normal file
869
extra/linux-2.6.10/drivers/serial/mpc52xx_uart.c
Normal file
@@ -0,0 +1,869 @@
|
||||
/*
|
||||
* drivers/serial/mpc52xx_uart.c
|
||||
*
|
||||
* Driver for the PSC of the Freescale MPC52xx PSCs configured as UARTs.
|
||||
*
|
||||
* FIXME According to the usermanual the status bits in the status register
|
||||
* are only updated when the peripherals access the FIFO and not when the
|
||||
* CPU access them. So since we use this bits to know when we stop writing
|
||||
* and reading, they may not be updated in-time and a race condition may
|
||||
* exists. But I haven't be able to prove this and I don't care. But if
|
||||
* any problem arises, it might worth checking. The TX/RX FIFO Stats
|
||||
* registers should be used in addition.
|
||||
* Update: Actually, they seem updated ... At least the bits we use.
|
||||
*
|
||||
*
|
||||
* Maintainer : Sylvain Munaut <tnt@246tNt.com>
|
||||
*
|
||||
* Some of the code has been inspired/copied from the 2.4 code written
|
||||
* by Dale Farnsworth <dfarnsworth@mvista.com>.
|
||||
*
|
||||
* Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
|
||||
* Copyright (C) 2003 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.
|
||||
*/
|
||||
|
||||
/* OCP Usage :
|
||||
*
|
||||
* This drivers uses the OCP model. To load the serial driver for one of the
|
||||
* PSCs, just add this to the core_ocp table :
|
||||
*
|
||||
* {
|
||||
* .vendor = OCP_VENDOR_FREESCALE,
|
||||
* .function = OCP_FUNC_PSC_UART,
|
||||
* .index = 0,
|
||||
* .paddr = MPC52xx_PSC1,
|
||||
* .irq = MPC52xx_PSC1_IRQ,
|
||||
* .pm = OCP_CPM_NA,
|
||||
* },
|
||||
*
|
||||
* This is for PSC1, replace the paddr and irq according to the PSC you want to
|
||||
* use. The driver all necessary registers to place the PSC in uart mode without
|
||||
* DCD. However, the pin multiplexing aren't changed and should be set either
|
||||
* by the bootloader or in the platform init code.
|
||||
* The index field must be equal to the PSC index ( e.g. 0 for PSC1, 1 for PSC2,
|
||||
* and so on). So the PSC1 is mapped to /dev/ttyS0, PSC2 to /dev/ttyS1 and so
|
||||
* on. But be warned, it's an ABSOLUTE REQUIREMENT ! This is needed mainly for
|
||||
* the console code : without this 1:1 mapping, at early boot time, when we are
|
||||
* parsing the kernel args console=ttyS?, we wouldn't know wich PSC it will be
|
||||
* mapped to because OCP stuff is not yet initialized.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/console.h>
|
||||
|
||||
#include <asm/delay.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/ocp.h>
|
||||
|
||||
#include <asm/mpc52xx.h>
|
||||
#include <asm/mpc52xx_psc.h>
|
||||
|
||||
#if defined(CONFIG_SERIAL_MPC52xx_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
||||
#define SUPPORT_SYSRQ
|
||||
#endif
|
||||
|
||||
#include <linux/serial_core.h>
|
||||
|
||||
|
||||
|
||||
#define ISR_PASS_LIMIT 256 /* Max number of iteration in the interrupt */
|
||||
|
||||
|
||||
static struct uart_port mpc52xx_uart_ports[MPC52xx_PSC_MAXNUM];
|
||||
/* Rem: - We use the read_status_mask as a shadow of
|
||||
* psc->mpc52xx_psc_imr
|
||||
* - It's important that is array is all zero on start as we
|
||||
* use it to know if it's initialized or not ! If it's not sure
|
||||
* it's cleared, then a memset(...,0,...) should be added to
|
||||
* the console_init
|
||||
*/
|
||||
|
||||
#define PSC(port) ((struct mpc52xx_psc *)((port)->membase))
|
||||
|
||||
|
||||
/* Forward declaration of the interruption handling routine */
|
||||
static irqreturn_t mpc52xx_uart_int(int irq,void *dev_id,struct pt_regs *regs);
|
||||
|
||||
|
||||
/* Simple macro to test if a port is console or not. This one is taken
|
||||
* for serial_core.c and maybe should be moved to serial_core.h ? */
|
||||
#ifdef CONFIG_SERIAL_CORE_CONSOLE
|
||||
#define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line)
|
||||
#else
|
||||
#define uart_console(port) (0)
|
||||
#endif
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* UART operations */
|
||||
/* ======================================================================== */
|
||||
|
||||
static unsigned int
|
||||
mpc52xx_uart_tx_empty(struct uart_port *port)
|
||||
{
|
||||
int status = in_be16(&PSC(port)->mpc52xx_psc_status);
|
||||
return (status & MPC52xx_PSC_SR_TXEMP) ? TIOCSER_TEMT : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
/* Not implemented */
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
mpc52xx_uart_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
/* Not implemented */
|
||||
return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
|
||||
}
|
||||
|
||||
static void
|
||||
mpc52xx_uart_stop_tx(struct uart_port *port, unsigned int tty_stop)
|
||||
{
|
||||
/* port->lock taken by caller */
|
||||
port->read_status_mask &= ~MPC52xx_PSC_IMR_TXRDY;
|
||||
out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask);
|
||||
}
|
||||
|
||||
static void
|
||||
mpc52xx_uart_start_tx(struct uart_port *port, unsigned int tty_start)
|
||||
{
|
||||
/* port->lock taken by caller */
|
||||
port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY;
|
||||
out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask);
|
||||
}
|
||||
|
||||
static void
|
||||
mpc52xx_uart_send_xchar(struct uart_port *port, char ch)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
port->x_char = ch;
|
||||
if (ch) {
|
||||
/* Make sure tx interrupts are on */
|
||||
/* Truly necessary ??? They should be anyway */
|
||||
port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY;
|
||||
out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
mpc52xx_uart_stop_rx(struct uart_port *port)
|
||||
{
|
||||
/* port->lock taken by caller */
|
||||
port->read_status_mask &= ~MPC52xx_PSC_IMR_RXRDY;
|
||||
out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask);
|
||||
}
|
||||
|
||||
static void
|
||||
mpc52xx_uart_enable_ms(struct uart_port *port)
|
||||
{
|
||||
/* Not implemented */
|
||||
}
|
||||
|
||||
static void
|
||||
mpc52xx_uart_break_ctl(struct uart_port *port, int ctl)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
if ( ctl == -1 )
|
||||
out_8(&PSC(port)->command,MPC52xx_PSC_START_BRK);
|
||||
else
|
||||
out_8(&PSC(port)->command,MPC52xx_PSC_STOP_BRK);
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
mpc52xx_uart_startup(struct uart_port *port)
|
||||
{
|
||||
struct mpc52xx_psc *psc = PSC(port);
|
||||
|
||||
/* Reset/activate the port, clear and enable interrupts */
|
||||
out_8(&psc->command,MPC52xx_PSC_RST_RX);
|
||||
out_8(&psc->command,MPC52xx_PSC_RST_TX);
|
||||
|
||||
out_be32(&psc->sicr,0); /* UART mode DCD ignored */
|
||||
|
||||
out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00); /* /16 prescaler on */
|
||||
|
||||
out_8(&psc->rfcntl, 0x00);
|
||||
out_be16(&psc->rfalarm, 0x1ff);
|
||||
out_8(&psc->tfcntl, 0x07);
|
||||
out_be16(&psc->tfalarm, 0x80);
|
||||
|
||||
port->read_status_mask |= MPC52xx_PSC_IMR_RXRDY | MPC52xx_PSC_IMR_TXRDY;
|
||||
out_be16(&psc->mpc52xx_psc_imr,port->read_status_mask);
|
||||
|
||||
out_8(&psc->command,MPC52xx_PSC_TX_ENABLE);
|
||||
out_8(&psc->command,MPC52xx_PSC_RX_ENABLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mpc52xx_uart_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct mpc52xx_psc *psc = PSC(port);
|
||||
|
||||
/* Shut down the port, interrupt and all */
|
||||
out_8(&psc->command,MPC52xx_PSC_RST_RX);
|
||||
out_8(&psc->command,MPC52xx_PSC_RST_TX);
|
||||
|
||||
port->read_status_mask = 0;
|
||||
out_be16(&psc->mpc52xx_psc_imr,port->read_status_mask);
|
||||
}
|
||||
|
||||
static void
|
||||
mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new,
|
||||
struct termios *old)
|
||||
{
|
||||
struct mpc52xx_psc *psc = PSC(port);
|
||||
unsigned long flags;
|
||||
unsigned char mr1, mr2;
|
||||
unsigned short ctr;
|
||||
unsigned int j, baud, quot;
|
||||
|
||||
/* Prepare what we're gonna write */
|
||||
mr1 = 0;
|
||||
|
||||
switch (new->c_cflag & CSIZE) {
|
||||
case CS5: mr1 |= MPC52xx_PSC_MODE_5_BITS;
|
||||
break;
|
||||
case CS6: mr1 |= MPC52xx_PSC_MODE_6_BITS;
|
||||
break;
|
||||
case CS7: mr1 |= MPC52xx_PSC_MODE_7_BITS;
|
||||
break;
|
||||
case CS8:
|
||||
default: mr1 |= MPC52xx_PSC_MODE_8_BITS;
|
||||
}
|
||||
|
||||
if (new->c_cflag & PARENB) {
|
||||
mr1 |= (new->c_cflag & PARODD) ?
|
||||
MPC52xx_PSC_MODE_PARODD : MPC52xx_PSC_MODE_PAREVEN;
|
||||
} else
|
||||
mr1 |= MPC52xx_PSC_MODE_PARNONE;
|
||||
|
||||
|
||||
mr2 = 0;
|
||||
|
||||
if (new->c_cflag & CSTOPB)
|
||||
mr2 |= MPC52xx_PSC_MODE_TWO_STOP;
|
||||
else
|
||||
mr2 |= ((new->c_cflag & CSIZE) == CS5) ?
|
||||
MPC52xx_PSC_MODE_ONE_STOP_5_BITS :
|
||||
MPC52xx_PSC_MODE_ONE_STOP;
|
||||
|
||||
|
||||
baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);
|
||||
quot = uart_get_divisor(port, baud);
|
||||
ctr = quot & 0xffff;
|
||||
|
||||
/* Get the lock */
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
/* Update the per-port timeout */
|
||||
uart_update_timeout(port, new->c_cflag, baud);
|
||||
|
||||
/* Do our best to flush TX & RX, so we don't loose anything */
|
||||
/* But we don't wait indefinitly ! */
|
||||
j = 5000000; /* Maximum wait */
|
||||
/* FIXME Can't receive chars since set_termios might be called at early
|
||||
* boot for the console, all stuff is not yet ready to receive at that
|
||||
* time and that just makes the kernel oops */
|
||||
/* while (j-- && mpc52xx_uart_int_rx_chars(port)); */
|
||||
while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) &&
|
||||
--j)
|
||||
udelay(1);
|
||||
|
||||
if (!j)
|
||||
printk( KERN_ERR "mpc52xx_uart.c: "
|
||||
"Unable to flush RX & TX fifos in-time in set_termios."
|
||||
"Some chars may have been lost.\n" );
|
||||
|
||||
/* Reset the TX & RX */
|
||||
out_8(&psc->command,MPC52xx_PSC_RST_RX);
|
||||
out_8(&psc->command,MPC52xx_PSC_RST_TX);
|
||||
|
||||
/* Send new mode settings */
|
||||
out_8(&psc->command,MPC52xx_PSC_SEL_MODE_REG_1);
|
||||
out_8(&psc->mode,mr1);
|
||||
out_8(&psc->mode,mr2);
|
||||
out_8(&psc->ctur,ctr >> 8);
|
||||
out_8(&psc->ctlr,ctr & 0xff);
|
||||
|
||||
/* Reenable TX & RX */
|
||||
out_8(&psc->command,MPC52xx_PSC_TX_ENABLE);
|
||||
out_8(&psc->command,MPC52xx_PSC_RX_ENABLE);
|
||||
|
||||
/* We're all set, release the lock */
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static const char *
|
||||
mpc52xx_uart_type(struct uart_port *port)
|
||||
{
|
||||
return port->type == PORT_MPC52xx ? "MPC52xx PSC" : NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
mpc52xx_uart_release_port(struct uart_port *port)
|
||||
{
|
||||
if (port->flags & UPF_IOREMAP) { /* remapped by us ? */
|
||||
iounmap(port->membase);
|
||||
port->membase = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mpc52xx_uart_request_port(struct uart_port *port)
|
||||
{
|
||||
if (port->flags & UPF_IOREMAP) /* Need to remap ? */
|
||||
port->membase = ioremap(port->mapbase, sizeof(struct mpc52xx_psc));
|
||||
|
||||
return port->membase != NULL ? 0 : -EBUSY;
|
||||
}
|
||||
|
||||
static void
|
||||
mpc52xx_uart_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
if ( (flags & UART_CONFIG_TYPE) &&
|
||||
(mpc52xx_uart_request_port(port) == 0) )
|
||||
port->type = PORT_MPC52xx;
|
||||
}
|
||||
|
||||
static int
|
||||
mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||
{
|
||||
if ( ser->type != PORT_UNKNOWN && ser->type != PORT_MPC52xx )
|
||||
return -EINVAL;
|
||||
|
||||
if ( (ser->irq != port->irq) ||
|
||||
(ser->io_type != SERIAL_IO_MEM) ||
|
||||
(ser->baud_base != port->uartclk) ||
|
||||
// FIXME Should check addresses/irq as well ?
|
||||
(ser->hub6 != 0 ) )
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct uart_ops mpc52xx_uart_ops = {
|
||||
.tx_empty = mpc52xx_uart_tx_empty,
|
||||
.set_mctrl = mpc52xx_uart_set_mctrl,
|
||||
.get_mctrl = mpc52xx_uart_get_mctrl,
|
||||
.stop_tx = mpc52xx_uart_stop_tx,
|
||||
.start_tx = mpc52xx_uart_start_tx,
|
||||
.send_xchar = mpc52xx_uart_send_xchar,
|
||||
.stop_rx = mpc52xx_uart_stop_rx,
|
||||
.enable_ms = mpc52xx_uart_enable_ms,
|
||||
.break_ctl = mpc52xx_uart_break_ctl,
|
||||
.startup = mpc52xx_uart_startup,
|
||||
.shutdown = mpc52xx_uart_shutdown,
|
||||
.set_termios = mpc52xx_uart_set_termios,
|
||||
/* .pm = mpc52xx_uart_pm, Not supported yet */
|
||||
/* .set_wake = mpc52xx_uart_set_wake, Not supported yet */
|
||||
.type = mpc52xx_uart_type,
|
||||
.release_port = mpc52xx_uart_release_port,
|
||||
.request_port = mpc52xx_uart_request_port,
|
||||
.config_port = mpc52xx_uart_config_port,
|
||||
.verify_port = mpc52xx_uart_verify_port
|
||||
};
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* Interrupt handling */
|
||||
/* ======================================================================== */
|
||||
|
||||
static inline int
|
||||
mpc52xx_uart_int_rx_chars(struct uart_port *port, struct pt_regs *regs)
|
||||
{
|
||||
struct tty_struct *tty = port->info->tty;
|
||||
unsigned char ch;
|
||||
unsigned short status;
|
||||
|
||||
/* While we can read, do so ! */
|
||||
while ( (status = in_be16(&PSC(port)->mpc52xx_psc_status)) &
|
||||
MPC52xx_PSC_SR_RXRDY) {
|
||||
|
||||
/* If we are full, just stop reading */
|
||||
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
|
||||
break;
|
||||
|
||||
/* Get the char */
|
||||
ch = in_8(&PSC(port)->mpc52xx_psc_buffer_8);
|
||||
|
||||
/* Handle sysreq char */
|
||||
#ifdef SUPPORT_SYSRQ
|
||||
if (uart_handle_sysrq_char(port, ch, regs)) {
|
||||
port->sysrq = 0;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Store it */
|
||||
*tty->flip.char_buf_ptr = ch;
|
||||
*tty->flip.flag_buf_ptr = 0;
|
||||
port->icount.rx++;
|
||||
|
||||
if ( status & (MPC52xx_PSC_SR_PE |
|
||||
MPC52xx_PSC_SR_FE |
|
||||
MPC52xx_PSC_SR_RB |
|
||||
MPC52xx_PSC_SR_OE) ) {
|
||||
|
||||
if (status & MPC52xx_PSC_SR_RB) {
|
||||
*tty->flip.flag_buf_ptr = TTY_BREAK;
|
||||
uart_handle_break(port);
|
||||
} else if (status & MPC52xx_PSC_SR_PE)
|
||||
*tty->flip.flag_buf_ptr = TTY_PARITY;
|
||||
else if (status & MPC52xx_PSC_SR_FE)
|
||||
*tty->flip.flag_buf_ptr = TTY_FRAME;
|
||||
if (status & MPC52xx_PSC_SR_OE) {
|
||||
/*
|
||||
* Overrun is special, since it's
|
||||
* reported immediately, and doesn't
|
||||
* affect the current character
|
||||
*/
|
||||
if (tty->flip.count < (TTY_FLIPBUF_SIZE-1)) {
|
||||
tty->flip.flag_buf_ptr++;
|
||||
tty->flip.char_buf_ptr++;
|
||||
tty->flip.count++;
|
||||
}
|
||||
*tty->flip.flag_buf_ptr = TTY_OVERRUN;
|
||||
}
|
||||
|
||||
/* Clear error condition */
|
||||
out_8(&PSC(port)->command,MPC52xx_PSC_RST_ERR_STAT);
|
||||
|
||||
}
|
||||
|
||||
tty->flip.char_buf_ptr++;
|
||||
tty->flip.flag_buf_ptr++;
|
||||
tty->flip.count++;
|
||||
|
||||
}
|
||||
|
||||
tty_flip_buffer_push(tty);
|
||||
|
||||
return in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY;
|
||||
}
|
||||
|
||||
static inline int
|
||||
mpc52xx_uart_int_tx_chars(struct uart_port *port)
|
||||
{
|
||||
struct circ_buf *xmit = &port->info->xmit;
|
||||
|
||||
/* Process out of band chars */
|
||||
if (port->x_char) {
|
||||
out_8(&PSC(port)->mpc52xx_psc_buffer_8, port->x_char);
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Nothing to do ? */
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
|
||||
mpc52xx_uart_stop_tx(port,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Send chars */
|
||||
while (in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXRDY) {
|
||||
out_8(&PSC(port)->mpc52xx_psc_buffer_8, xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Wake up */
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
/* Maybe we're done after all */
|
||||
if (uart_circ_empty(xmit)) {
|
||||
mpc52xx_uart_stop_tx(port,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
mpc52xx_uart_int(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct uart_port *port = (struct uart_port *) dev_id;
|
||||
unsigned long pass = ISR_PASS_LIMIT;
|
||||
unsigned int keepgoing;
|
||||
unsigned short status;
|
||||
|
||||
if ( irq != port->irq ) {
|
||||
printk( KERN_WARNING
|
||||
"mpc52xx_uart_int : " \
|
||||
"Received wrong int %d. Waiting for %d\n",
|
||||
irq, port->irq);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
spin_lock(&port->lock);
|
||||
|
||||
/* While we have stuff to do, we continue */
|
||||
do {
|
||||
/* If we don't find anything to do, we stop */
|
||||
keepgoing = 0;
|
||||
|
||||
/* Read status */
|
||||
status = in_be16(&PSC(port)->mpc52xx_psc_isr);
|
||||
status &= port->read_status_mask;
|
||||
|
||||
/* Do we need to receive chars ? */
|
||||
/* For this RX interrupts must be on and some chars waiting */
|
||||
if ( status & MPC52xx_PSC_IMR_RXRDY )
|
||||
keepgoing |= mpc52xx_uart_int_rx_chars(port, regs);
|
||||
|
||||
/* Do we need to send chars ? */
|
||||
/* For this, TX must be ready and TX interrupt enabled */
|
||||
if ( status & MPC52xx_PSC_IMR_TXRDY )
|
||||
keepgoing |= mpc52xx_uart_int_tx_chars(port);
|
||||
|
||||
/* Limit number of iteration */
|
||||
if ( !(--pass) )
|
||||
keepgoing = 0;
|
||||
|
||||
} while (keepgoing);
|
||||
|
||||
spin_unlock(&port->lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* Console ( if applicable ) */
|
||||
/* ======================================================================== */
|
||||
|
||||
#ifdef CONFIG_SERIAL_MPC52xx_CONSOLE
|
||||
|
||||
static void __init
|
||||
mpc52xx_console_get_options(struct uart_port *port,
|
||||
int *baud, int *parity, int *bits, int *flow)
|
||||
{
|
||||
struct mpc52xx_psc *psc = PSC(port);
|
||||
unsigned char mr1;
|
||||
|
||||
/* Read the mode registers */
|
||||
out_8(&psc->command,MPC52xx_PSC_SEL_MODE_REG_1);
|
||||
mr1 = in_8(&psc->mode);
|
||||
|
||||
/* CT{U,L}R are write-only ! */
|
||||
*baud = __res.bi_baudrate ?
|
||||
__res.bi_baudrate : CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
|
||||
|
||||
/* Parse them */
|
||||
switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) {
|
||||
case MPC52xx_PSC_MODE_5_BITS: *bits = 5; break;
|
||||
case MPC52xx_PSC_MODE_6_BITS: *bits = 6; break;
|
||||
case MPC52xx_PSC_MODE_7_BITS: *bits = 7; break;
|
||||
case MPC52xx_PSC_MODE_8_BITS:
|
||||
default: *bits = 8;
|
||||
}
|
||||
|
||||
if (mr1 & MPC52xx_PSC_MODE_PARNONE)
|
||||
*parity = 'n';
|
||||
else
|
||||
*parity = mr1 & MPC52xx_PSC_MODE_PARODD ? 'o' : 'e';
|
||||
}
|
||||
|
||||
static void
|
||||
mpc52xx_console_write(struct console *co, const char *s, unsigned int count)
|
||||
{
|
||||
struct uart_port *port = &mpc52xx_uart_ports[co->index];
|
||||
struct mpc52xx_psc *psc = PSC(port);
|
||||
unsigned int i, j;
|
||||
|
||||
/* Disable interrupts */
|
||||
out_be16(&psc->mpc52xx_psc_imr, 0);
|
||||
|
||||
/* Wait the TX buffer to be empty */
|
||||
j = 5000000; /* Maximum wait */
|
||||
while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) &&
|
||||
--j)
|
||||
udelay(1);
|
||||
|
||||
/* Write all the chars */
|
||||
for ( i=0 ; i<count ; i++ ) {
|
||||
|
||||
/* Send the char */
|
||||
out_8(&psc->mpc52xx_psc_buffer_8, *s);
|
||||
|
||||
/* Line return handling */
|
||||
if ( *s++ == '\n' )
|
||||
out_8(&psc->mpc52xx_psc_buffer_8, '\r');
|
||||
|
||||
/* Wait the TX buffer to be empty */
|
||||
j = 20000; /* Maximum wait */
|
||||
while (!(in_be16(&psc->mpc52xx_psc_status) &
|
||||
MPC52xx_PSC_SR_TXEMP) && --j)
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
/* Restore interrupt state */
|
||||
out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);
|
||||
}
|
||||
|
||||
static int __init
|
||||
mpc52xx_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_port *port = &mpc52xx_uart_ports[co->index];
|
||||
|
||||
int baud = 9600;
|
||||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
|
||||
if (co->index < 0 || co->index >= MPC52xx_PSC_MAXNUM)
|
||||
return -EINVAL;
|
||||
|
||||
/* Basic port init. Needed since we use some uart_??? func before
|
||||
* real init for early access */
|
||||
port->lock = SPIN_LOCK_UNLOCKED;
|
||||
port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */
|
||||
port->ops = &mpc52xx_uart_ops;
|
||||
port->mapbase = MPC52xx_PSCx(co->index);
|
||||
|
||||
/* We ioremap ourself */
|
||||
port->membase = ioremap(port->mapbase, sizeof(struct mpc52xx_psc));
|
||||
if (port->membase == NULL) {
|
||||
release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Setup the port parameters accoding to options */
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
else
|
||||
mpc52xx_console_get_options(port, &baud, &parity, &bits, &flow);
|
||||
|
||||
return uart_set_options(port, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
|
||||
extern struct uart_driver mpc52xx_uart_driver;
|
||||
|
||||
static struct console mpc52xx_console = {
|
||||
.name = "ttyS",
|
||||
.write = mpc52xx_console_write,
|
||||
.device = uart_console_device,
|
||||
.setup = mpc52xx_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1, /* Specified on the cmdline (e.g. console=ttyS0 ) */
|
||||
.data = &mpc52xx_uart_driver,
|
||||
};
|
||||
|
||||
|
||||
static int __init
|
||||
mpc52xx_console_init(void)
|
||||
{
|
||||
register_console(&mpc52xx_console);
|
||||
return 0;
|
||||
}
|
||||
|
||||
console_initcall(mpc52xx_console_init);
|
||||
|
||||
#define MPC52xx_PSC_CONSOLE &mpc52xx_console
|
||||
#else
|
||||
#define MPC52xx_PSC_CONSOLE NULL
|
||||
#endif
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* UART Driver */
|
||||
/* ======================================================================== */
|
||||
|
||||
static struct uart_driver mpc52xx_uart_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = "mpc52xx_psc_uart",
|
||||
.dev_name = "ttyS",
|
||||
.devfs_name = "ttyS",
|
||||
.major = TTY_MAJOR,
|
||||
.minor = 64,
|
||||
.nr = MPC52xx_PSC_MAXNUM,
|
||||
.cons = MPC52xx_PSC_CONSOLE,
|
||||
};
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* OCP Driver */
|
||||
/* ======================================================================== */
|
||||
|
||||
static int __devinit
|
||||
mpc52xx_uart_probe(struct ocp_device *ocp)
|
||||
{
|
||||
struct uart_port *port = NULL;
|
||||
int idx, ret;
|
||||
|
||||
/* Get the corresponding port struct */
|
||||
idx = ocp->def->index;
|
||||
if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM)
|
||||
return -EINVAL;
|
||||
|
||||
port = &mpc52xx_uart_ports[idx];
|
||||
|
||||
/* Init the port structure */
|
||||
port->lock = SPIN_LOCK_UNLOCKED;
|
||||
port->mapbase = ocp->def->paddr;
|
||||
port->irq = ocp->def->irq;
|
||||
port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */
|
||||
port->fifosize = 255; /* Should be 512 ! But it can't be */
|
||||
/* stored in a unsigned char */
|
||||
port->iotype = UPIO_MEM;
|
||||
port->flags = UPF_BOOT_AUTOCONF |
|
||||
( uart_console(port) ? 0 : UPF_IOREMAP );
|
||||
port->line = idx;
|
||||
port->ops = &mpc52xx_uart_ops;
|
||||
port->read_status_mask = 0;
|
||||
|
||||
/* Requests the mem & irqs */
|
||||
/* Unlike other serial drivers, we reserve the resources here, so we
|
||||
* can detect early if multiple drivers uses the same PSC. Special
|
||||
* care must be taken with the console PSC
|
||||
*/
|
||||
ret = request_irq(
|
||||
port->irq, mpc52xx_uart_int,
|
||||
SA_INTERRUPT | SA_SAMPLE_RANDOM, "mpc52xx_psc_uart", port);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc),
|
||||
"mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
|
||||
if (ret)
|
||||
goto free_irq;
|
||||
|
||||
/* Add the port to the uart sub-system */
|
||||
ret = uart_add_one_port(&mpc52xx_uart_driver, port);
|
||||
if (ret)
|
||||
goto release_mem;
|
||||
|
||||
ocp_set_drvdata(ocp, (void*)port);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
free_irq:
|
||||
free_irq(port->irq, mpc52xx_uart_int);
|
||||
|
||||
release_mem:
|
||||
release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
|
||||
|
||||
error:
|
||||
if (uart_console(port))
|
||||
printk( "mpc52xx_uart.c: Error during resource alloction for "
|
||||
"the console port !!! Check that the console PSC is "
|
||||
"not used by another OCP driver !!!\n" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
mpc52xx_uart_remove(struct ocp_device *ocp)
|
||||
{
|
||||
struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp);
|
||||
|
||||
ocp_set_drvdata(ocp, NULL);
|
||||
|
||||
if (port) {
|
||||
uart_remove_one_port(&mpc52xx_uart_driver, port);
|
||||
release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
|
||||
free_irq(port->irq, mpc52xx_uart_int);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int
|
||||
mpc52xx_uart_suspend(struct ocp_device *ocp, u32 state)
|
||||
{
|
||||
struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp);
|
||||
|
||||
uart_suspend_port(&mpc52xx_uart_driver, port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mpc52xx_uart_resume(struct ocp_device *ocp)
|
||||
{
|
||||
struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp);
|
||||
|
||||
uart_resume_port(&mpc52xx_uart_driver, port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct ocp_device_id mpc52xx_uart_ids[] __devinitdata = {
|
||||
{ .vendor = OCP_VENDOR_FREESCALE, .function = OCP_FUNC_PSC_UART },
|
||||
{ .vendor = OCP_VENDOR_INVALID /* Terminating entry */ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(ocp, mpc52xx_uart_ids);
|
||||
|
||||
static struct ocp_driver mpc52xx_uart_ocp_driver = {
|
||||
.name = "mpc52xx_psc_uart",
|
||||
.id_table = mpc52xx_uart_ids,
|
||||
.probe = mpc52xx_uart_probe,
|
||||
.remove = mpc52xx_uart_remove,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = mpc52xx_uart_suspend,
|
||||
.resume = mpc52xx_uart_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* Module */
|
||||
/* ======================================================================== */
|
||||
|
||||
static int __init
|
||||
mpc52xx_uart_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printk(KERN_INFO "Serial: MPC52xx PSC driver\n");
|
||||
|
||||
ret = uart_register_driver(&mpc52xx_uart_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ocp_register_driver(&mpc52xx_uart_ocp_driver);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit
|
||||
mpc52xx_uart_exit(void)
|
||||
{
|
||||
ocp_unregister_driver(&mpc52xx_uart_ocp_driver);
|
||||
uart_unregister_driver(&mpc52xx_uart_driver);
|
||||
}
|
||||
|
||||
|
||||
module_init(mpc52xx_uart_init);
|
||||
module_exit(mpc52xx_uart_exit);
|
||||
|
||||
MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
|
||||
MODULE_DESCRIPTION("Freescale MPC52xx PSC UART");
|
||||
MODULE_LICENSE("GPL");
|
||||
539
extra/linux-2.6.10/drivers/serial/mux.c
Normal file
539
extra/linux-2.6.10/drivers/serial/mux.c
Normal file
@@ -0,0 +1,539 @@
|
||||
/*
|
||||
** mux.c:
|
||||
** serial driver for the Mux console found in some PA-RISC servers.
|
||||
**
|
||||
** (c) Copyright 2002 Ryan Bradetich
|
||||
** (c) Copyright 2002 Hewlett-Packard Company
|
||||
**
|
||||
** 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 Driver currently only supports the console (port 0) on the MUX.
|
||||
** Additional work will be needed on this driver to enable the full
|
||||
** functionality of the MUX.
|
||||
**
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h> /* for udelay */
|
||||
#include <linux/device.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/parisc-device.h>
|
||||
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
#include <linux/sysrq.h>
|
||||
#define SUPPORT_SYSRQ
|
||||
#endif
|
||||
|
||||
#include <linux/serial_core.h>
|
||||
|
||||
#define MUX_OFFSET 0x800
|
||||
#define MUX_LINE_OFFSET 0x80
|
||||
|
||||
#define MUX_FIFO_SIZE 255
|
||||
#define MUX_POLL_DELAY (30 * HZ / 1000)
|
||||
|
||||
#define IO_DATA_REG_OFFSET 0x3c
|
||||
#define IO_DCOUNT_REG_OFFSET 0x40
|
||||
|
||||
#define MUX_EOFIFO(status) ((status & 0xF000) == 0xF000)
|
||||
#define MUX_STATUS(status) ((status & 0xF000) == 0x8000)
|
||||
#define MUX_BREAK(status) ((status & 0xF000) == 0x2000)
|
||||
|
||||
#define MUX_NR 256
|
||||
static unsigned int port_cnt = 0;
|
||||
static struct uart_port mux_ports[MUX_NR];
|
||||
|
||||
static struct uart_driver mux_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = "ttyB",
|
||||
.dev_name = "ttyB",
|
||||
.major = MUX_MAJOR,
|
||||
.minor = 0,
|
||||
.nr = MUX_NR,
|
||||
};
|
||||
|
||||
static struct timer_list mux_timer;
|
||||
|
||||
#define UART_PUT_CHAR(p, c) __raw_writel((c), (unsigned long)(p)->membase + IO_DATA_REG_OFFSET)
|
||||
#define UART_GET_FIFO_CNT(p) __raw_readl((unsigned long)(p)->membase + IO_DCOUNT_REG_OFFSET)
|
||||
#define GET_MUX_PORTS(iodc_data) ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8
|
||||
|
||||
/**
|
||||
* mux_tx_empty - Check if the transmitter fifo is empty.
|
||||
* @port: Ptr to the uart_port.
|
||||
*
|
||||
* This function test if the transmitter fifo for the port
|
||||
* described by 'port' is empty. If it is empty, this function
|
||||
* should return TIOCSER_TEMT, otherwise return 0.
|
||||
*/
|
||||
static unsigned int mux_tx_empty(struct uart_port *port)
|
||||
{
|
||||
unsigned int cnt = __raw_readl((unsigned long)port->membase
|
||||
+ IO_DCOUNT_REG_OFFSET);
|
||||
|
||||
return cnt ? 0 : TIOCSER_TEMT;
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_set_mctrl - Set the current state of the modem control inputs.
|
||||
* @ports: Ptr to the uart_port.
|
||||
* @mctrl: Modem control bits.
|
||||
*
|
||||
* The Serial MUX does not support CTS, DCD or DSR so this function
|
||||
* is ignored.
|
||||
*/
|
||||
static void mux_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_get_mctrl - Returns the current state of modem control inputs.
|
||||
* @port: Ptr to the uart_port.
|
||||
*
|
||||
* The Serial MUX does not support CTS, DCD or DSR so these lines are
|
||||
* treated as permanently active.
|
||||
*/
|
||||
static unsigned int mux_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_stop_tx - Stop transmitting characters.
|
||||
* @port: Ptr to the uart_port.
|
||||
* @tty_stop: tty layer issue this command?
|
||||
*
|
||||
* The Serial MUX does not support this function.
|
||||
*/
|
||||
static void mux_stop_tx(struct uart_port *port, unsigned int tty_stop)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_start_tx - Start transmitting characters.
|
||||
* @port: Ptr to the uart_port.
|
||||
* @tty_start: tty layer issue this command?
|
||||
*
|
||||
* The Serial Mux does not support this function.
|
||||
*/
|
||||
static void mux_start_tx(struct uart_port *port, unsigned int tty_start)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_stop_rx - Stop receiving characters.
|
||||
* @port: Ptr to the uart_port.
|
||||
*
|
||||
* The Serial Mux does not support this function.
|
||||
*/
|
||||
static void mux_stop_rx(struct uart_port *port)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_enable_ms - Enable modum status interrupts.
|
||||
* @port: Ptr to the uart_port.
|
||||
*
|
||||
* The Serial Mux does not support this function.
|
||||
*/
|
||||
static void mux_enable_ms(struct uart_port *port)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_break_ctl - Control the transmitssion of a break signal.
|
||||
* @port: Ptr to the uart_port.
|
||||
* @break_state: Raise/Lower the break signal.
|
||||
*
|
||||
* The Serial Mux does not support this function.
|
||||
*/
|
||||
static void mux_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_write - Write chars to the mux fifo.
|
||||
* @port: Ptr to the uart_port.
|
||||
*
|
||||
* This function writes all the data from the uart buffer to
|
||||
* the mux fifo.
|
||||
*/
|
||||
static void mux_write(struct uart_port *port)
|
||||
{
|
||||
int count;
|
||||
struct circ_buf *xmit = &port->info->xmit;
|
||||
|
||||
if(port->x_char) {
|
||||
UART_PUT_CHAR(port, port->x_char);
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(uart_circ_empty(xmit) || uart_tx_stopped(port)) {
|
||||
mux_stop_tx(port, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
count = (port->fifosize) - UART_GET_FIFO_CNT(port);
|
||||
do {
|
||||
UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
if(uart_circ_empty(xmit))
|
||||
break;
|
||||
|
||||
} while(--count > 0);
|
||||
|
||||
while(UART_GET_FIFO_CNT(port))
|
||||
udelay(1);
|
||||
|
||||
if(uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
mux_stop_tx(port, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_read - Read chars from the mux fifo.
|
||||
* @port: Ptr to the uart_port.
|
||||
*
|
||||
* This reads all available data from the mux's fifo and pushes
|
||||
* the data to the tty layer.
|
||||
*/
|
||||
static void mux_read(struct uart_port *port)
|
||||
{
|
||||
int data;
|
||||
struct tty_struct *tty = port->info->tty;
|
||||
__u32 start_count = port->icount.rx;
|
||||
|
||||
while(1) {
|
||||
data = __raw_readl((unsigned long)port->membase
|
||||
+ IO_DATA_REG_OFFSET);
|
||||
|
||||
if (MUX_STATUS(data))
|
||||
continue;
|
||||
|
||||
if (MUX_EOFIFO(data))
|
||||
break;
|
||||
|
||||
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
|
||||
continue;
|
||||
|
||||
*tty->flip.char_buf_ptr = data & 0xffu;
|
||||
*tty->flip.flag_buf_ptr = TTY_NORMAL;
|
||||
port->icount.rx++;
|
||||
|
||||
if (MUX_BREAK(data)) {
|
||||
port->icount.brk++;
|
||||
if(uart_handle_break(port))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uart_handle_sysrq_char(port, data & 0xffu, NULL))
|
||||
continue;
|
||||
|
||||
tty->flip.flag_buf_ptr++;
|
||||
tty->flip.char_buf_ptr++;
|
||||
tty->flip.count++;
|
||||
}
|
||||
|
||||
if (start_count != port->icount.rx) {
|
||||
tty_flip_buffer_push(tty);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_startup - Initialize the port.
|
||||
* @port: Ptr to the uart_port.
|
||||
*
|
||||
* Grab any resources needed for this port and start the
|
||||
* mux timer.
|
||||
*/
|
||||
static int mux_startup(struct uart_port *port)
|
||||
{
|
||||
mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_shutdown - Disable the port.
|
||||
* @port: Ptr to the uart_port.
|
||||
*
|
||||
* Release any resources needed for the port.
|
||||
*/
|
||||
static void mux_shutdown(struct uart_port *port)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_set_termios - Chane port parameters.
|
||||
* @port: Ptr to the uart_port.
|
||||
* @termios: new termios settings.
|
||||
* @old: old termios settings.
|
||||
*
|
||||
* The Serial Mux does not support this function.
|
||||
*/
|
||||
static void
|
||||
mux_set_termios(struct uart_port *port, struct termios *termios,
|
||||
struct termios *old)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_type - Describe the port.
|
||||
* @port: Ptr to the uart_port.
|
||||
*
|
||||
* Return a pointer to a string constant describing the
|
||||
* specified port.
|
||||
*/
|
||||
static const char *mux_type(struct uart_port *port)
|
||||
{
|
||||
return "Mux";
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_release_port - Release memory and IO regions.
|
||||
* @port: Ptr to the uart_port.
|
||||
*
|
||||
* Release any memory and IO region resources currently in use by
|
||||
* the port.
|
||||
*/
|
||||
static void mux_release_port(struct uart_port *port)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_request_port - Request memory and IO regions.
|
||||
* @port: Ptr to the uart_port.
|
||||
*
|
||||
* Request any memory and IO region resources required by the port.
|
||||
* If any fail, no resources should be registered when this function
|
||||
* returns, and it should return -EBUSY on failure.
|
||||
*/
|
||||
static int mux_request_port(struct uart_port *port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_config_port - Perform port autoconfiguration.
|
||||
* @port: Ptr to the uart_port.
|
||||
* @type: Bitmask of required configurations.
|
||||
*
|
||||
* Perform any autoconfiguration steps for the port. This functino is
|
||||
* called if the UPF_BOOT_AUTOCONF flag is specified for the port.
|
||||
* [Note: This is required for now because of a bug in the Serial core.
|
||||
* rmk has already submitted a patch to linus, should be available for
|
||||
* 2.5.47.]
|
||||
*/
|
||||
static void mux_config_port(struct uart_port *port, int type)
|
||||
{
|
||||
port->type = PORT_MUX;
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_verify_port - Verify the port information.
|
||||
* @port: Ptr to the uart_port.
|
||||
* @ser: Ptr to the serial information.
|
||||
*
|
||||
* Verify the new serial port information contained within serinfo is
|
||||
* suitable for this port type.
|
||||
*/
|
||||
static int mux_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||
{
|
||||
if(port->membase == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_drv_poll - Mux poll function.
|
||||
* @unused: Unused variable
|
||||
*
|
||||
* This function periodically polls the Serial MUX to check for new data.
|
||||
*/
|
||||
static void mux_poll(unsigned long unused)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < port_cnt; ++i) {
|
||||
if(!mux_ports[i].info)
|
||||
continue;
|
||||
|
||||
mux_read(&mux_ports[i]);
|
||||
mux_write(&mux_ports[i]);
|
||||
}
|
||||
|
||||
mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_SERIAL_MUX_CONSOLE
|
||||
static void mux_console_write(struct console *co, const char *s, unsigned count)
|
||||
{
|
||||
while(count--)
|
||||
pdc_iodc_putc(*s++);
|
||||
}
|
||||
|
||||
static int mux_console_setup(struct console *co, char *options)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct tty_driver *mux_console_device(struct console *co, int *index)
|
||||
{
|
||||
*index = co->index;
|
||||
return mux_driver.tty_driver;
|
||||
}
|
||||
|
||||
static struct console mux_console = {
|
||||
.name = "ttyB",
|
||||
.write = mux_console_write,
|
||||
.device = mux_console_device,
|
||||
.setup = mux_console_setup,
|
||||
.flags = CON_BOOT|CON_PRINTBUFFER|CON_ENABLED,
|
||||
.index = 0,
|
||||
};
|
||||
|
||||
#define MUX_CONSOLE &mux_console
|
||||
#else
|
||||
#define MUX_CONSOLE NULL
|
||||
#endif
|
||||
|
||||
static struct uart_ops mux_pops = {
|
||||
.tx_empty = mux_tx_empty,
|
||||
.set_mctrl = mux_set_mctrl,
|
||||
.get_mctrl = mux_get_mctrl,
|
||||
.stop_tx = mux_stop_tx,
|
||||
.start_tx = mux_start_tx,
|
||||
.stop_rx = mux_stop_rx,
|
||||
.enable_ms = mux_enable_ms,
|
||||
.break_ctl = mux_break_ctl,
|
||||
.startup = mux_startup,
|
||||
.shutdown = mux_shutdown,
|
||||
.set_termios = mux_set_termios,
|
||||
.type = mux_type,
|
||||
.release_port = mux_release_port,
|
||||
.request_port = mux_request_port,
|
||||
.config_port = mux_config_port,
|
||||
.verify_port = mux_verify_port,
|
||||
};
|
||||
|
||||
/**
|
||||
* mux_probe - Determine if the Serial Mux should claim this device.
|
||||
* @dev: The parisc device.
|
||||
*
|
||||
* Deterimine if the Serial Mux should claim this chip (return 0)
|
||||
* or not (return 1).
|
||||
*/
|
||||
static int __init mux_probe(struct parisc_device *dev)
|
||||
{
|
||||
int i, status, ports;
|
||||
u8 iodc_data[32];
|
||||
unsigned long bytecnt;
|
||||
struct uart_port *port;
|
||||
|
||||
status = pdc_iodc_read(&bytecnt, dev->hpa, 0, iodc_data, 32);
|
||||
if(status != PDC_OK) {
|
||||
printk(KERN_ERR "Serial mux: Unable to read IODC.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ports = GET_MUX_PORTS(iodc_data);
|
||||
printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.3\n", ports);
|
||||
|
||||
if(!port_cnt) {
|
||||
mux_driver.cons = MUX_CONSOLE;
|
||||
|
||||
status = uart_register_driver(&mux_driver);
|
||||
if(status) {
|
||||
printk(KERN_ERR "Serial mux: Unable to register driver.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
init_timer(&mux_timer);
|
||||
mux_timer.function = mux_poll;
|
||||
}
|
||||
|
||||
for(i = 0; i < ports; ++i, ++port_cnt) {
|
||||
port = &mux_ports[port_cnt];
|
||||
port->iobase = 0;
|
||||
port->mapbase = dev->hpa + MUX_OFFSET + (i * MUX_LINE_OFFSET);
|
||||
port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET);
|
||||
port->iotype = SERIAL_IO_MEM;
|
||||
port->type = PORT_MUX;
|
||||
port->irq = SERIAL_IRQ_NONE;
|
||||
port->uartclk = 0;
|
||||
port->fifosize = MUX_FIFO_SIZE;
|
||||
port->ops = &mux_pops;
|
||||
port->flags = UPF_BOOT_AUTOCONF;
|
||||
port->line = port_cnt;
|
||||
status = uart_add_one_port(&mux_driver, port);
|
||||
BUG_ON(status);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_MUX_CONSOLE
|
||||
register_console(&mux_console);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct parisc_device_id mux_tbl[] = {
|
||||
{ HPHW_A_DIRECT, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0000D },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(parisc, mux_tbl);
|
||||
|
||||
static struct parisc_driver serial_mux_driver = {
|
||||
.name = "Serial MUX",
|
||||
.id_table = mux_tbl,
|
||||
.probe = mux_probe,
|
||||
};
|
||||
|
||||
/**
|
||||
* mux_init - Serial MUX initalization procedure.
|
||||
*
|
||||
* Register the Serial MUX driver.
|
||||
*/
|
||||
static int __init mux_init(void)
|
||||
{
|
||||
return register_parisc_driver(&serial_mux_driver);
|
||||
}
|
||||
|
||||
/**
|
||||
* mux_exit - Serial MUX cleanup procedure.
|
||||
*
|
||||
* Unregister the Serial MUX driver from the tty layer.
|
||||
*/
|
||||
static void __exit mux_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < port_cnt; i++) {
|
||||
uart_remove_one_port(&mux_driver, &mux_ports[i]);
|
||||
}
|
||||
|
||||
uart_unregister_driver(&mux_driver);
|
||||
}
|
||||
|
||||
module_init(mux_init);
|
||||
module_exit(mux_exit);
|
||||
|
||||
MODULE_AUTHOR("Ryan Bradetich");
|
||||
MODULE_DESCRIPTION("Serial MUX driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_CHARDEV_MAJOR(MUX_MAJOR);
|
||||
2046
extra/linux-2.6.10/drivers/serial/pmac_zilog.c
Normal file
2046
extra/linux-2.6.10/drivers/serial/pmac_zilog.c
Normal file
File diff suppressed because it is too large
Load Diff
382
extra/linux-2.6.10/drivers/serial/pmac_zilog.h
Normal file
382
extra/linux-2.6.10/drivers/serial/pmac_zilog.h
Normal file
@@ -0,0 +1,382 @@
|
||||
#ifndef __PMAC_ZILOG_H__
|
||||
#define __PMAC_ZILOG_H__
|
||||
|
||||
#define pmz_debug(fmt,arg...) dev_dbg(&uap->dev->ofdev.dev, fmt, ## arg)
|
||||
|
||||
/*
|
||||
* At most 2 ESCCs with 2 ports each
|
||||
*/
|
||||
#define MAX_ZS_PORTS 4
|
||||
|
||||
/*
|
||||
* We wrap our port structure around the generic uart_port.
|
||||
*/
|
||||
#define NUM_ZSREGS 17
|
||||
|
||||
struct uart_pmac_port {
|
||||
struct uart_port port;
|
||||
struct uart_pmac_port *mate;
|
||||
|
||||
/* macio_dev for the escc holding this port (maybe be null on
|
||||
* early inited port)
|
||||
*/
|
||||
struct macio_dev *dev;
|
||||
/* device node to this port, this points to one of 2 childs
|
||||
* of "escc" node (ie. ch-a or ch-b)
|
||||
*/
|
||||
struct device_node *node;
|
||||
|
||||
/* Port type as obtained from device tree (IRDA, modem, ...) */
|
||||
int port_type;
|
||||
u8 curregs[NUM_ZSREGS];
|
||||
|
||||
unsigned int flags;
|
||||
#define PMACZILOG_FLAG_IS_CONS 0x00000001
|
||||
#define PMACZILOG_FLAG_IS_KGDB 0x00000002
|
||||
#define PMACZILOG_FLAG_MODEM_STATUS 0x00000004
|
||||
#define PMACZILOG_FLAG_IS_CHANNEL_A 0x00000008
|
||||
#define PMACZILOG_FLAG_REGS_HELD 0x00000010
|
||||
#define PMACZILOG_FLAG_TX_STOPPED 0x00000020
|
||||
#define PMACZILOG_FLAG_TX_ACTIVE 0x00000040
|
||||
#define PMACZILOG_FLAG_ENABLED 0x00000080
|
||||
#define PMACZILOG_FLAG_IS_IRDA 0x00000100
|
||||
#define PMACZILOG_FLAG_IS_INTMODEM 0x00000200
|
||||
#define PMACZILOG_FLAG_HAS_DMA 0x00000400
|
||||
#define PMACZILOG_FLAG_RSRC_REQUESTED 0x00000800
|
||||
#define PMACZILOG_FLAG_IS_ASLEEP 0x00001000
|
||||
#define PMACZILOG_FLAG_IS_OPEN 0x00002000
|
||||
#define PMACZILOG_FLAG_IS_IRQ_ON 0x00004000
|
||||
#define PMACZILOG_FLAG_IS_EXTCLK 0x00008000
|
||||
#define PMACZILOG_FLAG_BREAK 0x00010000
|
||||
|
||||
unsigned char parity_mask;
|
||||
unsigned char prev_status;
|
||||
|
||||
volatile u8 __iomem *control_reg;
|
||||
volatile u8 __iomem *data_reg;
|
||||
|
||||
unsigned int tx_dma_irq;
|
||||
unsigned int rx_dma_irq;
|
||||
volatile struct dbdma_regs __iomem *tx_dma_regs;
|
||||
volatile struct dbdma_regs __iomem *rx_dma_regs;
|
||||
|
||||
struct termios termios_cache;
|
||||
};
|
||||
|
||||
#define to_pmz(p) ((struct uart_pmac_port *)(p))
|
||||
|
||||
static inline struct uart_pmac_port *pmz_get_port_A(struct uart_pmac_port *uap)
|
||||
{
|
||||
if (uap->flags & PMACZILOG_FLAG_IS_CHANNEL_A)
|
||||
return uap;
|
||||
return uap->mate;
|
||||
}
|
||||
|
||||
/*
|
||||
* Register acessors. Note that we don't need to enforce a recovery
|
||||
* delay on PCI PowerMac hardware, it's dealt in HW by the MacIO chip,
|
||||
* though if we try to use this driver on older machines, we might have
|
||||
* to add it back
|
||||
*/
|
||||
static inline u8 read_zsreg(struct uart_pmac_port *port, u8 reg)
|
||||
{
|
||||
if (reg != 0)
|
||||
writeb(reg, port->control_reg);
|
||||
return readb(port->control_reg);
|
||||
}
|
||||
|
||||
static inline void write_zsreg(struct uart_pmac_port *port, u8 reg, u8 value)
|
||||
{
|
||||
if (reg != 0)
|
||||
writeb(reg, port->control_reg);
|
||||
writeb(value, port->control_reg);
|
||||
}
|
||||
|
||||
static inline u8 read_zsdata(struct uart_pmac_port *port)
|
||||
{
|
||||
return readb(port->data_reg);
|
||||
}
|
||||
|
||||
static inline void write_zsdata(struct uart_pmac_port *port, u8 data)
|
||||
{
|
||||
writeb(data, port->data_reg);
|
||||
}
|
||||
|
||||
static inline void zssync(struct uart_pmac_port *port)
|
||||
{
|
||||
(void)readb(port->control_reg);
|
||||
}
|
||||
|
||||
/* Conversion routines to/from brg time constants from/to bits
|
||||
* per second.
|
||||
*/
|
||||
#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2))
|
||||
#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2)
|
||||
|
||||
#define ZS_CLOCK 3686400 /* Z8530 RTxC input clock rate */
|
||||
|
||||
/* The Zilog register set */
|
||||
|
||||
#define FLAG 0x7e
|
||||
|
||||
/* Write Register 0 */
|
||||
#define R0 0 /* Register selects */
|
||||
#define R1 1
|
||||
#define R2 2
|
||||
#define R3 3
|
||||
#define R4 4
|
||||
#define R5 5
|
||||
#define R6 6
|
||||
#define R7 7
|
||||
#define R8 8
|
||||
#define R9 9
|
||||
#define R10 10
|
||||
#define R11 11
|
||||
#define R12 12
|
||||
#define R13 13
|
||||
#define R14 14
|
||||
#define R15 15
|
||||
#define R7P 16
|
||||
|
||||
#define NULLCODE 0 /* Null Code */
|
||||
#define POINT_HIGH 0x8 /* Select upper half of registers */
|
||||
#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */
|
||||
#define SEND_ABORT 0x18 /* HDLC Abort */
|
||||
#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */
|
||||
#define RES_Tx_P 0x28 /* Reset TxINT Pending */
|
||||
#define ERR_RES 0x30 /* Error Reset */
|
||||
#define RES_H_IUS 0x38 /* Reset highest IUS */
|
||||
|
||||
#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */
|
||||
#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */
|
||||
#define RES_EOM_L 0xC0 /* Reset EOM latch */
|
||||
|
||||
/* Write Register 1 */
|
||||
|
||||
#define EXT_INT_ENAB 0x1 /* Ext Int Enable */
|
||||
#define TxINT_ENAB 0x2 /* Tx Int Enable */
|
||||
#define PAR_SPEC 0x4 /* Parity is special condition */
|
||||
|
||||
#define RxINT_DISAB 0 /* Rx Int Disable */
|
||||
#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */
|
||||
#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */
|
||||
#define INT_ERR_Rx 0x18 /* Int on error only */
|
||||
#define RxINT_MASK 0x18
|
||||
|
||||
#define WT_RDY_RT 0x20 /* W/Req reflects recv if 1, xmit if 0 */
|
||||
#define WT_FN_RDYFN 0x40 /* W/Req pin is DMA request if 1, wait if 0 */
|
||||
#define WT_RDY_ENAB 0x80 /* Enable W/Req pin */
|
||||
|
||||
/* Write Register #2 (Interrupt Vector) */
|
||||
|
||||
/* Write Register 3 */
|
||||
|
||||
#define RxENABLE 0x1 /* Rx Enable */
|
||||
#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */
|
||||
#define ADD_SM 0x4 /* Address Search Mode (SDLC) */
|
||||
#define RxCRC_ENAB 0x8 /* Rx CRC Enable */
|
||||
#define ENT_HM 0x10 /* Enter Hunt Mode */
|
||||
#define AUTO_ENAB 0x20 /* Auto Enables */
|
||||
#define Rx5 0x0 /* Rx 5 Bits/Character */
|
||||
#define Rx7 0x40 /* Rx 7 Bits/Character */
|
||||
#define Rx6 0x80 /* Rx 6 Bits/Character */
|
||||
#define Rx8 0xc0 /* Rx 8 Bits/Character */
|
||||
#define RxN_MASK 0xc0
|
||||
|
||||
/* Write Register 4 */
|
||||
|
||||
#define PAR_ENAB 0x1 /* Parity Enable */
|
||||
#define PAR_EVEN 0x2 /* Parity Even/Odd* */
|
||||
|
||||
#define SYNC_ENAB 0 /* Sync Modes Enable */
|
||||
#define SB1 0x4 /* 1 stop bit/char */
|
||||
#define SB15 0x8 /* 1.5 stop bits/char */
|
||||
#define SB2 0xc /* 2 stop bits/char */
|
||||
#define SB_MASK 0xc
|
||||
|
||||
#define MONSYNC 0 /* 8 Bit Sync character */
|
||||
#define BISYNC 0x10 /* 16 bit sync character */
|
||||
#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */
|
||||
#define EXTSYNC 0x30 /* External Sync Mode */
|
||||
|
||||
#define X1CLK 0x0 /* x1 clock mode */
|
||||
#define X16CLK 0x40 /* x16 clock mode */
|
||||
#define X32CLK 0x80 /* x32 clock mode */
|
||||
#define X64CLK 0xC0 /* x64 clock mode */
|
||||
#define XCLK_MASK 0xC0
|
||||
|
||||
/* Write Register 5 */
|
||||
|
||||
#define TxCRC_ENAB 0x1 /* Tx CRC Enable */
|
||||
#define RTS 0x2 /* RTS */
|
||||
#define SDLC_CRC 0x4 /* SDLC/CRC-16 */
|
||||
#define TxENABLE 0x8 /* Tx Enable */
|
||||
#define SND_BRK 0x10 /* Send Break */
|
||||
#define Tx5 0x0 /* Tx 5 bits (or less)/character */
|
||||
#define Tx7 0x20 /* Tx 7 bits/character */
|
||||
#define Tx6 0x40 /* Tx 6 bits/character */
|
||||
#define Tx8 0x60 /* Tx 8 bits/character */
|
||||
#define TxN_MASK 0x60
|
||||
#define DTR 0x80 /* DTR */
|
||||
|
||||
/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
|
||||
|
||||
/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
|
||||
|
||||
/* Write Register 7' (Some enhanced feature control) */
|
||||
#define ENEXREAD 0x40 /* Enable read of some write registers */
|
||||
|
||||
/* Write Register 8 (transmit buffer) */
|
||||
|
||||
/* Write Register 9 (Master interrupt control) */
|
||||
#define VIS 1 /* Vector Includes Status */
|
||||
#define NV 2 /* No Vector */
|
||||
#define DLC 4 /* Disable Lower Chain */
|
||||
#define MIE 8 /* Master Interrupt Enable */
|
||||
#define STATHI 0x10 /* Status high */
|
||||
#define NORESET 0 /* No reset on write to R9 */
|
||||
#define CHRB 0x40 /* Reset channel B */
|
||||
#define CHRA 0x80 /* Reset channel A */
|
||||
#define FHWRES 0xc0 /* Force hardware reset */
|
||||
|
||||
/* Write Register 10 (misc control bits) */
|
||||
#define BIT6 1 /* 6 bit/8bit sync */
|
||||
#define LOOPMODE 2 /* SDLC Loop mode */
|
||||
#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */
|
||||
#define MARKIDLE 8 /* Mark/flag on idle */
|
||||
#define GAOP 0x10 /* Go active on poll */
|
||||
#define NRZ 0 /* NRZ mode */
|
||||
#define NRZI 0x20 /* NRZI mode */
|
||||
#define FM1 0x40 /* FM1 (transition = 1) */
|
||||
#define FM0 0x60 /* FM0 (transition = 0) */
|
||||
#define CRCPS 0x80 /* CRC Preset I/O */
|
||||
|
||||
/* Write Register 11 (Clock Mode control) */
|
||||
#define TRxCXT 0 /* TRxC = Xtal output */
|
||||
#define TRxCTC 1 /* TRxC = Transmit clock */
|
||||
#define TRxCBR 2 /* TRxC = BR Generator Output */
|
||||
#define TRxCDP 3 /* TRxC = DPLL output */
|
||||
#define TRxCOI 4 /* TRxC O/I */
|
||||
#define TCRTxCP 0 /* Transmit clock = RTxC pin */
|
||||
#define TCTRxCP 8 /* Transmit clock = TRxC pin */
|
||||
#define TCBR 0x10 /* Transmit clock = BR Generator output */
|
||||
#define TCDPLL 0x18 /* Transmit clock = DPLL output */
|
||||
#define RCRTxCP 0 /* Receive clock = RTxC pin */
|
||||
#define RCTRxCP 0x20 /* Receive clock = TRxC pin */
|
||||
#define RCBR 0x40 /* Receive clock = BR Generator output */
|
||||
#define RCDPLL 0x60 /* Receive clock = DPLL output */
|
||||
#define RTxCX 0x80 /* RTxC Xtal/No Xtal */
|
||||
|
||||
/* Write Register 12 (lower byte of baud rate generator time constant) */
|
||||
|
||||
/* Write Register 13 (upper byte of baud rate generator time constant) */
|
||||
|
||||
/* Write Register 14 (Misc control bits) */
|
||||
#define BRENAB 1 /* Baud rate generator enable */
|
||||
#define BRSRC 2 /* Baud rate generator source */
|
||||
#define DTRREQ 4 /* DTR/Request function */
|
||||
#define AUTOECHO 8 /* Auto Echo */
|
||||
#define LOOPBAK 0x10 /* Local loopback */
|
||||
#define SEARCH 0x20 /* Enter search mode */
|
||||
#define RMC 0x40 /* Reset missing clock */
|
||||
#define DISDPLL 0x60 /* Disable DPLL */
|
||||
#define SSBR 0x80 /* Set DPLL source = BR generator */
|
||||
#define SSRTxC 0xa0 /* Set DPLL source = RTxC */
|
||||
#define SFMM 0xc0 /* Set FM mode */
|
||||
#define SNRZI 0xe0 /* Set NRZI mode */
|
||||
|
||||
/* Write Register 15 (external/status interrupt control) */
|
||||
#define EN85C30 1 /* Enable some 85c30-enhanced registers */
|
||||
#define ZCIE 2 /* Zero count IE */
|
||||
#define ENSTFIFO 4 /* Enable status FIFO (SDLC) */
|
||||
#define DCDIE 8 /* DCD IE */
|
||||
#define SYNCIE 0x10 /* Sync/hunt IE */
|
||||
#define CTSIE 0x20 /* CTS IE */
|
||||
#define TxUIE 0x40 /* Tx Underrun/EOM IE */
|
||||
#define BRKIE 0x80 /* Break/Abort IE */
|
||||
|
||||
|
||||
/* Read Register 0 */
|
||||
#define Rx_CH_AV 0x1 /* Rx Character Available */
|
||||
#define ZCOUNT 0x2 /* Zero count */
|
||||
#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */
|
||||
#define DCD 0x8 /* DCD */
|
||||
#define SYNC_HUNT 0x10 /* Sync/hunt */
|
||||
#define CTS 0x20 /* CTS */
|
||||
#define TxEOM 0x40 /* Tx underrun */
|
||||
#define BRK_ABRT 0x80 /* Break/Abort */
|
||||
|
||||
/* Read Register 1 */
|
||||
#define ALL_SNT 0x1 /* All sent */
|
||||
/* Residue Data for 8 Rx bits/char programmed */
|
||||
#define RES3 0x8 /* 0/3 */
|
||||
#define RES4 0x4 /* 0/4 */
|
||||
#define RES5 0xc /* 0/5 */
|
||||
#define RES6 0x2 /* 0/6 */
|
||||
#define RES7 0xa /* 0/7 */
|
||||
#define RES8 0x6 /* 0/8 */
|
||||
#define RES18 0xe /* 1/8 */
|
||||
#define RES28 0x0 /* 2/8 */
|
||||
/* Special Rx Condition Interrupts */
|
||||
#define PAR_ERR 0x10 /* Parity error */
|
||||
#define Rx_OVR 0x20 /* Rx Overrun Error */
|
||||
#define CRC_ERR 0x40 /* CRC/Framing Error */
|
||||
#define END_FR 0x80 /* End of Frame (SDLC) */
|
||||
|
||||
/* Read Register 2 (channel b only) - Interrupt vector */
|
||||
#define CHB_Tx_EMPTY 0x00
|
||||
#define CHB_EXT_STAT 0x02
|
||||
#define CHB_Rx_AVAIL 0x04
|
||||
#define CHB_SPECIAL 0x06
|
||||
#define CHA_Tx_EMPTY 0x08
|
||||
#define CHA_EXT_STAT 0x0a
|
||||
#define CHA_Rx_AVAIL 0x0c
|
||||
#define CHA_SPECIAL 0x0e
|
||||
#define STATUS_MASK 0x06
|
||||
|
||||
/* Read Register 3 (interrupt pending register) ch a only */
|
||||
#define CHBEXT 0x1 /* Channel B Ext/Stat IP */
|
||||
#define CHBTxIP 0x2 /* Channel B Tx IP */
|
||||
#define CHBRxIP 0x4 /* Channel B Rx IP */
|
||||
#define CHAEXT 0x8 /* Channel A Ext/Stat IP */
|
||||
#define CHATxIP 0x10 /* Channel A Tx IP */
|
||||
#define CHARxIP 0x20 /* Channel A Rx IP */
|
||||
|
||||
/* Read Register 8 (receive data register) */
|
||||
|
||||
/* Read Register 10 (misc status bits) */
|
||||
#define ONLOOP 2 /* On loop */
|
||||
#define LOOPSEND 0x10 /* Loop sending */
|
||||
#define CLK2MIS 0x40 /* Two clocks missing */
|
||||
#define CLK1MIS 0x80 /* One clock missing */
|
||||
|
||||
/* Read Register 12 (lower byte of baud rate generator constant) */
|
||||
|
||||
/* Read Register 13 (upper byte of baud rate generator constant) */
|
||||
|
||||
/* Read Register 15 (value of WR 15) */
|
||||
|
||||
/* Misc macros */
|
||||
#define ZS_CLEARERR(port) (write_zsreg(port, 0, ERR_RES))
|
||||
#define ZS_CLEARFIFO(port) do { volatile unsigned char garbage; \
|
||||
garbage = read_zsdata(port); \
|
||||
garbage = read_zsdata(port); \
|
||||
garbage = read_zsdata(port); \
|
||||
} while(0)
|
||||
|
||||
#define ZS_IS_CONS(UP) ((UP)->flags & PMACZILOG_FLAG_IS_CONS)
|
||||
#define ZS_IS_KGDB(UP) ((UP)->flags & PMACZILOG_FLAG_IS_KGDB)
|
||||
#define ZS_IS_CHANNEL_A(UP) ((UP)->flags & PMACZILOG_FLAG_IS_CHANNEL_A)
|
||||
#define ZS_REGS_HELD(UP) ((UP)->flags & PMACZILOG_FLAG_REGS_HELD)
|
||||
#define ZS_TX_STOPPED(UP) ((UP)->flags & PMACZILOG_FLAG_TX_STOPPED)
|
||||
#define ZS_TX_ACTIVE(UP) ((UP)->flags & PMACZILOG_FLAG_TX_ACTIVE)
|
||||
#define ZS_WANTS_MODEM_STATUS(UP) ((UP)->flags & PMACZILOG_FLAG_MODEM_STATUS)
|
||||
#define ZS_IS_IRDA(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRDA)
|
||||
#define ZS_IS_INTMODEM(UP) ((UP)->flags & PMACZILOG_FLAG_IS_INTMODEM)
|
||||
#define ZS_HAS_DMA(UP) ((UP)->flags & PMACZILOG_FLAG_HAS_DMA)
|
||||
#define ZS_IS_ASLEEP(UP) ((UP)->flags & PMACZILOG_FLAG_IS_ASLEEP)
|
||||
#define ZS_IS_OPEN(UP) ((UP)->flags & PMACZILOG_FLAG_IS_OPEN)
|
||||
#define ZS_IS_IRQ_ON(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRQ_ON)
|
||||
#define ZS_IS_EXTCLK(UP) ((UP)->flags & PMACZILOG_FLAG_IS_EXTCLK)
|
||||
|
||||
#endif /* __PMAC_ZILOG_H__ */
|
||||
877
extra/linux-2.6.10/drivers/serial/pxa.c
Normal file
877
extra/linux-2.6.10/drivers/serial/pxa.c
Normal file
@@ -0,0 +1,877 @@
|
||||
/*
|
||||
* linux/drivers/serial/pxa.c
|
||||
*
|
||||
* Based on drivers/serial/8250.c by Russell King.
|
||||
*
|
||||
* Author: Nicolas Pitre
|
||||
* Created: Feb 20, 2003
|
||||
* Copyright: (C) 2003 Monta Vista Software, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Note 1: This driver is made separate from the already too overloaded
|
||||
* 8250.c because it needs some kirks of its own and that'll make it
|
||||
* easier to add DMA support.
|
||||
*
|
||||
* Note 2: I'm too sick of device allocation policies for serial ports.
|
||||
* If someone else wants to request an "official" allocation of major/minor
|
||||
* for this driver please be my guest. And don't forget that new hardware
|
||||
* to come from Intel might have more than 3 or 4 of those UARTs. Let's
|
||||
* hope for a better port registration and dynamic device allocation scheme
|
||||
* with the serial core maintainer satisfaction to appear soon.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
||||
#define SUPPORT_SYSRQ
|
||||
#endif
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/circ_buf.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial_core.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/arch/pxa-regs.h>
|
||||
|
||||
|
||||
struct uart_pxa_port {
|
||||
struct uart_port port;
|
||||
unsigned char ier;
|
||||
unsigned char lcr;
|
||||
unsigned char mcr;
|
||||
unsigned int lsr_break_flag;
|
||||
unsigned int cken;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
|
||||
{
|
||||
offset <<= 2;
|
||||
return readl(up->port.membase + offset);
|
||||
}
|
||||
|
||||
static inline void serial_out(struct uart_pxa_port *up, int offset, int value)
|
||||
{
|
||||
offset <<= 2;
|
||||
writel(value, up->port.membase + offset);
|
||||
}
|
||||
|
||||
static void serial_pxa_enable_ms(struct uart_port *port)
|
||||
{
|
||||
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
|
||||
|
||||
up->ier |= UART_IER_MSI;
|
||||
serial_out(up, UART_IER, up->ier);
|
||||
}
|
||||
|
||||
static void serial_pxa_stop_tx(struct uart_port *port, unsigned int tty_stop)
|
||||
{
|
||||
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
|
||||
|
||||
if (up->ier & UART_IER_THRI) {
|
||||
up->ier &= ~UART_IER_THRI;
|
||||
serial_out(up, UART_IER, up->ier);
|
||||
}
|
||||
}
|
||||
|
||||
static void serial_pxa_stop_rx(struct uart_port *port)
|
||||
{
|
||||
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
|
||||
|
||||
up->ier &= ~UART_IER_RLSI;
|
||||
up->port.read_status_mask &= ~UART_LSR_DR;
|
||||
serial_out(up, UART_IER, up->ier);
|
||||
}
|
||||
|
||||
static inline void
|
||||
receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs)
|
||||
{
|
||||
struct tty_struct *tty = up->port.info->tty;
|
||||
unsigned int ch, flag;
|
||||
int max_count = 256;
|
||||
|
||||
do {
|
||||
if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
|
||||
if (tty->low_latency)
|
||||
tty_flip_buffer_push(tty);
|
||||
/*
|
||||
* If this failed then we will throw away the
|
||||
* bytes but must do so to clear interrupts
|
||||
*/
|
||||
}
|
||||
ch = serial_in(up, UART_RX);
|
||||
flag = TTY_NORMAL;
|
||||
up->port.icount.rx++;
|
||||
|
||||
if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
|
||||
UART_LSR_FE | UART_LSR_OE))) {
|
||||
/*
|
||||
* For statistics only
|
||||
*/
|
||||
if (*status & UART_LSR_BI) {
|
||||
*status &= ~(UART_LSR_FE | UART_LSR_PE);
|
||||
up->port.icount.brk++;
|
||||
/*
|
||||
* We do the SysRQ and SAK checking
|
||||
* here because otherwise the break
|
||||
* may get masked by ignore_status_mask
|
||||
* or read_status_mask.
|
||||
*/
|
||||
if (uart_handle_break(&up->port))
|
||||
goto ignore_char;
|
||||
} else if (*status & UART_LSR_PE)
|
||||
up->port.icount.parity++;
|
||||
else if (*status & UART_LSR_FE)
|
||||
up->port.icount.frame++;
|
||||
if (*status & UART_LSR_OE)
|
||||
up->port.icount.overrun++;
|
||||
|
||||
/*
|
||||
* Mask off conditions which should be ignored.
|
||||
*/
|
||||
*status &= up->port.read_status_mask;
|
||||
|
||||
#ifdef CONFIG_SERIAL_PXA_CONSOLE
|
||||
if (up->port.line == up->port.cons->index) {
|
||||
/* Recover the break flag from console xmit */
|
||||
*status |= up->lsr_break_flag;
|
||||
up->lsr_break_flag = 0;
|
||||
}
|
||||
#endif
|
||||
if (*status & UART_LSR_BI) {
|
||||
flag = TTY_BREAK;
|
||||
} else if (*status & UART_LSR_PE)
|
||||
flag = TTY_PARITY;
|
||||
else if (*status & UART_LSR_FE)
|
||||
flag = TTY_FRAME;
|
||||
}
|
||||
if (uart_handle_sysrq_char(&up->port, ch, regs))
|
||||
goto ignore_char;
|
||||
if ((*status & up->port.ignore_status_mask) == 0) {
|
||||
tty_insert_flip_char(tty, ch, flag);
|
||||
}
|
||||
if ((*status & UART_LSR_OE) &&
|
||||
tty->flip.count < TTY_FLIPBUF_SIZE) {
|
||||
/*
|
||||
* Overrun is special, since it's reported
|
||||
* immediately, and doesn't affect the current
|
||||
* character.
|
||||
*/
|
||||
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
|
||||
}
|
||||
ignore_char:
|
||||
*status = serial_in(up, UART_LSR);
|
||||
} while ((*status & UART_LSR_DR) && (max_count-- > 0));
|
||||
tty_flip_buffer_push(tty);
|
||||
}
|
||||
|
||||
static void transmit_chars(struct uart_pxa_port *up)
|
||||
{
|
||||
struct circ_buf *xmit = &up->port.info->xmit;
|
||||
int count;
|
||||
|
||||
if (up->port.x_char) {
|
||||
serial_out(up, UART_TX, up->port.x_char);
|
||||
up->port.icount.tx++;
|
||||
up->port.x_char = 0;
|
||||
return;
|
||||
}
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
|
||||
serial_pxa_stop_tx(&up->port, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
count = up->port.fifosize / 2;
|
||||
do {
|
||||
serial_out(up, UART_TX, xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
up->port.icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
} while (--count > 0);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(&up->port);
|
||||
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
serial_pxa_stop_tx(&up->port, 0);
|
||||
}
|
||||
|
||||
static void serial_pxa_start_tx(struct uart_port *port, unsigned int tty_start)
|
||||
{
|
||||
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
|
||||
|
||||
if (!(up->ier & UART_IER_THRI)) {
|
||||
up->ier |= UART_IER_THRI;
|
||||
serial_out(up, UART_IER, up->ier);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void check_modem_status(struct uart_pxa_port *up)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = serial_in(up, UART_MSR);
|
||||
|
||||
if ((status & UART_MSR_ANY_DELTA) == 0)
|
||||
return;
|
||||
|
||||
if (status & UART_MSR_TERI)
|
||||
up->port.icount.rng++;
|
||||
if (status & UART_MSR_DDSR)
|
||||
up->port.icount.dsr++;
|
||||
if (status & UART_MSR_DDCD)
|
||||
uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
|
||||
if (status & UART_MSR_DCTS)
|
||||
uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
|
||||
|
||||
wake_up_interruptible(&up->port.info->delta_msr_wait);
|
||||
}
|
||||
|
||||
/*
|
||||
* This handles the interrupt from one port.
|
||||
*/
|
||||
static inline irqreturn_t
|
||||
serial_pxa_irq(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct uart_pxa_port *up = (struct uart_pxa_port *)dev_id;
|
||||
unsigned int iir, lsr;
|
||||
|
||||
iir = serial_in(up, UART_IIR);
|
||||
if (iir & UART_IIR_NO_INT)
|
||||
return IRQ_NONE;
|
||||
lsr = serial_in(up, UART_LSR);
|
||||
if (lsr & UART_LSR_DR)
|
||||
receive_chars(up, &lsr, regs);
|
||||
check_modem_status(up);
|
||||
if (lsr & UART_LSR_THRE)
|
||||
transmit_chars(up);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static unsigned int serial_pxa_tx_empty(struct uart_port *port)
|
||||
{
|
||||
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
|
||||
unsigned long flags;
|
||||
unsigned int ret;
|
||||
|
||||
spin_lock_irqsave(&up->port.lock, flags);
|
||||
ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
|
||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
|
||||
unsigned long flags;
|
||||
unsigned char status;
|
||||
unsigned int ret;
|
||||
|
||||
return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
|
||||
spin_lock_irqsave(&up->port.lock, flags);
|
||||
status = serial_in(up, UART_MSR);
|
||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
||||
|
||||
ret = 0;
|
||||
if (status & UART_MSR_DCD)
|
||||
ret |= TIOCM_CAR;
|
||||
if (status & UART_MSR_RI)
|
||||
ret |= TIOCM_RNG;
|
||||
if (status & UART_MSR_DSR)
|
||||
ret |= TIOCM_DSR;
|
||||
if (status & UART_MSR_CTS)
|
||||
ret |= TIOCM_CTS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
|
||||
unsigned char mcr = 0;
|
||||
|
||||
if (mctrl & TIOCM_RTS)
|
||||
mcr |= UART_MCR_RTS;
|
||||
if (mctrl & TIOCM_DTR)
|
||||
mcr |= UART_MCR_DTR;
|
||||
if (mctrl & TIOCM_OUT1)
|
||||
mcr |= UART_MCR_OUT1;
|
||||
if (mctrl & TIOCM_OUT2)
|
||||
mcr |= UART_MCR_OUT2;
|
||||
if (mctrl & TIOCM_LOOP)
|
||||
mcr |= UART_MCR_LOOP;
|
||||
|
||||
mcr |= up->mcr;
|
||||
|
||||
serial_out(up, UART_MCR, mcr);
|
||||
}
|
||||
|
||||
static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&up->port.lock, flags);
|
||||
if (break_state == -1)
|
||||
up->lcr |= UART_LCR_SBC;
|
||||
else
|
||||
up->lcr &= ~UART_LCR_SBC;
|
||||
serial_out(up, UART_LCR, up->lcr);
|
||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void serial_pxa_dma_init(struct pxa_uart *up)
|
||||
{
|
||||
up->rxdma =
|
||||
pxa_request_dma(up->name, DMA_PRIO_LOW, pxa_receive_dma, up);
|
||||
if (up->rxdma < 0)
|
||||
goto out;
|
||||
up->txdma =
|
||||
pxa_request_dma(up->name, DMA_PRIO_LOW, pxa_transmit_dma, up);
|
||||
if (up->txdma < 0)
|
||||
goto err_txdma;
|
||||
up->dmadesc = kmalloc(4 * sizeof(pxa_dma_desc), GFP_KERNEL);
|
||||
if (!up->dmadesc)
|
||||
goto err_alloc;
|
||||
|
||||
/* ... */
|
||||
err_alloc:
|
||||
pxa_free_dma(up->txdma);
|
||||
err_rxdma:
|
||||
pxa_free_dma(up->rxdma);
|
||||
out:
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int serial_pxa_startup(struct uart_port *port)
|
||||
{
|
||||
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
|
||||
unsigned long flags;
|
||||
int retval;
|
||||
|
||||
up->mcr = 0;
|
||||
|
||||
/*
|
||||
* Allocate the IRQ
|
||||
*/
|
||||
retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/*
|
||||
* Clear the FIFO buffers and disable them.
|
||||
* (they will be reenabled in set_termios())
|
||||
*/
|
||||
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
|
||||
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
|
||||
UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
|
||||
serial_out(up, UART_FCR, 0);
|
||||
|
||||
/*
|
||||
* Clear the interrupt registers.
|
||||
*/
|
||||
(void) serial_in(up, UART_LSR);
|
||||
(void) serial_in(up, UART_RX);
|
||||
(void) serial_in(up, UART_IIR);
|
||||
(void) serial_in(up, UART_MSR);
|
||||
|
||||
/*
|
||||
* Now, initialize the UART
|
||||
*/
|
||||
serial_out(up, UART_LCR, UART_LCR_WLEN8);
|
||||
|
||||
spin_lock_irqsave(&up->port.lock, flags);
|
||||
up->port.mctrl |= TIOCM_OUT2;
|
||||
serial_pxa_set_mctrl(&up->port, up->port.mctrl);
|
||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
||||
|
||||
/*
|
||||
* Finally, enable interrupts. Note: Modem status interrupts
|
||||
* are set via set_termios(), which will be occuring imminently
|
||||
* anyway, so we don't enable them here.
|
||||
*/
|
||||
up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
|
||||
serial_out(up, UART_IER, up->ier);
|
||||
|
||||
/*
|
||||
* And clear the interrupt registers again for luck.
|
||||
*/
|
||||
(void) serial_in(up, UART_LSR);
|
||||
(void) serial_in(up, UART_RX);
|
||||
(void) serial_in(up, UART_IIR);
|
||||
(void) serial_in(up, UART_MSR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void serial_pxa_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
|
||||
unsigned long flags;
|
||||
|
||||
free_irq(up->port.irq, up);
|
||||
|
||||
/*
|
||||
* Disable interrupts from this port
|
||||
*/
|
||||
up->ier = 0;
|
||||
serial_out(up, UART_IER, 0);
|
||||
|
||||
spin_lock_irqsave(&up->port.lock, flags);
|
||||
up->port.mctrl &= ~TIOCM_OUT2;
|
||||
serial_pxa_set_mctrl(&up->port, up->port.mctrl);
|
||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
||||
|
||||
/*
|
||||
* Disable break condition and FIFOs
|
||||
*/
|
||||
serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
|
||||
serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
|
||||
UART_FCR_CLEAR_RCVR |
|
||||
UART_FCR_CLEAR_XMIT);
|
||||
serial_out(up, UART_FCR, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
serial_pxa_set_termios(struct uart_port *port, struct termios *termios,
|
||||
struct termios *old)
|
||||
{
|
||||
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
|
||||
unsigned char cval, fcr = 0;
|
||||
unsigned long flags;
|
||||
unsigned int baud, quot;
|
||||
|
||||
switch (termios->c_cflag & CSIZE) {
|
||||
case CS5:
|
||||
cval = 0x00;
|
||||
break;
|
||||
case CS6:
|
||||
cval = 0x01;
|
||||
break;
|
||||
case CS7:
|
||||
cval = 0x02;
|
||||
break;
|
||||
default:
|
||||
case CS8:
|
||||
cval = 0x03;
|
||||
break;
|
||||
}
|
||||
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
cval |= 0x04;
|
||||
if (termios->c_cflag & PARENB)
|
||||
cval |= UART_LCR_PARITY;
|
||||
if (!(termios->c_cflag & PARODD))
|
||||
cval |= UART_LCR_EPAR;
|
||||
|
||||
/*
|
||||
* Ask the core to calculate the divisor for us.
|
||||
*/
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
|
||||
quot = uart_get_divisor(port, baud);
|
||||
|
||||
if ((up->port.uartclk / quot) < (2400 * 16))
|
||||
fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
|
||||
else
|
||||
fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8;
|
||||
|
||||
/*
|
||||
* Ok, we're now changing the port state. Do it with
|
||||
* interrupts disabled.
|
||||
*/
|
||||
spin_lock_irqsave(&up->port.lock, flags);
|
||||
|
||||
/*
|
||||
* Ensure the port will be enabled.
|
||||
* This is required especially for serial console.
|
||||
*/
|
||||
up->ier |= IER_UUE;
|
||||
|
||||
/*
|
||||
* Update the per-port timeout.
|
||||
*/
|
||||
uart_update_timeout(port, termios->c_cflag, quot);
|
||||
|
||||
up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
|
||||
if (termios->c_iflag & INPCK)
|
||||
up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
|
||||
if (termios->c_iflag & (BRKINT | PARMRK))
|
||||
up->port.read_status_mask |= UART_LSR_BI;
|
||||
|
||||
/*
|
||||
* Characters to ignore
|
||||
*/
|
||||
up->port.ignore_status_mask = 0;
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
|
||||
if (termios->c_iflag & IGNBRK) {
|
||||
up->port.ignore_status_mask |= UART_LSR_BI;
|
||||
/*
|
||||
* If we're ignoring parity and break indicators,
|
||||
* ignore overruns too (for real raw support).
|
||||
*/
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
up->port.ignore_status_mask |= UART_LSR_OE;
|
||||
}
|
||||
|
||||
/*
|
||||
* ignore all characters if CREAD is not set
|
||||
*/
|
||||
if ((termios->c_cflag & CREAD) == 0)
|
||||
up->port.ignore_status_mask |= UART_LSR_DR;
|
||||
|
||||
/*
|
||||
* CTS flow control flag and modem status interrupts
|
||||
*/
|
||||
up->ier &= ~UART_IER_MSI;
|
||||
if (UART_ENABLE_MS(&up->port, termios->c_cflag))
|
||||
up->ier |= UART_IER_MSI;
|
||||
|
||||
serial_out(up, UART_IER, up->ier);
|
||||
|
||||
serial_out(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
|
||||
serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */
|
||||
serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */
|
||||
serial_out(up, UART_LCR, cval); /* reset DLAB */
|
||||
up->lcr = cval; /* Save LCR */
|
||||
serial_pxa_set_mctrl(&up->port, up->port.mctrl);
|
||||
serial_out(up, UART_FCR, fcr);
|
||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
serial_pxa_pm(struct uart_port *port, unsigned int state,
|
||||
unsigned int oldstate)
|
||||
{
|
||||
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
|
||||
pxa_set_cken(up->cken, !state);
|
||||
if (!state)
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static void serial_pxa_release_port(struct uart_port *port)
|
||||
{
|
||||
}
|
||||
|
||||
static int serial_pxa_request_port(struct uart_port *port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void serial_pxa_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
|
||||
up->port.type = PORT_PXA;
|
||||
}
|
||||
|
||||
static int
|
||||
serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||
{
|
||||
/* we don't want the core code to modify any port params */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const char *
|
||||
serial_pxa_type(struct uart_port *port)
|
||||
{
|
||||
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
|
||||
return up->name;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_PXA_CONSOLE
|
||||
|
||||
extern struct uart_pxa_port serial_pxa_ports[];
|
||||
extern struct uart_driver serial_pxa_reg;
|
||||
|
||||
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
|
||||
|
||||
/*
|
||||
* Wait for transmitter & holding register to empty
|
||||
*/
|
||||
static inline void wait_for_xmitr(struct uart_pxa_port *up)
|
||||
{
|
||||
unsigned int status, tmout = 10000;
|
||||
|
||||
/* Wait up to 10ms for the character(s) to be sent. */
|
||||
do {
|
||||
status = serial_in(up, UART_LSR);
|
||||
|
||||
if (status & UART_LSR_BI)
|
||||
up->lsr_break_flag = UART_LSR_BI;
|
||||
|
||||
if (--tmout == 0)
|
||||
break;
|
||||
udelay(1);
|
||||
} while ((status & BOTH_EMPTY) != BOTH_EMPTY);
|
||||
|
||||
/* Wait up to 1s for flow control if necessary */
|
||||
if (up->port.flags & UPF_CONS_FLOW) {
|
||||
tmout = 1000000;
|
||||
while (--tmout &&
|
||||
((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
|
||||
udelay(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a string to the serial port trying not to disturb
|
||||
* any possible real use of the port...
|
||||
*
|
||||
* The console_lock must be held when we get here.
|
||||
*/
|
||||
static void
|
||||
serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
|
||||
{
|
||||
struct uart_pxa_port *up = &serial_pxa_ports[co->index];
|
||||
unsigned int ier;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* First save the UER then disable the interrupts
|
||||
*/
|
||||
ier = serial_in(up, UART_IER);
|
||||
serial_out(up, UART_IER, UART_IER_UUE);
|
||||
|
||||
/*
|
||||
* Now, do each character
|
||||
*/
|
||||
for (i = 0; i < count; i++, s++) {
|
||||
wait_for_xmitr(up);
|
||||
|
||||
/*
|
||||
* Send the character out.
|
||||
* If a LF, also do CR...
|
||||
*/
|
||||
serial_out(up, UART_TX, *s);
|
||||
if (*s == 10) {
|
||||
wait_for_xmitr(up);
|
||||
serial_out(up, UART_TX, 13);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, wait for transmitter to become empty
|
||||
* and restore the IER
|
||||
*/
|
||||
wait_for_xmitr(up);
|
||||
serial_out(up, UART_IER, ier);
|
||||
}
|
||||
|
||||
static int __init
|
||||
serial_pxa_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_pxa_port *up;
|
||||
int baud = 9600;
|
||||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
|
||||
if (co->index == -1 || co->index >= serial_pxa_reg.nr)
|
||||
co->index = 0;
|
||||
up = &serial_pxa_ports[co->index];
|
||||
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
|
||||
return uart_set_options(&up->port, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
static struct console serial_pxa_console = {
|
||||
.name = "ttyS",
|
||||
.write = serial_pxa_console_write,
|
||||
.device = uart_console_device,
|
||||
.setup = serial_pxa_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
.data = &serial_pxa_reg,
|
||||
};
|
||||
|
||||
static int __init
|
||||
serial_pxa_console_init(void)
|
||||
{
|
||||
register_console(&serial_pxa_console);
|
||||
return 0;
|
||||
}
|
||||
|
||||
console_initcall(serial_pxa_console_init);
|
||||
|
||||
#define PXA_CONSOLE &serial_pxa_console
|
||||
#else
|
||||
#define PXA_CONSOLE NULL
|
||||
#endif
|
||||
|
||||
struct uart_ops serial_pxa_pops = {
|
||||
.tx_empty = serial_pxa_tx_empty,
|
||||
.set_mctrl = serial_pxa_set_mctrl,
|
||||
.get_mctrl = serial_pxa_get_mctrl,
|
||||
.stop_tx = serial_pxa_stop_tx,
|
||||
.start_tx = serial_pxa_start_tx,
|
||||
.stop_rx = serial_pxa_stop_rx,
|
||||
.enable_ms = serial_pxa_enable_ms,
|
||||
.break_ctl = serial_pxa_break_ctl,
|
||||
.startup = serial_pxa_startup,
|
||||
.shutdown = serial_pxa_shutdown,
|
||||
.set_termios = serial_pxa_set_termios,
|
||||
.pm = serial_pxa_pm,
|
||||
.type = serial_pxa_type,
|
||||
.release_port = serial_pxa_release_port,
|
||||
.request_port = serial_pxa_request_port,
|
||||
.config_port = serial_pxa_config_port,
|
||||
.verify_port = serial_pxa_verify_port,
|
||||
};
|
||||
|
||||
static struct uart_pxa_port serial_pxa_ports[] = {
|
||||
{ /* FFUART */
|
||||
.name = "FFUART",
|
||||
.cken = CKEN6_FFUART,
|
||||
.port = {
|
||||
.type = PORT_PXA,
|
||||
.iotype = UPIO_MEM,
|
||||
.membase = (void *)&FFUART,
|
||||
.mapbase = __PREG(FFUART),
|
||||
.irq = IRQ_FFUART,
|
||||
.uartclk = 921600 * 16,
|
||||
.fifosize = 64,
|
||||
.ops = &serial_pxa_pops,
|
||||
.line = 0,
|
||||
},
|
||||
}, { /* BTUART */
|
||||
.name = "BTUART",
|
||||
.cken = CKEN7_BTUART,
|
||||
.port = {
|
||||
.type = PORT_PXA,
|
||||
.iotype = UPIO_MEM,
|
||||
.membase = (void *)&BTUART,
|
||||
.mapbase = __PREG(BTUART),
|
||||
.irq = IRQ_BTUART,
|
||||
.uartclk = 921600 * 16,
|
||||
.fifosize = 64,
|
||||
.ops = &serial_pxa_pops,
|
||||
.line = 1,
|
||||
},
|
||||
}, { /* STUART */
|
||||
.name = "STUART",
|
||||
.cken = CKEN5_STUART,
|
||||
.port = {
|
||||
.type = PORT_PXA,
|
||||
.iotype = UPIO_MEM,
|
||||
.membase = (void *)&STUART,
|
||||
.mapbase = __PREG(STUART),
|
||||
.irq = IRQ_STUART,
|
||||
.uartclk = 921600 * 16,
|
||||
.fifosize = 64,
|
||||
.ops = &serial_pxa_pops,
|
||||
.line = 2,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
static struct uart_driver serial_pxa_reg = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = "PXA serial",
|
||||
.devfs_name = "tts/",
|
||||
.dev_name = "ttyS",
|
||||
.major = TTY_MAJOR,
|
||||
.minor = 64,
|
||||
.nr = ARRAY_SIZE(serial_pxa_ports),
|
||||
.cons = PXA_CONSOLE,
|
||||
};
|
||||
|
||||
static int serial_pxa_suspend(struct device *_dev, u32 state, u32 level)
|
||||
{
|
||||
struct uart_pxa_port *sport = dev_get_drvdata(_dev);
|
||||
|
||||
if (sport && level == SUSPEND_DISABLE)
|
||||
uart_suspend_port(&serial_pxa_reg, &sport->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serial_pxa_resume(struct device *_dev, u32 level)
|
||||
{
|
||||
struct uart_pxa_port *sport = dev_get_drvdata(_dev);
|
||||
|
||||
if (sport && level == RESUME_ENABLE)
|
||||
uart_resume_port(&serial_pxa_reg, &sport->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serial_pxa_probe(struct device *_dev)
|
||||
{
|
||||
struct platform_device *dev = to_platform_device(_dev);
|
||||
|
||||
serial_pxa_ports[dev->id].port.dev = _dev;
|
||||
uart_add_one_port(&serial_pxa_reg, &serial_pxa_ports[dev->id].port);
|
||||
dev_set_drvdata(_dev, &serial_pxa_ports[dev->id]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serial_pxa_remove(struct device *_dev)
|
||||
{
|
||||
struct uart_pxa_port *sport = dev_get_drvdata(_dev);
|
||||
|
||||
dev_set_drvdata(_dev, NULL);
|
||||
|
||||
if (sport)
|
||||
uart_remove_one_port(&serial_pxa_reg, &sport->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct device_driver serial_pxa_driver = {
|
||||
.name = "pxa2xx-uart",
|
||||
.bus = &platform_bus_type,
|
||||
.probe = serial_pxa_probe,
|
||||
.remove = serial_pxa_remove,
|
||||
|
||||
.suspend = serial_pxa_suspend,
|
||||
.resume = serial_pxa_resume,
|
||||
};
|
||||
|
||||
int __init serial_pxa_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = uart_register_driver(&serial_pxa_reg);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = driver_register(&serial_pxa_driver);
|
||||
if (ret != 0)
|
||||
uart_unregister_driver(&serial_pxa_reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __exit serial_pxa_exit(void)
|
||||
{
|
||||
driver_unregister(&serial_pxa_driver);
|
||||
uart_unregister_driver(&serial_pxa_reg);
|
||||
}
|
||||
|
||||
module_init(serial_pxa_init);
|
||||
module_exit(serial_pxa_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
1644
extra/linux-2.6.10/drivers/serial/s3c2410.c
Normal file
1644
extra/linux-2.6.10/drivers/serial/s3c2410.c
Normal file
File diff suppressed because it is too large
Load Diff
952
extra/linux-2.6.10/drivers/serial/sa1100.c
Normal file
952
extra/linux-2.6.10/drivers/serial/sa1100.c
Normal file
@@ -0,0 +1,952 @@
|
||||
/*
|
||||
* linux/drivers/char/sa1100.c
|
||||
*
|
||||
* Driver for SA11x0 serial ports
|
||||
*
|
||||
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
|
||||
*
|
||||
* Copyright (C) 2000 Deep Blue Solutions Ltd.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* $Id: sa1100.c,v 1.50 2002/07/29 14:41:04 rmk Exp $
|
||||
*
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
|
||||
#if defined(CONFIG_SERIAL_SA1100_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
||||
#define SUPPORT_SYSRQ
|
||||
#endif
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/mach/serial_sa1100.h>
|
||||
|
||||
/* We've been assigned a range on the "Low-density serial ports" major */
|
||||
#define SERIAL_SA1100_MAJOR 204
|
||||
#define MINOR_START 5
|
||||
|
||||
#define NR_PORTS 3
|
||||
|
||||
#define SA1100_ISR_PASS_LIMIT 256
|
||||
|
||||
/*
|
||||
* Convert from ignore_status_mask or read_status_mask to UTSR[01]
|
||||
*/
|
||||
#define SM_TO_UTSR0(x) ((x) & 0xff)
|
||||
#define SM_TO_UTSR1(x) ((x) >> 8)
|
||||
#define UTSR0_TO_SM(x) ((x))
|
||||
#define UTSR1_TO_SM(x) ((x) << 8)
|
||||
|
||||
#define UART_GET_UTCR0(sport) __raw_readl((sport)->port.membase + UTCR0)
|
||||
#define UART_GET_UTCR1(sport) __raw_readl((sport)->port.membase + UTCR1)
|
||||
#define UART_GET_UTCR2(sport) __raw_readl((sport)->port.membase + UTCR2)
|
||||
#define UART_GET_UTCR3(sport) __raw_readl((sport)->port.membase + UTCR3)
|
||||
#define UART_GET_UTSR0(sport) __raw_readl((sport)->port.membase + UTSR0)
|
||||
#define UART_GET_UTSR1(sport) __raw_readl((sport)->port.membase + UTSR1)
|
||||
#define UART_GET_CHAR(sport) __raw_readl((sport)->port.membase + UTDR)
|
||||
|
||||
#define UART_PUT_UTCR0(sport,v) __raw_writel((v),(sport)->port.membase + UTCR0)
|
||||
#define UART_PUT_UTCR1(sport,v) __raw_writel((v),(sport)->port.membase + UTCR1)
|
||||
#define UART_PUT_UTCR2(sport,v) __raw_writel((v),(sport)->port.membase + UTCR2)
|
||||
#define UART_PUT_UTCR3(sport,v) __raw_writel((v),(sport)->port.membase + UTCR3)
|
||||
#define UART_PUT_UTSR0(sport,v) __raw_writel((v),(sport)->port.membase + UTSR0)
|
||||
#define UART_PUT_UTSR1(sport,v) __raw_writel((v),(sport)->port.membase + UTSR1)
|
||||
#define UART_PUT_CHAR(sport,v) __raw_writel((v),(sport)->port.membase + UTDR)
|
||||
|
||||
/*
|
||||
* This is the size of our serial port register set.
|
||||
*/
|
||||
#define UART_PORT_SIZE 0x24
|
||||
|
||||
/*
|
||||
* This determines how often we check the modem status signals
|
||||
* for any change. They generally aren't connected to an IRQ
|
||||
* so we have to poll them. We also check immediately before
|
||||
* filling the TX fifo incase CTS has been dropped.
|
||||
*/
|
||||
#define MCTRL_TIMEOUT (250*HZ/1000)
|
||||
|
||||
struct sa1100_port {
|
||||
struct uart_port port;
|
||||
struct timer_list timer;
|
||||
unsigned int old_status;
|
||||
};
|
||||
|
||||
/*
|
||||
* Handle any change of modem status signal since we were last called.
|
||||
*/
|
||||
static void sa1100_mctrl_check(struct sa1100_port *sport)
|
||||
{
|
||||
unsigned int status, changed;
|
||||
|
||||
status = sport->port.ops->get_mctrl(&sport->port);
|
||||
changed = status ^ sport->old_status;
|
||||
|
||||
if (changed == 0)
|
||||
return;
|
||||
|
||||
sport->old_status = status;
|
||||
|
||||
if (changed & TIOCM_RI)
|
||||
sport->port.icount.rng++;
|
||||
if (changed & TIOCM_DSR)
|
||||
sport->port.icount.dsr++;
|
||||
if (changed & TIOCM_CAR)
|
||||
uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
|
||||
if (changed & TIOCM_CTS)
|
||||
uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
|
||||
|
||||
wake_up_interruptible(&sport->port.info->delta_msr_wait);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is our per-port timeout handler, for checking the
|
||||
* modem status signals.
|
||||
*/
|
||||
static void sa1100_timeout(unsigned long data)
|
||||
{
|
||||
struct sa1100_port *sport = (struct sa1100_port *)data;
|
||||
unsigned long flags;
|
||||
|
||||
if (sport->port.info) {
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
sa1100_mctrl_check(sport);
|
||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||
|
||||
mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* interrupts disabled on entry
|
||||
*/
|
||||
static void sa1100_stop_tx(struct uart_port *port, unsigned int tty_stop)
|
||||
{
|
||||
struct sa1100_port *sport = (struct sa1100_port *)port;
|
||||
u32 utcr3;
|
||||
|
||||
utcr3 = UART_GET_UTCR3(sport);
|
||||
UART_PUT_UTCR3(sport, utcr3 & ~UTCR3_TIE);
|
||||
sport->port.read_status_mask &= ~UTSR0_TO_SM(UTSR0_TFS);
|
||||
}
|
||||
|
||||
/*
|
||||
* interrupts may not be disabled on entry
|
||||
*/
|
||||
static void sa1100_start_tx(struct uart_port *port, unsigned int tty_start)
|
||||
{
|
||||
struct sa1100_port *sport = (struct sa1100_port *)port;
|
||||
unsigned long flags;
|
||||
u32 utcr3;
|
||||
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
utcr3 = UART_GET_UTCR3(sport);
|
||||
sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_TFS);
|
||||
UART_PUT_UTCR3(sport, utcr3 | UTCR3_TIE);
|
||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupts enabled
|
||||
*/
|
||||
static void sa1100_stop_rx(struct uart_port *port)
|
||||
{
|
||||
struct sa1100_port *sport = (struct sa1100_port *)port;
|
||||
u32 utcr3;
|
||||
|
||||
utcr3 = UART_GET_UTCR3(sport);
|
||||
UART_PUT_UTCR3(sport, utcr3 & ~UTCR3_RIE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the modem control timer to fire immediately.
|
||||
*/
|
||||
static void sa1100_enable_ms(struct uart_port *port)
|
||||
{
|
||||
struct sa1100_port *sport = (struct sa1100_port *)port;
|
||||
|
||||
mod_timer(&sport->timer, jiffies);
|
||||
}
|
||||
|
||||
static void
|
||||
sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
|
||||
{
|
||||
struct tty_struct *tty = sport->port.info->tty;
|
||||
unsigned int status, ch, flg, ignored = 0;
|
||||
|
||||
status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
|
||||
UTSR0_TO_SM(UART_GET_UTSR0(sport));
|
||||
while (status & UTSR1_TO_SM(UTSR1_RNE)) {
|
||||
ch = UART_GET_CHAR(sport);
|
||||
|
||||
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
|
||||
goto ignore_char;
|
||||
sport->port.icount.rx++;
|
||||
|
||||
flg = TTY_NORMAL;
|
||||
|
||||
/*
|
||||
* note that the error handling code is
|
||||
* out of the main execution path
|
||||
*/
|
||||
if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR))
|
||||
goto handle_error;
|
||||
|
||||
if (uart_handle_sysrq_char(&sport->port, ch, regs))
|
||||
goto ignore_char;
|
||||
|
||||
error_return:
|
||||
tty_insert_flip_char(tty, ch, flg);
|
||||
ignore_char:
|
||||
status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
|
||||
UTSR0_TO_SM(UART_GET_UTSR0(sport));
|
||||
}
|
||||
out:
|
||||
tty_flip_buffer_push(tty);
|
||||
return;
|
||||
|
||||
handle_error:
|
||||
if (status & UTSR1_TO_SM(UTSR1_PRE))
|
||||
sport->port.icount.parity++;
|
||||
else if (status & UTSR1_TO_SM(UTSR1_FRE))
|
||||
sport->port.icount.frame++;
|
||||
if (status & UTSR1_TO_SM(UTSR1_ROR))
|
||||
sport->port.icount.overrun++;
|
||||
|
||||
if (status & sport->port.ignore_status_mask) {
|
||||
if (++ignored > 100)
|
||||
goto out;
|
||||
goto ignore_char;
|
||||
}
|
||||
|
||||
status &= sport->port.read_status_mask;
|
||||
|
||||
if (status & UTSR1_TO_SM(UTSR1_PRE))
|
||||
flg = TTY_PARITY;
|
||||
else if (status & UTSR1_TO_SM(UTSR1_FRE))
|
||||
flg = TTY_FRAME;
|
||||
|
||||
if (status & UTSR1_TO_SM(UTSR1_ROR)) {
|
||||
/*
|
||||
* overrun does *not* affect the character
|
||||
* we read from the FIFO
|
||||
*/
|
||||
tty_insert_flip_char(tty, ch, flg);
|
||||
ch = 0;
|
||||
flg = TTY_OVERRUN;
|
||||
}
|
||||
#ifdef SUPPORT_SYSRQ
|
||||
sport->port.sysrq = 0;
|
||||
#endif
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
static void sa1100_tx_chars(struct sa1100_port *sport)
|
||||
{
|
||||
struct circ_buf *xmit = &sport->port.info->xmit;
|
||||
|
||||
if (sport->port.x_char) {
|
||||
UART_PUT_CHAR(sport, sport->port.x_char);
|
||||
sport->port.icount.tx++;
|
||||
sport->port.x_char = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the modem control lines before
|
||||
* transmitting anything.
|
||||
*/
|
||||
sa1100_mctrl_check(sport);
|
||||
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
|
||||
sa1100_stop_tx(&sport->port, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tried using FIFO (not checking TNF) for fifo fill:
|
||||
* still had the '4 bytes repeated' problem.
|
||||
*/
|
||||
while (UART_GET_UTSR1(sport) & UTSR1_TNF) {
|
||||
UART_PUT_CHAR(sport, xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
sport->port.icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
}
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(&sport->port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
sa1100_stop_tx(&sport->port, 0);
|
||||
}
|
||||
|
||||
static irqreturn_t sa1100_int(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct sa1100_port *sport = dev_id;
|
||||
unsigned int status, pass_counter = 0;
|
||||
|
||||
spin_lock(&sport->port.lock);
|
||||
status = UART_GET_UTSR0(sport);
|
||||
status &= SM_TO_UTSR0(sport->port.read_status_mask) | ~UTSR0_TFS;
|
||||
do {
|
||||
if (status & (UTSR0_RFS | UTSR0_RID)) {
|
||||
/* Clear the receiver idle bit, if set */
|
||||
if (status & UTSR0_RID)
|
||||
UART_PUT_UTSR0(sport, UTSR0_RID);
|
||||
sa1100_rx_chars(sport, regs);
|
||||
}
|
||||
|
||||
/* Clear the relevant break bits */
|
||||
if (status & (UTSR0_RBB | UTSR0_REB))
|
||||
UART_PUT_UTSR0(sport, status & (UTSR0_RBB | UTSR0_REB));
|
||||
|
||||
if (status & UTSR0_RBB)
|
||||
sport->port.icount.brk++;
|
||||
|
||||
if (status & UTSR0_REB)
|
||||
uart_handle_break(&sport->port);
|
||||
|
||||
if (status & UTSR0_TFS)
|
||||
sa1100_tx_chars(sport);
|
||||
if (pass_counter++ > SA1100_ISR_PASS_LIMIT)
|
||||
break;
|
||||
status = UART_GET_UTSR0(sport);
|
||||
status &= SM_TO_UTSR0(sport->port.read_status_mask) |
|
||||
~UTSR0_TFS;
|
||||
} while (status & (UTSR0_TFS | UTSR0_RFS | UTSR0_RID));
|
||||
spin_unlock(&sport->port.lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TIOCSER_TEMT when transmitter is not busy.
|
||||
*/
|
||||
static unsigned int sa1100_tx_empty(struct uart_port *port)
|
||||
{
|
||||
struct sa1100_port *sport = (struct sa1100_port *)port;
|
||||
|
||||
return UART_GET_UTSR1(sport) & UTSR1_TBY ? 0 : TIOCSER_TEMT;
|
||||
}
|
||||
|
||||
static unsigned int sa1100_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
|
||||
}
|
||||
|
||||
static void sa1100_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupts always disabled.
|
||||
*/
|
||||
static void sa1100_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
struct sa1100_port *sport = (struct sa1100_port *)port;
|
||||
unsigned long flags;
|
||||
unsigned int utcr3;
|
||||
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
utcr3 = UART_GET_UTCR3(sport);
|
||||
if (break_state == -1)
|
||||
utcr3 |= UTCR3_BRK;
|
||||
else
|
||||
utcr3 &= ~UTCR3_BRK;
|
||||
UART_PUT_UTCR3(sport, utcr3);
|
||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||
}
|
||||
|
||||
static int sa1100_startup(struct uart_port *port)
|
||||
{
|
||||
struct sa1100_port *sport = (struct sa1100_port *)port;
|
||||
int retval;
|
||||
|
||||
/*
|
||||
* Allocate the IRQ
|
||||
*/
|
||||
retval = request_irq(sport->port.irq, sa1100_int, 0,
|
||||
"sa11x0-uart", sport);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/*
|
||||
* Finally, clear and enable interrupts
|
||||
*/
|
||||
UART_PUT_UTSR0(sport, -1);
|
||||
UART_PUT_UTCR3(sport, UTCR3_RXE | UTCR3_TXE | UTCR3_RIE);
|
||||
|
||||
/*
|
||||
* Enable modem status interrupts
|
||||
*/
|
||||
spin_lock_irq(&sport->port.lock);
|
||||
sa1100_enable_ms(&sport->port);
|
||||
spin_unlock_irq(&sport->port.lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sa1100_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct sa1100_port *sport = (struct sa1100_port *)port;
|
||||
|
||||
/*
|
||||
* Stop our timer.
|
||||
*/
|
||||
del_timer_sync(&sport->timer);
|
||||
|
||||
/*
|
||||
* Free the interrupt
|
||||
*/
|
||||
free_irq(sport->port.irq, sport);
|
||||
|
||||
/*
|
||||
* Disable all interrupts, port and break condition.
|
||||
*/
|
||||
UART_PUT_UTCR3(sport, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
sa1100_set_termios(struct uart_port *port, struct termios *termios,
|
||||
struct termios *old)
|
||||
{
|
||||
struct sa1100_port *sport = (struct sa1100_port *)port;
|
||||
unsigned long flags;
|
||||
unsigned int utcr0, old_utcr3, baud, quot;
|
||||
unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
|
||||
|
||||
/*
|
||||
* We only support CS7 and CS8.
|
||||
*/
|
||||
while ((termios->c_cflag & CSIZE) != CS7 &&
|
||||
(termios->c_cflag & CSIZE) != CS8) {
|
||||
termios->c_cflag &= ~CSIZE;
|
||||
termios->c_cflag |= old_csize;
|
||||
old_csize = CS8;
|
||||
}
|
||||
|
||||
if ((termios->c_cflag & CSIZE) == CS8)
|
||||
utcr0 = UTCR0_DSS;
|
||||
else
|
||||
utcr0 = 0;
|
||||
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
utcr0 |= UTCR0_SBS;
|
||||
if (termios->c_cflag & PARENB) {
|
||||
utcr0 |= UTCR0_PE;
|
||||
if (!(termios->c_cflag & PARODD))
|
||||
utcr0 |= UTCR0_OES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ask the core to calculate the divisor for us.
|
||||
*/
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
|
||||
quot = uart_get_divisor(port, baud);
|
||||
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
|
||||
sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS);
|
||||
sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR);
|
||||
if (termios->c_iflag & INPCK)
|
||||
sport->port.read_status_mask |=
|
||||
UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
|
||||
if (termios->c_iflag & (BRKINT | PARMRK))
|
||||
sport->port.read_status_mask |=
|
||||
UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
|
||||
|
||||
/*
|
||||
* Characters to ignore
|
||||
*/
|
||||
sport->port.ignore_status_mask = 0;
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
sport->port.ignore_status_mask |=
|
||||
UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE);
|
||||
if (termios->c_iflag & IGNBRK) {
|
||||
sport->port.ignore_status_mask |=
|
||||
UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB);
|
||||
/*
|
||||
* If we're ignoring parity and break indicators,
|
||||
* ignore overruns too (for real raw support).
|
||||
*/
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
sport->port.ignore_status_mask |=
|
||||
UTSR1_TO_SM(UTSR1_ROR);
|
||||
}
|
||||
|
||||
del_timer_sync(&sport->timer);
|
||||
|
||||
/*
|
||||
* Update the per-port timeout.
|
||||
*/
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
/*
|
||||
* disable interrupts and drain transmitter
|
||||
*/
|
||||
old_utcr3 = UART_GET_UTCR3(sport);
|
||||
UART_PUT_UTCR3(sport, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE));
|
||||
|
||||
while (UART_GET_UTSR1(sport) & UTSR1_TBY)
|
||||
barrier();
|
||||
|
||||
/* then, disable everything */
|
||||
UART_PUT_UTCR3(sport, 0);
|
||||
|
||||
/* set the parity, stop bits and data size */
|
||||
UART_PUT_UTCR0(sport, utcr0);
|
||||
|
||||
/* set the baud rate */
|
||||
quot -= 1;
|
||||
UART_PUT_UTCR1(sport, ((quot & 0xf00) >> 8));
|
||||
UART_PUT_UTCR2(sport, (quot & 0xff));
|
||||
|
||||
UART_PUT_UTSR0(sport, -1);
|
||||
|
||||
UART_PUT_UTCR3(sport, old_utcr3);
|
||||
|
||||
if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
|
||||
sa1100_enable_ms(&sport->port);
|
||||
|
||||
spin_unlock_irqrestore(&sport->port.lock, flags);
|
||||
}
|
||||
|
||||
static const char *sa1100_type(struct uart_port *port)
|
||||
{
|
||||
struct sa1100_port *sport = (struct sa1100_port *)port;
|
||||
|
||||
return sport->port.type == PORT_SA1100 ? "SA1100" : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the memory region(s) being used by 'port'.
|
||||
*/
|
||||
static void sa1100_release_port(struct uart_port *port)
|
||||
{
|
||||
struct sa1100_port *sport = (struct sa1100_port *)port;
|
||||
|
||||
release_mem_region(sport->port.mapbase, UART_PORT_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Request the memory region(s) being used by 'port'.
|
||||
*/
|
||||
static int sa1100_request_port(struct uart_port *port)
|
||||
{
|
||||
struct sa1100_port *sport = (struct sa1100_port *)port;
|
||||
|
||||
return request_mem_region(sport->port.mapbase, UART_PORT_SIZE,
|
||||
"sa11x0-uart") != NULL ? 0 : -EBUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure/autoconfigure the port.
|
||||
*/
|
||||
static void sa1100_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
struct sa1100_port *sport = (struct sa1100_port *)port;
|
||||
|
||||
if (flags & UART_CONFIG_TYPE &&
|
||||
sa1100_request_port(&sport->port) == 0)
|
||||
sport->port.type = PORT_SA1100;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify the new serial_struct (for TIOCSSERIAL).
|
||||
* The only change we allow are to the flags and type, and
|
||||
* even then only between PORT_SA1100 and PORT_UNKNOWN
|
||||
*/
|
||||
static int
|
||||
sa1100_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||
{
|
||||
struct sa1100_port *sport = (struct sa1100_port *)port;
|
||||
int ret = 0;
|
||||
|
||||
if (ser->type != PORT_UNKNOWN && ser->type != PORT_SA1100)
|
||||
ret = -EINVAL;
|
||||
if (sport->port.irq != ser->irq)
|
||||
ret = -EINVAL;
|
||||
if (ser->io_type != SERIAL_IO_MEM)
|
||||
ret = -EINVAL;
|
||||
if (sport->port.uartclk / 16 != ser->baud_base)
|
||||
ret = -EINVAL;
|
||||
if ((void *)sport->port.mapbase != ser->iomem_base)
|
||||
ret = -EINVAL;
|
||||
if (sport->port.iobase != ser->port)
|
||||
ret = -EINVAL;
|
||||
if (ser->hub6 != 0)
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct uart_ops sa1100_pops = {
|
||||
.tx_empty = sa1100_tx_empty,
|
||||
.set_mctrl = sa1100_set_mctrl,
|
||||
.get_mctrl = sa1100_get_mctrl,
|
||||
.stop_tx = sa1100_stop_tx,
|
||||
.start_tx = sa1100_start_tx,
|
||||
.stop_rx = sa1100_stop_rx,
|
||||
.enable_ms = sa1100_enable_ms,
|
||||
.break_ctl = sa1100_break_ctl,
|
||||
.startup = sa1100_startup,
|
||||
.shutdown = sa1100_shutdown,
|
||||
.set_termios = sa1100_set_termios,
|
||||
.type = sa1100_type,
|
||||
.release_port = sa1100_release_port,
|
||||
.request_port = sa1100_request_port,
|
||||
.config_port = sa1100_config_port,
|
||||
.verify_port = sa1100_verify_port,
|
||||
};
|
||||
|
||||
static struct sa1100_port sa1100_ports[NR_PORTS];
|
||||
|
||||
/*
|
||||
* Setup the SA1100 serial ports. Note that we don't include the IrDA
|
||||
* port here since we have our own SIR/FIR driver (see drivers/net/irda)
|
||||
*
|
||||
* Note also that we support "console=ttySAx" where "x" is either 0 or 1.
|
||||
* Which serial port this ends up being depends on the machine you're
|
||||
* running this kernel on. I'm not convinced that this is a good idea,
|
||||
* but that's the way it traditionally works.
|
||||
*
|
||||
* Note that NanoEngine UART3 becomes UART2, and UART2 is no longer
|
||||
* used here.
|
||||
*/
|
||||
static void __init sa1100_init_ports(void)
|
||||
{
|
||||
static int first = 1;
|
||||
int i;
|
||||
|
||||
if (!first)
|
||||
return;
|
||||
first = 0;
|
||||
|
||||
for (i = 0; i < NR_PORTS; i++) {
|
||||
sa1100_ports[i].port.uartclk = 3686400;
|
||||
sa1100_ports[i].port.ops = &sa1100_pops;
|
||||
sa1100_ports[i].port.fifosize = 8;
|
||||
sa1100_ports[i].port.line = i;
|
||||
sa1100_ports[i].port.iotype = SERIAL_IO_MEM;
|
||||
init_timer(&sa1100_ports[i].timer);
|
||||
sa1100_ports[i].timer.function = sa1100_timeout;
|
||||
sa1100_ports[i].timer.data = (unsigned long)&sa1100_ports[i];
|
||||
}
|
||||
|
||||
/*
|
||||
* make transmit lines outputs, so that when the port
|
||||
* is closed, the output is in the MARK state.
|
||||
*/
|
||||
PPDR |= PPC_TXD1 | PPC_TXD3;
|
||||
PPSR |= PPC_TXD1 | PPC_TXD3;
|
||||
}
|
||||
|
||||
void __init sa1100_register_uart_fns(struct sa1100_port_fns *fns)
|
||||
{
|
||||
if (fns->get_mctrl)
|
||||
sa1100_pops.get_mctrl = fns->get_mctrl;
|
||||
if (fns->set_mctrl)
|
||||
sa1100_pops.set_mctrl = fns->set_mctrl;
|
||||
|
||||
sa1100_pops.pm = fns->pm;
|
||||
sa1100_pops.set_wake = fns->set_wake;
|
||||
}
|
||||
|
||||
void __init sa1100_register_uart(int idx, int port)
|
||||
{
|
||||
if (idx >= NR_PORTS) {
|
||||
printk(KERN_ERR "%s: bad index number %d\n", __FUNCTION__, idx);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (port) {
|
||||
case 1:
|
||||
sa1100_ports[idx].port.membase = (void *)&Ser1UTCR0;
|
||||
sa1100_ports[idx].port.mapbase = _Ser1UTCR0;
|
||||
sa1100_ports[idx].port.irq = IRQ_Ser1UART;
|
||||
sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
sa1100_ports[idx].port.membase = (void *)&Ser2UTCR0;
|
||||
sa1100_ports[idx].port.mapbase = _Ser2UTCR0;
|
||||
sa1100_ports[idx].port.irq = IRQ_Ser2ICP;
|
||||
sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
sa1100_ports[idx].port.membase = (void *)&Ser3UTCR0;
|
||||
sa1100_ports[idx].port.mapbase = _Ser3UTCR0;
|
||||
sa1100_ports[idx].port.irq = IRQ_Ser3UART;
|
||||
sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR "%s: bad port number %d\n", __FUNCTION__, port);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_SERIAL_SA1100_CONSOLE
|
||||
|
||||
/*
|
||||
* Interrupts are disabled on entering
|
||||
*/
|
||||
static void
|
||||
sa1100_console_write(struct console *co, const char *s, unsigned int count)
|
||||
{
|
||||
struct sa1100_port *sport = &sa1100_ports[co->index];
|
||||
unsigned int old_utcr3, status, i;
|
||||
|
||||
/*
|
||||
* First, save UTCR3 and then disable interrupts
|
||||
*/
|
||||
old_utcr3 = UART_GET_UTCR3(sport);
|
||||
UART_PUT_UTCR3(sport, (old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)) |
|
||||
UTCR3_TXE);
|
||||
|
||||
/*
|
||||
* Now, do each character
|
||||
*/
|
||||
for (i = 0; i < count; i++) {
|
||||
do {
|
||||
status = UART_GET_UTSR1(sport);
|
||||
} while (!(status & UTSR1_TNF));
|
||||
UART_PUT_CHAR(sport, s[i]);
|
||||
if (s[i] == '\n') {
|
||||
do {
|
||||
status = UART_GET_UTSR1(sport);
|
||||
} while (!(status & UTSR1_TNF));
|
||||
UART_PUT_CHAR(sport, '\r');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, wait for transmitter to become empty
|
||||
* and restore UTCR3
|
||||
*/
|
||||
do {
|
||||
status = UART_GET_UTSR1(sport);
|
||||
} while (status & UTSR1_TBY);
|
||||
UART_PUT_UTCR3(sport, old_utcr3);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the port was already initialised (eg, by a boot loader),
|
||||
* try to determine the current setup.
|
||||
*/
|
||||
static void __init
|
||||
sa1100_console_get_options(struct sa1100_port *sport, int *baud,
|
||||
int *parity, int *bits)
|
||||
{
|
||||
unsigned int utcr3;
|
||||
|
||||
utcr3 = UART_GET_UTCR3(sport) & (UTCR3_RXE | UTCR3_TXE);
|
||||
if (utcr3 == (UTCR3_RXE | UTCR3_TXE)) {
|
||||
/* ok, the port was enabled */
|
||||
unsigned int utcr0, quot;
|
||||
|
||||
utcr0 = UART_GET_UTCR0(sport);
|
||||
|
||||
*parity = 'n';
|
||||
if (utcr0 & UTCR0_PE) {
|
||||
if (utcr0 & UTCR0_OES)
|
||||
*parity = 'e';
|
||||
else
|
||||
*parity = 'o';
|
||||
}
|
||||
|
||||
if (utcr0 & UTCR0_DSS)
|
||||
*bits = 8;
|
||||
else
|
||||
*bits = 7;
|
||||
|
||||
quot = UART_GET_UTCR2(sport) | UART_GET_UTCR1(sport) << 8;
|
||||
quot &= 0xfff;
|
||||
*baud = sport->port.uartclk / (16 * (quot + 1));
|
||||
}
|
||||
}
|
||||
|
||||
static int __init
|
||||
sa1100_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct sa1100_port *sport;
|
||||
int baud = 9600;
|
||||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
|
||||
/*
|
||||
* Check whether an invalid uart number has been specified, and
|
||||
* if so, search for the first available port that does have
|
||||
* console support.
|
||||
*/
|
||||
if (co->index == -1 || co->index >= NR_PORTS)
|
||||
co->index = 0;
|
||||
sport = &sa1100_ports[co->index];
|
||||
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
else
|
||||
sa1100_console_get_options(sport, &baud, &parity, &bits);
|
||||
|
||||
return uart_set_options(&sport->port, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
extern struct uart_driver sa1100_reg;
|
||||
static struct console sa1100_console = {
|
||||
.name = "ttySA",
|
||||
.write = sa1100_console_write,
|
||||
.device = uart_console_device,
|
||||
.setup = sa1100_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
.data = &sa1100_reg,
|
||||
};
|
||||
|
||||
static int __init sa1100_rs_console_init(void)
|
||||
{
|
||||
sa1100_init_ports();
|
||||
register_console(&sa1100_console);
|
||||
return 0;
|
||||
}
|
||||
console_initcall(sa1100_rs_console_init);
|
||||
|
||||
#define SA1100_CONSOLE &sa1100_console
|
||||
#else
|
||||
#define SA1100_CONSOLE NULL
|
||||
#endif
|
||||
|
||||
static struct uart_driver sa1100_reg = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = "ttySA",
|
||||
.dev_name = "ttySA",
|
||||
.devfs_name = "ttySA",
|
||||
.major = SERIAL_SA1100_MAJOR,
|
||||
.minor = MINOR_START,
|
||||
.nr = NR_PORTS,
|
||||
.cons = SA1100_CONSOLE,
|
||||
};
|
||||
|
||||
static int sa1100_serial_suspend(struct device *_dev, u32 state, u32 level)
|
||||
{
|
||||
struct sa1100_port *sport = dev_get_drvdata(_dev);
|
||||
|
||||
if (sport && level == SUSPEND_DISABLE)
|
||||
uart_suspend_port(&sa1100_reg, &sport->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sa1100_serial_resume(struct device *_dev, u32 level)
|
||||
{
|
||||
struct sa1100_port *sport = dev_get_drvdata(_dev);
|
||||
|
||||
if (sport && level == RESUME_ENABLE)
|
||||
uart_resume_port(&sa1100_reg, &sport->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sa1100_serial_probe(struct device *_dev)
|
||||
{
|
||||
struct platform_device *dev = to_platform_device(_dev);
|
||||
struct resource *res = dev->resource;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev->num_resources; i++, res++)
|
||||
if (res->flags & IORESOURCE_MEM)
|
||||
break;
|
||||
|
||||
if (i < dev->num_resources) {
|
||||
for (i = 0; i < NR_PORTS; i++) {
|
||||
if (sa1100_ports[i].port.mapbase != res->start)
|
||||
continue;
|
||||
|
||||
sa1100_ports[i].port.dev = _dev;
|
||||
uart_add_one_port(&sa1100_reg, &sa1100_ports[i].port);
|
||||
dev_set_drvdata(_dev, &sa1100_ports[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sa1100_serial_remove(struct device *_dev)
|
||||
{
|
||||
struct sa1100_port *sport = dev_get_drvdata(_dev);
|
||||
|
||||
dev_set_drvdata(_dev, NULL);
|
||||
|
||||
if (sport)
|
||||
uart_remove_one_port(&sa1100_reg, &sport->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct device_driver sa11x0_serial_driver = {
|
||||
.name = "sa11x0-uart",
|
||||
.bus = &platform_bus_type,
|
||||
.probe = sa1100_serial_probe,
|
||||
.remove = sa1100_serial_remove,
|
||||
.suspend = sa1100_serial_suspend,
|
||||
.resume = sa1100_serial_resume,
|
||||
};
|
||||
|
||||
static int __init sa1100_serial_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printk(KERN_INFO "Serial: SA11x0 driver $Revision: 1.50 $\n");
|
||||
|
||||
sa1100_init_ports();
|
||||
|
||||
ret = uart_register_driver(&sa1100_reg);
|
||||
if (ret == 0) {
|
||||
ret = driver_register(&sa11x0_serial_driver);
|
||||
if (ret)
|
||||
uart_unregister_driver(&sa1100_reg);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit sa1100_serial_exit(void)
|
||||
{
|
||||
driver_unregister(&sa11x0_serial_driver);
|
||||
uart_unregister_driver(&sa1100_reg);
|
||||
}
|
||||
|
||||
module_init(sa1100_serial_init);
|
||||
module_exit(sa1100_serial_exit);
|
||||
|
||||
MODULE_AUTHOR("Deep Blue Solutions Ltd");
|
||||
MODULE_DESCRIPTION("SA1100 generic serial port driver $Revision: 1.50 $");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_SA1100_MAJOR);
|
||||
2380
extra/linux-2.6.10/drivers/serial/serial_core.c
Normal file
2380
extra/linux-2.6.10/drivers/serial/serial_core.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
extra/linux-2.6.10/drivers/serial/serial_core.o
Normal file
BIN
extra/linux-2.6.10/drivers/serial/serial_core.o
Normal file
Binary file not shown.
761
extra/linux-2.6.10/drivers/serial/serial_cs.c
Normal file
761
extra/linux-2.6.10/drivers/serial/serial_cs.c
Normal file
@@ -0,0 +1,761 @@
|
||||
/*======================================================================
|
||||
|
||||
A driver for PCMCIA serial devices
|
||||
|
||||
serial_cs.c 1.134 2002/05/04 05:48:53
|
||||
|
||||
The contents of this file are subject to the Mozilla Public
|
||||
License Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License. You may obtain a copy of
|
||||
the License at http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS
|
||||
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
rights and limitations under the License.
|
||||
|
||||
The initial developer of the original code is David A. Hinds
|
||||
<dahinds@users.sourceforge.net>. Portions created by David A. Hinds
|
||||
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
|
||||
|
||||
Alternatively, the contents of this file may be used under the
|
||||
terms of the GNU General Public License version 2 (the "GPL"), in which
|
||||
case the provisions of the GPL are applicable instead of the
|
||||
above. If you wish to allow the use of your version of this file
|
||||
only under the terms of the GPL and not to allow others to use
|
||||
your version of this file under the MPL, indicate your decision
|
||||
by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this
|
||||
file under either the MPL or the GPL.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/major.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
#include <pcmcia/version.h>
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include <pcmcia/ciscode.h>
|
||||
#include <pcmcia/ds.h>
|
||||
#include <pcmcia/cisreg.h>
|
||||
|
||||
#include "8250.h"
|
||||
|
||||
#ifdef PCMCIA_DEBUG
|
||||
static int pc_debug = PCMCIA_DEBUG;
|
||||
module_param(pc_debug, int, 0644);
|
||||
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
|
||||
static char *version = "serial_cs.c 1.134 2002/05/04 05:48:53 (David Hinds)";
|
||||
#else
|
||||
#define DEBUG(n, args...)
|
||||
#endif
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
/* Parameters that can be set with 'insmod' */
|
||||
|
||||
/* Bit map of interrupts to choose from */
|
||||
static u_int irq_mask = 0xdeb8;
|
||||
static int irq_list[4];
|
||||
static unsigned int irq_list_count;
|
||||
|
||||
/* Enable the speaker? */
|
||||
static int do_sound = 1;
|
||||
/* Skip strict UART tests? */
|
||||
static int buggy_uart;
|
||||
|
||||
module_param(irq_mask, uint, 0444);
|
||||
module_param_array(irq_list, int, &irq_list_count, 0444);
|
||||
module_param(do_sound, int, 0444);
|
||||
module_param(buggy_uart, int, 0444);
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
/* Table of multi-port card ID's */
|
||||
|
||||
struct multi_id {
|
||||
u_short manfid;
|
||||
u_short prodid;
|
||||
int multi; /* 1 = multifunction, > 1 = # ports */
|
||||
};
|
||||
|
||||
static struct multi_id multi_id[] = {
|
||||
{ MANFID_OMEGA, PRODID_OMEGA_QSP_100, 4 },
|
||||
{ MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232, 2 },
|
||||
{ MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232_D1, 2 },
|
||||
{ MANFID_QUATECH, PRODID_QUATECH_QUAD_RS232, 4 },
|
||||
{ MANFID_SOCKET, PRODID_SOCKET_DUAL_RS232, 2 },
|
||||
{ MANFID_INTEL, PRODID_INTEL_DUAL_RS232, 2 },
|
||||
{ MANFID_NATINST, PRODID_NATINST_QUAD_RS232, 4 }
|
||||
};
|
||||
#define MULTI_COUNT (sizeof(multi_id)/sizeof(struct multi_id))
|
||||
|
||||
struct serial_info {
|
||||
dev_link_t link;
|
||||
int ndev;
|
||||
int multi;
|
||||
int slave;
|
||||
int manfid;
|
||||
dev_node_t node[4];
|
||||
int line[4];
|
||||
};
|
||||
|
||||
static void serial_config(dev_link_t * link);
|
||||
static int serial_event(event_t event, int priority,
|
||||
event_callback_args_t * args);
|
||||
|
||||
static dev_info_t dev_info = "serial_cs";
|
||||
|
||||
static dev_link_t *serial_attach(void);
|
||||
static void serial_detach(dev_link_t *);
|
||||
|
||||
static dev_link_t *dev_list = NULL;
|
||||
|
||||
/*======================================================================
|
||||
|
||||
After a card is removed, serial_remove() will unregister
|
||||
the serial device(s), and release the PCMCIA configuration.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static void serial_remove(dev_link_t *link)
|
||||
{
|
||||
struct serial_info *info = link->priv;
|
||||
int i;
|
||||
|
||||
link->state &= ~DEV_PRESENT;
|
||||
|
||||
DEBUG(0, "serial_release(0x%p)\n", link);
|
||||
|
||||
/*
|
||||
* Recheck to see if the device is still configured.
|
||||
*/
|
||||
if (info->link.state & DEV_CONFIG) {
|
||||
for (i = 0; i < info->ndev; i++)
|
||||
serial8250_unregister_port(info->line[i]);
|
||||
|
||||
info->link.dev = NULL;
|
||||
|
||||
if (!info->slave) {
|
||||
pcmcia_release_configuration(info->link.handle);
|
||||
pcmcia_release_io(info->link.handle, &info->link.io);
|
||||
pcmcia_release_irq(info->link.handle, &info->link.irq);
|
||||
}
|
||||
|
||||
info->link.state &= ~DEV_CONFIG;
|
||||
}
|
||||
}
|
||||
|
||||
static void serial_suspend(dev_link_t *link)
|
||||
{
|
||||
link->state |= DEV_SUSPEND;
|
||||
|
||||
if (link->state & DEV_CONFIG) {
|
||||
struct serial_info *info = link->priv;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < info->ndev; i++)
|
||||
serial8250_suspend_port(info->line[i]);
|
||||
|
||||
if (!info->slave)
|
||||
pcmcia_release_configuration(link->handle);
|
||||
}
|
||||
}
|
||||
|
||||
static void serial_resume(dev_link_t *link)
|
||||
{
|
||||
link->state &= ~DEV_SUSPEND;
|
||||
|
||||
if (DEV_OK(link)) {
|
||||
struct serial_info *info = link->priv;
|
||||
int i;
|
||||
|
||||
if (!info->slave)
|
||||
pcmcia_request_configuration(link->handle, &link->conf);
|
||||
|
||||
for (i = 0; i < info->ndev; i++)
|
||||
serial8250_resume_port(info->line[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*======================================================================
|
||||
|
||||
serial_attach() creates an "instance" of the driver, allocating
|
||||
local data structures for one device. The device is registered
|
||||
with Card Services.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static dev_link_t *serial_attach(void)
|
||||
{
|
||||
struct serial_info *info;
|
||||
client_reg_t client_reg;
|
||||
dev_link_t *link;
|
||||
int i, ret;
|
||||
|
||||
DEBUG(0, "serial_attach()\n");
|
||||
|
||||
/* Create new serial device */
|
||||
info = kmalloc(sizeof (*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return NULL;
|
||||
memset(info, 0, sizeof (*info));
|
||||
link = &info->link;
|
||||
link->priv = info;
|
||||
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
|
||||
link->io.NumPorts1 = 8;
|
||||
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
|
||||
link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
|
||||
if (irq_list_count == 0)
|
||||
link->irq.IRQInfo2 = irq_mask;
|
||||
else
|
||||
for (i = 0; i < irq_list_count; i++)
|
||||
link->irq.IRQInfo2 |= 1 << irq_list[i];
|
||||
link->conf.Attributes = CONF_ENABLE_IRQ;
|
||||
if (do_sound) {
|
||||
link->conf.Attributes |= CONF_ENABLE_SPKR;
|
||||
link->conf.Status = CCSR_AUDIO_ENA;
|
||||
}
|
||||
link->conf.IntType = INT_MEMORY_AND_IO;
|
||||
|
||||
/* Register with Card Services */
|
||||
link->next = dev_list;
|
||||
dev_list = link;
|
||||
client_reg.dev_info = &dev_info;
|
||||
client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
|
||||
client_reg.EventMask =
|
||||
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
|
||||
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
|
||||
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
|
||||
client_reg.event_handler = &serial_event;
|
||||
client_reg.Version = 0x0210;
|
||||
client_reg.event_callback_args.client_data = link;
|
||||
ret = pcmcia_register_client(&link->handle, &client_reg);
|
||||
if (ret != CS_SUCCESS) {
|
||||
cs_error(link->handle, RegisterClient, ret);
|
||||
serial_detach(link);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
/*======================================================================
|
||||
|
||||
This deletes a driver "instance". The device is de-registered
|
||||
with Card Services. If it has been released, all local data
|
||||
structures are freed. Otherwise, the structures will be freed
|
||||
when the device is released.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static void serial_detach(dev_link_t * link)
|
||||
{
|
||||
struct serial_info *info = link->priv;
|
||||
dev_link_t **linkp;
|
||||
int ret;
|
||||
|
||||
DEBUG(0, "serial_detach(0x%p)\n", link);
|
||||
|
||||
/* Locate device structure */
|
||||
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
|
||||
if (*linkp == link)
|
||||
break;
|
||||
if (*linkp == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Ensure any outstanding scheduled tasks are completed.
|
||||
*/
|
||||
flush_scheduled_work();
|
||||
|
||||
/*
|
||||
* Ensure that the ports have been released.
|
||||
*/
|
||||
serial_remove(link);
|
||||
|
||||
if (link->handle) {
|
||||
ret = pcmcia_deregister_client(link->handle);
|
||||
if (ret != CS_SUCCESS)
|
||||
cs_error(link->handle, DeregisterClient, ret);
|
||||
}
|
||||
|
||||
/* Unlink device structure, free bits */
|
||||
*linkp = link->next;
|
||||
kfree(info);
|
||||
}
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
static int setup_serial(struct serial_info * info, ioaddr_t iobase, int irq)
|
||||
{
|
||||
struct uart_port port;
|
||||
int line;
|
||||
|
||||
memset(&port, 0, sizeof (struct uart_port));
|
||||
port.iobase = iobase;
|
||||
port.irq = irq;
|
||||
port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
|
||||
port.uartclk = 1843200;
|
||||
if (buggy_uart)
|
||||
port.flags |= UPF_BUGGY_UART;
|
||||
line = serial8250_register_port(&port);
|
||||
if (line < 0) {
|
||||
printk(KERN_NOTICE "serial_cs: serial8250_register_port() at "
|
||||
"0x%04lx, irq %d failed\n", (u_long)iobase, irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info->line[info->ndev] = line;
|
||||
sprintf(info->node[info->ndev].dev_name, "ttyS%d", line);
|
||||
info->node[info->ndev].major = TTY_MAJOR;
|
||||
info->node[info->ndev].minor = 0x40 + line;
|
||||
if (info->ndev > 0)
|
||||
info->node[info->ndev - 1].next = &info->node[info->ndev];
|
||||
info->ndev++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
static int
|
||||
first_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
|
||||
{
|
||||
int i;
|
||||
i = pcmcia_get_first_tuple(handle, tuple);
|
||||
if (i != CS_SUCCESS)
|
||||
return CS_NO_MORE_ITEMS;
|
||||
i = pcmcia_get_tuple_data(handle, tuple);
|
||||
if (i != CS_SUCCESS)
|
||||
return i;
|
||||
return pcmcia_parse_tuple(handle, tuple, parse);
|
||||
}
|
||||
|
||||
static int
|
||||
next_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
|
||||
{
|
||||
int i;
|
||||
i = pcmcia_get_next_tuple(handle, tuple);
|
||||
if (i != CS_SUCCESS)
|
||||
return CS_NO_MORE_ITEMS;
|
||||
i = pcmcia_get_tuple_data(handle, tuple);
|
||||
if (i != CS_SUCCESS)
|
||||
return i;
|
||||
return pcmcia_parse_tuple(handle, tuple, parse);
|
||||
}
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
static int simple_config(dev_link_t *link)
|
||||
{
|
||||
static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
|
||||
static int size_table[2] = { 8, 16 };
|
||||
client_handle_t handle = link->handle;
|
||||
struct serial_info *info = link->priv;
|
||||
tuple_t tuple;
|
||||
u_char buf[256];
|
||||
cisparse_t parse;
|
||||
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
|
||||
config_info_t config;
|
||||
int i, j, try;
|
||||
int s;
|
||||
|
||||
/* If the card is already configured, look up the port and irq */
|
||||
i = pcmcia_get_configuration_info(handle, &config);
|
||||
if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) {
|
||||
ioaddr_t port = 0;
|
||||
if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) {
|
||||
port = config.BasePort2;
|
||||
info->slave = 1;
|
||||
} else if ((info->manfid == MANFID_OSITECH) &&
|
||||
(config.NumPorts1 == 0x40)) {
|
||||
port = config.BasePort1 + 0x28;
|
||||
info->slave = 1;
|
||||
}
|
||||
if (info->slave)
|
||||
return setup_serial(info, port, config.AssignedIRQ);
|
||||
}
|
||||
link->conf.Vcc = config.Vcc;
|
||||
|
||||
/* First pass: look for a config entry that looks normal. */
|
||||
tuple.TupleData = (cisdata_t *) buf;
|
||||
tuple.TupleOffset = 0;
|
||||
tuple.TupleDataMax = 255;
|
||||
tuple.Attributes = 0;
|
||||
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
/* Two tries: without IO aliases, then with aliases */
|
||||
for (s = 0; s < 2; s++) {
|
||||
for (try = 0; try < 2; try++) {
|
||||
i = first_tuple(handle, &tuple, &parse);
|
||||
while (i != CS_NO_MORE_ITEMS) {
|
||||
if (i != CS_SUCCESS)
|
||||
goto next_entry;
|
||||
if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
|
||||
link->conf.Vpp1 = link->conf.Vpp2 =
|
||||
cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
|
||||
if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[s]) &&
|
||||
(cf->io.win[0].base != 0)) {
|
||||
link->conf.ConfigIndex = cf->index;
|
||||
link->io.BasePort1 = cf->io.win[0].base;
|
||||
link->io.IOAddrLines = (try == 0) ?
|
||||
16 : cf->io.flags & CISTPL_IO_LINES_MASK;
|
||||
i = pcmcia_request_io(link->handle, &link->io);
|
||||
if (i == CS_SUCCESS)
|
||||
goto found_port;
|
||||
}
|
||||
next_entry:
|
||||
i = next_tuple(handle, &tuple, &parse);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Second pass: try to find an entry that isn't picky about
|
||||
its base address, then try to grab any standard serial port
|
||||
address, and finally try to get any free port. */
|
||||
i = first_tuple(handle, &tuple, &parse);
|
||||
while (i != CS_NO_MORE_ITEMS) {
|
||||
if ((i == CS_SUCCESS) && (cf->io.nwin > 0) &&
|
||||
((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
|
||||
link->conf.ConfigIndex = cf->index;
|
||||
for (j = 0; j < 5; j++) {
|
||||
link->io.BasePort1 = base[j];
|
||||
link->io.IOAddrLines = base[j] ? 16 : 3;
|
||||
i = pcmcia_request_io(link->handle, &link->io);
|
||||
if (i == CS_SUCCESS)
|
||||
goto found_port;
|
||||
}
|
||||
}
|
||||
i = next_tuple(handle, &tuple, &parse);
|
||||
}
|
||||
|
||||
found_port:
|
||||
if (i != CS_SUCCESS) {
|
||||
printk(KERN_NOTICE
|
||||
"serial_cs: no usable port range found, giving up\n");
|
||||
cs_error(link->handle, RequestIO, i);
|
||||
return -1;
|
||||
}
|
||||
|
||||
i = pcmcia_request_irq(link->handle, &link->irq);
|
||||
if (i != CS_SUCCESS) {
|
||||
cs_error(link->handle, RequestIRQ, i);
|
||||
link->irq.AssignedIRQ = 0;
|
||||
}
|
||||
if (info->multi && (info->manfid == MANFID_3COM))
|
||||
link->conf.ConfigIndex &= ~(0x08);
|
||||
i = pcmcia_request_configuration(link->handle, &link->conf);
|
||||
if (i != CS_SUCCESS) {
|
||||
cs_error(link->handle, RequestConfiguration, i);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ);
|
||||
}
|
||||
|
||||
static int multi_config(dev_link_t * link)
|
||||
{
|
||||
client_handle_t handle = link->handle;
|
||||
struct serial_info *info = link->priv;
|
||||
tuple_t tuple;
|
||||
u_char buf[256];
|
||||
cisparse_t parse;
|
||||
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
|
||||
config_info_t config;
|
||||
int i, base2 = 0;
|
||||
|
||||
i = pcmcia_get_configuration_info(handle, &config);
|
||||
if (i != CS_SUCCESS) {
|
||||
cs_error(handle, GetConfigurationInfo, i);
|
||||
return -1;
|
||||
}
|
||||
link->conf.Vcc = config.Vcc;
|
||||
|
||||
tuple.TupleData = (cisdata_t *) buf;
|
||||
tuple.TupleOffset = 0;
|
||||
tuple.TupleDataMax = 255;
|
||||
tuple.Attributes = 0;
|
||||
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
|
||||
/* First, look for a generic full-sized window */
|
||||
link->io.NumPorts1 = info->multi * 8;
|
||||
i = first_tuple(handle, &tuple, &parse);
|
||||
while (i != CS_NO_MORE_ITEMS) {
|
||||
/* The quad port cards have bad CIS's, so just look for a
|
||||
window larger than 8 ports and assume it will be right */
|
||||
if ((i == CS_SUCCESS) && (cf->io.nwin == 1) &&
|
||||
(cf->io.win[0].len > 8)) {
|
||||
link->conf.ConfigIndex = cf->index;
|
||||
link->io.BasePort1 = cf->io.win[0].base;
|
||||
link->io.IOAddrLines =
|
||||
cf->io.flags & CISTPL_IO_LINES_MASK;
|
||||
i = pcmcia_request_io(link->handle, &link->io);
|
||||
base2 = link->io.BasePort1 + 8;
|
||||
if (i == CS_SUCCESS)
|
||||
break;
|
||||
}
|
||||
i = next_tuple(handle, &tuple, &parse);
|
||||
}
|
||||
|
||||
/* If that didn't work, look for two windows */
|
||||
if (i != CS_SUCCESS) {
|
||||
link->io.NumPorts1 = link->io.NumPorts2 = 8;
|
||||
info->multi = 2;
|
||||
i = first_tuple(handle, &tuple, &parse);
|
||||
while (i != CS_NO_MORE_ITEMS) {
|
||||
if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) {
|
||||
link->conf.ConfigIndex = cf->index;
|
||||
link->io.BasePort1 = cf->io.win[0].base;
|
||||
link->io.BasePort2 = cf->io.win[1].base;
|
||||
link->io.IOAddrLines =
|
||||
cf->io.flags & CISTPL_IO_LINES_MASK;
|
||||
i = pcmcia_request_io(link->handle, &link->io);
|
||||
base2 = link->io.BasePort2;
|
||||
if (i == CS_SUCCESS)
|
||||
break;
|
||||
}
|
||||
i = next_tuple(handle, &tuple, &parse);
|
||||
}
|
||||
}
|
||||
|
||||
if (i != CS_SUCCESS) {
|
||||
cs_error(link->handle, RequestIO, i);
|
||||
return -1;
|
||||
}
|
||||
|
||||
i = pcmcia_request_irq(link->handle, &link->irq);
|
||||
if (i != CS_SUCCESS) {
|
||||
printk(KERN_NOTICE
|
||||
"serial_cs: no usable port range found, giving up\n");
|
||||
cs_error(link->handle, RequestIRQ, i);
|
||||
link->irq.AssignedIRQ = 0;
|
||||
}
|
||||
/* Socket Dual IO: this enables irq's for second port */
|
||||
if (info->multi && (info->manfid == MANFID_SOCKET)) {
|
||||
link->conf.Present |= PRESENT_EXT_STATUS;
|
||||
link->conf.ExtStatus = ESR_REQ_ATTN_ENA;
|
||||
}
|
||||
i = pcmcia_request_configuration(link->handle, &link->conf);
|
||||
if (i != CS_SUCCESS) {
|
||||
cs_error(link->handle, RequestConfiguration, i);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The Oxford Semiconductor OXCF950 cards are in fact single-port:
|
||||
8 registers are for the UART, the others are extra registers */
|
||||
if (info->manfid == MANFID_OXSEMI) {
|
||||
if (cf->index == 1 || cf->index == 3) {
|
||||
setup_serial(info, base2, link->irq.AssignedIRQ);
|
||||
outb(12, link->io.BasePort1 + 1);
|
||||
} else {
|
||||
setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ);
|
||||
outb(12, base2 + 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ);
|
||||
/* The Nokia cards are not really multiport cards */
|
||||
if (info->manfid == MANFID_NOKIA)
|
||||
return 0;
|
||||
for (i = 0; i < info->multi - 1; i++)
|
||||
setup_serial(info, base2 + (8 * i), link->irq.AssignedIRQ);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*======================================================================
|
||||
|
||||
serial_config() is scheduled to run after a CARD_INSERTION event
|
||||
is received, to configure the PCMCIA socket, and to make the
|
||||
serial device available to the system.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
void serial_config(dev_link_t * link)
|
||||
{
|
||||
client_handle_t handle = link->handle;
|
||||
struct serial_info *info = link->priv;
|
||||
tuple_t tuple;
|
||||
u_short buf[128];
|
||||
cisparse_t parse;
|
||||
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
|
||||
int i, last_ret, last_fn;
|
||||
|
||||
DEBUG(0, "serial_config(0x%p)\n", link);
|
||||
|
||||
tuple.TupleData = (cisdata_t *) buf;
|
||||
tuple.TupleOffset = 0;
|
||||
tuple.TupleDataMax = 255;
|
||||
tuple.Attributes = 0;
|
||||
/* Get configuration register information */
|
||||
tuple.DesiredTuple = CISTPL_CONFIG;
|
||||
last_ret = first_tuple(handle, &tuple, &parse);
|
||||
if (last_ret != CS_SUCCESS) {
|
||||
last_fn = ParseTuple;
|
||||
goto cs_failed;
|
||||
}
|
||||
link->conf.ConfigBase = parse.config.base;
|
||||
link->conf.Present = parse.config.rmask[0];
|
||||
|
||||
/* Configure card */
|
||||
link->state |= DEV_CONFIG;
|
||||
|
||||
/* Is this a compliant multifunction card? */
|
||||
tuple.DesiredTuple = CISTPL_LONGLINK_MFC;
|
||||
tuple.Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK;
|
||||
info->multi = (first_tuple(handle, &tuple, &parse) == CS_SUCCESS);
|
||||
|
||||
/* Is this a multiport card? */
|
||||
tuple.DesiredTuple = CISTPL_MANFID;
|
||||
if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) {
|
||||
info->manfid = le16_to_cpu(buf[0]);
|
||||
for (i = 0; i < MULTI_COUNT; i++)
|
||||
if ((info->manfid == multi_id[i].manfid) &&
|
||||
(le16_to_cpu(buf[1]) == multi_id[i].prodid))
|
||||
break;
|
||||
if (i < MULTI_COUNT)
|
||||
info->multi = multi_id[i].multi;
|
||||
}
|
||||
|
||||
/* Another check for dual-serial cards: look for either serial or
|
||||
multifunction cards that ask for appropriate IO port ranges */
|
||||
tuple.DesiredTuple = CISTPL_FUNCID;
|
||||
if ((info->multi == 0) &&
|
||||
((first_tuple(handle, &tuple, &parse) != CS_SUCCESS) ||
|
||||
(parse.funcid.func == CISTPL_FUNCID_MULTI) ||
|
||||
(parse.funcid.func == CISTPL_FUNCID_SERIAL))) {
|
||||
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) {
|
||||
if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
|
||||
info->multi = cf->io.win[0].len >> 3;
|
||||
if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
|
||||
(cf->io.win[1].len == 8))
|
||||
info->multi = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->multi > 1)
|
||||
multi_config(link);
|
||||
else
|
||||
simple_config(link);
|
||||
|
||||
if (info->ndev == 0)
|
||||
goto failed;
|
||||
|
||||
if (info->manfid == MANFID_IBM) {
|
||||
conf_reg_t reg = { 0, CS_READ, 0x800, 0 };
|
||||
last_ret = pcmcia_access_configuration_register(link->handle, ®);
|
||||
if (last_ret) {
|
||||
last_fn = AccessConfigurationRegister;
|
||||
goto cs_failed;
|
||||
}
|
||||
reg.Action = CS_WRITE;
|
||||
reg.Value = reg.Value | 1;
|
||||
last_ret = pcmcia_access_configuration_register(link->handle, ®);
|
||||
if (last_ret) {
|
||||
last_fn = AccessConfigurationRegister;
|
||||
goto cs_failed;
|
||||
}
|
||||
}
|
||||
|
||||
link->dev = &info->node[0];
|
||||
link->state &= ~DEV_CONFIG_PENDING;
|
||||
return;
|
||||
|
||||
cs_failed:
|
||||
cs_error(link->handle, last_fn, last_ret);
|
||||
failed:
|
||||
serial_remove(link);
|
||||
link->state &= ~DEV_CONFIG_PENDING;
|
||||
}
|
||||
|
||||
/*======================================================================
|
||||
|
||||
The card status event handler. Mostly, this schedules other
|
||||
stuff to run after an event is received. A CARD_REMOVAL event
|
||||
also sets some flags to discourage the serial drivers from
|
||||
talking to the ports.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static int
|
||||
serial_event(event_t event, int priority, event_callback_args_t * args)
|
||||
{
|
||||
dev_link_t *link = args->client_data;
|
||||
struct serial_info *info = link->priv;
|
||||
|
||||
DEBUG(1, "serial_event(0x%06x)\n", event);
|
||||
|
||||
switch (event) {
|
||||
case CS_EVENT_CARD_REMOVAL:
|
||||
serial_remove(link);
|
||||
break;
|
||||
|
||||
case CS_EVENT_CARD_INSERTION:
|
||||
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
|
||||
serial_config(link);
|
||||
break;
|
||||
|
||||
case CS_EVENT_PM_SUSPEND:
|
||||
serial_suspend(link);
|
||||
break;
|
||||
|
||||
case CS_EVENT_RESET_PHYSICAL:
|
||||
if ((link->state & DEV_CONFIG) && !info->slave)
|
||||
pcmcia_release_configuration(link->handle);
|
||||
break;
|
||||
|
||||
case CS_EVENT_PM_RESUME:
|
||||
serial_resume(link);
|
||||
break;
|
||||
|
||||
case CS_EVENT_CARD_RESET:
|
||||
if (DEV_OK(link) && !info->slave)
|
||||
pcmcia_request_configuration(link->handle, &link->conf);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pcmcia_driver serial_cs_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.drv = {
|
||||
.name = "serial_cs",
|
||||
},
|
||||
.attach = serial_attach,
|
||||
.detach = serial_detach,
|
||||
};
|
||||
|
||||
static int __init init_serial_cs(void)
|
||||
{
|
||||
return pcmcia_register_driver(&serial_cs_driver);
|
||||
}
|
||||
|
||||
static void __exit exit_serial_cs(void)
|
||||
{
|
||||
pcmcia_unregister_driver(&serial_cs_driver);
|
||||
|
||||
/* XXX: this really needs to move into generic code.. */
|
||||
while (dev_list != NULL)
|
||||
serial_detach(dev_list);
|
||||
}
|
||||
|
||||
module_init(init_serial_cs);
|
||||
module_exit(exit_serial_cs);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
711
extra/linux-2.6.10/drivers/serial/serial_lh7a40x.c
Normal file
711
extra/linux-2.6.10/drivers/serial/serial_lh7a40x.c
Normal file
@@ -0,0 +1,711 @@
|
||||
/* drivers/serial/serial_lh7a40x.c
|
||||
*
|
||||
* Copyright (C) 2004 Coastal Environmental Systems
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Driver for Sharp LH7A40X embedded serial ports
|
||||
*
|
||||
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
|
||||
* Based on drivers/serial/amba.c, by Deep Blue Solutions Ltd.
|
||||
*
|
||||
* ---
|
||||
*
|
||||
* This driver supports the embedded UARTs of the Sharp LH7A40X series
|
||||
* CPUs. While similar to the 16550 and other UART chips, there is
|
||||
* nothing close to register compatibility. Moreover, some of the
|
||||
* modem control lines are not available, either in the chip or they
|
||||
* are lacking in the board-level implementation.
|
||||
*
|
||||
* - Use of SIRDIS
|
||||
* For simplicity, we disable the IR functions of any UART whenever
|
||||
* we enable it.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
#if defined(CONFIG_SERIAL_LH7A40X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
||||
#define SUPPORT_SYSRQ
|
||||
#endif
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#define DEV_MAJOR 204
|
||||
#define DEV_MINOR 16
|
||||
#define DEV_NR 3
|
||||
|
||||
#define ISR_LOOP_LIMIT 256
|
||||
|
||||
#define UR(p,o) _UR ((p)->membase, o)
|
||||
#define _UR(b,o) (*((volatile unsigned int*)(((unsigned char*) b) + (o))))
|
||||
#define BIT_CLR(p,o,m) UR(p,o) = UR(p,o) & (~(unsigned int)m)
|
||||
#define BIT_SET(p,o,m) UR(p,o) = UR(p,o) | ( (unsigned int)m)
|
||||
|
||||
#define UART_REG_SIZE 32
|
||||
|
||||
#define UART_R_DATA (0x00)
|
||||
#define UART_R_FCON (0x04)
|
||||
#define UART_R_BRCON (0x08)
|
||||
#define UART_R_CON (0x0c)
|
||||
#define UART_R_STATUS (0x10)
|
||||
#define UART_R_RAWISR (0x14)
|
||||
#define UART_R_INTEN (0x18)
|
||||
#define UART_R_ISR (0x1c)
|
||||
|
||||
#define UARTEN (0x01) /* UART enable */
|
||||
#define SIRDIS (0x02) /* Serial IR disable (UART1 only) */
|
||||
|
||||
#define RxEmpty (0x10)
|
||||
#define TxEmpty (0x80)
|
||||
#define TxFull (0x20)
|
||||
#define nRxRdy RxEmpty
|
||||
#define nTxRdy TxFull
|
||||
#define TxBusy (0x08)
|
||||
|
||||
#define RxBreak (0x0800)
|
||||
#define RxOverrunError (0x0400)
|
||||
#define RxParityError (0x0200)
|
||||
#define RxFramingError (0x0100)
|
||||
#define RxError (RxBreak | RxOverrunError | RxParityError | RxFramingError)
|
||||
|
||||
#define DCD (0x04)
|
||||
#define DSR (0x02)
|
||||
#define CTS (0x01)
|
||||
|
||||
#define RxInt (0x01)
|
||||
#define TxInt (0x02)
|
||||
#define ModemInt (0x04)
|
||||
#define RxTimeoutInt (0x08)
|
||||
|
||||
#define MSEOI (0x10)
|
||||
|
||||
#define WLEN_8 (0x60)
|
||||
#define WLEN_7 (0x40)
|
||||
#define WLEN_6 (0x20)
|
||||
#define WLEN_5 (0x00)
|
||||
#define WLEN (0x60) /* Mask for all word-length bits */
|
||||
#define STP2 (0x08)
|
||||
#define PEN (0x02) /* Parity Enable */
|
||||
#define EPS (0x04) /* Even Parity Set */
|
||||
#define FEN (0x10) /* FIFO Enable */
|
||||
#define BRK (0x01) /* Send Break */
|
||||
|
||||
|
||||
struct uart_port_lh7a40x {
|
||||
struct uart_port port;
|
||||
unsigned int statusPrev; /* Most recently read modem status */
|
||||
};
|
||||
|
||||
static void lh7a40xuart_stop_tx (struct uart_port* port, unsigned int tty_stop)
|
||||
{
|
||||
BIT_CLR (port, UART_R_INTEN, TxInt);
|
||||
}
|
||||
|
||||
static void lh7a40xuart_start_tx (struct uart_port* port,
|
||||
unsigned int tty_start)
|
||||
{
|
||||
BIT_SET (port, UART_R_INTEN, TxInt);
|
||||
|
||||
/* *** FIXME: do I need to check for startup of the
|
||||
transmitter? The old driver did, but AMBA
|
||||
doesn't . */
|
||||
}
|
||||
|
||||
static void lh7a40xuart_stop_rx (struct uart_port* port)
|
||||
{
|
||||
BIT_SET (port, UART_R_INTEN, RxTimeoutInt | RxInt);
|
||||
}
|
||||
|
||||
static void lh7a40xuart_enable_ms (struct uart_port* port)
|
||||
{
|
||||
BIT_SET (port, UART_R_INTEN, ModemInt);
|
||||
}
|
||||
|
||||
static void
|
||||
#ifdef SUPPORT_SYSRQ
|
||||
lh7a40xuart_rx_chars (struct uart_port* port, struct pt_regs* regs)
|
||||
#else
|
||||
lh7a40xuart_rx_chars (struct uart_port* port)
|
||||
#endif
|
||||
{
|
||||
struct tty_struct* tty = port->info->tty;
|
||||
int cbRxMax = 256; /* (Gross) limit on receive */
|
||||
unsigned int data, flag;/* Received data and status */
|
||||
|
||||
while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) {
|
||||
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
|
||||
if (tty->low_latency)
|
||||
tty_flip_buffer_push(tty);
|
||||
/*
|
||||
* If this failed then we will throw away the
|
||||
* bytes but must do so to clear interrupts
|
||||
*/
|
||||
}
|
||||
|
||||
data = UR (port, UART_R_DATA);
|
||||
flag = TTY_NORMAL;
|
||||
++port->icount.rx;
|
||||
|
||||
if (data & RxError) { /* Quick check, short-circuit */
|
||||
if (data & RxBreak) {
|
||||
data &= ~(RxFramingError | RxParityError);
|
||||
++port->icount.brk;
|
||||
if (uart_handle_break (port))
|
||||
continue;
|
||||
}
|
||||
else if (data & RxParityError)
|
||||
++port->icount.parity;
|
||||
else if (data & RxFramingError)
|
||||
++port->icount.frame;
|
||||
if (data & RxOverrunError)
|
||||
++port->icount.overrun;
|
||||
|
||||
/* Mask by termios, leave Rx'd byte */
|
||||
data &= port->read_status_mask | 0xff;
|
||||
|
||||
if (data & RxBreak)
|
||||
flag = TTY_BREAK;
|
||||
else if (data & RxParityError)
|
||||
flag = TTY_PARITY;
|
||||
else if (data & RxFramingError)
|
||||
flag = TTY_FRAME;
|
||||
}
|
||||
|
||||
if (uart_handle_sysrq_char (port, (unsigned char) data, regs))
|
||||
continue;
|
||||
|
||||
if ((data & port->ignore_status_mask) == 0) {
|
||||
tty_insert_flip_char(tty, data, flag);
|
||||
}
|
||||
if ((data & RxOverrunError)
|
||||
&& tty->flip.count < TTY_FLIPBUF_SIZE) {
|
||||
/*
|
||||
* Overrun is special, since it's reported
|
||||
* immediately, and doesn't affect the current
|
||||
* character
|
||||
*/
|
||||
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
|
||||
}
|
||||
}
|
||||
tty_flip_buffer_push (tty);
|
||||
return;
|
||||
}
|
||||
|
||||
static void lh7a40xuart_tx_chars (struct uart_port* port)
|
||||
{
|
||||
struct circ_buf* xmit = &port->info->xmit;
|
||||
int cbTxMax = port->fifosize;
|
||||
|
||||
if (port->x_char) {
|
||||
UR (port, UART_R_DATA) = port->x_char;
|
||||
++port->icount.tx;
|
||||
port->x_char = 0;
|
||||
return;
|
||||
}
|
||||
if (uart_circ_empty (xmit) || uart_tx_stopped (port)) {
|
||||
lh7a40xuart_stop_tx (port, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Unlike the AMBA UART, the lh7a40x UART does not guarantee
|
||||
that at least half of the FIFO is empty. Instead, we check
|
||||
status for every character. Using the AMBA method causes
|
||||
the transmitter to drop characters. */
|
||||
|
||||
do {
|
||||
UR (port, UART_R_DATA) = xmit->buf[xmit->tail];
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
++port->icount.tx;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
} while (!(UR (port, UART_R_STATUS) & nTxRdy)
|
||||
&& cbTxMax--);
|
||||
|
||||
if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup (port);
|
||||
|
||||
if (uart_circ_empty (xmit))
|
||||
lh7a40xuart_stop_tx (port, 0);
|
||||
}
|
||||
|
||||
static void lh7a40xuart_modem_status (struct uart_port* port)
|
||||
{
|
||||
unsigned int status = UR (port, UART_R_STATUS);
|
||||
unsigned int delta
|
||||
= status ^ ((struct uart_port_lh7a40x*) port)->statusPrev;
|
||||
|
||||
BIT_SET (port, UART_R_RAWISR, MSEOI); /* Clear modem status intr */
|
||||
|
||||
if (!delta) /* Only happens if we missed 2 transitions */
|
||||
return;
|
||||
|
||||
((struct uart_port_lh7a40x*) port)->statusPrev = status;
|
||||
|
||||
if (delta & DCD)
|
||||
uart_handle_dcd_change (port, status & DCD);
|
||||
|
||||
if (delta & DSR)
|
||||
++port->icount.dsr;
|
||||
|
||||
if (delta & CTS)
|
||||
uart_handle_cts_change (port, status & CTS);
|
||||
|
||||
wake_up_interruptible (&port->info->delta_msr_wait);
|
||||
}
|
||||
|
||||
static irqreturn_t lh7a40xuart_int (int irq, void* dev_id,
|
||||
struct pt_regs* regs)
|
||||
{
|
||||
struct uart_port* port = dev_id;
|
||||
unsigned int cLoopLimit = ISR_LOOP_LIMIT;
|
||||
unsigned int isr = UR (port, UART_R_ISR);
|
||||
|
||||
|
||||
do {
|
||||
if (isr & (RxInt | RxTimeoutInt))
|
||||
#ifdef SUPPORT_SYSRQ
|
||||
lh7a40xuart_rx_chars(port, regs);
|
||||
#else
|
||||
lh7a40xuart_rx_chars(port);
|
||||
#endif
|
||||
if (isr & ModemInt)
|
||||
lh7a40xuart_modem_status (port);
|
||||
if (isr & TxInt)
|
||||
lh7a40xuart_tx_chars (port);
|
||||
|
||||
if (--cLoopLimit == 0)
|
||||
break;
|
||||
|
||||
isr = UR (port, UART_R_ISR);
|
||||
} while (isr & (RxInt | TxInt | RxTimeoutInt));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static unsigned int lh7a40xuart_tx_empty (struct uart_port* port)
|
||||
{
|
||||
return (UR (port, UART_R_STATUS) & TxEmpty) ? TIOCSER_TEMT : 0;
|
||||
}
|
||||
|
||||
static unsigned int lh7a40xuart_get_mctrl (struct uart_port* port)
|
||||
{
|
||||
unsigned int result = 0;
|
||||
unsigned int status = UR (port, UART_R_STATUS);
|
||||
|
||||
if (status & DCD)
|
||||
result |= TIOCM_CAR;
|
||||
if (status & DSR)
|
||||
result |= TIOCM_DSR;
|
||||
if (status & CTS)
|
||||
result |= TIOCM_CTS;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void lh7a40xuart_set_mctrl (struct uart_port* port, unsigned int mctrl)
|
||||
{
|
||||
/* None of the ports supports DTR. UART1 supports RTS through GPIO. */
|
||||
/* Note, kernel appears to be setting DTR and RTS on console. */
|
||||
|
||||
/* *** FIXME: this deserves more work. There's some work in
|
||||
tracing all of the IO pins. */
|
||||
#if 0
|
||||
if( port->mapbase == UART1_PHYS) {
|
||||
gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS);
|
||||
|
||||
if (mctrl & TIOCM_RTS)
|
||||
gpio->pbdr &= ~GPIOB_UART1_RTS;
|
||||
else
|
||||
gpio->pbdr |= GPIOB_UART1_RTS;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void lh7a40xuart_break_ctl (struct uart_port* port, int break_state)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
if (break_state == -1)
|
||||
BIT_SET (port, UART_R_FCON, BRK); /* Assert break */
|
||||
else
|
||||
BIT_CLR (port, UART_R_FCON, BRK); /* Deassert break */
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static int lh7a40xuart_startup (struct uart_port* port)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = request_irq (port->irq, lh7a40xuart_int, 0,
|
||||
"serial_lh7a40x", port);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/* Initial modem control-line settings */
|
||||
((struct uart_port_lh7a40x*) port)->statusPrev
|
||||
= UR (port, UART_R_STATUS);
|
||||
|
||||
/* There is presently no configuration option to enable IR.
|
||||
Thus, we always disable it. */
|
||||
|
||||
BIT_SET (port, UART_R_CON, UARTEN | SIRDIS);
|
||||
BIT_SET (port, UART_R_INTEN, RxTimeoutInt | RxInt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lh7a40xuart_shutdown (struct uart_port* port)
|
||||
{
|
||||
free_irq (port->irq, port);
|
||||
BIT_CLR (port, UART_R_FCON, BRK | FEN);
|
||||
BIT_CLR (port, UART_R_CON, UARTEN);
|
||||
}
|
||||
|
||||
static void lh7a40xuart_set_termios (struct uart_port* port,
|
||||
struct termios* termios,
|
||||
struct termios* old)
|
||||
{
|
||||
unsigned int con;
|
||||
unsigned int inten;
|
||||
unsigned int fcon;
|
||||
unsigned long flags;
|
||||
unsigned int baud;
|
||||
unsigned int quot;
|
||||
|
||||
baud = uart_get_baud_rate (port, termios, old, 8, port->uartclk/16);
|
||||
quot = uart_get_divisor (port, baud); /* -1 performed elsewhere */
|
||||
|
||||
switch (termios->c_cflag & CSIZE) {
|
||||
case CS5:
|
||||
fcon = WLEN_5;
|
||||
break;
|
||||
case CS6:
|
||||
fcon = WLEN_6;
|
||||
break;
|
||||
case CS7:
|
||||
fcon = WLEN_7;
|
||||
break;
|
||||
case CS8:
|
||||
default:
|
||||
fcon = WLEN_8;
|
||||
break;
|
||||
}
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
fcon |= STP2;
|
||||
if (termios->c_cflag & PARENB) {
|
||||
fcon |= PEN;
|
||||
if (!(termios->c_cflag & PARODD))
|
||||
fcon |= EPS;
|
||||
}
|
||||
if (port->fifosize > 1)
|
||||
fcon |= FEN;
|
||||
|
||||
spin_lock_irqsave (&port->lock, flags);
|
||||
|
||||
uart_update_timeout (port, termios->c_cflag, baud);
|
||||
|
||||
port->read_status_mask = RxOverrunError;
|
||||
if (termios->c_iflag & INPCK)
|
||||
port->read_status_mask |= RxFramingError | RxParityError;
|
||||
if (termios->c_iflag & (BRKINT | PARMRK))
|
||||
port->read_status_mask |= RxBreak;
|
||||
|
||||
/* Figure mask for status we ignore */
|
||||
port->ignore_status_mask = 0;
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
port->ignore_status_mask |= RxFramingError | RxParityError;
|
||||
if (termios->c_iflag & IGNBRK) {
|
||||
port->ignore_status_mask |= RxBreak;
|
||||
/* Ignore overrun when ignorning parity */
|
||||
/* *** FIXME: is this in the right place? */
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
port->ignore_status_mask |= RxOverrunError;
|
||||
}
|
||||
|
||||
/* Ignore all receive errors when receive disabled */
|
||||
if ((termios->c_cflag & CREAD) == 0)
|
||||
port->ignore_status_mask |= RxError;
|
||||
|
||||
con = UR (port, UART_R_CON);
|
||||
inten = (UR (port, UART_R_INTEN) & ~ModemInt);
|
||||
|
||||
if (UART_ENABLE_MS (port, termios->c_cflag))
|
||||
inten |= ModemInt;
|
||||
|
||||
BIT_CLR (port, UART_R_CON, UARTEN); /* Disable UART */
|
||||
UR (port, UART_R_INTEN) = 0; /* Disable interrupts */
|
||||
UR (port, UART_R_BRCON) = quot - 1; /* Set baud rate divisor */
|
||||
UR (port, UART_R_FCON) = fcon; /* Set FIFO and frame ctrl */
|
||||
UR (port, UART_R_INTEN) = inten; /* Enable interrupts */
|
||||
UR (port, UART_R_CON) = con; /* Restore UART mode */
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static const char* lh7a40xuart_type (struct uart_port* port)
|
||||
{
|
||||
return port->type == PORT_LH7A40X ? "LH7A40X" : NULL;
|
||||
}
|
||||
|
||||
static void lh7a40xuart_release_port (struct uart_port* port)
|
||||
{
|
||||
release_mem_region (port->mapbase, UART_REG_SIZE);
|
||||
}
|
||||
|
||||
static int lh7a40xuart_request_port (struct uart_port* port)
|
||||
{
|
||||
return request_mem_region (port->mapbase, UART_REG_SIZE,
|
||||
"serial_lh7a40x") != NULL
|
||||
? 0 : -EBUSY;
|
||||
}
|
||||
|
||||
static void lh7a40xuart_config_port (struct uart_port* port, int flags)
|
||||
{
|
||||
if (flags & UART_CONFIG_TYPE) {
|
||||
port->type = PORT_LH7A40X;
|
||||
lh7a40xuart_request_port (port);
|
||||
}
|
||||
}
|
||||
|
||||
static int lh7a40xuart_verify_port (struct uart_port* port,
|
||||
struct serial_struct* ser)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (ser->type != PORT_UNKNOWN && ser->type != PORT_LH7A40X)
|
||||
ret = -EINVAL;
|
||||
if (ser->irq < 0 || ser->irq >= NR_IRQS)
|
||||
ret = -EINVAL;
|
||||
if (ser->baud_base < 9600) /* *** FIXME: is this true? */
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct uart_ops lh7a40x_uart_ops = {
|
||||
.tx_empty = lh7a40xuart_tx_empty,
|
||||
.set_mctrl = lh7a40xuart_set_mctrl,
|
||||
.get_mctrl = lh7a40xuart_get_mctrl,
|
||||
.stop_tx = lh7a40xuart_stop_tx,
|
||||
.start_tx = lh7a40xuart_start_tx,
|
||||
.stop_rx = lh7a40xuart_stop_rx,
|
||||
.enable_ms = lh7a40xuart_enable_ms,
|
||||
.break_ctl = lh7a40xuart_break_ctl,
|
||||
.startup = lh7a40xuart_startup,
|
||||
.shutdown = lh7a40xuart_shutdown,
|
||||
.set_termios = lh7a40xuart_set_termios,
|
||||
.type = lh7a40xuart_type,
|
||||
.release_port = lh7a40xuart_release_port,
|
||||
.request_port = lh7a40xuart_request_port,
|
||||
.config_port = lh7a40xuart_config_port,
|
||||
.verify_port = lh7a40xuart_verify_port,
|
||||
};
|
||||
|
||||
static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = {
|
||||
{
|
||||
.port = {
|
||||
.membase = (void*) io_p2v (UART1_PHYS),
|
||||
.mapbase = UART1_PHYS,
|
||||
.iotype = SERIAL_IO_MEM,
|
||||
.irq = IRQ_UART1INTR,
|
||||
.uartclk = 14745600/2,
|
||||
.fifosize = 16,
|
||||
.ops = &lh7a40x_uart_ops,
|
||||
.flags = ASYNC_BOOT_AUTOCONF,
|
||||
.line = 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
.port = {
|
||||
.membase = (void*) io_p2v (UART2_PHYS),
|
||||
.mapbase = UART2_PHYS,
|
||||
.iotype = SERIAL_IO_MEM,
|
||||
.irq = IRQ_UART2INTR,
|
||||
.uartclk = 14745600/2,
|
||||
.fifosize = 16,
|
||||
.ops = &lh7a40x_uart_ops,
|
||||
.flags = ASYNC_BOOT_AUTOCONF,
|
||||
.line = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
.port = {
|
||||
.membase = (void*) io_p2v (UART3_PHYS),
|
||||
.mapbase = UART3_PHYS,
|
||||
.iotype = SERIAL_IO_MEM,
|
||||
.irq = IRQ_UART3INTR,
|
||||
.uartclk = 14745600/2,
|
||||
.fifosize = 16,
|
||||
.ops = &lh7a40x_uart_ops,
|
||||
.flags = ASYNC_BOOT_AUTOCONF,
|
||||
.line = 2,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
#ifndef CONFIG_SERIAL_LH7A40X_CONSOLE
|
||||
# define LH7A40X_CONSOLE NULL
|
||||
#else
|
||||
# define LH7A40X_CONSOLE &lh7a40x_console
|
||||
|
||||
|
||||
static void lh7a40xuart_console_write (struct console* co,
|
||||
const char* s,
|
||||
unsigned int count)
|
||||
{
|
||||
struct uart_port* port = &lh7a40x_ports[co->index].port;
|
||||
unsigned int con = UR (port, UART_R_CON);
|
||||
unsigned int inten = UR (port, UART_R_INTEN);
|
||||
|
||||
|
||||
UR (port, UART_R_INTEN) = 0; /* Disable all interrupts */
|
||||
BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); /* Enable UART */
|
||||
|
||||
for (; count-- > 0; ++s) {
|
||||
while (UR (port, UART_R_STATUS) & nTxRdy)
|
||||
;
|
||||
UR (port, UART_R_DATA) = *s;
|
||||
if (*s == '\n') {
|
||||
while ((UR (port, UART_R_STATUS) & TxBusy))
|
||||
;
|
||||
UR (port, UART_R_DATA) = '\r';
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait until all characters are sent */
|
||||
while (UR (port, UART_R_STATUS) & TxBusy)
|
||||
;
|
||||
|
||||
/* Restore control and interrupt mask */
|
||||
UR (port, UART_R_CON) = con;
|
||||
UR (port, UART_R_INTEN) = inten;
|
||||
}
|
||||
|
||||
static void __init lh7a40xuart_console_get_options (struct uart_port* port,
|
||||
int* baud,
|
||||
int* parity,
|
||||
int* bits)
|
||||
{
|
||||
if (UR (port, UART_R_CON) & UARTEN) {
|
||||
unsigned int fcon = UR (port, UART_R_FCON);
|
||||
unsigned int quot = UR (port, UART_R_BRCON) + 1;
|
||||
|
||||
switch (fcon & (PEN | EPS)) {
|
||||
default: *parity = 'n'; break;
|
||||
case PEN: *parity = 'o'; break;
|
||||
case PEN | EPS: *parity = 'e'; break;
|
||||
}
|
||||
|
||||
switch (fcon & WLEN) {
|
||||
default:
|
||||
case WLEN_8: *bits = 8; break;
|
||||
case WLEN_7: *bits = 7; break;
|
||||
case WLEN_6: *bits = 6; break;
|
||||
case WLEN_5: *bits = 5; break;
|
||||
}
|
||||
|
||||
*baud = port->uartclk/(16*quot);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init lh7a40xuart_console_setup (struct console* co, char* options)
|
||||
{
|
||||
struct uart_port* port;
|
||||
int baud = 38400;
|
||||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
|
||||
if (co->index >= DEV_NR) /* Bounds check on device number */
|
||||
co->index = 0;
|
||||
port = &lh7a40x_ports[co->index].port;
|
||||
|
||||
if (options)
|
||||
uart_parse_options (options, &baud, &parity, &bits, &flow);
|
||||
else
|
||||
lh7a40xuart_console_get_options (port, &baud, &parity, &bits);
|
||||
|
||||
return uart_set_options (port, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
extern struct uart_driver lh7a40x_reg;
|
||||
static struct console lh7a40x_console = {
|
||||
.name = "ttyAM",
|
||||
.write = lh7a40xuart_console_write,
|
||||
.device = uart_console_device,
|
||||
.setup = lh7a40xuart_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
.data = &lh7a40x_reg,
|
||||
};
|
||||
|
||||
static int __init lh7a40xuart_console_init(void)
|
||||
{
|
||||
register_console (&lh7a40x_console);
|
||||
return 0;
|
||||
}
|
||||
|
||||
console_initcall (lh7a40xuart_console_init);
|
||||
|
||||
#endif
|
||||
|
||||
static struct uart_driver lh7a40x_reg = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = "ttyAM",
|
||||
.dev_name = "ttyAM",
|
||||
.major = DEV_MAJOR,
|
||||
.minor = DEV_MINOR,
|
||||
.nr = DEV_NR,
|
||||
.cons = LH7A40X_CONSOLE,
|
||||
};
|
||||
|
||||
static int __init lh7a40xuart_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printk (KERN_INFO "serial: LH7A40X serial driver\n");
|
||||
|
||||
ret = uart_register_driver (&lh7a40x_reg);
|
||||
|
||||
if (ret == 0) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DEV_NR; i++)
|
||||
uart_add_one_port (&lh7a40x_reg,
|
||||
&lh7a40x_ports[i].port);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit lh7a40xuart_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DEV_NR; i++)
|
||||
uart_remove_one_port (&lh7a40x_reg, &lh7a40x_ports[i].port);
|
||||
|
||||
uart_unregister_driver (&lh7a40x_reg);
|
||||
}
|
||||
|
||||
module_init (lh7a40xuart_init);
|
||||
module_exit (lh7a40xuart_exit);
|
||||
|
||||
MODULE_AUTHOR ("Marc Singer");
|
||||
MODULE_DESCRIPTION ("Sharp LH7A40X serial port driver");
|
||||
MODULE_LICENSE ("GPL");
|
||||
1692
extra/linux-2.6.10/drivers/serial/sh-sci.c
Normal file
1692
extra/linux-2.6.10/drivers/serial/sh-sci.c
Normal file
File diff suppressed because it is too large
Load Diff
573
extra/linux-2.6.10/drivers/serial/sh-sci.h
Normal file
573
extra/linux-2.6.10/drivers/serial/sh-sci.h
Normal file
@@ -0,0 +1,573 @@
|
||||
/* $Id: sh-sci.h,v 1.4 2004/02/19 16:43:56 lethal Exp $
|
||||
*
|
||||
* linux/drivers/serial/sh-sci.h
|
||||
*
|
||||
* SuperH on-chip serial module support. (SCI with no FIFO / with FIFO)
|
||||
* Copyright (C) 1999, 2000 Niibe Yutaka
|
||||
* Copyright (C) 2000 Greg Banks
|
||||
* Copyright (C) 2002, 2003 Paul Mundt
|
||||
* Modified to support multiple serial ports. Stuart Menefy (May 2000).
|
||||
* Modified to support SH7300(SH-Mobile) SCIF. Takashi Kusuda (Jun 2003).
|
||||
* Modified to support H8/300 Series Yoshinori Sato (Feb 2004).
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
#include <linux/serial_core.h>
|
||||
|
||||
#if defined(__H8300H__) || defined(__H8300S__)
|
||||
#include <asm/gpio.h>
|
||||
#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
|
||||
#include <asm/regs306x.h>
|
||||
#endif
|
||||
#if defined(CONFIG_H8S2678)
|
||||
#include <asm/regs267x.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Offsets into the sci_port->irqs array */
|
||||
#define SCIx_ERI_IRQ 0
|
||||
#define SCIx_RXI_IRQ 1
|
||||
#define SCIx_TXI_IRQ 2
|
||||
|
||||
/* ERI, RXI, TXI, BRI */
|
||||
#define SCI_IRQS { 23, 24, 25, 0 }
|
||||
#define SH3_SCIF_IRQS { 56, 57, 59, 58 }
|
||||
#define SH3_IRDA_IRQS { 52, 53, 55, 54 }
|
||||
#define SH4_SCIF_IRQS { 40, 41, 43, 42 }
|
||||
#define STB1_SCIF1_IRQS {23, 24, 26, 25 }
|
||||
#define SH7760_SCIF0_IRQS { 52, 53, 55, 54 }
|
||||
#define SH7760_SCIF1_IRQS { 72, 73, 75, 74 }
|
||||
#define SH7760_SCIF2_IRQS { 76, 77, 79, 78 }
|
||||
#define SH7300_SCIF0_IRQS {80, 80, 80, 80 }
|
||||
#define SH73180_SCIF_IRQS {80, 81, 83, 82 }
|
||||
#define H8300H_SCI_IRQS0 {52, 53, 54, 0 }
|
||||
#define H8300H_SCI_IRQS1 {56, 57, 58, 0 }
|
||||
#define H8300H_SCI_IRQS2 {60, 61, 62, 0 }
|
||||
#define H8S_SCI_IRQS0 {88, 89, 90, 0 }
|
||||
#define H8S_SCI_IRQS1 {92, 93, 94, 0 }
|
||||
#define H8S_SCI_IRQS2 {96, 97, 98, 0 }
|
||||
#define SH5_SCIF_IRQS {39, 40, 42, 0 }
|
||||
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7708)
|
||||
# define SCI_NPORTS 1
|
||||
# define SCSPTR 0xffffff7c /* 8 bit */
|
||||
# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
|
||||
# define SCI_ONLY
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
|
||||
# define SCI_NPORTS 3
|
||||
# define SCPCR 0xA4000116 /* 16 bit SCI and SCIF */
|
||||
# define SCPDR 0xA4000136 /* 8 bit SCI and SCIF */
|
||||
# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
|
||||
# define SCI_AND_SCIF
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
|
||||
# define SCIF0 0xA4400000
|
||||
# define SCIF2 0xA4410000
|
||||
# define SCSMR_Ir 0xA44A0000
|
||||
# define IRDA_SCIF SCIF0
|
||||
# define SCI_NPORTS 2
|
||||
# define SCPCR 0xA4000116
|
||||
# define SCPDR 0xA4000136
|
||||
|
||||
/* Set the clock source,
|
||||
* SCIF2 (0xA4410000) -> External clock, SCK pin used as clock input
|
||||
* SCIF0 (0xA4400000) -> Internal clock, SCK pin as serial clock output
|
||||
*/
|
||||
# define SCSCR_INIT(port) (port->mapbase == SCIF2) ? 0xF3 : 0xF0
|
||||
# define SCIF_ONLY
|
||||
#elif defined(CONFIG_SH_RTS7751R2D)
|
||||
# define SCI_NPORTS 1
|
||||
# define SCSPTR1 0xffe0001c /* 8 bit SCI */
|
||||
# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
|
||||
# define SCIF_ORER 0x0001 /* overrun error bit */
|
||||
# define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
|
||||
# define SCIF_ONLY
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751)
|
||||
# define SCI_NPORTS 2
|
||||
# define SCSPTR1 0xffe0001c /* 8 bit SCI */
|
||||
# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
|
||||
# define SCIF_ORER 0x0001 /* overrun error bit */
|
||||
# define SCSCR_INIT(port) (((port)->type == PORT_SCI) ? \
|
||||
0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ : \
|
||||
0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ )
|
||||
# define SCI_AND_SCIF
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
|
||||
# define SCI_NPORTS 3
|
||||
# define SCSPTR0 0xfe600000 /* 16 bit SCIF */
|
||||
# define SCSPTR1 0xfe610000 /* 16 bit SCIF */
|
||||
# define SCSPTR2 0xfe620000 /* 16 bit SCIF */
|
||||
# define SCIF_ORER 0x0001 /* overrun error bit */
|
||||
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
|
||||
# define SCIF_ONLY
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7300)
|
||||
# define SCI_NPORTS 1
|
||||
# define SCPCR 0xA4050116 /* 16 bit SCIF */
|
||||
# define SCPDR 0xA4050136 /* 16 bit SCIF */
|
||||
# define SCSCR_INIT(port) 0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */
|
||||
# define SCIF_ONLY
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH73180)
|
||||
# define SCI_NPORTS 1
|
||||
# define SCPDR 0xA4050138 /* 16 bit SCIF */
|
||||
# define SCSPTR2 SCPDR
|
||||
# define SCIF_ORER 0x0001 /* overrun error bit */
|
||||
# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1 */
|
||||
# define SCIF_ONLY
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
|
||||
# define SCI_NPORTS 1
|
||||
# define SCSPTR2 0xffe80020 /* 16 bit SCIF */
|
||||
# define SCIF_ORER 0x0001 /* overrun error bit */
|
||||
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
|
||||
# define SCIF_ONLY
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
|
||||
# define SCI_NPORTS 2
|
||||
# define SCSPTR1 0xffe00020 /* 16 bit SCIF */
|
||||
# define SCSPTR2 0xffe80020 /* 16 bit SCIF */
|
||||
# define SCIF_ORER 0x0001 /* overrun error bit */
|
||||
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
|
||||
# define SCIF_ONLY
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
|
||||
# include <asm/hardware.h>
|
||||
# define SCIF_BASE_ADDR 0x01030000
|
||||
# define SCIF_ADDR_SH5 PHYS_PERIPHERAL_BLOCK+SCIF_BASE_ADDR
|
||||
# define SCIF_PTR2_OFFS 0x0000020
|
||||
# define SCIF_LSR2_OFFS 0x0000024
|
||||
# define SCI_NPORTS 1
|
||||
# define SCI_INIT { \
|
||||
{ {}, PORT_SCIF, 0, \
|
||||
SH5_SCIF_IRQS, sci_init_pins_scif } \
|
||||
}
|
||||
# define SCSPTR2 ((port->mapbase)+SCIF_PTR2_OFFS) /* 16 bit SCIF */
|
||||
# define SCLSR2 ((port->mapbase)+SCIF_LSR2_OFFS) /* 16 bit SCIF */
|
||||
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,
|
||||
TE=1,RE=1,REIE=1 */
|
||||
# define SCIF_ONLY
|
||||
#elif defined(CONFIG_H83007) || defined(CONFIG_H83068)
|
||||
# define SCI_NPORTS 3
|
||||
# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
|
||||
# define SCI_ONLY
|
||||
# define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port)
|
||||
#elif defined(CONFIG_H8S2678)
|
||||
# define SCI_NPORTS 3
|
||||
# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
|
||||
# define SCI_ONLY
|
||||
# define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port)
|
||||
#else
|
||||
# error CPU subtype not defined
|
||||
#endif
|
||||
|
||||
/* SCSCR */
|
||||
#define SCI_CTRL_FLAGS_TIE 0x80 /* all */
|
||||
#define SCI_CTRL_FLAGS_RIE 0x40 /* all */
|
||||
#define SCI_CTRL_FLAGS_TE 0x20 /* all */
|
||||
#define SCI_CTRL_FLAGS_RE 0x10 /* all */
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751)
|
||||
#define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */
|
||||
#else
|
||||
#define SCI_CTRL_FLAGS_REIE 0
|
||||
#endif
|
||||
/* SCI_CTRL_FLAGS_MPIE 0x08 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
|
||||
/* SCI_CTRL_FLAGS_TEIE 0x04 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
|
||||
/* SCI_CTRL_FLAGS_CKE1 0x02 * all */
|
||||
/* SCI_CTRL_FLAGS_CKE0 0x01 * 7707 SCI/SCIF, 7708 SCI, 7709 SCI/SCIF, 7750 SCI */
|
||||
|
||||
/* SCxSR SCI */
|
||||
#define SCI_TDRE 0x80 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
|
||||
#define SCI_RDRF 0x40 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
|
||||
#define SCI_ORER 0x20 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
|
||||
#define SCI_FER 0x10 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
|
||||
#define SCI_PER 0x08 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
|
||||
#define SCI_TEND 0x04 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
|
||||
/* SCI_MPB 0x02 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
|
||||
/* SCI_MPBT 0x01 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
|
||||
|
||||
#define SCI_ERRORS ( SCI_PER | SCI_FER | SCI_ORER)
|
||||
|
||||
/* SCxSR SCIF */
|
||||
#define SCIF_ER 0x0080 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
|
||||
#define SCIF_TEND 0x0040 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
|
||||
#define SCIF_TDFE 0x0020 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
|
||||
#define SCIF_BRK 0x0010 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
|
||||
#define SCIF_FER 0x0008 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
|
||||
#define SCIF_PER 0x0004 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
|
||||
#define SCIF_RDF 0x0002 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
|
||||
#define SCIF_DR 0x0001 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
|
||||
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
|
||||
#define SCIF_ORER 0x0200
|
||||
#define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK | SCIF_ORER)
|
||||
#define SCIF_RFDC_MASK 0x007f
|
||||
#define SCIF_TXROOM_MAX 64
|
||||
#else
|
||||
#define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
|
||||
#define SCIF_RFDC_MASK 0x001f
|
||||
#define SCIF_TXROOM_MAX 16
|
||||
#endif
|
||||
|
||||
#if defined(SCI_ONLY)
|
||||
# define SCxSR_TEND(port) SCI_TEND
|
||||
# define SCxSR_ERRORS(port) SCI_ERRORS
|
||||
# define SCxSR_RDxF(port) SCI_RDRF
|
||||
# define SCxSR_TDxE(port) SCI_TDRE
|
||||
# define SCxSR_ORER(port) SCI_ORER
|
||||
# define SCxSR_FER(port) SCI_FER
|
||||
# define SCxSR_PER(port) SCI_PER
|
||||
# define SCxSR_BRK(port) 0x00
|
||||
# define SCxSR_RDxF_CLEAR(port) 0xbc
|
||||
# define SCxSR_ERROR_CLEAR(port) 0xc4
|
||||
# define SCxSR_TDxE_CLEAR(port) 0x78
|
||||
# define SCxSR_BREAK_CLEAR(port) 0xc4
|
||||
#elif defined(SCIF_ONLY)
|
||||
# define SCxSR_TEND(port) SCIF_TEND
|
||||
# define SCxSR_ERRORS(port) SCIF_ERRORS
|
||||
# define SCxSR_RDxF(port) SCIF_RDF
|
||||
# define SCxSR_TDxE(port) SCIF_TDFE
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
|
||||
# define SCxSR_ORER(port) SCIF_ORER
|
||||
#else
|
||||
# define SCxSR_ORER(port) 0x0000
|
||||
#endif
|
||||
# define SCxSR_FER(port) SCIF_FER
|
||||
# define SCxSR_PER(port) SCIF_PER
|
||||
# define SCxSR_BRK(port) SCIF_BRK
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
|
||||
# define SCxSR_RDxF_CLEAR(port) (sci_in(port,SCxSR)&0xfffc)
|
||||
# define SCxSR_ERROR_CLEAR(port) (sci_in(port,SCxSR)&0xfd73)
|
||||
# define SCxSR_TDxE_CLEAR(port) (sci_in(port,SCxSR)&0xffdf)
|
||||
# define SCxSR_BREAK_CLEAR(port) (sci_in(port,SCxSR)&0xffe3)
|
||||
#else
|
||||
/* SH7705 can also use this, clearing is same between 7705 and 7709 and 7300 */
|
||||
# define SCxSR_RDxF_CLEAR(port) 0x00fc
|
||||
# define SCxSR_ERROR_CLEAR(port) 0x0073
|
||||
# define SCxSR_TDxE_CLEAR(port) 0x00df
|
||||
# define SCxSR_BREAK_CLEAR(port) 0x00e3
|
||||
#endif
|
||||
#else
|
||||
# define SCxSR_TEND(port) (((port)->type == PORT_SCI) ? SCI_TEND : SCIF_TEND)
|
||||
# define SCxSR_ERRORS(port) (((port)->type == PORT_SCI) ? SCI_ERRORS : SCIF_ERRORS)
|
||||
# define SCxSR_RDxF(port) (((port)->type == PORT_SCI) ? SCI_RDRF : SCIF_RDF)
|
||||
# define SCxSR_TDxE(port) (((port)->type == PORT_SCI) ? SCI_TDRE : SCIF_TDFE)
|
||||
# define SCxSR_ORER(port) (((port)->type == PORT_SCI) ? SCI_ORER : 0x0000)
|
||||
# define SCxSR_FER(port) (((port)->type == PORT_SCI) ? SCI_FER : SCIF_FER)
|
||||
# define SCxSR_PER(port) (((port)->type == PORT_SCI) ? SCI_PER : SCIF_PER)
|
||||
# define SCxSR_BRK(port) (((port)->type == PORT_SCI) ? 0x00 : SCIF_BRK)
|
||||
# define SCxSR_RDxF_CLEAR(port) (((port)->type == PORT_SCI) ? 0xbc : 0x00fc)
|
||||
# define SCxSR_ERROR_CLEAR(port) (((port)->type == PORT_SCI) ? 0xc4 : 0x0073)
|
||||
# define SCxSR_TDxE_CLEAR(port) (((port)->type == PORT_SCI) ? 0x78 : 0x00df)
|
||||
# define SCxSR_BREAK_CLEAR(port) (((port)->type == PORT_SCI) ? 0xc4 : 0x00e3)
|
||||
#endif
|
||||
|
||||
/* SCFCR */
|
||||
#define SCFCR_RFRST 0x0002
|
||||
#define SCFCR_TFRST 0x0004
|
||||
#define SCFCR_TCRST 0x4000
|
||||
#define SCFCR_MCE 0x0008
|
||||
|
||||
#define SCI_MAJOR 204
|
||||
#define SCI_MINOR_START 8
|
||||
|
||||
/* Generic serial flags */
|
||||
#define SCI_RX_THROTTLE 0x0000001
|
||||
|
||||
#define SCI_MAGIC 0xbabeface
|
||||
|
||||
/*
|
||||
* Events are used to schedule things to happen at timer-interrupt
|
||||
* time, instead of at rs interrupt time.
|
||||
*/
|
||||
#define SCI_EVENT_WRITE_WAKEUP 0
|
||||
|
||||
struct sci_port {
|
||||
struct uart_port port;
|
||||
int type;
|
||||
unsigned char irqs[4]; /* ERI, RXI, TXI, BRI */
|
||||
void (*init_pins)(struct uart_port *port, unsigned int cflag);
|
||||
int break_flag;
|
||||
struct timer_list break_timer;
|
||||
};
|
||||
|
||||
#define SCI_IN(size, offset) \
|
||||
unsigned int addr = port->mapbase + (offset); \
|
||||
if ((size) == 8) { \
|
||||
return ctrl_inb(addr); \
|
||||
} else { \
|
||||
return ctrl_inw(addr); \
|
||||
}
|
||||
#define SCI_OUT(size, offset, value) \
|
||||
unsigned int addr = port->mapbase + (offset); \
|
||||
if ((size) == 8) { \
|
||||
ctrl_outb(value, addr); \
|
||||
} else { \
|
||||
ctrl_outw(value, addr); \
|
||||
}
|
||||
|
||||
#define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\
|
||||
static inline unsigned int sci_##name##_in(struct uart_port *port) \
|
||||
{ \
|
||||
if (port->type == PORT_SCI) { \
|
||||
SCI_IN(sci_size, sci_offset) \
|
||||
} else { \
|
||||
SCI_IN(scif_size, scif_offset); \
|
||||
} \
|
||||
} \
|
||||
static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
|
||||
{ \
|
||||
if (port->type == PORT_SCI) { \
|
||||
SCI_OUT(sci_size, sci_offset, value) \
|
||||
} else { \
|
||||
SCI_OUT(scif_size, scif_offset, value); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CPU_SCIF_FNS(name, scif_offset, scif_size) \
|
||||
static inline unsigned int sci_##name##_in(struct uart_port *port) \
|
||||
{ \
|
||||
SCI_IN(scif_size, scif_offset); \
|
||||
} \
|
||||
static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \
|
||||
{ \
|
||||
SCI_OUT(scif_size, scif_offset, value); \
|
||||
}
|
||||
|
||||
#define CPU_SCI_FNS(name, sci_offset, sci_size) \
|
||||
static inline unsigned int sci_##name##_in(struct uart_port* port) \
|
||||
{ \
|
||||
SCI_IN(sci_size, sci_offset); \
|
||||
} \
|
||||
static inline void sci_##name##_out(struct uart_port* port, unsigned int value) \
|
||||
{ \
|
||||
SCI_OUT(sci_size, sci_offset, value); \
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CPU_SH3
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
|
||||
#define SCIF_FNS(name, scif_offset, scif_size) \
|
||||
CPU_SCIF_FNS(name, scif_offset, scif_size)
|
||||
#else
|
||||
#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
|
||||
sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
|
||||
h8_sci_offset, h8_sci_size) \
|
||||
CPU_SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh3_scif_offset, sh3_scif_size)
|
||||
#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \
|
||||
CPU_SCIF_FNS(name, sh3_scif_offset, sh3_scif_size)
|
||||
#endif
|
||||
#elif defined(__H8300H__) || defined(__H8300S__)
|
||||
#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
|
||||
sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
|
||||
h8_sci_offset, h8_sci_size) \
|
||||
CPU_SCI_FNS(name, h8_sci_offset, h8_sci_size)
|
||||
#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size)
|
||||
#else
|
||||
#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
|
||||
sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
|
||||
h8_sci_offset, h8_sci_size) \
|
||||
CPU_SCIx_FNS(name, sh4_sci_offset, sh4_sci_size, sh4_scif_offset, sh4_scif_size)
|
||||
#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \
|
||||
CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
|
||||
SCIF_FNS(SCSMR, 0x00, 16)
|
||||
SCIF_FNS(SCBRR, 0x04, 8)
|
||||
SCIF_FNS(SCSCR, 0x08, 16)
|
||||
SCIF_FNS(SCTDSR, 0x0c, 8)
|
||||
SCIF_FNS(SCFER, 0x10, 16)
|
||||
SCIF_FNS(SCxSR, 0x14, 16)
|
||||
SCIF_FNS(SCFCR, 0x18, 16)
|
||||
SCIF_FNS(SCFDR, 0x1c, 16)
|
||||
SCIF_FNS(SCxTDR, 0x20, 8)
|
||||
SCIF_FNS(SCxRDR, 0x24, 8)
|
||||
SCIF_FNS(SCLSR, 0x24, 16)
|
||||
#else
|
||||
/* reg SCI/SH3 SCI/SH4 SCIF/SH3 SCIF/SH4 SCI/H8*/
|
||||
/* name off sz off sz off sz off sz off sz*/
|
||||
SCIx_FNS(SCSMR, 0x00, 8, 0x00, 8, 0x00, 8, 0x00, 16, 0x00, 8)
|
||||
SCIx_FNS(SCBRR, 0x02, 8, 0x04, 8, 0x02, 8, 0x04, 8, 0x01, 8)
|
||||
SCIx_FNS(SCSCR, 0x04, 8, 0x08, 8, 0x04, 8, 0x08, 16, 0x02, 8)
|
||||
SCIx_FNS(SCxTDR, 0x06, 8, 0x0c, 8, 0x06, 8, 0x0C, 8, 0x03, 8)
|
||||
SCIx_FNS(SCxSR, 0x08, 8, 0x10, 8, 0x08, 16, 0x10, 16, 0x04, 8)
|
||||
SCIx_FNS(SCxRDR, 0x0a, 8, 0x14, 8, 0x0A, 8, 0x14, 8, 0x05, 8)
|
||||
SCIF_FNS(SCFCR, 0x0c, 8, 0x18, 16)
|
||||
SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16)
|
||||
SCIF_FNS(SCSPTR, 0, 0, 0x20, 16)
|
||||
SCIF_FNS(SCLSR, 0, 0, 0x24, 16)
|
||||
#endif
|
||||
#define sci_in(port, reg) sci_##reg##_in(port)
|
||||
#define sci_out(port, reg, value) sci_##reg##_out(port, value)
|
||||
|
||||
/* H8/300 series SCI pins assignment */
|
||||
#if defined(__H8300H__) || defined(__H8300S__)
|
||||
static const struct __attribute__((packed)) {
|
||||
int port; /* GPIO port no */
|
||||
unsigned short rx,tx; /* GPIO bit no */
|
||||
} h8300_sci_pins[] = {
|
||||
#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
|
||||
{ /* SCI0 */
|
||||
.port = H8300_GPIO_P9,
|
||||
.rx = H8300_GPIO_B2,
|
||||
.tx = H8300_GPIO_B0,
|
||||
},
|
||||
{ /* SCI1 */
|
||||
.port = H8300_GPIO_P9,
|
||||
.rx = H8300_GPIO_B3,
|
||||
.tx = H8300_GPIO_B1,
|
||||
},
|
||||
{ /* SCI2 */
|
||||
.port = H8300_GPIO_PB,
|
||||
.rx = H8300_GPIO_B7,
|
||||
.tx = H8300_GPIO_B6,
|
||||
}
|
||||
#elif defined(CONFIG_H8S2678)
|
||||
{ /* SCI0 */
|
||||
.port = H8300_GPIO_P3,
|
||||
.rx = H8300_GPIO_B2,
|
||||
.tx = H8300_GPIO_B0,
|
||||
},
|
||||
{ /* SCI1 */
|
||||
.port = H8300_GPIO_P3,
|
||||
.rx = H8300_GPIO_B3,
|
||||
.tx = H8300_GPIO_B1,
|
||||
},
|
||||
{ /* SCI2 */
|
||||
.port = H8300_GPIO_P5,
|
||||
.rx = H8300_GPIO_B1,
|
||||
.tx = H8300_GPIO_B0,
|
||||
}
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7708)
|
||||
static inline int sci_rxd_in(struct uart_port *port)
|
||||
{
|
||||
if (port->mapbase == 0xfffffe80)
|
||||
return ctrl_inb(SCSPTR)&0x01 ? 1 : 0; /* SCI */
|
||||
return 1;
|
||||
}
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
|
||||
static inline int sci_rxd_in(struct uart_port *port)
|
||||
{
|
||||
if (port->mapbase == 0xfffffe80)
|
||||
return ctrl_inb(SCPDR)&0x01 ? 1 : 0; /* SCI */
|
||||
if (port->mapbase == 0xa4000150)
|
||||
return ctrl_inb(SCPDR)&0x10 ? 1 : 0; /* SCIF */
|
||||
if (port->mapbase == 0xa4000140)
|
||||
return ctrl_inb(SCPDR)&0x04 ? 1 : 0; /* IRDA */
|
||||
return 1;
|
||||
}
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
|
||||
static inline int sci_rxd_in(struct uart_port *port)
|
||||
{
|
||||
if (port->mapbase == SCIF0)
|
||||
return ctrl_inb(SCPDR)&0x04 ? 1 : 0; /* IRDA */
|
||||
if (port->mapbase == SCIF2)
|
||||
return ctrl_inb(SCPDR)&0x10 ? 1 : 0; /* SCIF */
|
||||
return 1;
|
||||
}
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \
|
||||
defined(CONFIG_CPU_SUBTYPE_SH7751) || \
|
||||
defined(CONFIG_CPU_SUBTYPE_SH4_202)
|
||||
static inline int sci_rxd_in(struct uart_port *port)
|
||||
{
|
||||
#ifndef SCIF_ONLY
|
||||
if (port->mapbase == 0xffe00000)
|
||||
return ctrl_inb(SCSPTR1)&0x01 ? 1 : 0; /* SCI */
|
||||
#endif
|
||||
#ifndef SCI_ONLY
|
||||
if (port->mapbase == 0xffe80000)
|
||||
return ctrl_inw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
|
||||
static inline int sci_rxd_in(struct uart_port *port)
|
||||
{
|
||||
if (port->mapbase == 0xfe600000)
|
||||
return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
|
||||
if (port->mapbase == 0xfe610000)
|
||||
return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
|
||||
if (port->mapbase == 0xfe620000)
|
||||
return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
|
||||
}
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7300)
|
||||
static inline int sci_rxd_in(struct uart_port *port)
|
||||
{
|
||||
if (port->mapbase == 0xa4430000)
|
||||
return ctrl_inb(SCPDR)&0x01 ? 1 : 0; /* SCIF0 */
|
||||
return 1;
|
||||
}
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH73180)
|
||||
static inline int sci_rxd_in(struct uart_port *port)
|
||||
{
|
||||
return ctrl_inb(SCPDR)&0x01 ? 1 : 0; /* SCIF0 */
|
||||
}
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
|
||||
static inline int sci_rxd_in(struct uart_port *port)
|
||||
{
|
||||
if (port->mapbase == 0xffe00000)
|
||||
return ctrl_inw(SCSPTR1)&0x0001 ? 1 : 0; /* SCIF */
|
||||
else
|
||||
return ctrl_inw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */
|
||||
|
||||
}
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
|
||||
static inline int sci_rxd_in(struct uart_port *port)
|
||||
{
|
||||
return sci_in(port, SCSPTR)&0x0001 ? 1 : 0; /* SCIF */
|
||||
}
|
||||
#elif defined(__H8300H__) || defined(__H8300S__)
|
||||
static inline int sci_rxd_in(struct uart_port *port)
|
||||
{
|
||||
int ch = (port->mapbase - SMR0) >> 3;
|
||||
return (H8300_SCI_DR(ch) & h8300_sci_pins[ch].rx) ? 1 : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Values for the BitRate Register (SCBRR)
|
||||
*
|
||||
* The values are actually divisors for a frequency which can
|
||||
* be internal to the SH3 (14.7456MHz) or derived from an external
|
||||
* clock source. This driver assumes the internal clock is used;
|
||||
* to support using an external clock source, config options or
|
||||
* possibly command-line options would need to be added.
|
||||
*
|
||||
* Also, to support speeds below 2400 (why?) the lower 2 bits of
|
||||
* the SCSMR register would also need to be set to non-zero values.
|
||||
*
|
||||
* -- Greg Banks 27Feb2000
|
||||
*
|
||||
* Answer: The SCBRR register is only eight bits, and the value in
|
||||
* it gets larger with lower baud rates. At around 2400 (depending on
|
||||
* the peripherial module clock) you run out of bits. However the
|
||||
* lower two bits of SCSMR allow the module clock to be divided down,
|
||||
* scaling the value which is needed in SCBRR.
|
||||
*
|
||||
* -- Stuart Menefy - 23 May 2000
|
||||
*
|
||||
* I meant, why would anyone bother with bitrates below 2400.
|
||||
*
|
||||
* -- Greg Banks - 7Jul2000
|
||||
*
|
||||
* You "speedist"! How will I use my 110bps ASR-33 teletype with paper
|
||||
* tape reader as a console!
|
||||
*
|
||||
* -- Mitch Davis - 15 Jul 2000
|
||||
*/
|
||||
|
||||
#define PCLK (current_cpu_data.module_clock)
|
||||
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7300)
|
||||
#define SCBRR_VALUE(bps) ((PCLK+16*bps)/(16*bps)-1)
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
|
||||
#define SCBRR_VALUE(bps) (((PCLK*2)+16*bps)/(32*bps)-1)
|
||||
#elif !defined(__H8300H__) && !defined(__H8300S__)
|
||||
#define SCBRR_VALUE(bps) ((PCLK+16*bps)/(32*bps)-1)
|
||||
#else
|
||||
#define SCBRR_VALUE(bps) (((CONFIG_CPU_CLOCK*1000/32)/bps)-1)
|
||||
#endif
|
||||
#define BPS_2400 SCBRR_VALUE(2400)
|
||||
#define BPS_4800 SCBRR_VALUE(4800)
|
||||
#define BPS_9600 SCBRR_VALUE(9600)
|
||||
#define BPS_19200 SCBRR_VALUE(19200)
|
||||
#define BPS_38400 SCBRR_VALUE(38400)
|
||||
#define BPS_57600 SCBRR_VALUE(57600)
|
||||
#define BPS_115200 SCBRR_VALUE(115200)
|
||||
|
||||
1121
extra/linux-2.6.10/drivers/serial/sn_console.c
Normal file
1121
extra/linux-2.6.10/drivers/serial/sn_console.c
Normal file
File diff suppressed because it is too large
Load Diff
218
extra/linux-2.6.10/drivers/serial/suncore.c
Normal file
218
extra/linux-2.6.10/drivers/serial/suncore.c
Normal file
@@ -0,0 +1,218 @@
|
||||
/* suncore.c
|
||||
*
|
||||
* Common SUN serial routines. Based entirely
|
||||
* upon drivers/sbus/char/sunserial.c which is:
|
||||
*
|
||||
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
|
||||
*
|
||||
* Adaptation to new UART layer is:
|
||||
*
|
||||
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/oplib.h>
|
||||
|
||||
#include "suncore.h"
|
||||
|
||||
int sunserial_current_minor = 64;
|
||||
|
||||
EXPORT_SYMBOL(sunserial_current_minor);
|
||||
|
||||
void
|
||||
sunserial_console_termios(struct console *con)
|
||||
{
|
||||
char mode[16], buf[16], *s;
|
||||
char *mode_prop = "ttyX-mode";
|
||||
char *cd_prop = "ttyX-ignore-cd";
|
||||
char *dtr_prop = "ttyX-rts-dtr-off";
|
||||
int baud, bits, stop, cflag;
|
||||
char parity;
|
||||
int carrier = 0;
|
||||
int rtsdtr = 1;
|
||||
int topnd, nd;
|
||||
|
||||
if (!serial_console)
|
||||
return;
|
||||
|
||||
if (serial_console == 1) {
|
||||
mode_prop[3] = 'a';
|
||||
cd_prop[3] = 'a';
|
||||
dtr_prop[3] = 'a';
|
||||
} else {
|
||||
mode_prop[3] = 'b';
|
||||
cd_prop[3] = 'b';
|
||||
dtr_prop[3] = 'b';
|
||||
}
|
||||
|
||||
topnd = prom_getchild(prom_root_node);
|
||||
nd = prom_searchsiblings(topnd, "options");
|
||||
if (!nd) {
|
||||
strcpy(mode, "9600,8,n,1,-");
|
||||
goto no_options;
|
||||
}
|
||||
|
||||
if (!prom_node_has_property(nd, mode_prop)) {
|
||||
strcpy(mode, "9600,8,n,1,-");
|
||||
goto no_options;
|
||||
}
|
||||
|
||||
memset(mode, 0, sizeof(mode));
|
||||
prom_getstring(nd, mode_prop, mode, sizeof(mode));
|
||||
|
||||
if (prom_node_has_property(nd, cd_prop)) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
prom_getstring(nd, cd_prop, buf, sizeof(buf));
|
||||
if (!strcmp(buf, "false"))
|
||||
carrier = 1;
|
||||
|
||||
/* XXX: this is unused below. */
|
||||
}
|
||||
|
||||
if (prom_node_has_property(nd, dtr_prop)) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
prom_getstring(nd, dtr_prop, buf, sizeof(buf));
|
||||
if (!strcmp(buf, "false"))
|
||||
rtsdtr = 0;
|
||||
|
||||
/* XXX: this is unused below. */
|
||||
}
|
||||
|
||||
no_options:
|
||||
cflag = CREAD | HUPCL | CLOCAL;
|
||||
|
||||
s = mode;
|
||||
baud = simple_strtoul(s, NULL, 0);
|
||||
s = strchr(s, ',');
|
||||
bits = simple_strtoul(++s, NULL, 0);
|
||||
s = strchr(s, ',');
|
||||
parity = *(++s);
|
||||
s = strchr(s, ',');
|
||||
stop = simple_strtoul(++s, NULL, 0);
|
||||
s = strchr(s, ',');
|
||||
/* XXX handshake is not handled here. */
|
||||
|
||||
switch (baud) {
|
||||
case 150: cflag |= B150; break;
|
||||
case 300: cflag |= B300; break;
|
||||
case 600: cflag |= B600; break;
|
||||
case 1200: cflag |= B1200; break;
|
||||
case 2400: cflag |= B2400; break;
|
||||
case 4800: cflag |= B4800; break;
|
||||
case 9600: cflag |= B9600; break;
|
||||
case 19200: cflag |= B19200; break;
|
||||
case 38400: cflag |= B38400; break;
|
||||
default: baud = 9600; cflag |= B9600; break;
|
||||
}
|
||||
|
||||
switch (bits) {
|
||||
case 5: cflag |= CS5; break;
|
||||
case 6: cflag |= CS6; break;
|
||||
case 7: cflag |= CS7; break;
|
||||
case 8: cflag |= CS8; break;
|
||||
default: cflag |= CS8; break;
|
||||
}
|
||||
|
||||
switch (parity) {
|
||||
case 'o': cflag |= (PARENB | PARODD); break;
|
||||
case 'e': cflag |= PARENB; break;
|
||||
case 'n': default: break;
|
||||
}
|
||||
|
||||
switch (stop) {
|
||||
case 2: cflag |= CSTOPB; break;
|
||||
case 1: default: break;
|
||||
}
|
||||
|
||||
con->cflag = cflag;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(sunserial_console_termios);
|
||||
|
||||
/* Sun serial MOUSE auto baud rate detection. */
|
||||
static struct mouse_baud_cflag {
|
||||
int baud;
|
||||
unsigned int cflag;
|
||||
} mouse_baud_table[] = {
|
||||
{ 1200, B1200 },
|
||||
{ 2400, B2400 },
|
||||
{ 4800, B4800 },
|
||||
{ 9600, B9600 },
|
||||
{ -1, ~0 },
|
||||
{ -1, ~0 },
|
||||
};
|
||||
|
||||
unsigned int suncore_mouse_baud_cflag_next(unsigned int cflag, int *new_baud)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; mouse_baud_table[i].baud != -1; i++)
|
||||
if (mouse_baud_table[i].cflag == (cflag & CBAUD))
|
||||
break;
|
||||
|
||||
i += 1;
|
||||
if (mouse_baud_table[i].baud == -1)
|
||||
i = 0;
|
||||
|
||||
*new_baud = mouse_baud_table[i].baud;
|
||||
return mouse_baud_table[i].cflag;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(suncore_mouse_baud_cflag_next);
|
||||
|
||||
/* Basically, when the baud rate is wrong the mouse spits out
|
||||
* breaks to us.
|
||||
*/
|
||||
int suncore_mouse_baud_detection(unsigned char ch, int is_break)
|
||||
{
|
||||
static int mouse_got_break = 0;
|
||||
static int ctr = 0;
|
||||
|
||||
if (is_break) {
|
||||
/* Let a few normal bytes go by before we jump the gun
|
||||
* and say we need to try another baud rate.
|
||||
*/
|
||||
if (mouse_got_break && ctr < 8)
|
||||
return 1;
|
||||
|
||||
/* Ok, we need to try another baud. */
|
||||
ctr = 0;
|
||||
mouse_got_break = 1;
|
||||
return 2;
|
||||
}
|
||||
if (mouse_got_break) {
|
||||
ctr++;
|
||||
if (ch == 0x87) {
|
||||
/* Correct baud rate determined. */
|
||||
mouse_got_break = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(suncore_mouse_baud_detection);
|
||||
|
||||
static int __init suncore_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit suncore_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
module_init(suncore_init);
|
||||
module_exit(suncore_exit);
|
||||
|
||||
MODULE_AUTHOR("Eddie C. Dost, David S. Miller");
|
||||
MODULE_DESCRIPTION("Sun serial common layer");
|
||||
MODULE_LICENSE("GPL");
|
||||
29
extra/linux-2.6.10/drivers/serial/suncore.h
Normal file
29
extra/linux-2.6.10/drivers/serial/suncore.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* suncore.h
|
||||
*
|
||||
* Generic SUN serial/kbd/ms layer. Based entirely
|
||||
* upon drivers/sbus/char/sunserial.h which is:
|
||||
*
|
||||
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
|
||||
*
|
||||
* Port to new UART layer is:
|
||||
*
|
||||
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
|
||||
*/
|
||||
|
||||
#ifndef _SERIAL_SUN_H
|
||||
#define _SERIAL_SUN_H
|
||||
|
||||
/* Serial keyboard defines for L1-A processing... */
|
||||
#define SUNKBD_RESET 0xff
|
||||
#define SUNKBD_L1 0x01
|
||||
#define SUNKBD_UP 0x80
|
||||
#define SUNKBD_A 0x4d
|
||||
|
||||
extern unsigned int suncore_mouse_baud_cflag_next(unsigned int, int *);
|
||||
extern int suncore_mouse_baud_detection(unsigned char, int);
|
||||
|
||||
extern int sunserial_current_minor;
|
||||
|
||||
extern void sunserial_console_termios(struct console *);
|
||||
|
||||
#endif /* !(_SERIAL_SUN_H) */
|
||||
1171
extra/linux-2.6.10/drivers/serial/sunsab.c
Normal file
1171
extra/linux-2.6.10/drivers/serial/sunsab.c
Normal file
File diff suppressed because it is too large
Load Diff
321
extra/linux-2.6.10/drivers/serial/sunsab.h
Normal file
321
extra/linux-2.6.10/drivers/serial/sunsab.h
Normal file
@@ -0,0 +1,321 @@
|
||||
/* sunsab.h: Register Definitions for the Siemens SAB82532 DUSCC
|
||||
*
|
||||
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
|
||||
*/
|
||||
|
||||
#ifndef _SUNSAB_H
|
||||
#define _SUNSAB_H
|
||||
|
||||
struct sab82532_async_rd_regs {
|
||||
u8 rfifo[0x20]; /* Receive FIFO */
|
||||
u8 star; /* Status Register */
|
||||
u8 __pad1;
|
||||
u8 mode; /* Mode Register */
|
||||
u8 timr; /* Timer Register */
|
||||
u8 xon; /* XON Character */
|
||||
u8 xoff; /* XOFF Character */
|
||||
u8 tcr; /* Termination Character Register */
|
||||
u8 dafo; /* Data Format */
|
||||
u8 rfc; /* RFIFO Control Register */
|
||||
u8 __pad2;
|
||||
u8 rbcl; /* Receive Byte Count Low */
|
||||
u8 rbch; /* Receive Byte Count High */
|
||||
u8 ccr0; /* Channel Configuration Register 0 */
|
||||
u8 ccr1; /* Channel Configuration Register 1 */
|
||||
u8 ccr2; /* Channel Configuration Register 2 */
|
||||
u8 ccr3; /* Channel Configuration Register 3 */
|
||||
u8 __pad3[4];
|
||||
u8 vstr; /* Version Status Register */
|
||||
u8 __pad4[3];
|
||||
u8 gis; /* Global Interrupt Status */
|
||||
u8 ipc; /* Interrupt Port Configuration */
|
||||
u8 isr0; /* Interrupt Status 0 */
|
||||
u8 isr1; /* Interrupt Status 1 */
|
||||
u8 pvr; /* Port Value Register */
|
||||
u8 pis; /* Port Interrupt Status */
|
||||
u8 pcr; /* Port Configuration Register */
|
||||
u8 ccr4; /* Channel Configuration Register 4 */
|
||||
};
|
||||
|
||||
struct sab82532_async_wr_regs {
|
||||
u8 xfifo[0x20]; /* Transmit FIFO */
|
||||
u8 cmdr; /* Command Register */
|
||||
u8 __pad1;
|
||||
u8 mode;
|
||||
u8 timr;
|
||||
u8 xon;
|
||||
u8 xoff;
|
||||
u8 tcr;
|
||||
u8 dafo;
|
||||
u8 rfc;
|
||||
u8 __pad2;
|
||||
u8 xbcl; /* Transmit Byte Count Low */
|
||||
u8 xbch; /* Transmit Byte Count High */
|
||||
u8 ccr0;
|
||||
u8 ccr1;
|
||||
u8 ccr2;
|
||||
u8 ccr3;
|
||||
u8 tsax; /* Time-Slot Assignment Reg. Transmit */
|
||||
u8 tsar; /* Time-Slot Assignment Reg. Receive */
|
||||
u8 xccr; /* Transmit Channel Capacity Register */
|
||||
u8 rccr; /* Receive Channel Capacity Register */
|
||||
u8 bgr; /* Baud Rate Generator Register */
|
||||
u8 tic; /* Transmit Immediate Character */
|
||||
u8 mxn; /* Mask XON Character */
|
||||
u8 mxf; /* Mask XOFF Character */
|
||||
u8 iva; /* Interrupt Vector Address */
|
||||
u8 ipc;
|
||||
u8 imr0; /* Interrupt Mask Register 0 */
|
||||
u8 imr1; /* Interrupt Mask Register 1 */
|
||||
u8 pvr;
|
||||
u8 pim; /* Port Interrupt Mask */
|
||||
u8 pcr;
|
||||
u8 ccr4;
|
||||
};
|
||||
|
||||
struct sab82532_async_rw_regs { /* Read/Write registers */
|
||||
u8 __pad1[0x20];
|
||||
u8 __pad2;
|
||||
u8 __pad3;
|
||||
u8 mode;
|
||||
u8 timr;
|
||||
u8 xon;
|
||||
u8 xoff;
|
||||
u8 tcr;
|
||||
u8 dafo;
|
||||
u8 rfc;
|
||||
u8 __pad4;
|
||||
u8 __pad5;
|
||||
u8 __pad6;
|
||||
u8 ccr0;
|
||||
u8 ccr1;
|
||||
u8 ccr2;
|
||||
u8 ccr3;
|
||||
u8 __pad7;
|
||||
u8 __pad8;
|
||||
u8 __pad9;
|
||||
u8 __pad10;
|
||||
u8 __pad11;
|
||||
u8 __pad12;
|
||||
u8 __pad13;
|
||||
u8 __pad14;
|
||||
u8 __pad15;
|
||||
u8 ipc;
|
||||
u8 __pad16;
|
||||
u8 __pad17;
|
||||
u8 pvr;
|
||||
u8 __pad18;
|
||||
u8 pcr;
|
||||
u8 ccr4;
|
||||
};
|
||||
|
||||
union sab82532_async_regs {
|
||||
__volatile__ struct sab82532_async_rd_regs r;
|
||||
__volatile__ struct sab82532_async_wr_regs w;
|
||||
__volatile__ struct sab82532_async_rw_regs rw;
|
||||
};
|
||||
|
||||
union sab82532_irq_status {
|
||||
unsigned short stat;
|
||||
struct {
|
||||
unsigned char isr0;
|
||||
unsigned char isr1;
|
||||
} sreg;
|
||||
};
|
||||
|
||||
/* irqflags bits */
|
||||
#define SAB82532_ALLS 0x00000001
|
||||
#define SAB82532_XPR 0x00000002
|
||||
|
||||
/* RFIFO Status Byte */
|
||||
#define SAB82532_RSTAT_PE 0x80
|
||||
#define SAB82532_RSTAT_FE 0x40
|
||||
#define SAB82532_RSTAT_PARITY 0x01
|
||||
|
||||
/* Status Register (STAR) */
|
||||
#define SAB82532_STAR_XDOV 0x80
|
||||
#define SAB82532_STAR_XFW 0x40
|
||||
#define SAB82532_STAR_RFNE 0x20
|
||||
#define SAB82532_STAR_FCS 0x10
|
||||
#define SAB82532_STAR_TEC 0x08
|
||||
#define SAB82532_STAR_CEC 0x04
|
||||
#define SAB82532_STAR_CTS 0x02
|
||||
|
||||
/* Command Register (CMDR) */
|
||||
#define SAB82532_CMDR_RMC 0x80
|
||||
#define SAB82532_CMDR_RRES 0x40
|
||||
#define SAB82532_CMDR_RFRD 0x20
|
||||
#define SAB82532_CMDR_STI 0x10
|
||||
#define SAB82532_CMDR_XF 0x08
|
||||
#define SAB82532_CMDR_XRES 0x01
|
||||
|
||||
/* Mode Register (MODE) */
|
||||
#define SAB82532_MODE_FRTS 0x40
|
||||
#define SAB82532_MODE_FCTS 0x20
|
||||
#define SAB82532_MODE_FLON 0x10
|
||||
#define SAB82532_MODE_RAC 0x08
|
||||
#define SAB82532_MODE_RTS 0x04
|
||||
#define SAB82532_MODE_TRS 0x02
|
||||
#define SAB82532_MODE_TLP 0x01
|
||||
|
||||
/* Timer Register (TIMR) */
|
||||
#define SAB82532_TIMR_CNT_MASK 0xe0
|
||||
#define SAB82532_TIMR_VALUE_MASK 0x1f
|
||||
|
||||
/* Data Format (DAFO) */
|
||||
#define SAB82532_DAFO_XBRK 0x40
|
||||
#define SAB82532_DAFO_STOP 0x20
|
||||
#define SAB82532_DAFO_PAR_SPACE 0x00
|
||||
#define SAB82532_DAFO_PAR_ODD 0x08
|
||||
#define SAB82532_DAFO_PAR_EVEN 0x10
|
||||
#define SAB82532_DAFO_PAR_MARK 0x18
|
||||
#define SAB82532_DAFO_PARE 0x04
|
||||
#define SAB82532_DAFO_CHL8 0x00
|
||||
#define SAB82532_DAFO_CHL7 0x01
|
||||
#define SAB82532_DAFO_CHL6 0x02
|
||||
#define SAB82532_DAFO_CHL5 0x03
|
||||
|
||||
/* RFIFO Control Register (RFC) */
|
||||
#define SAB82532_RFC_DPS 0x40
|
||||
#define SAB82532_RFC_DXS 0x20
|
||||
#define SAB82532_RFC_RFDF 0x10
|
||||
#define SAB82532_RFC_RFTH_1 0x00
|
||||
#define SAB82532_RFC_RFTH_4 0x04
|
||||
#define SAB82532_RFC_RFTH_16 0x08
|
||||
#define SAB82532_RFC_RFTH_32 0x0c
|
||||
#define SAB82532_RFC_TCDE 0x01
|
||||
|
||||
/* Received Byte Count High (RBCH) */
|
||||
#define SAB82532_RBCH_DMA 0x80
|
||||
#define SAB82532_RBCH_CAS 0x20
|
||||
|
||||
/* Transmit Byte Count High (XBCH) */
|
||||
#define SAB82532_XBCH_DMA 0x80
|
||||
#define SAB82532_XBCH_CAS 0x20
|
||||
#define SAB82532_XBCH_XC 0x10
|
||||
|
||||
/* Channel Configuration Register 0 (CCR0) */
|
||||
#define SAB82532_CCR0_PU 0x80
|
||||
#define SAB82532_CCR0_MCE 0x40
|
||||
#define SAB82532_CCR0_SC_NRZ 0x00
|
||||
#define SAB82532_CCR0_SC_NRZI 0x08
|
||||
#define SAB82532_CCR0_SC_FM0 0x10
|
||||
#define SAB82532_CCR0_SC_FM1 0x14
|
||||
#define SAB82532_CCR0_SC_MANCH 0x18
|
||||
#define SAB82532_CCR0_SM_HDLC 0x00
|
||||
#define SAB82532_CCR0_SM_SDLC_LOOP 0x01
|
||||
#define SAB82532_CCR0_SM_BISYNC 0x02
|
||||
#define SAB82532_CCR0_SM_ASYNC 0x03
|
||||
|
||||
/* Channel Configuration Register 1 (CCR1) */
|
||||
#define SAB82532_CCR1_ODS 0x10
|
||||
#define SAB82532_CCR1_BCR 0x08
|
||||
#define SAB82532_CCR1_CM_MASK 0x07
|
||||
|
||||
/* Channel Configuration Register 2 (CCR2) */
|
||||
#define SAB82532_CCR2_SOC1 0x80
|
||||
#define SAB82532_CCR2_SOC0 0x40
|
||||
#define SAB82532_CCR2_BR9 0x80
|
||||
#define SAB82532_CCR2_BR8 0x40
|
||||
#define SAB82532_CCR2_BDF 0x20
|
||||
#define SAB82532_CCR2_SSEL 0x10
|
||||
#define SAB82532_CCR2_XCS0 0x20
|
||||
#define SAB82532_CCR2_RCS0 0x10
|
||||
#define SAB82532_CCR2_TOE 0x08
|
||||
#define SAB82532_CCR2_RWX 0x04
|
||||
#define SAB82532_CCR2_DIV 0x01
|
||||
|
||||
/* Channel Configuration Register 3 (CCR3) */
|
||||
#define SAB82532_CCR3_PSD 0x01
|
||||
|
||||
/* Time Slot Assignment Register Transmit (TSAX) */
|
||||
#define SAB82532_TSAX_TSNX_MASK 0xfc
|
||||
#define SAB82532_TSAX_XCS2 0x02 /* see also CCR2 */
|
||||
#define SAB82532_TSAX_XCS1 0x01
|
||||
|
||||
/* Time Slot Assignment Register Receive (TSAR) */
|
||||
#define SAB82532_TSAR_TSNR_MASK 0xfc
|
||||
#define SAB82532_TSAR_RCS2 0x02 /* see also CCR2 */
|
||||
#define SAB82532_TSAR_RCS1 0x01
|
||||
|
||||
/* Version Status Register (VSTR) */
|
||||
#define SAB82532_VSTR_CD 0x80
|
||||
#define SAB82532_VSTR_DPLA 0x40
|
||||
#define SAB82532_VSTR_VN_MASK 0x0f
|
||||
#define SAB82532_VSTR_VN_1 0x00
|
||||
#define SAB82532_VSTR_VN_2 0x01
|
||||
#define SAB82532_VSTR_VN_3_2 0x02
|
||||
|
||||
/* Global Interrupt Status Register (GIS) */
|
||||
#define SAB82532_GIS_PI 0x80
|
||||
#define SAB82532_GIS_ISA1 0x08
|
||||
#define SAB82532_GIS_ISA0 0x04
|
||||
#define SAB82532_GIS_ISB1 0x02
|
||||
#define SAB82532_GIS_ISB0 0x01
|
||||
|
||||
/* Interrupt Vector Address (IVA) */
|
||||
#define SAB82532_IVA_MASK 0xf1
|
||||
|
||||
/* Interrupt Port Configuration (IPC) */
|
||||
#define SAB82532_IPC_VIS 0x80
|
||||
#define SAB82532_IPC_SLA1 0x10
|
||||
#define SAB82532_IPC_SLA0 0x08
|
||||
#define SAB82532_IPC_CASM 0x04
|
||||
#define SAB82532_IPC_IC_OPEN_DRAIN 0x00
|
||||
#define SAB82532_IPC_IC_ACT_LOW 0x01
|
||||
#define SAB82532_IPC_IC_ACT_HIGH 0x03
|
||||
|
||||
/* Interrupt Status Register 0 (ISR0) */
|
||||
#define SAB82532_ISR0_TCD 0x80
|
||||
#define SAB82532_ISR0_TIME 0x40
|
||||
#define SAB82532_ISR0_PERR 0x20
|
||||
#define SAB82532_ISR0_FERR 0x10
|
||||
#define SAB82532_ISR0_PLLA 0x08
|
||||
#define SAB82532_ISR0_CDSC 0x04
|
||||
#define SAB82532_ISR0_RFO 0x02
|
||||
#define SAB82532_ISR0_RPF 0x01
|
||||
|
||||
/* Interrupt Status Register 1 (ISR1) */
|
||||
#define SAB82532_ISR1_BRK 0x80
|
||||
#define SAB82532_ISR1_BRKT 0x40
|
||||
#define SAB82532_ISR1_ALLS 0x20
|
||||
#define SAB82532_ISR1_XOFF 0x10
|
||||
#define SAB82532_ISR1_TIN 0x08
|
||||
#define SAB82532_ISR1_CSC 0x04
|
||||
#define SAB82532_ISR1_XON 0x02
|
||||
#define SAB82532_ISR1_XPR 0x01
|
||||
|
||||
/* Interrupt Mask Register 0 (IMR0) */
|
||||
#define SAB82532_IMR0_TCD 0x80
|
||||
#define SAB82532_IMR0_TIME 0x40
|
||||
#define SAB82532_IMR0_PERR 0x20
|
||||
#define SAB82532_IMR0_FERR 0x10
|
||||
#define SAB82532_IMR0_PLLA 0x08
|
||||
#define SAB82532_IMR0_CDSC 0x04
|
||||
#define SAB82532_IMR0_RFO 0x02
|
||||
#define SAB82532_IMR0_RPF 0x01
|
||||
|
||||
/* Interrupt Mask Register 1 (IMR1) */
|
||||
#define SAB82532_IMR1_BRK 0x80
|
||||
#define SAB82532_IMR1_BRKT 0x40
|
||||
#define SAB82532_IMR1_ALLS 0x20
|
||||
#define SAB82532_IMR1_XOFF 0x10
|
||||
#define SAB82532_IMR1_TIN 0x08
|
||||
#define SAB82532_IMR1_CSC 0x04
|
||||
#define SAB82532_IMR1_XON 0x02
|
||||
#define SAB82532_IMR1_XPR 0x01
|
||||
|
||||
/* Port Interrupt Status Register (PIS) */
|
||||
#define SAB82532_PIS_SYNC_B 0x08
|
||||
#define SAB82532_PIS_DTR_B 0x04
|
||||
#define SAB82532_PIS_DTR_A 0x02
|
||||
#define SAB82532_PIS_SYNC_A 0x01
|
||||
|
||||
/* Channel Configuration Register 4 (CCR4) */
|
||||
#define SAB82532_CCR4_MCK4 0x80
|
||||
#define SAB82532_CCR4_EBRG 0x40
|
||||
#define SAB82532_CCR4_TST1 0x20
|
||||
#define SAB82532_CCR4_ICD 0x10
|
||||
|
||||
|
||||
#endif /* !(_SUNSAB_H) */
|
||||
1739
extra/linux-2.6.10/drivers/serial/sunsu.c
Normal file
1739
extra/linux-2.6.10/drivers/serial/sunsu.c
Normal file
File diff suppressed because it is too large
Load Diff
1772
extra/linux-2.6.10/drivers/serial/sunzilog.c
Normal file
1772
extra/linux-2.6.10/drivers/serial/sunzilog.c
Normal file
File diff suppressed because it is too large
Load Diff
272
extra/linux-2.6.10/drivers/serial/sunzilog.h
Normal file
272
extra/linux-2.6.10/drivers/serial/sunzilog.h
Normal file
@@ -0,0 +1,272 @@
|
||||
#ifndef _SUNZILOG_H
|
||||
#define _SUNZILOG_H
|
||||
|
||||
struct zilog_channel {
|
||||
volatile unsigned char control;
|
||||
volatile unsigned char __pad1;
|
||||
volatile unsigned char data;
|
||||
volatile unsigned char __pad2;
|
||||
};
|
||||
|
||||
struct zilog_layout {
|
||||
struct zilog_channel channelB;
|
||||
struct zilog_channel channelA;
|
||||
};
|
||||
|
||||
#define NUM_ZSREGS 16
|
||||
|
||||
/* Conversion routines to/from brg time constants from/to bits
|
||||
* per second.
|
||||
*/
|
||||
#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2))
|
||||
#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2)
|
||||
|
||||
/* The Zilog register set */
|
||||
|
||||
#define FLAG 0x7e
|
||||
|
||||
/* Write Register 0 */
|
||||
#define R0 0 /* Register selects */
|
||||
#define R1 1
|
||||
#define R2 2
|
||||
#define R3 3
|
||||
#define R4 4
|
||||
#define R5 5
|
||||
#define R6 6
|
||||
#define R7 7
|
||||
#define R8 8
|
||||
#define R9 9
|
||||
#define R10 10
|
||||
#define R11 11
|
||||
#define R12 12
|
||||
#define R13 13
|
||||
#define R14 14
|
||||
#define R15 15
|
||||
|
||||
#define NULLCODE 0 /* Null Code */
|
||||
#define POINT_HIGH 0x8 /* Select upper half of registers */
|
||||
#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */
|
||||
#define SEND_ABORT 0x18 /* HDLC Abort */
|
||||
#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */
|
||||
#define RES_Tx_P 0x28 /* Reset TxINT Pending */
|
||||
#define ERR_RES 0x30 /* Error Reset */
|
||||
#define RES_H_IUS 0x38 /* Reset highest IUS */
|
||||
|
||||
#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */
|
||||
#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */
|
||||
#define RES_EOM_L 0xC0 /* Reset EOM latch */
|
||||
|
||||
/* Write Register 1 */
|
||||
|
||||
#define EXT_INT_ENAB 0x1 /* Ext Int Enable */
|
||||
#define TxINT_ENAB 0x2 /* Tx Int Enable */
|
||||
#define PAR_SPEC 0x4 /* Parity is special condition */
|
||||
|
||||
#define RxINT_DISAB 0 /* Rx Int Disable */
|
||||
#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */
|
||||
#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */
|
||||
#define INT_ERR_Rx 0x18 /* Int on error only */
|
||||
#define RxINT_MASK 0x18
|
||||
|
||||
#define WT_RDY_RT 0x20 /* Wait/Ready on R/T */
|
||||
#define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */
|
||||
#define WT_RDY_ENAB 0x80 /* Wait/Ready Enable */
|
||||
|
||||
/* Write Register #2 (Interrupt Vector) */
|
||||
|
||||
/* Write Register 3 */
|
||||
|
||||
#define RxENAB 0x1 /* Rx Enable */
|
||||
#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */
|
||||
#define ADD_SM 0x4 /* Address Search Mode (SDLC) */
|
||||
#define RxCRC_ENAB 0x8 /* Rx CRC Enable */
|
||||
#define ENT_HM 0x10 /* Enter Hunt Mode */
|
||||
#define AUTO_ENAB 0x20 /* Auto Enables */
|
||||
#define Rx5 0x0 /* Rx 5 Bits/Character */
|
||||
#define Rx7 0x40 /* Rx 7 Bits/Character */
|
||||
#define Rx6 0x80 /* Rx 6 Bits/Character */
|
||||
#define Rx8 0xc0 /* Rx 8 Bits/Character */
|
||||
#define RxN_MASK 0xc0
|
||||
|
||||
/* Write Register 4 */
|
||||
|
||||
#define PAR_ENAB 0x1 /* Parity Enable */
|
||||
#define PAR_EVEN 0x2 /* Parity Even/Odd* */
|
||||
|
||||
#define SYNC_ENAB 0 /* Sync Modes Enable */
|
||||
#define SB1 0x4 /* 1 stop bit/char */
|
||||
#define SB15 0x8 /* 1.5 stop bits/char */
|
||||
#define SB2 0xc /* 2 stop bits/char */
|
||||
|
||||
#define MONSYNC 0 /* 8 Bit Sync character */
|
||||
#define BISYNC 0x10 /* 16 bit sync character */
|
||||
#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */
|
||||
#define EXTSYNC 0x30 /* External Sync Mode */
|
||||
|
||||
#define X1CLK 0x0 /* x1 clock mode */
|
||||
#define X16CLK 0x40 /* x16 clock mode */
|
||||
#define X32CLK 0x80 /* x32 clock mode */
|
||||
#define X64CLK 0xC0 /* x64 clock mode */
|
||||
#define XCLK_MASK 0xC0
|
||||
|
||||
/* Write Register 5 */
|
||||
|
||||
#define TxCRC_ENAB 0x1 /* Tx CRC Enable */
|
||||
#define RTS 0x2 /* RTS */
|
||||
#define SDLC_CRC 0x4 /* SDLC/CRC-16 */
|
||||
#define TxENAB 0x8 /* Tx Enable */
|
||||
#define SND_BRK 0x10 /* Send Break */
|
||||
#define Tx5 0x0 /* Tx 5 bits (or less)/character */
|
||||
#define Tx7 0x20 /* Tx 7 bits/character */
|
||||
#define Tx6 0x40 /* Tx 6 bits/character */
|
||||
#define Tx8 0x60 /* Tx 8 bits/character */
|
||||
#define TxN_MASK 0x60
|
||||
#define DTR 0x80 /* DTR */
|
||||
|
||||
/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
|
||||
|
||||
/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
|
||||
|
||||
/* Write Register 8 (transmit buffer) */
|
||||
|
||||
/* Write Register 9 (Master interrupt control) */
|
||||
#define VIS 1 /* Vector Includes Status */
|
||||
#define NV 2 /* No Vector */
|
||||
#define DLC 4 /* Disable Lower Chain */
|
||||
#define MIE 8 /* Master Interrupt Enable */
|
||||
#define STATHI 0x10 /* Status high */
|
||||
#define NORESET 0 /* No reset on write to R9 */
|
||||
#define CHRB 0x40 /* Reset channel B */
|
||||
#define CHRA 0x80 /* Reset channel A */
|
||||
#define FHWRES 0xc0 /* Force hardware reset */
|
||||
|
||||
/* Write Register 10 (misc control bits) */
|
||||
#define BIT6 1 /* 6 bit/8bit sync */
|
||||
#define LOOPMODE 2 /* SDLC Loop mode */
|
||||
#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */
|
||||
#define MARKIDLE 8 /* Mark/flag on idle */
|
||||
#define GAOP 0x10 /* Go active on poll */
|
||||
#define NRZ 0 /* NRZ mode */
|
||||
#define NRZI 0x20 /* NRZI mode */
|
||||
#define FM1 0x40 /* FM1 (transition = 1) */
|
||||
#define FM0 0x60 /* FM0 (transition = 0) */
|
||||
#define CRCPS 0x80 /* CRC Preset I/O */
|
||||
|
||||
/* Write Register 11 (Clock Mode control) */
|
||||
#define TRxCXT 0 /* TRxC = Xtal output */
|
||||
#define TRxCTC 1 /* TRxC = Transmit clock */
|
||||
#define TRxCBR 2 /* TRxC = BR Generator Output */
|
||||
#define TRxCDP 3 /* TRxC = DPLL output */
|
||||
#define TRxCOI 4 /* TRxC O/I */
|
||||
#define TCRTxCP 0 /* Transmit clock = RTxC pin */
|
||||
#define TCTRxCP 8 /* Transmit clock = TRxC pin */
|
||||
#define TCBR 0x10 /* Transmit clock = BR Generator output */
|
||||
#define TCDPLL 0x18 /* Transmit clock = DPLL output */
|
||||
#define RCRTxCP 0 /* Receive clock = RTxC pin */
|
||||
#define RCTRxCP 0x20 /* Receive clock = TRxC pin */
|
||||
#define RCBR 0x40 /* Receive clock = BR Generator output */
|
||||
#define RCDPLL 0x60 /* Receive clock = DPLL output */
|
||||
#define RTxCX 0x80 /* RTxC Xtal/No Xtal */
|
||||
|
||||
/* Write Register 12 (lower byte of baud rate generator time constant) */
|
||||
|
||||
/* Write Register 13 (upper byte of baud rate generator time constant) */
|
||||
|
||||
/* Write Register 14 (Misc control bits) */
|
||||
#define BRENAB 1 /* Baud rate generator enable */
|
||||
#define BRSRC 2 /* Baud rate generator source */
|
||||
#define DTRREQ 4 /* DTR/Request function */
|
||||
#define AUTOECHO 8 /* Auto Echo */
|
||||
#define LOOPBAK 0x10 /* Local loopback */
|
||||
#define SEARCH 0x20 /* Enter search mode */
|
||||
#define RMC 0x40 /* Reset missing clock */
|
||||
#define DISDPLL 0x60 /* Disable DPLL */
|
||||
#define SSBR 0x80 /* Set DPLL source = BR generator */
|
||||
#define SSRTxC 0xa0 /* Set DPLL source = RTxC */
|
||||
#define SFMM 0xc0 /* Set FM mode */
|
||||
#define SNRZI 0xe0 /* Set NRZI mode */
|
||||
|
||||
/* Write Register 15 (external/status interrupt control) */
|
||||
#define ZCIE 2 /* Zero count IE */
|
||||
#define DCDIE 8 /* DCD IE */
|
||||
#define SYNCIE 0x10 /* Sync/hunt IE */
|
||||
#define CTSIE 0x20 /* CTS IE */
|
||||
#define TxUIE 0x40 /* Tx Underrun/EOM IE */
|
||||
#define BRKIE 0x80 /* Break/Abort IE */
|
||||
|
||||
|
||||
/* Read Register 0 */
|
||||
#define Rx_CH_AV 0x1 /* Rx Character Available */
|
||||
#define ZCOUNT 0x2 /* Zero count */
|
||||
#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */
|
||||
#define DCD 0x8 /* DCD */
|
||||
#define SYNC 0x10 /* Sync/hunt */
|
||||
#define CTS 0x20 /* CTS */
|
||||
#define TxEOM 0x40 /* Tx underrun */
|
||||
#define BRK_ABRT 0x80 /* Break/Abort */
|
||||
|
||||
/* Read Register 1 */
|
||||
#define ALL_SNT 0x1 /* All sent */
|
||||
/* Residue Data for 8 Rx bits/char programmed */
|
||||
#define RES3 0x8 /* 0/3 */
|
||||
#define RES4 0x4 /* 0/4 */
|
||||
#define RES5 0xc /* 0/5 */
|
||||
#define RES6 0x2 /* 0/6 */
|
||||
#define RES7 0xa /* 0/7 */
|
||||
#define RES8 0x6 /* 0/8 */
|
||||
#define RES18 0xe /* 1/8 */
|
||||
#define RES28 0x0 /* 2/8 */
|
||||
/* Special Rx Condition Interrupts */
|
||||
#define PAR_ERR 0x10 /* Parity error */
|
||||
#define Rx_OVR 0x20 /* Rx Overrun Error */
|
||||
#define CRC_ERR 0x40 /* CRC/Framing Error */
|
||||
#define END_FR 0x80 /* End of Frame (SDLC) */
|
||||
|
||||
/* Read Register 2 (channel b only) - Interrupt vector */
|
||||
#define CHB_Tx_EMPTY 0x00
|
||||
#define CHB_EXT_STAT 0x02
|
||||
#define CHB_Rx_AVAIL 0x04
|
||||
#define CHB_SPECIAL 0x06
|
||||
#define CHA_Tx_EMPTY 0x08
|
||||
#define CHA_EXT_STAT 0x0a
|
||||
#define CHA_Rx_AVAIL 0x0c
|
||||
#define CHA_SPECIAL 0x0e
|
||||
#define STATUS_MASK 0x0e
|
||||
|
||||
/* Read Register 3 (interrupt pending register) ch a only */
|
||||
#define CHBEXT 0x1 /* Channel B Ext/Stat IP */
|
||||
#define CHBTxIP 0x2 /* Channel B Tx IP */
|
||||
#define CHBRxIP 0x4 /* Channel B Rx IP */
|
||||
#define CHAEXT 0x8 /* Channel A Ext/Stat IP */
|
||||
#define CHATxIP 0x10 /* Channel A Tx IP */
|
||||
#define CHARxIP 0x20 /* Channel A Rx IP */
|
||||
|
||||
/* Read Register 8 (receive data register) */
|
||||
|
||||
/* Read Register 10 (misc status bits) */
|
||||
#define ONLOOP 2 /* On loop */
|
||||
#define LOOPSEND 0x10 /* Loop sending */
|
||||
#define CLK2MIS 0x40 /* Two clocks missing */
|
||||
#define CLK1MIS 0x80 /* One clock missing */
|
||||
|
||||
/* Read Register 12 (lower byte of baud rate generator constant) */
|
||||
|
||||
/* Read Register 13 (upper byte of baud rate generator constant) */
|
||||
|
||||
/* Read Register 15 (value of WR 15) */
|
||||
|
||||
/* Misc macros */
|
||||
#define ZS_CLEARERR(channel) do { sbus_writeb(ERR_RES, &channel->control); \
|
||||
udelay(5); } while(0)
|
||||
|
||||
#define ZS_CLEARSTAT(channel) do { sbus_writeb(RES_EXT_INT, &channel->control); \
|
||||
udelay(5); } while(0)
|
||||
|
||||
#define ZS_CLEARFIFO(channel) do { sbus_readb(&channel->data); \
|
||||
udelay(2); \
|
||||
sbus_readb(&channel->data); \
|
||||
udelay(2); \
|
||||
sbus_readb(&channel->data); \
|
||||
udelay(2); } while(0)
|
||||
|
||||
#endif /* _SUNZILOG_H */
|
||||
782
extra/linux-2.6.10/drivers/serial/uart00.c
Normal file
782
extra/linux-2.6.10/drivers/serial/uart00.c
Normal file
@@ -0,0 +1,782 @@
|
||||
/*
|
||||
* linux/drivers/serial/uart00.c
|
||||
*
|
||||
* Driver for UART00 serial ports
|
||||
*
|
||||
* Based on drivers/char/serial_amba.c, by ARM Limited &
|
||||
* Deep Blue Solutions Ltd.
|
||||
* Copyright 2001 Altera Corporation
|
||||
*
|
||||
* Update for 2.6.4 by Dirk Behme <dirk.behme@de.bosch.com>
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* $Id: uart00.c,v 1.35 2002/07/28 10:03:28 rmk Exp $
|
||||
*
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
|
||||
#if defined(CONFIG_SERIAL_UART00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
||||
#define SUPPORT_SYSRQ
|
||||
#endif
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/sizes.h>
|
||||
|
||||
#include <asm/arch/excalibur.h>
|
||||
#define UART00_TYPE (volatile unsigned int*)
|
||||
#include <asm/arch/uart00.h>
|
||||
#include <asm/arch/int_ctrl00.h>
|
||||
|
||||
#define UART_NR 2
|
||||
|
||||
#define SERIAL_UART00_NAME "ttyUA"
|
||||
#define SERIAL_UART00_MAJOR 204
|
||||
#define SERIAL_UART00_MINOR 16 /* Temporary - will change in future */
|
||||
#define SERIAL_UART00_NR UART_NR
|
||||
#define UART_PORT_SIZE 0x50
|
||||
|
||||
#define UART00_ISR_PASS_LIMIT 256
|
||||
|
||||
/*
|
||||
* Access macros for the UART00 UARTs
|
||||
*/
|
||||
#define UART_GET_INT_STATUS(p) inl(UART_ISR((p)->membase))
|
||||
#define UART_PUT_IES(p, c) outl(c,UART_IES((p)->membase))
|
||||
#define UART_GET_IES(p) inl(UART_IES((p)->membase))
|
||||
#define UART_PUT_IEC(p, c) outl(c,UART_IEC((p)->membase))
|
||||
#define UART_GET_IEC(p) inl(UART_IEC((p)->membase))
|
||||
#define UART_PUT_CHAR(p, c) outl(c,UART_TD((p)->membase))
|
||||
#define UART_GET_CHAR(p) inl(UART_RD((p)->membase))
|
||||
#define UART_GET_RSR(p) inl(UART_RSR((p)->membase))
|
||||
#define UART_GET_RDS(p) inl(UART_RDS((p)->membase))
|
||||
#define UART_GET_MSR(p) inl(UART_MSR((p)->membase))
|
||||
#define UART_GET_MCR(p) inl(UART_MCR((p)->membase))
|
||||
#define UART_PUT_MCR(p, c) outl(c,UART_MCR((p)->membase))
|
||||
#define UART_GET_MC(p) inl(UART_MC((p)->membase))
|
||||
#define UART_PUT_MC(p, c) outl(c,UART_MC((p)->membase))
|
||||
#define UART_GET_TSR(p) inl(UART_TSR((p)->membase))
|
||||
#define UART_GET_DIV_HI(p) inl(UART_DIV_HI((p)->membase))
|
||||
#define UART_PUT_DIV_HI(p,c) outl(c,UART_DIV_HI((p)->membase))
|
||||
#define UART_GET_DIV_LO(p) inl(UART_DIV_LO((p)->membase))
|
||||
#define UART_PUT_DIV_LO(p,c) outl(c,UART_DIV_LO((p)->membase))
|
||||
#define UART_RX_DATA(s) ((s) & UART_RSR_RX_LEVEL_MSK)
|
||||
#define UART_TX_READY(s) (((s) & UART_TSR_TX_LEVEL_MSK) < 15)
|
||||
//#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART00_UARTFR_TMSK) == 0)
|
||||
|
||||
static void uart00_stop_tx(struct uart_port *port, unsigned int tty_stop)
|
||||
{
|
||||
UART_PUT_IEC(port, UART_IEC_TIE_MSK);
|
||||
}
|
||||
|
||||
static void uart00_stop_rx(struct uart_port *port)
|
||||
{
|
||||
UART_PUT_IEC(port, UART_IEC_RE_MSK);
|
||||
}
|
||||
|
||||
static void uart00_enable_ms(struct uart_port *port)
|
||||
{
|
||||
UART_PUT_IES(port, UART_IES_ME_MSK);
|
||||
}
|
||||
|
||||
static void
|
||||
uart00_rx_chars(struct uart_port *port, struct pt_regs *regs)
|
||||
{
|
||||
struct tty_struct *tty = port->info->tty;
|
||||
unsigned int status, ch, rds, flg, ignored = 0;
|
||||
|
||||
status = UART_GET_RSR(port);
|
||||
while (UART_RX_DATA(status)) {
|
||||
/*
|
||||
* We need to read rds before reading the
|
||||
* character from the fifo
|
||||
*/
|
||||
rds = UART_GET_RDS(port);
|
||||
ch = UART_GET_CHAR(port);
|
||||
port->icount.rx++;
|
||||
|
||||
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
|
||||
goto ignore_char;
|
||||
|
||||
flg = TTY_NORMAL;
|
||||
|
||||
/*
|
||||
* Note that the error handling code is
|
||||
* out of the main execution path
|
||||
*/
|
||||
if (rds & (UART_RDS_BI_MSK |UART_RDS_FE_MSK|
|
||||
UART_RDS_PE_MSK |UART_RDS_PE_MSK))
|
||||
goto handle_error;
|
||||
if (uart_handle_sysrq_char(port, ch, regs))
|
||||
goto ignore_char;
|
||||
|
||||
error_return:
|
||||
tty_insert_flip_char(tty, ch, flg);
|
||||
|
||||
ignore_char:
|
||||
status = UART_GET_RSR(port);
|
||||
}
|
||||
out:
|
||||
tty_flip_buffer_push(tty);
|
||||
return;
|
||||
|
||||
handle_error:
|
||||
if (rds & UART_RDS_BI_MSK) {
|
||||
status &= ~(UART_RDS_FE_MSK | UART_RDS_PE_MSK);
|
||||
port->icount.brk++;
|
||||
if (uart_handle_break(port))
|
||||
goto ignore_char;
|
||||
} else if (rds & UART_RDS_PE_MSK)
|
||||
port->icount.parity++;
|
||||
else if (rds & UART_RDS_FE_MSK)
|
||||
port->icount.frame++;
|
||||
if (rds & UART_RDS_OE_MSK)
|
||||
port->icount.overrun++;
|
||||
|
||||
if (rds & port->ignore_status_mask) {
|
||||
if (++ignored > 100)
|
||||
goto out;
|
||||
goto ignore_char;
|
||||
}
|
||||
rds &= port->read_status_mask;
|
||||
|
||||
if (rds & UART_RDS_BI_MSK)
|
||||
flg = TTY_BREAK;
|
||||
else if (rds & UART_RDS_PE_MSK)
|
||||
flg = TTY_PARITY;
|
||||
else if (rds & UART_RDS_FE_MSK)
|
||||
flg = TTY_FRAME;
|
||||
|
||||
if (rds & UART_RDS_OE_MSK) {
|
||||
/*
|
||||
* CHECK: does overrun affect the current character?
|
||||
* ASSUMPTION: it does not.
|
||||
*/
|
||||
tty_insert_flip_char(tty, ch, flg);
|
||||
ch = 0;
|
||||
flg = TTY_OVERRUN;
|
||||
}
|
||||
#ifdef SUPPORT_SYSRQ
|
||||
port->sysrq = 0;
|
||||
#endif
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
static void uart00_tx_chars(struct uart_port *port)
|
||||
{
|
||||
struct circ_buf *xmit = &port->info->xmit;
|
||||
int count;
|
||||
|
||||
if (port->x_char) {
|
||||
while ((UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK) == 15)
|
||||
barrier();
|
||||
UART_PUT_CHAR(port, port->x_char);
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
return;
|
||||
}
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
|
||||
uart00_stop_tx(port, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
count = port->fifosize >> 1;
|
||||
do {
|
||||
while ((UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK) == 15)
|
||||
barrier();
|
||||
UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
} while (--count > 0);
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if (uart_circ_empty(xmit))
|
||||
uart00_stop_tx(port, 0);
|
||||
}
|
||||
|
||||
static void uart00_start_tx(struct uart_port *port, unsigned int tty_start)
|
||||
{
|
||||
UART_PUT_IES(port, UART_IES_TIE_MSK);
|
||||
uart00_tx_chars(port);
|
||||
}
|
||||
|
||||
static void uart00_modem_status(struct uart_port *port)
|
||||
{
|
||||
unsigned int status;
|
||||
|
||||
status = UART_GET_MSR(port);
|
||||
|
||||
if (!(status & (UART_MSR_DCTS_MSK | UART_MSR_DDSR_MSK |
|
||||
UART_MSR_TERI_MSK | UART_MSR_DDCD_MSK)))
|
||||
return;
|
||||
|
||||
if (status & UART_MSR_DDCD_MSK)
|
||||
uart_handle_dcd_change(port, status & UART_MSR_DCD_MSK);
|
||||
|
||||
if (status & UART_MSR_DDSR_MSK)
|
||||
port->icount.dsr++;
|
||||
|
||||
if (status & UART_MSR_DCTS_MSK)
|
||||
uart_handle_cts_change(port, status & UART_MSR_CTS_MSK);
|
||||
|
||||
wake_up_interruptible(&port->info->delta_msr_wait);
|
||||
}
|
||||
|
||||
static irqreturn_t uart00_int(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct uart_port *port = dev_id;
|
||||
unsigned int status, pass_counter = 0;
|
||||
|
||||
status = UART_GET_INT_STATUS(port);
|
||||
do {
|
||||
if (status & UART_ISR_RI_MSK)
|
||||
uart00_rx_chars(port, regs);
|
||||
if (status & UART_ISR_MI_MSK)
|
||||
uart00_modem_status(port);
|
||||
if (status & (UART_ISR_TI_MSK | UART_ISR_TII_MSK))
|
||||
uart00_tx_chars(port);
|
||||
if (pass_counter++ > UART00_ISR_PASS_LIMIT)
|
||||
break;
|
||||
|
||||
status = UART_GET_INT_STATUS(port);
|
||||
} while (status);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static unsigned int uart00_tx_empty(struct uart_port *port)
|
||||
{
|
||||
return UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK? 0 : TIOCSER_TEMT;
|
||||
}
|
||||
|
||||
static unsigned int uart00_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
unsigned int result = 0;
|
||||
unsigned int status;
|
||||
|
||||
status = UART_GET_MSR(port);
|
||||
if (status & UART_MSR_DCD_MSK)
|
||||
result |= TIOCM_CAR;
|
||||
if (status & UART_MSR_DSR_MSK)
|
||||
result |= TIOCM_DSR;
|
||||
if (status & UART_MSR_CTS_MSK)
|
||||
result |= TIOCM_CTS;
|
||||
if (status & UART_MSR_RI_MSK)
|
||||
result |= TIOCM_RI;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void uart00_set_mctrl_null(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
}
|
||||
|
||||
static void uart00_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int mcr;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
mcr = UART_GET_MCR(port);
|
||||
if (break_state == -1)
|
||||
mcr |= UART_MCR_BR_MSK;
|
||||
else
|
||||
mcr &= ~UART_MCR_BR_MSK;
|
||||
UART_PUT_MCR(port, mcr);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
uart00_set_termios(struct uart_port *port, struct termios *termios,
|
||||
struct termios *old)
|
||||
{
|
||||
unsigned int uart_mc, old_ies, baud, quot;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* We don't support CREAD (yet)
|
||||
*/
|
||||
termios->c_cflag |= CREAD;
|
||||
|
||||
/*
|
||||
* Ask the core to calculate the divisor for us.
|
||||
*/
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
|
||||
quot = uart_get_divisor(port, baud);
|
||||
|
||||
/* byte size and parity */
|
||||
switch (termios->c_cflag & CSIZE) {
|
||||
case CS5:
|
||||
uart_mc = UART_MC_CLS_CHARLEN_5;
|
||||
break;
|
||||
case CS6:
|
||||
uart_mc = UART_MC_CLS_CHARLEN_6;
|
||||
break;
|
||||
case CS7:
|
||||
uart_mc = UART_MC_CLS_CHARLEN_7;
|
||||
break;
|
||||
default: // CS8
|
||||
uart_mc = UART_MC_CLS_CHARLEN_8;
|
||||
break;
|
||||
}
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
uart_mc|= UART_MC_ST_TWO;
|
||||
if (termios->c_cflag & PARENB) {
|
||||
uart_mc |= UART_MC_PE_MSK;
|
||||
if (!(termios->c_cflag & PARODD))
|
||||
uart_mc |= UART_MC_EP_MSK;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
/*
|
||||
* Update the per-port timeout.
|
||||
*/
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
port->read_status_mask = UART_RDS_OE_MSK;
|
||||
if (termios->c_iflag & INPCK)
|
||||
port->read_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK;
|
||||
if (termios->c_iflag & (BRKINT | PARMRK))
|
||||
port->read_status_mask |= UART_RDS_BI_MSK;
|
||||
|
||||
/*
|
||||
* Characters to ignore
|
||||
*/
|
||||
port->ignore_status_mask = 0;
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
port->ignore_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK;
|
||||
if (termios->c_iflag & IGNBRK) {
|
||||
port->ignore_status_mask |= UART_RDS_BI_MSK;
|
||||
/*
|
||||
* If we're ignoring parity and break indicators,
|
||||
* ignore overruns to (for real raw support).
|
||||
*/
|
||||
if (termios->c_iflag & IGNPAR)
|
||||
port->ignore_status_mask |= UART_RDS_OE_MSK;
|
||||
}
|
||||
|
||||
/* first, disable everything */
|
||||
old_ies = UART_GET_IES(port);
|
||||
|
||||
if (UART_ENABLE_MS(port, termios->c_cflag))
|
||||
old_ies |= UART_IES_ME_MSK;
|
||||
|
||||
/* Set baud rate */
|
||||
UART_PUT_DIV_LO(port, (quot & 0xff));
|
||||
UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
|
||||
|
||||
UART_PUT_MC(port, uart_mc);
|
||||
UART_PUT_IES(port, old_ies);
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static int uart00_startup(struct uart_port *port)
|
||||
{
|
||||
int result;
|
||||
|
||||
/*
|
||||
* Allocate the IRQ
|
||||
*/
|
||||
result = request_irq(port->irq, uart00_int, 0, "uart00", port);
|
||||
if (result) {
|
||||
printk(KERN_ERR "Request of irq %d failed\n", port->irq);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, enable interrupts. Use the TII interrupt to minimise
|
||||
* the number of interrupts generated. If higher performance is
|
||||
* needed, consider using the TI interrupt with a suitable FIFO
|
||||
* threshold
|
||||
*/
|
||||
UART_PUT_IES(port, UART_IES_RE_MSK | UART_IES_TIE_MSK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uart00_shutdown(struct uart_port *port)
|
||||
{
|
||||
/*
|
||||
* disable all interrupts, disable the port
|
||||
*/
|
||||
UART_PUT_IEC(port, 0xff);
|
||||
|
||||
/* disable break condition and fifos */
|
||||
UART_PUT_MCR(port, UART_GET_MCR(port) &~UART_MCR_BR_MSK);
|
||||
|
||||
/*
|
||||
* Free the interrupt
|
||||
*/
|
||||
free_irq(port->irq, port);
|
||||
}
|
||||
|
||||
static const char *uart00_type(struct uart_port *port)
|
||||
{
|
||||
return port->type == PORT_UART00 ? "Altera UART00" : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the memory region(s) being used by 'port'
|
||||
*/
|
||||
static void uart00_release_port(struct uart_port *port)
|
||||
{
|
||||
release_mem_region(port->mapbase, UART_PORT_SIZE);
|
||||
|
||||
#ifdef CONFIG_ARCH_CAMELOT
|
||||
if (port->membase != (void*)IO_ADDRESS(EXC_UART00_BASE)) {
|
||||
iounmap(port->membase);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Request the memory region(s) being used by 'port'
|
||||
*/
|
||||
static int uart00_request_port(struct uart_port *port)
|
||||
{
|
||||
return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_uart00")
|
||||
!= NULL ? 0 : -EBUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure/autoconfigure the port.
|
||||
*/
|
||||
static void uart00_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
|
||||
/*
|
||||
* Map the io memory if this is a soft uart
|
||||
*/
|
||||
if (!port->membase)
|
||||
port->membase = ioremap_nocache(port->mapbase,SZ_4K);
|
||||
|
||||
if (!port->membase)
|
||||
printk(KERN_ERR "serial00: cannot map io memory\n");
|
||||
else
|
||||
port->type = PORT_UART00;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* verify the new serial_struct (for TIOCSSERIAL).
|
||||
*/
|
||||
static int uart00_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||
{
|
||||
int ret = 0;
|
||||
if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
|
||||
ret = -EINVAL;
|
||||
if (ser->irq < 0 || ser->irq >= NR_IRQS)
|
||||
ret = -EINVAL;
|
||||
if (ser->baud_base < 9600)
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct uart_ops uart00_pops = {
|
||||
.tx_empty = uart00_tx_empty,
|
||||
.set_mctrl = uart00_set_mctrl_null,
|
||||
.get_mctrl = uart00_get_mctrl,
|
||||
.stop_tx = uart00_stop_tx,
|
||||
.start_tx = uart00_start_tx,
|
||||
.stop_rx = uart00_stop_rx,
|
||||
.enable_ms = uart00_enable_ms,
|
||||
.break_ctl = uart00_break_ctl,
|
||||
.startup = uart00_startup,
|
||||
.shutdown = uart00_shutdown,
|
||||
.set_termios = uart00_set_termios,
|
||||
.type = uart00_type,
|
||||
.release_port = uart00_release_port,
|
||||
.request_port = uart00_request_port,
|
||||
.config_port = uart00_config_port,
|
||||
.verify_port = uart00_verify_port,
|
||||
};
|
||||
|
||||
|
||||
#ifdef CONFIG_ARCH_CAMELOT
|
||||
static struct uart_port epxa10db_port = {
|
||||
.membase = (void*)IO_ADDRESS(EXC_UART00_BASE),
|
||||
.mapbase = EXC_UART00_BASE,
|
||||
.iotype = SERIAL_IO_MEM,
|
||||
.irq = IRQ_UART,
|
||||
.uartclk = EXC_AHB2_CLK_FREQUENCY,
|
||||
.fifosize = 16,
|
||||
.ops = &uart00_pops,
|
||||
.flags = ASYNC_BOOT_AUTOCONF,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_SERIAL_UART00_CONSOLE
|
||||
static void uart00_console_write(struct console *co, const char *s, unsigned count)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_CAMELOT
|
||||
struct uart_port *port = &epxa10db_port;
|
||||
unsigned int status, old_ies;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* First save the CR then disable the interrupts
|
||||
*/
|
||||
old_ies = UART_GET_IES(port);
|
||||
UART_PUT_IEC(port,0xff);
|
||||
|
||||
/*
|
||||
* Now, do each character
|
||||
*/
|
||||
for (i = 0; i < count; i++) {
|
||||
do {
|
||||
status = UART_GET_TSR(port);
|
||||
} while (!UART_TX_READY(status));
|
||||
UART_PUT_CHAR(port, s[i]);
|
||||
if (s[i] == '\n') {
|
||||
do {
|
||||
status = UART_GET_TSR(port);
|
||||
} while (!UART_TX_READY(status));
|
||||
UART_PUT_CHAR(port, '\r');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, wait for transmitter to become empty
|
||||
* and restore the IES
|
||||
*/
|
||||
do {
|
||||
status = UART_GET_TSR(port);
|
||||
} while (status & UART_TSR_TX_LEVEL_MSK);
|
||||
UART_PUT_IES(port, old_ies);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __init
|
||||
uart00_console_get_options(struct uart_port *port, int *baud,
|
||||
int *parity, int *bits)
|
||||
{
|
||||
unsigned int uart_mc, quot;
|
||||
|
||||
uart_mc = UART_GET_MC(port);
|
||||
|
||||
*parity = 'n';
|
||||
if (uart_mc & UART_MC_PE_MSK) {
|
||||
if (uart_mc & UART_MC_EP_MSK)
|
||||
*parity = 'e';
|
||||
else
|
||||
*parity = 'o';
|
||||
}
|
||||
|
||||
switch (uart_mc & UART_MC_CLS_MSK) {
|
||||
case UART_MC_CLS_CHARLEN_5:
|
||||
*bits = 5;
|
||||
break;
|
||||
case UART_MC_CLS_CHARLEN_6:
|
||||
*bits = 6;
|
||||
break;
|
||||
case UART_MC_CLS_CHARLEN_7:
|
||||
*bits = 7;
|
||||
break;
|
||||
case UART_MC_CLS_CHARLEN_8:
|
||||
*bits = 8;
|
||||
break;
|
||||
}
|
||||
quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
|
||||
*baud = port->uartclk / (16 *quot );
|
||||
}
|
||||
|
||||
static int __init uart00_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_port *port;
|
||||
int baud = 115200;
|
||||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
|
||||
#ifdef CONFIG_ARCH_CAMELOT
|
||||
port = &epxa10db_port; ;
|
||||
#else
|
||||
return -ENODEV;
|
||||
#endif
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
else
|
||||
uart00_console_get_options(port, &baud, &parity, &bits);
|
||||
|
||||
return uart_set_options(port, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
extern struct uart_driver uart00_reg;
|
||||
static struct console uart00_console = {
|
||||
.name = SERIAL_UART00_NAME,
|
||||
.write = uart00_console_write,
|
||||
.device = uart_console_device,
|
||||
.setup = uart00_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = 0,
|
||||
.data = &uart00_reg,
|
||||
};
|
||||
|
||||
static int __init uart00_console_init(void)
|
||||
{
|
||||
register_console(&uart00_console);
|
||||
return 0;
|
||||
}
|
||||
console_initcall(uart00_console_init);
|
||||
|
||||
#define UART00_CONSOLE &uart00_console
|
||||
#else
|
||||
#define UART00_CONSOLE NULL
|
||||
#endif
|
||||
|
||||
static struct uart_driver uart00_reg = {
|
||||
.owner = NULL,
|
||||
.driver_name = SERIAL_UART00_NAME,
|
||||
.dev_name = SERIAL_UART00_NAME,
|
||||
.major = SERIAL_UART00_MAJOR,
|
||||
.minor = SERIAL_UART00_MINOR,
|
||||
.nr = UART_NR,
|
||||
.cons = UART00_CONSOLE,
|
||||
};
|
||||
|
||||
struct dev_port_entry{
|
||||
unsigned int base_addr;
|
||||
struct uart_port *port;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PLD_HOTSWAP
|
||||
|
||||
static struct dev_port_entry dev_port_map[UART_NR];
|
||||
|
||||
/*
|
||||
* Keep a mapping of dev_info addresses -> port lines to use when
|
||||
* removing ports dev==NULL indicates unused entry
|
||||
*/
|
||||
|
||||
struct uart00_ps_data{
|
||||
unsigned int clk;
|
||||
unsigned int fifosize;
|
||||
};
|
||||
|
||||
int uart00_add_device(struct pldhs_dev_info* dev_info, void* dev_ps_data)
|
||||
{
|
||||
struct uart00_ps_data* dev_ps=dev_ps_data;
|
||||
struct uart_port * port;
|
||||
int i,result;
|
||||
|
||||
i=0;
|
||||
while(dev_port_map[i].port)
|
||||
i++;
|
||||
|
||||
if(i==UART_NR){
|
||||
printk(KERN_WARNING "uart00: Maximum number of ports reached\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
port=kmalloc(sizeof(struct uart_port),GFP_KERNEL);
|
||||
if(!port)
|
||||
return -ENOMEM;
|
||||
|
||||
printk("clk=%d fifo=%d\n",dev_ps->clk,dev_ps->fifosize);
|
||||
port->membase=0;
|
||||
port->mapbase=dev_info->base_addr;
|
||||
port->iotype=SERIAL_IO_MEM;
|
||||
port->irq=dev_info->irq;
|
||||
port->uartclk=dev_ps->clk;
|
||||
port->fifosize=dev_ps->fifosize;
|
||||
port->ops=&uart00_pops;
|
||||
port->line=i;
|
||||
port->flags=ASYNC_BOOT_AUTOCONF;
|
||||
|
||||
result=uart_add_one_port(&uart00_reg, port);
|
||||
if(result){
|
||||
printk("uart_add_one_port returned %d\n",result);
|
||||
return result;
|
||||
}
|
||||
dev_port_map[i].base_addr=dev_info->base_addr;
|
||||
dev_port_map[i].port=port;
|
||||
printk("uart00: added device at %x as ttyUA%d\n",dev_port_map[i].base_addr,i);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int uart00_remove_devices(void)
|
||||
{
|
||||
int i,result;
|
||||
|
||||
|
||||
result=0;
|
||||
for(i=1;i<UART_NR;i++){
|
||||
if(dev_port_map[i].base_addr){
|
||||
result=uart_remove_one_port(&uart00_reg, dev_port_map[i].port);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* port removed sucessfully, so now tidy up */
|
||||
kfree(dev_port_map[i].port);
|
||||
dev_port_map[i].base_addr=0;
|
||||
dev_port_map[i].port=NULL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
struct pld_hotswap_ops uart00_pldhs_ops={
|
||||
.name = "uart00",
|
||||
.add_device = uart00_add_device,
|
||||
.remove_devices = uart00_remove_devices,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static int __init uart00_init(void)
|
||||
{
|
||||
int result;
|
||||
|
||||
printk(KERN_INFO "Serial: UART00 driver $Revision: 1.35 $\n");
|
||||
|
||||
printk(KERN_WARNING "serial_uart00:Using temporary major/minor pairs"
|
||||
" - these WILL change in the future\n");
|
||||
|
||||
result = uart_register_driver(&uart00_reg);
|
||||
if (result)
|
||||
return result;
|
||||
#ifdef CONFIG_ARCH_CAMELOT
|
||||
result = uart_add_one_port(&uart00_reg,&epxa10db_port);
|
||||
#endif
|
||||
if (result)
|
||||
uart_unregister_driver(&uart00_reg);
|
||||
|
||||
#ifdef CONFIG_PLD_HOTSWAP
|
||||
pldhs_register_driver(&uart00_pldhs_ops);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
__initcall(uart00_init);
|
||||
549
extra/linux-2.6.10/drivers/serial/v850e_uart.c
Normal file
549
extra/linux-2.6.10/drivers/serial/v850e_uart.c
Normal file
@@ -0,0 +1,549 @@
|
||||
/*
|
||||
* drivers/serial/v850e_uart.c -- Serial I/O using V850E on-chip UART or UARTB
|
||||
*
|
||||
* Copyright (C) 2001,02,03 NEC Electronics Corporation
|
||||
* Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License. See the file COPYING in the main directory of this
|
||||
* archive for more details.
|
||||
*
|
||||
* Written by Miles Bader <miles@gnu.org>
|
||||
*/
|
||||
|
||||
/* This driver supports both the original V850E UART interface (called
|
||||
merely `UART' in the docs) and the newer `UARTB' interface, which is
|
||||
roughly a superset of the first one. The selection is made at
|
||||
configure time -- if CONFIG_V850E_UARTB is defined, then UARTB is
|
||||
presumed, otherwise the old UART -- as these are on-CPU UARTS, a system
|
||||
can never have both.
|
||||
|
||||
The UARTB interface also has a 16-entry FIFO mode, which is not
|
||||
yet supported by this driver. */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_core.h>
|
||||
|
||||
#include <asm/v850e_uart.h>
|
||||
|
||||
/* Initial UART state. This may be overridden by machine-dependent headers. */
|
||||
#ifndef V850E_UART_INIT_BAUD
|
||||
#define V850E_UART_INIT_BAUD 115200
|
||||
#endif
|
||||
#ifndef V850E_UART_INIT_CFLAGS
|
||||
#define V850E_UART_INIT_CFLAGS (B115200 | CS8 | CREAD)
|
||||
#endif
|
||||
|
||||
/* A string used for prefixing printed descriptions; since the same UART
|
||||
macro is actually used on other chips than the V850E. This must be a
|
||||
constant string. */
|
||||
#ifndef V850E_UART_CHIP_NAME
|
||||
#define V850E_UART_CHIP_NAME "V850E"
|
||||
#endif
|
||||
|
||||
#define V850E_UART_MINOR_BASE 64 /* First tty minor number */
|
||||
|
||||
|
||||
/* Low-level UART functions. */
|
||||
|
||||
/* Configure and turn on uart channel CHAN, using the termios `control
|
||||
modes' bits in CFLAGS, and a baud-rate of BAUD. */
|
||||
void v850e_uart_configure (unsigned chan, unsigned cflags, unsigned baud)
|
||||
{
|
||||
int flags;
|
||||
v850e_uart_speed_t old_speed;
|
||||
v850e_uart_config_t old_config;
|
||||
v850e_uart_speed_t new_speed = v850e_uart_calc_speed (baud);
|
||||
v850e_uart_config_t new_config = v850e_uart_calc_config (cflags);
|
||||
|
||||
/* Disable interrupts while we're twiddling the hardware. */
|
||||
local_irq_save (flags);
|
||||
|
||||
#ifdef V850E_UART_PRE_CONFIGURE
|
||||
V850E_UART_PRE_CONFIGURE (chan, cflags, baud);
|
||||
#endif
|
||||
|
||||
old_config = V850E_UART_CONFIG (chan);
|
||||
old_speed = v850e_uart_speed (chan);
|
||||
|
||||
if (! v850e_uart_speed_eq (old_speed, new_speed)) {
|
||||
/* The baud rate has changed. First, disable the UART. */
|
||||
V850E_UART_CONFIG (chan) = V850E_UART_CONFIG_FINI;
|
||||
old_config = 0; /* Force the uart to be re-initialized. */
|
||||
|
||||
/* Reprogram the baud-rate generator. */
|
||||
v850e_uart_set_speed (chan, new_speed);
|
||||
}
|
||||
|
||||
if (! (old_config & V850E_UART_CONFIG_ENABLED)) {
|
||||
/* If we are using the uart for the first time, start by
|
||||
enabling it, which must be done before turning on any
|
||||
other bits. */
|
||||
V850E_UART_CONFIG (chan) = V850E_UART_CONFIG_INIT;
|
||||
/* See the initial state. */
|
||||
old_config = V850E_UART_CONFIG (chan);
|
||||
}
|
||||
|
||||
if (new_config != old_config) {
|
||||
/* Which of the TXE/RXE bits we'll temporarily turn off
|
||||
before changing other control bits. */
|
||||
unsigned temp_disable = 0;
|
||||
/* Which of the TXE/RXE bits will be enabled. */
|
||||
unsigned enable = 0;
|
||||
unsigned changed_bits = new_config ^ old_config;
|
||||
|
||||
/* Which of RX/TX will be enabled in the new configuration. */
|
||||
if (new_config & V850E_UART_CONFIG_RX_BITS)
|
||||
enable |= (new_config & V850E_UART_CONFIG_RX_ENABLE);
|
||||
if (new_config & V850E_UART_CONFIG_TX_BITS)
|
||||
enable |= (new_config & V850E_UART_CONFIG_TX_ENABLE);
|
||||
|
||||
/* Figure out which of RX/TX needs to be disabled; note
|
||||
that this will only happen if they're not already
|
||||
disabled. */
|
||||
if (changed_bits & V850E_UART_CONFIG_RX_BITS)
|
||||
temp_disable
|
||||
|= (old_config & V850E_UART_CONFIG_RX_ENABLE);
|
||||
if (changed_bits & V850E_UART_CONFIG_TX_BITS)
|
||||
temp_disable
|
||||
|= (old_config & V850E_UART_CONFIG_TX_ENABLE);
|
||||
|
||||
/* We have to turn off RX and/or TX mode before changing
|
||||
any associated control bits. */
|
||||
if (temp_disable)
|
||||
V850E_UART_CONFIG (chan) = old_config & ~temp_disable;
|
||||
|
||||
/* Write the new control bits, while RX/TX are disabled. */
|
||||
if (changed_bits & ~enable)
|
||||
V850E_UART_CONFIG (chan) = new_config & ~enable;
|
||||
|
||||
v850e_uart_config_delay (new_config, new_speed);
|
||||
|
||||
/* Write the final version, with enable bits turned on. */
|
||||
V850E_UART_CONFIG (chan) = new_config;
|
||||
}
|
||||
|
||||
local_irq_restore (flags);
|
||||
}
|
||||
|
||||
|
||||
/* Low-level console. */
|
||||
|
||||
#ifdef CONFIG_V850E_UART_CONSOLE
|
||||
|
||||
static void v850e_uart_cons_write (struct console *co,
|
||||
const char *s, unsigned count)
|
||||
{
|
||||
if (count > 0) {
|
||||
unsigned chan = co->index;
|
||||
unsigned irq = V850E_UART_TX_IRQ (chan);
|
||||
int irq_was_enabled, irq_was_pending, flags;
|
||||
|
||||
/* We don't want to get `transmission completed'
|
||||
interrupts, since we're busy-waiting, so we disable them
|
||||
while sending (we don't disable interrupts entirely
|
||||
because sending over a serial line is really slow). We
|
||||
save the status of the tx interrupt and restore it when
|
||||
we're done so that using printk doesn't interfere with
|
||||
normal serial transmission (other than interleaving the
|
||||
output, of course!). This should work correctly even if
|
||||
this function is interrupted and the interrupt printks
|
||||
something. */
|
||||
|
||||
/* Disable interrupts while fiddling with tx interrupt. */
|
||||
local_irq_save (flags);
|
||||
/* Get current tx interrupt status. */
|
||||
irq_was_enabled = v850e_intc_irq_enabled (irq);
|
||||
irq_was_pending = v850e_intc_irq_pending (irq);
|
||||
/* Disable tx interrupt if necessary. */
|
||||
if (irq_was_enabled)
|
||||
v850e_intc_disable_irq (irq);
|
||||
/* Turn interrupts back on. */
|
||||
local_irq_restore (flags);
|
||||
|
||||
/* Send characters. */
|
||||
while (count > 0) {
|
||||
int ch = *s++;
|
||||
|
||||
if (ch == '\n') {
|
||||
/* We don't have the benefit of a tty
|
||||
driver, so translate NL into CR LF. */
|
||||
v850e_uart_wait_for_xmit_ok (chan);
|
||||
v850e_uart_putc (chan, '\r');
|
||||
}
|
||||
|
||||
v850e_uart_wait_for_xmit_ok (chan);
|
||||
v850e_uart_putc (chan, ch);
|
||||
|
||||
count--;
|
||||
}
|
||||
|
||||
/* Restore saved tx interrupt status. */
|
||||
if (irq_was_enabled) {
|
||||
/* Wait for the last character we sent to be
|
||||
completely transmitted (as we'll get an
|
||||
interrupt interrupt at that point). */
|
||||
v850e_uart_wait_for_xmit_done (chan);
|
||||
/* Clear pending interrupts received due
|
||||
to our transmission, unless there was already
|
||||
one pending, in which case we want the
|
||||
handler to be called. */
|
||||
if (! irq_was_pending)
|
||||
v850e_intc_clear_pending_irq (irq);
|
||||
/* ... and then turn back on handling. */
|
||||
v850e_intc_enable_irq (irq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern struct uart_driver v850e_uart_driver;
|
||||
static struct console v850e_uart_cons =
|
||||
{
|
||||
.name = "ttyS",
|
||||
.write = v850e_uart_cons_write,
|
||||
.device = uart_console_device,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.cflag = V850E_UART_INIT_CFLAGS,
|
||||
.index = -1,
|
||||
.data = &v850e_uart_driver,
|
||||
};
|
||||
|
||||
void v850e_uart_cons_init (unsigned chan)
|
||||
{
|
||||
v850e_uart_configure (chan, V850E_UART_INIT_CFLAGS,
|
||||
V850E_UART_INIT_BAUD);
|
||||
v850e_uart_cons.index = chan;
|
||||
register_console (&v850e_uart_cons);
|
||||
printk ("Console: %s on-chip UART channel %d\n",
|
||||
V850E_UART_CHIP_NAME, chan);
|
||||
}
|
||||
|
||||
/* This is what the init code actually calls. */
|
||||
static int v850e_uart_console_init (void)
|
||||
{
|
||||
v850e_uart_cons_init (V850E_UART_CONSOLE_CHANNEL);
|
||||
return 0;
|
||||
}
|
||||
console_initcall(v850e_uart_console_init);
|
||||
|
||||
#define V850E_UART_CONSOLE &v850e_uart_cons
|
||||
|
||||
#else /* !CONFIG_V850E_UART_CONSOLE */
|
||||
#define V850E_UART_CONSOLE 0
|
||||
#endif /* CONFIG_V850E_UART_CONSOLE */
|
||||
|
||||
/* TX/RX interrupt handlers. */
|
||||
|
||||
static void v850e_uart_stop_tx (struct uart_port *port, unsigned tty_stop);
|
||||
|
||||
void v850e_uart_tx (struct uart_port *port)
|
||||
{
|
||||
struct circ_buf *xmit = &port->info->xmit;
|
||||
int stopped = uart_tx_stopped (port);
|
||||
|
||||
if (v850e_uart_xmit_ok (port->line)) {
|
||||
int tx_ch;
|
||||
|
||||
if (port->x_char) {
|
||||
tx_ch = port->x_char;
|
||||
port->x_char = 0;
|
||||
} else if (!uart_circ_empty (xmit) && !stopped) {
|
||||
tx_ch = xmit->buf[xmit->tail];
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
} else
|
||||
goto no_xmit;
|
||||
|
||||
v850e_uart_putc (port->line, tx_ch);
|
||||
port->icount.tx++;
|
||||
|
||||
if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup (port);
|
||||
}
|
||||
|
||||
no_xmit:
|
||||
if (uart_circ_empty (xmit) || stopped)
|
||||
v850e_uart_stop_tx (port, stopped);
|
||||
}
|
||||
|
||||
static irqreturn_t v850e_uart_tx_irq(int irq, void *data, struct pt_regs *regs)
|
||||
{
|
||||
struct uart_port *port = data;
|
||||
v850e_uart_tx (port);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t v850e_uart_rx_irq(int irq, void *data, struct pt_regs *regs)
|
||||
{
|
||||
struct uart_port *port = data;
|
||||
unsigned ch_stat = TTY_NORMAL;
|
||||
unsigned ch = v850e_uart_getc (port->line);
|
||||
unsigned err = v850e_uart_err (port->line);
|
||||
|
||||
if (err) {
|
||||
if (err & V850E_UART_ERR_OVERRUN) {
|
||||
ch_stat = TTY_OVERRUN;
|
||||
port->icount.overrun++;
|
||||
} else if (err & V850E_UART_ERR_FRAME) {
|
||||
ch_stat = TTY_FRAME;
|
||||
port->icount.frame++;
|
||||
} else if (err & V850E_UART_ERR_PARITY) {
|
||||
ch_stat = TTY_PARITY;
|
||||
port->icount.parity++;
|
||||
}
|
||||
}
|
||||
|
||||
port->icount.rx++;
|
||||
|
||||
tty_insert_flip_char (port->info->tty, ch, ch_stat);
|
||||
tty_schedule_flip (port->info->tty);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
/* Control functions for the serial framework. */
|
||||
|
||||
static void v850e_uart_nop (struct uart_port *port) { }
|
||||
static int v850e_uart_success (struct uart_port *port) { return 0; }
|
||||
|
||||
static unsigned v850e_uart_tx_empty (struct uart_port *port)
|
||||
{
|
||||
return TIOCSER_TEMT; /* Can't detect. */
|
||||
}
|
||||
|
||||
static void v850e_uart_set_mctrl (struct uart_port *port, unsigned mctrl)
|
||||
{
|
||||
#ifdef V850E_UART_SET_RTS
|
||||
V850E_UART_SET_RTS (port->line, (mctrl & TIOCM_RTS));
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned v850e_uart_get_mctrl (struct uart_port *port)
|
||||
{
|
||||
/* We don't support DCD or DSR, so consider them permanently active. */
|
||||
int mctrl = TIOCM_CAR | TIOCM_DSR;
|
||||
|
||||
/* We may support CTS. */
|
||||
#ifdef V850E_UART_CTS
|
||||
mctrl |= V850E_UART_CTS(port->line) ? TIOCM_CTS : 0;
|
||||
#else
|
||||
mctrl |= TIOCM_CTS;
|
||||
#endif
|
||||
|
||||
return mctrl;
|
||||
}
|
||||
|
||||
static void v850e_uart_start_tx (struct uart_port *port, unsigned tty_start)
|
||||
{
|
||||
v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line));
|
||||
v850e_uart_tx (port);
|
||||
v850e_intc_enable_irq (V850E_UART_TX_IRQ (port->line));
|
||||
}
|
||||
|
||||
static void v850e_uart_stop_tx (struct uart_port *port, unsigned tty_stop)
|
||||
{
|
||||
v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line));
|
||||
}
|
||||
|
||||
static void v850e_uart_start_rx (struct uart_port *port)
|
||||
{
|
||||
v850e_intc_enable_irq (V850E_UART_RX_IRQ (port->line));
|
||||
}
|
||||
|
||||
static void v850e_uart_stop_rx (struct uart_port *port)
|
||||
{
|
||||
v850e_intc_disable_irq (V850E_UART_RX_IRQ (port->line));
|
||||
}
|
||||
|
||||
static void v850e_uart_break_ctl (struct uart_port *port, int break_ctl)
|
||||
{
|
||||
/* Umm, do this later. */
|
||||
}
|
||||
|
||||
static int v850e_uart_startup (struct uart_port *port)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Alloc RX irq. */
|
||||
err = request_irq (V850E_UART_RX_IRQ (port->line), v850e_uart_rx_irq,
|
||||
SA_INTERRUPT, "v850e_uart", port);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Alloc TX irq. */
|
||||
err = request_irq (V850E_UART_TX_IRQ (port->line), v850e_uart_tx_irq,
|
||||
SA_INTERRUPT, "v850e_uart", port);
|
||||
if (err) {
|
||||
free_irq (V850E_UART_RX_IRQ (port->line), port);
|
||||
return err;
|
||||
}
|
||||
|
||||
v850e_uart_start_rx (port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void v850e_uart_shutdown (struct uart_port *port)
|
||||
{
|
||||
/* Disable port interrupts. */
|
||||
free_irq (V850E_UART_TX_IRQ (port->line), port);
|
||||
free_irq (V850E_UART_RX_IRQ (port->line), port);
|
||||
|
||||
/* Turn off xmit/recv enable bits. */
|
||||
V850E_UART_CONFIG (port->line)
|
||||
&= ~(V850E_UART_CONFIG_TX_ENABLE
|
||||
| V850E_UART_CONFIG_RX_ENABLE);
|
||||
/* Then reset the channel. */
|
||||
V850E_UART_CONFIG (port->line) = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
v850e_uart_set_termios (struct uart_port *port, struct termios *termios,
|
||||
struct termios *old)
|
||||
{
|
||||
unsigned cflags = termios->c_cflag;
|
||||
|
||||
/* Restrict flags to legal values. */
|
||||
if ((cflags & CSIZE) != CS7 && (cflags & CSIZE) != CS8)
|
||||
/* The new value of CSIZE is invalid, use the old value. */
|
||||
cflags = (cflags & ~CSIZE)
|
||||
| (old ? (old->c_cflag & CSIZE) : CS8);
|
||||
|
||||
termios->c_cflag = cflags;
|
||||
|
||||
v850e_uart_configure (port->line, cflags,
|
||||
uart_get_baud_rate (port, termios, old,
|
||||
v850e_uart_min_baud(),
|
||||
v850e_uart_max_baud()));
|
||||
}
|
||||
|
||||
static const char *v850e_uart_type (struct uart_port *port)
|
||||
{
|
||||
return port->type == PORT_V850E_UART ? "v850e_uart" : 0;
|
||||
}
|
||||
|
||||
static void v850e_uart_config_port (struct uart_port *port, int flags)
|
||||
{
|
||||
if (flags & UART_CONFIG_TYPE)
|
||||
port->type = PORT_V850E_UART;
|
||||
}
|
||||
|
||||
static int
|
||||
v850e_uart_verify_port (struct uart_port *port, struct serial_struct *ser)
|
||||
{
|
||||
if (ser->type != PORT_UNKNOWN && ser->type != PORT_V850E_UART)
|
||||
return -EINVAL;
|
||||
if (ser->irq != V850E_UART_TX_IRQ (port->line))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct uart_ops v850e_uart_ops = {
|
||||
.tx_empty = v850e_uart_tx_empty,
|
||||
.get_mctrl = v850e_uart_get_mctrl,
|
||||
.set_mctrl = v850e_uart_set_mctrl,
|
||||
.start_tx = v850e_uart_start_tx,
|
||||
.stop_tx = v850e_uart_stop_tx,
|
||||
.stop_rx = v850e_uart_stop_rx,
|
||||
.enable_ms = v850e_uart_nop,
|
||||
.break_ctl = v850e_uart_break_ctl,
|
||||
.startup = v850e_uart_startup,
|
||||
.shutdown = v850e_uart_shutdown,
|
||||
.set_termios = v850e_uart_set_termios,
|
||||
.type = v850e_uart_type,
|
||||
.release_port = v850e_uart_nop,
|
||||
.request_port = v850e_uart_success,
|
||||
.config_port = v850e_uart_config_port,
|
||||
.verify_port = v850e_uart_verify_port,
|
||||
};
|
||||
|
||||
/* Initialization and cleanup. */
|
||||
|
||||
static struct uart_driver v850e_uart_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = "v850e_uart",
|
||||
.devfs_name = "tts/",
|
||||
.dev_name = "ttyS",
|
||||
.major = TTY_MAJOR,
|
||||
.minor = V850E_UART_MINOR_BASE,
|
||||
.nr = V850E_UART_NUM_CHANNELS,
|
||||
.cons = V850E_UART_CONSOLE,
|
||||
};
|
||||
|
||||
|
||||
static struct uart_port v850e_uart_ports[V850E_UART_NUM_CHANNELS];
|
||||
|
||||
static int __init v850e_uart_init (void)
|
||||
{
|
||||
int rval;
|
||||
|
||||
printk (KERN_INFO "%s on-chip UART\n", V850E_UART_CHIP_NAME);
|
||||
|
||||
rval = uart_register_driver (&v850e_uart_driver);
|
||||
if (rval == 0) {
|
||||
unsigned chan;
|
||||
|
||||
for (chan = 0; chan < V850E_UART_NUM_CHANNELS; chan++) {
|
||||
struct uart_port *port = &v850e_uart_ports[chan];
|
||||
|
||||
memset (port, 0, sizeof *port);
|
||||
|
||||
port->ops = &v850e_uart_ops;
|
||||
port->line = chan;
|
||||
port->iotype = SERIAL_IO_MEM;
|
||||
port->flags = UPF_BOOT_AUTOCONF;
|
||||
|
||||
/* We actually use multiple IRQs, but the serial
|
||||
framework seems to mainly use this for
|
||||
informational purposes anyway. Here we use the TX
|
||||
irq. */
|
||||
port->irq = V850E_UART_TX_IRQ (chan);
|
||||
|
||||
/* The serial framework doesn't really use these
|
||||
membase/mapbase fields for anything useful, but
|
||||
it requires that they be something non-zero to
|
||||
consider the port `valid', and also uses them
|
||||
for informational purposes. */
|
||||
port->membase = (void *)V850E_UART_BASE_ADDR (chan);
|
||||
port->mapbase = V850E_UART_BASE_ADDR (chan);
|
||||
|
||||
/* The framework insists on knowing the uart's master
|
||||
clock freq, though it doesn't seem to do anything
|
||||
useful for us with it. We must make it at least
|
||||
higher than (the maximum baud rate * 16), otherwise
|
||||
the framework will puke during its internal
|
||||
calculations, and force the baud rate to be 9600.
|
||||
To be accurate though, just repeat the calculation
|
||||
we use when actually setting the speed. */
|
||||
port->uartclk = v850e_uart_max_clock() * 16;
|
||||
|
||||
uart_add_one_port (&v850e_uart_driver, port);
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static void __exit v850e_uart_exit (void)
|
||||
{
|
||||
unsigned chan;
|
||||
|
||||
for (chan = 0; chan < V850E_UART_NUM_CHANNELS; chan++)
|
||||
uart_remove_one_port (&v850e_uart_driver,
|
||||
&v850e_uart_ports[chan]);
|
||||
|
||||
uart_unregister_driver (&v850e_uart_driver);
|
||||
}
|
||||
|
||||
module_init (v850e_uart_init);
|
||||
module_exit (v850e_uart_exit);
|
||||
|
||||
MODULE_AUTHOR ("Miles Bader");
|
||||
MODULE_DESCRIPTION ("NEC " V850E_UART_CHIP_NAME " on-chip UART");
|
||||
MODULE_LICENSE ("GPL");
|
||||
Reference in New Issue
Block a user